security/manager/ssl/tests/unit/test_pinning.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
     2 // This Source Code Form is subject to the terms of the Mozilla Public
     3 // License, v. 2.0. If a copy of the MPL was not distributed with this
     4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 //
     6 // For all cases, the acceptable pinset includes only certificates pinned to
     7 // Test End Entity Cert (signed by issuer testCA). Other certificates
     8 // are issued by otherCA, which is never in the pinset but is a user-specified
     9 // trust anchor. This test covers multiple cases:
    10 //
    11 // Pinned domain include-subdomains.pinning.example.com includes subdomains
    12 // - PASS: include-subdomains.pinning.example.com serves a correct cert
    13 // - PASS: good.include-subdomains.pinning.example.com serves a correct cert
    14 // - FAIL (strict): bad.include-subdomains.pinning.example.com serves a cert
    15 // not in the pinset
    16 // - PASS (mitm): bad.include-subdomains.pinning.example.com serves a cert not
    17 // in the pinset, but issued by a user-specified trust domain
    18 //
    19 // Pinned domain exclude-subdomains.pinning.example.com excludes subdomains
    20 // - PASS: exclude-subdomains.pinning.example.com serves a correct cert
    21 // - FAIL: exclude-subdomains.pinning.example.com services an incorrect cert
    22 // (TODO: test using verifyCertnow)
    23 // - PASS: sub.exclude-subdomains.pinning.example.com serves an incorrect cert
    25 "use strict";
    27 do_get_profile(); // must be called before getting nsIX509CertDB
    28 const certdb = Cc["@mozilla.org/security/x509certdb;1"]
    29                   .getService(Ci.nsIX509CertDB);
    31 function test_strict() {
    32   // In strict mode, we always evaluate pinning data, regardless of whether the
    33   // issuer is a built-in trust anchor. We only enforce pins that are not in
    34   // test mode.
    35   add_test(function() {
    36     Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 2);
    37     run_next_test();
    38   });
    40   // If a host should be pinned but other errors (particularly overridable
    41   // errors) like 'unknown issuer' are encountered, the pinning error takes
    42   // precedence. This prevents overrides for such hosts.
    43   add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
    44     getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
    46   // Issued by otherCA, which is not in the pinset for pinning.example.com.
    47   add_connection_test("bad.include-subdomains.pinning.example.com",
    48     getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
    50   // These domains serve certs that match the pinset.
    51   add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
    52   add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
    53   add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
    55   // This domain serves a cert that doesn't match the pinset, but subdomains
    56   // are excluded.
    57   add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
    59   // This domain's pinset is exactly the same as
    60   // include-subdomains.pinning.example.com, serves the same cert as
    61   // bad.include-subdomains.pinning.example.com, but it should pass because
    62   // it's in test_mode.
    63   add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
    64 }
    66 function test_mitm() {
    67   // In MITM mode, we allow pinning to pass if the chain resolves to any
    68   // user-specified trust anchor, even if it is not in the pinset.
    69   add_test(function() {
    70     Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 1);
    71     run_next_test();
    72   });
    74   add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
    75   add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
    77   add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
    78     getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
    80   // In this case, even though otherCA is not in the pinset, it is a
    81   // user-specified trust anchor and the pinning check succeeds.
    82   add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
    84   add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
    85   add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
    86   add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
    87 };
    89 function test_disabled() {
    90   // Disable pinning.
    91   add_test(function() {
    92     Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 0);
    93     run_next_test();
    94   });
    96   add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
    97   add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
    98   add_connection_test("bad.include-subdomains.pinning.example.com", Cr.NS_OK);
    99   add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
   100   add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
   101   add_connection_test("test-mode.pinning.example.com", Cr.NS_OK);
   103   add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
   104     getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER));
   105 }
   107 function test_enforce_test_mode() {
   108   // In enforce test mode, we always enforce all pins, even test pins.
   109   add_test(function() {
   110     Services.prefs.setIntPref("security.cert_pinning.enforcement_level", 3);
   111     run_next_test();
   112   });
   114   add_connection_test("unknownissuer.include-subdomains.pinning.example.com",
   115     getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   117   // Issued by otherCA, which is not in the pinset for pinning.example.com.
   118   add_connection_test("bad.include-subdomains.pinning.example.com",
   119     getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   121   // These domains serve certs that match the pinset.
   122   add_connection_test("include-subdomains.pinning.example.com", Cr.NS_OK);
   123   add_connection_test("good.include-subdomains.pinning.example.com", Cr.NS_OK);
   124   add_connection_test("exclude-subdomains.pinning.example.com", Cr.NS_OK);
   126   // This domain serves a cert that doesn't match the pinset, but subdomains
   127   // are excluded.
   128   add_connection_test("sub.exclude-subdomains.pinning.example.com", Cr.NS_OK);
   130   // This domain's pinset is exactly the same as
   131   // include-subdomains.pinning.example.com, serves the same cert as
   132   // bad.include-subdomains.pinning.example.com, is in test-mode, but we are
   133   // enforcing test mode pins.
   134   add_connection_test("test-mode.pinning.example.com",
   135     getXPCOMStatusFromNSS(MOZILLA_PKIX_ERROR_KEY_PINNING_FAILURE));
   136 }
   138 function check_pinning_telemetry() {
   139   let service = Cc["@mozilla.org/base/telemetry;1"].getService(Ci.nsITelemetry);
   140   let prod_histogram = service.getHistogramById("CERT_PINNING_RESULTS")
   141                          .snapshot();
   142   let test_histogram = service.getHistogramById("CERT_PINNING_TEST_RESULTS")
   143                          .snapshot();
   144   // Because all of our test domains are pinned to user-specified trust
   145   // anchors, effectively only strict mode and enforce test-mode get evaluated
   146   do_check_eq(prod_histogram.counts[0], 4); // Failure count
   147   do_check_eq(prod_histogram.counts[1], 4); // Success count
   148   do_check_eq(test_histogram.counts[0], 2); // Failure count
   149   do_check_eq(test_histogram.counts[1], 0); // Success count
   151   let moz_prod_histogram = service.getHistogramById("CERT_PINNING_MOZ_RESULTS")
   152                              .snapshot();
   153   let moz_test_histogram =
   154     service.getHistogramById("CERT_PINNING_MOZ_TEST_RESULTS").snapshot();
   155   do_check_eq(moz_prod_histogram.counts[0], 0); // Failure count
   156   do_check_eq(moz_prod_histogram.counts[1], 0); // Success count
   157   do_check_eq(moz_test_histogram.counts[0], 0); // Failure count
   158   do_check_eq(moz_test_histogram.counts[1], 0); // Success count
   160   let per_host_histogram =
   161     service.getHistogramById("CERT_PINNING_MOZ_RESULTS_BY_HOST").snapshot();
   162   do_check_eq(per_host_histogram.counts[0], 0); // Failure count
   163   do_check_eq(per_host_histogram.counts[1], 2); // Success count
   164   run_next_test();
   165 }
   167 function run_test() {
   168   add_tls_server_setup("BadCertServer");
   170   // Add a user-specified trust anchor.
   171   addCertFromFile(certdb, "tlsserver/other-test-ca.der", "CTu,u,u");
   173   test_strict();
   174   test_mitm();
   175   test_disabled();
   176   test_enforce_test_mode();
   178   add_test(function () {
   179     check_pinning_telemetry();
   180   });
   181   run_next_test();
   182 }

mercurial