test_keysize_ev.js (5518B)
1 // -*- indent-tabs-mode: nil; js-indent-level: 2 -*- 2 // Any copyright is dedicated to the Public Domain. 3 // http://creativecommons.org/publicdomain/zero/1.0/ 4 "use strict"; 5 6 // Checks that RSA certs with key sizes below 2048 bits when verifying for EV 7 // are rejected. 8 9 do_get_profile(); // Must be called before getting nsIX509CertDB 10 const certDB = Cc["@mozilla.org/security/x509certdb;1"].getService( 11 Ci.nsIX509CertDB 12 ); 13 14 const SERVER_PORT = 8888; 15 16 function getOCSPResponder(expectedCertNames) { 17 let expectedPaths = expectedCertNames.slice(); 18 return startOCSPResponder( 19 SERVER_PORT, 20 "www.example.com", 21 "test_keysize_ev/", 22 expectedCertNames, 23 expectedPaths 24 ); 25 } 26 27 function loadCert(certName, trustString) { 28 let certFilename = "test_keysize_ev/" + certName + ".pem"; 29 addCertFromFile(certDB, certFilename, trustString); 30 return constructCertFromFile(certFilename); 31 } 32 33 /** 34 * Asynchronously runs a single EV key size test. 35 * 36 * @param {Array} expectedNamesForOCSP 37 * An array of nicknames of the certs to be responded to. 38 * @param {string} rootCertFileName 39 * The file name of the root cert. Can begin with ".." to reference 40 * certs in folders other than "test_keysize_ev/". 41 * @param {Array} intCertFileNames 42 * An array of file names of any intermediate certificates. 43 * @param {string} endEntityCertFileName 44 * The file name of the end entity cert. 45 * @param {boolean} expectedResult 46 * Whether the chain is expected to validate as EV. 47 */ 48 async function keySizeTestForEV( 49 expectedNamesForOCSP, 50 rootCertFileName, 51 intCertFileNames, 52 endEntityCertFileName, 53 expectedResult 54 ) { 55 clearOCSPCache(); 56 let ocspResponder = getOCSPResponder(expectedNamesForOCSP); 57 58 loadCert(rootCertFileName, "CTu,CTu,CTu"); 59 for (let intCertFileName of intCertFileNames) { 60 loadCert(intCertFileName, ",,"); 61 } 62 await checkEVStatus( 63 certDB, 64 constructCertFromFile(`test_keysize_ev/${endEntityCertFileName}.pem`), 65 Ci.nsIX509CertDB.verifyUsageTLSServer, 66 expectedResult 67 ); 68 69 await stopOCSPResponder(ocspResponder); 70 } 71 72 /** 73 * For debug builds which have the test EV roots compiled in, checks RSA chains 74 * which contain certs with key sizes adequate for EV are validated as such, 75 * while chains that contain any cert with an inadequate key size fail EV and 76 * validate as DV. 77 * For opt builds which don't have the test EV roots compiled in, checks that 78 * none of the chains validate as EV. 79 * 80 * Note: This function assumes that the key size requirements for EV are greater 81 * than the requirements for DV. 82 * 83 * @param {number} inadequateKeySize 84 * The inadequate key size of the generated certs. 85 * @param {number} adequateKeySize 86 * The adequate key size of the generated certs. 87 */ 88 async function checkRSAChains(inadequateKeySize, adequateKeySize) { 89 // Reuse the existing test RSA EV root 90 let rootOKCertFileName = "../test_ev_certs/evroot"; 91 let rootOKName = "evroot"; 92 let rootNotOKName = "ev_root_rsa_" + inadequateKeySize; 93 let intOKName = "ev_int_rsa_" + adequateKeySize; 94 let intNotOKName = "ev_int_rsa_" + inadequateKeySize; 95 let eeOKName = "ev_ee_rsa_" + adequateKeySize; 96 let eeNotOKName = "ev_ee_rsa_" + inadequateKeySize; 97 98 // Chain with certs that have adequate sizes for EV and DV 99 // In opt builds, this chain is only validated for DV. Hence, an OCSP fetch 100 // will for example not be done for the "ev_int_rsa_2048-evroot" intermediate 101 // in such a build. 102 let intFullName = intOKName + "-" + rootOKName; 103 let eeFullName = eeOKName + "-" + intOKName + "-" + rootOKName; 104 let expectedNamesForOCSP = [eeFullName]; 105 await keySizeTestForEV( 106 expectedNamesForOCSP, 107 rootOKCertFileName, 108 [intFullName], 109 eeFullName, 110 gEVExpected 111 ); 112 113 // Chain with a root cert that has an inadequate size for EV, but 114 // adequate size for DV 115 intFullName = intOKName + "-" + rootNotOKName; 116 eeFullName = eeOKName + "-" + intOKName + "-" + rootNotOKName; 117 expectedNamesForOCSP = [eeFullName]; 118 await keySizeTestForEV( 119 expectedNamesForOCSP, 120 rootNotOKName, 121 [intFullName], 122 eeFullName, 123 false 124 ); 125 126 // Chain with an intermediate cert that has an inadequate size for EV, but 127 // adequate size for DV 128 intFullName = intNotOKName + "-" + rootOKName; 129 eeFullName = eeOKName + "-" + intNotOKName + "-" + rootOKName; 130 expectedNamesForOCSP = [eeFullName]; 131 await keySizeTestForEV( 132 expectedNamesForOCSP, 133 rootOKCertFileName, 134 [intFullName], 135 eeFullName, 136 false 137 ); 138 139 // Chain with an end entity cert that has an inadequate size for EV, but 140 // adequate size for DV 141 intFullName = intOKName + "-" + rootOKName; 142 eeFullName = eeNotOKName + "-" + intOKName + "-" + rootOKName; 143 expectedNamesForOCSP = [eeFullName]; 144 await keySizeTestForEV( 145 expectedNamesForOCSP, 146 rootOKCertFileName, 147 [intFullName], 148 eeFullName, 149 false 150 ); 151 } 152 153 add_task(async function () { 154 Services.prefs.setCharPref("network.dns.localDomains", "www.example.com"); 155 Services.prefs.setIntPref("security.OCSP.enabled", 1); 156 157 let smallKeyEVRoot = constructCertFromFile( 158 "test_keysize_ev/ev_root_rsa_2040.pem" 159 ); 160 equal( 161 smallKeyEVRoot.sha256Fingerprint, 162 "40:AB:5D:A5:89:15:A9:4B:82:87:B8:A6:9A:84:B1:DB:" + 163 "7A:9D:DB:B8:4E:E1:23:E3:C6:64:E7:50:DC:35:8C:68", 164 "test sanity check: the small-key EV root must have the same " + 165 "fingerprint as the corresponding entry in ExtendedValidation.cpp" 166 ); 167 168 await checkRSAChains(2040, 2048); 169 });