tor-browser

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

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