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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
michael@0 2 // This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 // License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 5
michael@0 6 "use strict";
michael@0 7
michael@0 8 // XXX: The isDebugBuild tests you see are here because the test EV root is
michael@0 9 // only enabled for EV in debug builds, as a security measure. An ugly hack.
michael@0 10
michael@0 11 do_get_profile(); // must be called before getting nsIX509CertDB
michael@0 12 const certdb = Cc["@mozilla.org/security/x509certdb;1"]
michael@0 13 .getService(Ci.nsIX509CertDB);
michael@0 14
michael@0 15 const evrootnick = "XPCShell EV Testing (untrustworthy) CA - Mozilla - " +
michael@0 16 "EV debug test CA";
michael@0 17
michael@0 18 // This is the list of certificates needed for the test
michael@0 19 // The certificates prefixed by 'int-' are intermediates
michael@0 20 let certList = [
michael@0 21 // Test for successful EV validation
michael@0 22 'int-ev-valid',
michael@0 23 'ev-valid',
michael@0 24 'ev-valid-anypolicy-int',
michael@0 25 'int-ev-valid-anypolicy-int',
michael@0 26 'no-ocsp-url-cert', // a cert signed by the EV auth that has no OCSP url
michael@0 27 // but that contains a valid CRLDP.
michael@0 28
michael@0 29 // Testing a root that looks like EV but is not EV enabled
michael@0 30 'int-non-ev-root',
michael@0 31 'non-ev-root',
michael@0 32 ]
michael@0 33
michael@0 34 function load_ca(ca_name) {
michael@0 35 var ca_filename = ca_name + ".der";
michael@0 36 addCertFromFile(certdb, "test_ev_certs/" + ca_filename, 'CTu,CTu,CTu');
michael@0 37 }
michael@0 38
michael@0 39 const SERVER_PORT = 8888;
michael@0 40
michael@0 41 function failingOCSPResponder() {
michael@0 42 return getFailingHttpServer(SERVER_PORT,
michael@0 43 ["www.example.com", "crl.example.com"]);
michael@0 44 }
michael@0 45
michael@0 46 function start_ocsp_responder(expectedCertNames) {
michael@0 47 let expectedPaths = expectedCertNames.slice();
michael@0 48 return startOCSPResponder(SERVER_PORT, "www.example.com", ["crl.example.com"],
michael@0 49 "test_ev_certs", expectedCertNames, expectedPaths);
michael@0 50 }
michael@0 51
michael@0 52 function check_cert_err(cert_name, expected_error) {
michael@0 53 let cert = certdb.findCertByNickname(null, cert_name);
michael@0 54 let hasEVPolicy = {};
michael@0 55 let verifiedChain = {};
michael@0 56 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
michael@0 57 NO_FLAGS, verifiedChain, hasEVPolicy);
michael@0 58 do_check_eq(error, expected_error);
michael@0 59 }
michael@0 60
michael@0 61
michael@0 62 function check_ee_for_ev(cert_name, expected_ev) {
michael@0 63 let cert = certdb.findCertByNickname(null, cert_name);
michael@0 64 let hasEVPolicy = {};
michael@0 65 let verifiedChain = {};
michael@0 66 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
michael@0 67 NO_FLAGS, verifiedChain, hasEVPolicy);
michael@0 68 do_check_eq(hasEVPolicy.value, expected_ev);
michael@0 69 do_check_eq(0, error);
michael@0 70 }
michael@0 71
michael@0 72 function run_test() {
michael@0 73 for (let i = 0 ; i < certList.length; i++) {
michael@0 74 let cert_filename = certList[i] + ".der";
michael@0 75 addCertFromFile(certdb, "test_ev_certs/" + cert_filename, ',,');
michael@0 76 }
michael@0 77 load_ca("evroot");
michael@0 78 load_ca("non-evroot-ca");
michael@0 79
michael@0 80 // setup and start ocsp responder
michael@0 81 Services.prefs.setCharPref("network.dns.localDomains",
michael@0 82 'www.example.com, crl.example.com');
michael@0 83 add_tests_in_mode(true);
michael@0 84 add_tests_in_mode(false);
michael@0 85 run_next_test();
michael@0 86 }
michael@0 87
michael@0 88 function add_tests_in_mode(useMozillaPKIX)
michael@0 89 {
michael@0 90 add_test(function () {
michael@0 91 Services.prefs.setBoolPref("security.use_mozillapkix_verification",
michael@0 92 useMozillaPKIX);
michael@0 93 run_next_test();
michael@0 94 });
michael@0 95
michael@0 96 add_test(function () {
michael@0 97 clearOCSPCache();
michael@0 98 let ocspResponder = start_ocsp_responder(
michael@0 99 isDebugBuild ? ["int-ev-valid", "ev-valid"]
michael@0 100 : ["ev-valid"]);
michael@0 101 check_ee_for_ev("ev-valid", isDebugBuild);
michael@0 102 ocspResponder.stop(run_next_test);
michael@0 103 });
michael@0 104
michael@0 105
michael@0 106 add_test(function () {
michael@0 107 clearOCSPCache();
michael@0 108
michael@0 109 let ocspResponder = start_ocsp_responder(
michael@0 110 isDebugBuild ? ["int-ev-valid-anypolicy-int", "ev-valid-anypolicy-int"]
michael@0 111 : ["ev-valid-anypolicy-int"]);
michael@0 112 check_ee_for_ev("ev-valid-anypolicy-int", isDebugBuild);
michael@0 113 ocspResponder.stop(run_next_test);
michael@0 114 });
michael@0 115
michael@0 116 add_test(function() {
michael@0 117 clearOCSPCache();
michael@0 118 let ocspResponder = start_ocsp_responder(["non-ev-root"]);
michael@0 119 check_ee_for_ev("non-ev-root", false);
michael@0 120 ocspResponder.stop(run_next_test);
michael@0 121 });
michael@0 122
michael@0 123 add_test(function() {
michael@0 124 clearOCSPCache();
michael@0 125 // libpkix will attempt to validate the intermediate, which does have an
michael@0 126 // OCSP URL.
michael@0 127 let ocspResponder = isDebugBuild ? start_ocsp_responder(["int-ev-valid"])
michael@0 128 : failingOCSPResponder();
michael@0 129 check_ee_for_ev("no-ocsp-url-cert", false);
michael@0 130 ocspResponder.stop(run_next_test);
michael@0 131 });
michael@0 132
michael@0 133 // bug 917380: Chcek that an untrusted EV root is untrusted.
michael@0 134 const nsIX509Cert = Ci.nsIX509Cert;
michael@0 135 add_test(function() {
michael@0 136 let evRootCA = certdb.findCertByNickname(null, evrootnick);
michael@0 137 certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT, 0);
michael@0 138
michael@0 139 clearOCSPCache();
michael@0 140 let ocspResponder = failingOCSPResponder();
michael@0 141 check_cert_err("ev-valid",
michael@0 142 useMozillaPKIX ? SEC_ERROR_UNKNOWN_ISSUER
michael@0 143 : SEC_ERROR_UNTRUSTED_ISSUER);
michael@0 144 ocspResponder.stop(run_next_test);
michael@0 145 });
michael@0 146
michael@0 147 // bug 917380: Chcek that a trusted EV root is trusted after disabling and
michael@0 148 // re-enabling trust.
michael@0 149 add_test(function() {
michael@0 150 let evRootCA = certdb.findCertByNickname(null, evrootnick);
michael@0 151 certdb.setCertTrust(evRootCA, nsIX509Cert.CA_CERT,
michael@0 152 Ci.nsIX509CertDB.TRUSTED_SSL |
michael@0 153 Ci.nsIX509CertDB.TRUSTED_EMAIL |
michael@0 154 Ci.nsIX509CertDB.TRUSTED_OBJSIGN);
michael@0 155
michael@0 156 clearOCSPCache();
michael@0 157 let ocspResponder = start_ocsp_responder(
michael@0 158 isDebugBuild ? ["int-ev-valid", "ev-valid"]
michael@0 159 : ["ev-valid"]);
michael@0 160 check_ee_for_ev("ev-valid", isDebugBuild);
michael@0 161 ocspResponder.stop(run_next_test);
michael@0 162 });
michael@0 163
michael@0 164 add_test(function () {
michael@0 165 check_no_ocsp_requests("ev-valid",
michael@0 166 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
michael@0 167 : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
michael@0 168 : SEC_ERROR_EXTENSION_NOT_FOUND));
michael@0 169 });
michael@0 170
michael@0 171 add_test(function () {
michael@0 172 check_no_ocsp_requests("non-ev-root",
michael@0 173 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
michael@0 174 : (isDebugBuild ? SEC_ERROR_UNTRUSTED_ISSUER
michael@0 175 : SEC_ERROR_EXTENSION_NOT_FOUND));
michael@0 176 });
michael@0 177
michael@0 178 add_test(function () {
michael@0 179 check_no_ocsp_requests("no-ocsp-url-cert",
michael@0 180 useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
michael@0 181 : (isDebugBuild ? SEC_ERROR_REVOKED_CERTIFICATE
michael@0 182 : SEC_ERROR_EXTENSION_NOT_FOUND));
michael@0 183 });
michael@0 184
michael@0 185
michael@0 186 // Test the EV continues to work with flags after successful EV verification
michael@0 187 add_test(function () {
michael@0 188 clearOCSPCache();
michael@0 189 let ocspResponder = start_ocsp_responder(
michael@0 190 isDebugBuild ? ["int-ev-valid", "ev-valid"]
michael@0 191 : ["ev-valid"]);
michael@0 192 check_ee_for_ev("ev-valid", isDebugBuild);
michael@0 193 ocspResponder.stop(function () {
michael@0 194 // without net it must be able to EV verify
michael@0 195 let failingOcspResponder = failingOCSPResponder();
michael@0 196 let cert = certdb.findCertByNickname(null, "ev-valid");
michael@0 197 let hasEVPolicy = {};
michael@0 198 let verifiedChain = {};
michael@0 199 let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
michael@0 200 Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
michael@0 201
michael@0 202 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer,
michael@0 203 flags, verifiedChain, hasEVPolicy);
michael@0 204 do_check_eq(hasEVPolicy.value, isDebugBuild);
michael@0 205 do_check_eq(error,
michael@0 206 isDebugBuild ? 0
michael@0 207 : (useMozillaPKIX ? SEC_ERROR_POLICY_VALIDATION_FAILED
michael@0 208 : SEC_ERROR_EXTENSION_NOT_FOUND));
michael@0 209 failingOcspResponder.stop(run_next_test);
michael@0 210 });
michael@0 211 });
michael@0 212
michael@0 213 // Bug 991815 old but valid intermediates are OK
michael@0 214 add_test(function () {
michael@0 215 clearOCSPCache();
michael@0 216 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
michael@0 217 "test_ev_certs",
michael@0 218 isDebugBuild ? ["int-ev-valid", "ev-valid"]
michael@0 219 : ["ev-valid"],
michael@0 220 [], [],
michael@0 221 isDebugBuild ? ["longvalidityalmostold", "good"]
michael@0 222 : ["good"]);
michael@0 223 check_ee_for_ev("ev-valid", isDebugBuild);
michael@0 224 ocspResponder.stop(run_next_test);
michael@0 225 });
michael@0 226
michael@0 227 // Bug 991815 old but valid end-entities are NOT OK for EV
michael@0 228 // Unfortunatelly because of soft-fail we consider these OK for DV
michael@0 229 // libpkix does not enforce the age restriction and thus EV is valid
michael@0 230 add_test(function () {
michael@0 231 clearOCSPCache();
michael@0 232 // Since Mozilla::pkix does not consider the old amost invalid OCSP
michael@0 233 // response valid, it does not cache the old response and thus
michael@0 234 // makes a separate request for DV
michael@0 235 let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
michael@0 236 let debugResponseArray = ["good", "longvalidityalmostold",
michael@0 237 "longvalidityalmostold"];
michael@0 238 if (!useMozillaPKIX) {
michael@0 239 debugCertNickArray = ["int-ev-valid", "ev-valid"];
michael@0 240 debugResponseArray = ["good", "longvalidityalmostold"];
michael@0 241 }
michael@0 242 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
michael@0 243 "test_ev_certs",
michael@0 244 isDebugBuild ? debugCertNickArray : ["ev-valid"],
michael@0 245 [], [],
michael@0 246 isDebugBuild ? debugResponseArray
michael@0 247 : ["longvalidityalmostold"]);
michael@0 248 check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
michael@0 249 ocspResponder.stop(run_next_test);
michael@0 250 });
michael@0 251
michael@0 252 // Bug 991815 Valid but Ancient (almost two year old) responses are Not OK for
michael@0 253 // EV (still OK for soft fail DV)
michael@0 254 add_test(function () {
michael@0 255 clearOCSPCache();
michael@0 256 let debugCertNickArray = ["int-ev-valid", "ev-valid", "ev-valid"];
michael@0 257 let debugResponseArray = ["good", "ancientstillvalid",
michael@0 258 "ancientstillvalid"];
michael@0 259 if (!useMozillaPKIX) {
michael@0 260 debugCertNickArray = ["int-ev-valid", "ev-valid"];
michael@0 261 debugResponseArray = ["good", "ancientstillvalid"];
michael@0 262 }
michael@0 263 let ocspResponder = startOCSPResponder(SERVER_PORT, "www.example.com", [],
michael@0 264 "test_ev_certs",
michael@0 265 isDebugBuild ? debugCertNickArray : ["ev-valid"],
michael@0 266 [], [],
michael@0 267 isDebugBuild ? debugResponseArray
michael@0 268 : ["ancientstillvalid"]);
michael@0 269 check_ee_for_ev("ev-valid", !useMozillaPKIX && isDebugBuild);
michael@0 270 ocspResponder.stop(run_next_test);
michael@0 271 });
michael@0 272 }
michael@0 273
michael@0 274 // bug 950240: add FLAG_MUST_BE_EV to CertVerifier::VerifyCert
michael@0 275 // to prevent spurious OCSP requests that race with OCSP stapling.
michael@0 276 // This has the side-effect of saying an EV certificate is not EV if
michael@0 277 // it hasn't already been verified (e.g. on the verification thread when
michael@0 278 // connecting to a site).
michael@0 279 // This flag is mostly a hack that should be removed once FLAG_LOCAL_ONLY
michael@0 280 // works as intended.
michael@0 281 function check_no_ocsp_requests(cert_name, expected_error) {
michael@0 282 clearOCSPCache();
michael@0 283 let ocspResponder = failingOCSPResponder();
michael@0 284 let cert = certdb.findCertByNickname(null, cert_name);
michael@0 285 let hasEVPolicy = {};
michael@0 286 let verifiedChain = {};
michael@0 287 let flags = Ci.nsIX509CertDB.FLAG_LOCAL_ONLY |
michael@0 288 Ci.nsIX509CertDB.FLAG_MUST_BE_EV;
michael@0 289 let error = certdb.verifyCertNow(cert, certificateUsageSSLServer, flags,
michael@0 290 verifiedChain, hasEVPolicy);
michael@0 291 // Since we're not doing OCSP requests, no certificate will be EV.
michael@0 292 do_check_eq(hasEVPolicy.value, false);
michael@0 293 do_check_eq(expected_error, error);
michael@0 294 // Also check that isExtendedValidation doesn't cause OCSP requests.
michael@0 295 let identityInfo = cert.QueryInterface(Ci.nsIIdentityInfo);
michael@0 296 do_check_eq(identityInfo.isExtendedValidation, false);
michael@0 297 ocspResponder.stop(run_next_test);
michael@0 298 }
michael@0 299

mercurial