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 });