1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,139 @@ 1.4 +"use strict"; 1.5 +/* To regenerate the certificates for this test: 1.6 + * 1.7 + * cd security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints 1.8 + * ./generate.py 1.9 + * cd ../../../../../.. 1.10 + * make -C $OBJDIR/security/manager/ssl/tests 1.11 + * 1.12 + * Check in the generated files. These steps are not done as part of the build 1.13 + * because we do not want to add a build-time dependency on the OpenSSL or NSS 1.14 + * tools or libraries built for the host platform. 1.15 + */ 1.16 + 1.17 +do_get_profile(); // must be called before getting nsIX509CertDB 1.18 +const certdb = Cc["@mozilla.org/security/x509certdb;1"] 1.19 + .getService(Ci.nsIX509CertDB); 1.20 + 1.21 +function load_cert(name, trust) { 1.22 + let filename = "test_intermediate_basic_usage_constraints/" + name + ".der"; 1.23 + addCertFromFile(certdb, filename, trust); 1.24 +} 1.25 + 1.26 +function test_cert_for_usages(certChainNicks, expected_usages_string) { 1.27 + let certs = []; 1.28 + for (let i in certChainNicks) { 1.29 + let certNick = certChainNicks[i]; 1.30 + let certDER = readFile(do_get_file( 1.31 + "test_intermediate_basic_usage_constraints/" 1.32 + + certNick + ".der"), false); 1.33 + certs.push(certdb.constructX509(certDER, certDER.length)); 1.34 + } 1.35 + 1.36 + let cert = certs[0]; 1.37 + let verified = {}; 1.38 + let usages = {}; 1.39 + cert.getUsagesString(true, verified, usages); 1.40 + do_print("usages.value = " + usages.value); 1.41 + do_check_eq(expected_usages_string, usages.value); 1.42 +} 1.43 + 1.44 +function run_test_in_mode(useMozillaPKIX) { 1.45 + Services.prefs.setBoolPref("security.use_mozillapkix_verification", useMozillaPKIX); 1.46 + 1.47 + // mozilla::pkix doesn't support the obsolete Netscape object signing 1.48 + // extension, but NSS does. 1.49 + let ee_usage1 = useMozillaPKIX 1.50 + ? 'Client,Server,Sign,Encrypt,Object Signer' 1.51 + : 'Client,Server,Sign,Encrypt' 1.52 + 1.53 + // mozilla::pkix doesn't validate CA certificates for non-CA uses, but 1.54 + // NSS does. 1.55 + let ca_usage1 = useMozillaPKIX 1.56 + ? "SSL CA" 1.57 + : 'Client,Server,Sign,Encrypt,SSL CA,Status Responder'; 1.58 + 1.59 + // Load the ca into mem 1.60 + let ca_name = "ca"; 1.61 + load_cert(ca_name, "CTu,CTu,CTu"); 1.62 + do_print("ca_name = " + ca_name); 1.63 + test_cert_for_usages([ca_name], ca_usage1); 1.64 + 1.65 + // A certificate with no basicConstraints extension is considered an EE. 1.66 + test_cert_for_usages(["int-no-extensions"], ee_usage1); 1.67 + 1.68 + // int-no-extensions is an EE (see previous case), so no certs can chain to 1.69 + // it. 1.70 + test_cert_for_usages(["ee-int-no-extensions", "int-no-extensions"], ""); 1.71 + 1.72 + // a certificate with bsaicConstraints.cA==false is considered an EE. 1.73 + test_cert_for_usages(["int-not-a-ca"], ee_usage1); 1.74 + 1.75 + // int-not-a-ca is an EE (see previous case), so no certs can chain to it. 1.76 + test_cert_for_usages(["ee-int-not-a-ca", "int-not-a-ca"], ""); 1.77 + 1.78 + // int-limited-depth has cA==true and a path length constraint of zero. 1.79 + test_cert_for_usages(["int-limited-depth"], ca_usage1); 1.80 + 1.81 + // path length constraints do not affect the ability of a non-CA cert to 1.82 + // chain to to the CA cert. 1.83 + test_cert_for_usages(["ee-int-limited-depth", "int-limited-depth"], 1.84 + ee_usage1); 1.85 + 1.86 + // ca 1.87 + // int-limited-depth (cA==true, pathLenConstraint==0) 1.88 + // int-limited-depth-invalid (cA==true) 1.89 + // 1.90 + // XXX: It seems the NSS code does not consider the path length of the 1.91 + // certificate we're validating, but mozilla::pkix does. mozilla::pkix's 1.92 + // behavior is correct. 1.93 + test_cert_for_usages(["int-limited-depth-invalid", "int-limited-depth"], 1.94 + useMozillaPKIX ? "" : ca_usage1); 1.95 + test_cert_for_usages(["ee-int-limited-depth-invalid", 1.96 + "int-limited-depth-invalid", 1.97 + "int-limited-depth"], 1.98 + ""); 1.99 + 1.100 + // int-valid-ku-no-eku has keyCertSign 1.101 + test_cert_for_usages(["int-valid-ku-no-eku"], "SSL CA"); 1.102 + test_cert_for_usages(["ee-int-valid-ku-no-eku", "int-valid-ku-no-eku"], 1.103 + ee_usage1); 1.104 + 1.105 + // int-bad-ku-no-eku has basicConstraints.cA==true and has a KU extension 1.106 + // but the KU extension is missing keyCertSign. Note that mozilla::pkix 1.107 + // doesn't validate certificates with basicConstraints.Ca==true for non-CA 1.108 + // uses, but NSS does. 1.109 + test_cert_for_usages(["int-bad-ku-no-eku"], 1.110 + useMozillaPKIX 1.111 + ? "" 1.112 + : 'Client,Server,Sign,Encrypt,Status Responder'); 1.113 + test_cert_for_usages(["ee-int-bad-ku-no-eku", "int-bad-ku-no-eku"], ""); 1.114 + 1.115 + // int-no-ku-no-eku has basicConstraints.cA==true and no KU extension. 1.116 + // We treat a missing KU as "any key usage is OK". 1.117 + test_cert_for_usages(["int-no-ku-no-eku"], ca_usage1); 1.118 + test_cert_for_usages(["ee-int-no-ku-no-eku", "int-no-ku-no-eku"], ee_usage1); 1.119 + 1.120 + // int-valid-ku-server-eku has basicConstraints.cA==true, keyCertSign in KU, 1.121 + // and EKU=={id-kp-serverAuth,id-kp-clientAuth}. 1.122 + test_cert_for_usages(["int-valid-ku-server-eku"], "SSL CA"); 1.123 + test_cert_for_usages(["ee-int-valid-ku-server-eku", 1.124 + "int-valid-ku-server-eku"], "Client,Server"); 1.125 + 1.126 + // int-bad-ku-server-eku has basicConstraints.cA==true, a KU without 1.127 + // keyCertSign, and EKU=={id-kp-serverAuth,id-kp-clientAuth}. 1.128 + test_cert_for_usages(["int-bad-ku-server-eku"], ""); 1.129 + test_cert_for_usages(["ee-int-bad-ku-server-eku", "int-bad-ku-server-eku"], 1.130 + ""); 1.131 + 1.132 + // int-bad-ku-server-eku has basicConstraints.cA==true, no KU, and 1.133 + // EKU=={id-kp-serverAuth,id-kp-clientAuth}. 1.134 + test_cert_for_usages(["int-no-ku-server-eku"], "SSL CA"); 1.135 + test_cert_for_usages(["ee-int-no-ku-server-eku", "int-no-ku-server-eku"], 1.136 + "Client,Server"); 1.137 +} 1.138 + 1.139 +function run_test() { 1.140 + run_test_in_mode(true); 1.141 + run_test_in_mode(false); 1.142 +}