tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_self_signed_certs.js (5016B)


      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 "use strict";
      6 
      7 // This test uses a specially-crafted NSS cert DB containing 12 self-signed certificates that all
      8 // have the same subject and issuer distinguished name. Since they all have different keys and none
      9 // of them are trust anchors, there are a large number of potential trust paths that could be
     10 // explored. If our trust domain were naive enough to allow mozilla::pkix to explore them all, it
     11 // would take a long time to perform (mozilla::pkix does have the concept of a path-building budget,
     12 // but even on a fast computer, it takes an unacceptable amount of time to exhaust). To prevent the
     13 // full exploration of this space, NSSCertDBTrustDomain skips searching through self-signed
     14 // certificates that aren't trust anchors, since those would never otherwise be essential to
     15 // complete a path (note that this is only true as long as the extensions we support are restrictive
     16 // rather than additive).
     17 // When we try to verify one of these certificates in this test, we should finish relatively
     18 // quickly, even on slow hardware.
     19 // Should these certificates ever need regenerating, they were produced with the following commands:
     20 // certutil -N -d . --empty-password
     21 // for num in 00 01 02 03 04 05 06 07 08 09 10 11; do
     22 //   echo -ne "5\n6\n9\ny\ny\n\ny\n" | certutil -d . -S -s "CN=self-signed cert" -t ,, \
     23 //   -q secp256r1 -x -k ec -z <(date +%s) -1 -2 -n cert$num; sleep 2;
     24 // done
     25 
     26 add_task(async function test_no_overlong_path_building() {
     27  let profile = do_get_profile();
     28  const CERT_DB_NAME = "cert9.db";
     29  let srcCertDBFile = do_get_file(`test_self_signed_certs/${CERT_DB_NAME}`);
     30  srcCertDBFile.copyTo(profile, CERT_DB_NAME);
     31 
     32  let certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
     33    Ci.nsIX509CertDB
     34  );
     35  let certToVerify = null;
     36  for (let cert of certDB.getCerts()) {
     37    if (cert.subjectName == "CN=self-signed cert") {
     38      certToVerify = cert;
     39      break;
     40    }
     41  }
     42  notEqual(
     43    certToVerify,
     44    null,
     45    "should have found one of the preloaded self-signed certs"
     46  );
     47  let timeBefore = Date.now();
     48  // As mentioned above, mozilla::pkix limits how much it will search for a trusted path, even if a
     49  // trust domain keeps providing potential issuers. So, if we only tried to verify a certificate
     50  // once, this test could potentially pass on a fast computer even if we weren't properly skipping
     51  // unnecessary paths. If we were to try and lower our time limit (the comparison with
     52  // secondsElapsed, below), this test would intermittently fail on slow hardware. By trying to
     53  // verify the certificate 10 times, we hopefully end up with a meaningful test (it should still
     54  // fail on fast hardware if we don't properly skip unproductive paths) that won't intermittently
     55  // time out on slow hardware.
     56  for (let i = 0; i < 10; i++) {
     57    let date = new Date("2019-05-15T00:00:00.000Z");
     58    await checkCertErrorGenericAtTime(
     59      certDB,
     60      certToVerify,
     61      SEC_ERROR_UNKNOWN_ISSUER,
     62      Ci.nsIX509CertDB.verifyUsageTLSServerCA,
     63      date.getTime() / 1000
     64    );
     65  }
     66  let timeAfter = Date.now();
     67  let secondsElapsed = (timeAfter - timeBefore) / 1000;
     68  Assert.less(secondsElapsed, 120, "verifications shouldn't take too long");
     69 });
     70 
     71 add_task(async function test_no_bad_signature() {
     72  // If there are two self-signed CA certificates with the same subject and
     73  // issuer but different keys, where one is trusted, test that using the other
     74  // one as a server certificate doesn't result in a non-overridable "bad
     75  // signature" error but rather a "self-signed cert" error.
     76  let selfSignedCert = constructCertFromFile("test_self_signed_certs/ca1.pem");
     77  let certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
     78    Ci.nsIX509CertDB
     79  );
     80  addCertFromFile(certDB, "test_self_signed_certs/ca2.pem", "CTu,,");
     81  await checkCertErrorGeneric(
     82    certDB,
     83    selfSignedCert,
     84    MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT,
     85    Ci.nsIX509CertDB.verifyUsageTLSServer,
     86    false,
     87    "example.com"
     88  );
     89 });
     90 
     91 add_task(async function test_no_inadequate_key_usage() {
     92  // If there are two different non-CA, self-signed certificates with the same
     93  // subject and issuer but different keys, test that using one of them as a
     94  // server certificate doesn't result in a non-overridable "inadequate key
     95  // usage" error but rather a "self-signed cert" error.
     96  let selfSignedCert = constructCertFromFile("test_self_signed_certs/ee1.pem");
     97  let certDB = Cc["@mozilla.org/security/x509certdb;1"].getService(
     98    Ci.nsIX509CertDB
     99  );
    100  addCertFromFile(certDB, "test_self_signed_certs/ee2.pem", ",,");
    101  await checkCertErrorGeneric(
    102    certDB,
    103    selfSignedCert,
    104    MOZILLA_PKIX_ERROR_SELF_SIGNED_CERT,
    105    Ci.nsIX509CertDB.verifyUsageTLSServer,
    106    false,
    107    "example.com"
    108  );
    109 });