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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/tests/unit/test_ev_certs.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,299 @@
     1.4 +// -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 +// This Source Code Form is subject to the terms of the Mozilla Public
     1.6 +// License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 +// file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.8 +
     1.9 +"use strict";
    1.10 +
    1.11 +// XXX: The isDebugBuild tests you see are here because the test EV root is
    1.12 +// only enabled for EV in debug builds, as a security measure. An ugly hack.
    1.13 +
    1.14 +do_get_profile(); // must be called before getting nsIX509CertDB
    1.15 +const certdb = Cc["@mozilla.org/security/x509certdb;1"]
    1.16 +                 .getService(Ci.nsIX509CertDB);
    1.17 +
    1.18 +const evrootnick = "XPCShell EV Testing (untrustworthy) CA - Mozilla - " +
    1.19 +                   "EV debug test CA";
    1.20 +
    1.21 +// This is the list of certificates needed for the test
    1.22 +// The certificates prefixed by 'int-' are intermediates
    1.23 +let certList = [
    1.24 +  // Test for successful EV validation
    1.25 +  'int-ev-valid',
    1.26 +  'ev-valid',
    1.27 +  'ev-valid-anypolicy-int',
    1.28 +  'int-ev-valid-anypolicy-int',
    1.29 +  'no-ocsp-url-cert', // a cert signed by the EV auth that has no OCSP url
    1.30 +                      // but that contains a valid CRLDP.
    1.31 +
    1.32 +  // Testing a root that looks like EV but is not EV enabled
    1.33 +  'int-non-ev-root',
    1.34 +  'non-ev-root',
    1.35 +]
    1.36 +
    1.37 +function load_ca(ca_name) {
    1.38 +  var ca_filename = ca_name + ".der";
    1.39 +  addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
    1.40 +}
    1.41 +
    1.42 +const SERVER_PORT = 8888;
    1.43 +
    1.44 +function failingOCSPResponder() {
    1.45 +  return getFailingHttpServer(SERVER_PORT,
    1.46 +                              ["www.example.com", "crl.example.com"]);
    1.47 +}
    1.48 +
    1.49 +function start_ocsp_responder(expectedCertNames) {
    1.50 +  let expectedPaths = expectedCertNames.slice();
    1.51 +  return startOCSPResponder(SERVER_PORT, "www.example.com", ["crl.example.com"],
    1.52 +                            "test_ev_certs", expectedCertNames, expectedPaths);
    1.53 +}
    1.54 +
    1.55 +function check_cert_err(cert_name, expected_error) {
    1.56 +  let cert = certdb.findCertByNickname(null, cert_name);
    1.57 +  let hasEVPolicy = {};
    1.58 +  let verifiedChain = {};
    1.59 +  let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
    1.60 +                                   NO_FLAGS, verifiedChain, hasEVPolicy);
    1.61 +  do_check_eq(error,  expected_error);
    1.62 +}
    1.63 +
    1.64 +
    1.65 +function check_ee_for_ev(cert_name, expected_ev) {
    1.66 +    let cert = certdb.findCertByNickname(null, cert_name);
    1.67 +    let hasEVPolicy = {};
    1.68 +    let verifiedChain = {};
    1.69 +    let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
    1.70 +                                     NO_FLAGS, verifiedChain, hasEVPolicy);
    1.71 +    do_check_eq(hasEVPolicy.value, expected_ev);
    1.72 +    do_check_eq(0, error);
    1.73 +}
    1.74 +
    1.75 +function run_test() {
    1.76 +  for (let i = 0 ; i < certList.length; i++) {
    1.77 +    let cert_filename = certList[i] + ".der";
    1.78 +    addCertFromFile(certdb, "test_ev_certs/" + cert_filename, ',,');
    1.79 +  }
    1.80 +  load_ca("evroot");
    1.81 +  load_ca("non-evroot-ca");
    1.82 +
    1.83 +  // setup and start ocsp responder
    1.84 +  Services.prefs.setCharPref("network.dns.localDomains",
    1.85 +                             'www.example.com, crl.example.com');
    1.86 +  add_tests_in_mode(true);
    1.87 +  add_tests_in_mode(false);
    1.88 +  run_next_test();
    1.89 +}
    1.90 +
    1.91 +function add_tests_in_mode(useMozillaPKIX)
    1.92 +{
    1.93 +  add_test(function () {
    1.94 +    Services.prefs.setBoolPref("security.use_mozillapkix_verification",
    1.95 +                               useMozillaPKIX);
    1.96 +    run_next_test();
    1.97 +  });
    1.98 +
    1.99 +  add_test(function () {
   1.100 +    clearOCSPCache();
   1.101 +    let ocspResponder = start_ocsp_responder(
   1.102 +                          isDebugBuild ? ["int-ev-valid", "ev-valid"]
   1.103 +                                       : ["ev-valid"]);
   1.104 +    check_ee_for_ev("ev-valid", isDebugBuild);
   1.105 +    ocspResponder.stop(run_next_test);
   1.106 +  });
   1.107 +
   1.108 +
   1.109 +  add_test(function () {
   1.110 +    clearOCSPCache();
   1.111 +
   1.112 +    let ocspResponder = start_ocsp_responder(
   1.113 +                          isDebugBuild ? ["int-ev-valid-anypolicy-int", "ev-valid-anypolicy-int"]
   1.114 +                                       : ["ev-valid-anypolicy-int"]);
   1.115 +    check_ee_for_ev("ev-valid-anypolicy-int", isDebugBuild);
   1.116 +    ocspResponder.stop(run_next_test);
   1.117 +  });
   1.118 +
   1.119 +  add_test(function() {
   1.120 +    clearOCSPCache();
   1.121 +    let ocspResponder = start_ocsp_responder(["non-ev-root"]);
   1.122 +    check_ee_for_ev("non-ev-root", false);
   1.123 +    ocspResponder.stop(run_next_test);
   1.124 +  });
   1.125 +
   1.126 +  add_test(function() {
   1.127 +    clearOCSPCache();
   1.128 +    // libpkix will attempt to validate the intermediate, which does have an
   1.129 +    // OCSP URL.
   1.130 +    let ocspResponder = isDebugBuild ? start_ocsp_responder(["int-ev-valid"])
   1.131 +                                     : failingOCSPResponder();
   1.132 +    check_ee_for_ev("no-ocsp-url-cert", false);
   1.133 +    ocspResponder.stop(run_next_test);
   1.134 +  });
   1.135 +
   1.136 +  // bug 917380: Chcek that an untrusted EV root is untrusted.
   1.137 +  const nsIX509Cert = Ci.nsIX509Cert;
   1.138 +  add_test(function() {
   1.139 +    let evRootCA = certdb.findCertByNickname(null, evrootnick);
   1.140 +    certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT, 0);
   1.141 +
   1.142 +    clearOCSPCache();
   1.143 +    let ocspResponder = failingOCSPResponder();
   1.144 +    check_cert_err("ev-valid",
   1.145 +                   useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
   1.146 +                                  : SEC_ERROR_UNTRUSTED_ISSUER);
   1.147 +    ocspResponder.stop(run_next_test);
   1.148 +  });
   1.149 +
   1.150 +  // bug 917380: Chcek that a trusted EV root is trusted after disabling and
   1.151 +  // re-enabling trust.
   1.152 +  add_test(function() {
   1.153 +    let evRootCA = certdb.findCertByNickname(null, evrootnick);
   1.154 +    certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT,
   1.155 +                        Ci.nsIX509CertDB.TRUSTED_SSL |
   1.156 +                        Ci.nsIX509CertDB.TRUSTED_EMAIL |
   1.157 +                        Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
   1.158 +
   1.159 +    clearOCSPCache();
   1.160 +    let ocspResponder = start_ocsp_responder(
   1.161 +                          isDebugBuild ? ["int-ev-valid", "ev-valid"]
   1.162 +                                       : ["ev-valid"]);
   1.163 +    check_ee_for_ev("ev-valid", isDebugBuild);
   1.164 +    ocspResponder.stop(run_next_test);
   1.165 +  });
   1.166 +
   1.167 +  add_test(function () {
   1.168 +    check_no_ocsp_requests("ev-valid",
   1.169 +      useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
   1.170 +                     : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
   1.171 +                                     : SEC_ERROR_EXTENSION_NOT_FOUND));
   1.172 +  });
   1.173 +
   1.174 +  add_test(function () {
   1.175 +    check_no_ocsp_requests("non-ev-root",
   1.176 +      useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
   1.177 +                     : (isDebugBuild ? SEC_ERROR_UNTRUSTED_ISSUER
   1.178 +                                     : SEC_ERROR_EXTENSION_NOT_FOUND));
   1.179 +  });
   1.180 +
   1.181 +  add_test(function () {
   1.182 +    check_no_ocsp_requests("no-ocsp-url-cert",
   1.183 +      useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
   1.184 +                     : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
   1.185 +                                     : SEC_ERROR_EXTENSION_NOT_FOUND));
   1.186 +  });
   1.187 +
   1.188 +
   1.189 +  // Test the EV continues to work with flags after successful EV verification
   1.190 +  add_test(function () {
   1.191 +    clearOCSPCache();
   1.192 +    let ocspResponder = start_ocsp_responder(
   1.193 +                          isDebugBuild ? ["int-ev-valid", "ev-valid"]
   1.194 +                                       : ["ev-valid"]);
   1.195 +    check_ee_for_ev("ev-valid", isDebugBuild);
   1.196 +    ocspResponder.stop(function () {
   1.197 +      // without net it must be able to EV verify
   1.198 +      let failingOcspResponder = failingOCSPResponder();
   1.199 +      let cert = certdb.findCertByNickname(null, "ev-valid");
   1.200 +      let hasEVPolicy = {};
   1.201 +      let verifiedChain = {};
   1.202 +      let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
   1.203 +                  Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
   1.204 +
   1.205 +      let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
   1.206 +                                       flags, verifiedChain, hasEVPolicy);
   1.207 +      do_check_eq(hasEVPolicy.value, isDebugBuild);
   1.208 +      do_check_eq(error,
   1.209 +                  isDebugBuild ? 0
   1.210 +                               : (useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
   1.211 +                                                 : SEC_ERROR_EXTENSION_NOT_FOUND));
   1.212 +      failingOcspResponder.stop(run_next_test);
   1.213 +    });
   1.214 +  });
   1.215 +
   1.216 +  // Bug 991815 old but valid intermediates are OK
   1.217 +  add_test(function () {
   1.218 +    clearOCSPCache();
   1.219 +    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
   1.220 +                          "test_ev_certs",
   1.221 +                          isDebugBuild ? ["int-ev-valid", "ev-valid"]
   1.222 +                                       : ["ev-valid"],
   1.223 +                          [], [],
   1.224 +                          isDebugBuild ? ["longvalidityalmostold", "good"]
   1.225 +                                       : ["good"]);
   1.226 +    check_ee_for_ev("ev-valid", isDebugBuild);
   1.227 +    ocspResponder.stop(run_next_test);
   1.228 +  });
   1.229 +
   1.230 +  // Bug 991815 old but valid end-entities are NOT OK for EV
   1.231 +  // Unfortunatelly because of soft-fail we consider these OK for DV
   1.232 +  // libpkix does not enforce the age restriction and thus EV is valid
   1.233 +  add_test(function () {
   1.234 +    clearOCSPCache();
   1.235 +    // Since Mozilla::pkix does not consider the old amost invalid OCSP
   1.236 +    // response valid, it does not cache the old response and thus
   1.237 +    // makes a separate request for DV
   1.238 +    let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
   1.239 +    let debugResponseArray = ["good", "longvalidityalmostold",
   1.240 +                              "longvalidityalmostold"];
   1.241 +    if (!useMozillaPKIX) {
   1.242 +      debugCertNickArray = ["int-ev-valid", "ev-valid"];
   1.243 +      debugResponseArray = ["good", "longvalidityalmostold"];
   1.244 +    }
   1.245 +    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
   1.246 +                          "test_ev_certs",
   1.247 +                          isDebugBuild ? debugCertNickArray : ["ev-valid"],
   1.248 +                          [], [],
   1.249 +                          isDebugBuild ? debugResponseArray
   1.250 +                                       : ["longvalidityalmostold"]);
   1.251 +    check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
   1.252 +    ocspResponder.stop(run_next_test);
   1.253 +  });
   1.254 +
   1.255 +  // Bug 991815 Valid but Ancient (almost two year old) responses are Not OK for
   1.256 +  // EV (still OK for soft fail DV)
   1.257 +  add_test(function () {
   1.258 +    clearOCSPCache();
   1.259 +    let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
   1.260 +    let debugResponseArray = ["good", "ancientstillvalid",
   1.261 +                              "ancientstillvalid"];
   1.262 +    if (!useMozillaPKIX) {
   1.263 +      debugCertNickArray = ["int-ev-valid", "ev-valid"];
   1.264 +      debugResponseArray = ["good", "ancientstillvalid"];
   1.265 +    }
   1.266 +    let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
   1.267 +                          "test_ev_certs",
   1.268 +                          isDebugBuild ? debugCertNickArray : ["ev-valid"],
   1.269 +                          [], [],
   1.270 +                          isDebugBuild ? debugResponseArray
   1.271 +                                       : ["ancientstillvalid"]);
   1.272 +    check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
   1.273 +    ocspResponder.stop(run_next_test);
   1.274 +  });
   1.275 +}
   1.276 +
   1.277 +// bug 950240: add FLAG_MUST_BE_EV to CertVerifier::VerifyCert
   1.278 +// to prevent spurious OCSP requests that race with OCSP stapling.
   1.279 +// This has the side-effect of saying an EV certificate is not EV if
   1.280 +// it hasn't already been verified (e.g. on the verification thread when
   1.281 +// connecting to a site).
   1.282 +// This flag is mostly a hack that should be removed once FLAG_LOCAL_ONLY
   1.283 +// works as intended.
   1.284 +function check_no_ocsp_requests(cert_name, expected_error) {
   1.285 +  clearOCSPCache();
   1.286 +  let ocspResponder = failingOCSPResponder();
   1.287 +  let cert = certdb.findCertByNickname(null, cert_name);
   1.288 +  let hasEVPolicy = {};
   1.289 +  let verifiedChain = {};
   1.290 +  let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
   1.291 +              Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
   1.292 +  let error = certdb.verifyCertNow(cert, certificateUsageSSLServer, flags,
   1.293 +                                   verifiedChain, hasEVPolicy);
   1.294 +  // Since we're not doing OCSP requests, no certificate will be EV.
   1.295 +  do_check_eq(hasEVPolicy.value, false);
   1.296 +  do_check_eq(expected_error, error);
   1.297 +  // Also check that isExtendedValidation doesn't cause OCSP requests.
   1.298 +  let identityInfo = cert.QueryInterface(Ci.nsIIdentityInfo);
   1.299 +  do_check_eq(identityInfo.isExtendedValidation, false);
   1.300 +  ocspResponder.stop(run_next_test);
   1.301 +}
   1.302 +

mercurial