michael@0: "use strict"; michael@0: /* To regenerate the certificates for this test: michael@0: * michael@0: * cd security/manager/ssl/tests/unit/test_intermediate_basic_usage_constraints michael@0: * ./generate.py michael@0: * cd ../../../../../.. michael@0: * make -C $OBJDIR/security/manager/ssl/tests michael@0: * michael@0: * Check in the generated files. These steps are not done as part of the build michael@0: * because we do not want to add a build-time dependency on the OpenSSL or NSS michael@0: * tools or libraries built for the host platform. michael@0: */ michael@0: michael@0: do_get_profile(); // must be called before getting nsIX509CertDB michael@0: const certdb = Cc["@mozilla.org/security/x509certdb;1"] michael@0: .getService(Ci.nsIX509CertDB); michael@0: michael@0: function load_cert(name, trust) { michael@0: let filename = "test_intermediate_basic_usage_constraints/" + name + ".der"; michael@0: addCertFromFile(certdb, filename, trust); michael@0: } michael@0: michael@0: function test_cert_for_usages(certChainNicks, expected_usages_string) { michael@0: let certs = []; michael@0: for (let i in certChainNicks) { michael@0: let certNick = certChainNicks[i]; michael@0: let certDER = readFile(do_get_file( michael@0: "test_intermediate_basic_usage_constraints/" michael@0: + certNick + ".der"), false); michael@0: certs.push(certdb.constructX509(certDER, certDER.length)); michael@0: } michael@0: michael@0: let cert = certs[0]; michael@0: let verified = {}; michael@0: let usages = {}; michael@0: cert.getUsagesString(true, verified, usages); michael@0: do_print("usages.value = " + usages.value); michael@0: do_check_eq(expected_usages_string, usages.value); michael@0: } michael@0: michael@0: function run_test_in_mode(useMozillaPKIX) { michael@0: Services.prefs.setBoolPref("security.use_mozillapkix_verification", useMozillaPKIX); michael@0: michael@0: // mozilla::pkix doesn't support the obsolete Netscape object signing michael@0: // extension, but NSS does. michael@0: let ee_usage1 = useMozillaPKIX michael@0: ? 'Client,Server,Sign,Encrypt,Object Signer' michael@0: : 'Client,Server,Sign,Encrypt' michael@0: michael@0: // mozilla::pkix doesn't validate CA certificates for non-CA uses, but michael@0: // NSS does. michael@0: let ca_usage1 = useMozillaPKIX michael@0: ? "SSL CA" michael@0: : 'Client,Server,Sign,Encrypt,SSL CA,Status Responder'; michael@0: michael@0: // Load the ca into mem michael@0: let ca_name = "ca"; michael@0: load_cert(ca_name, "CTu,CTu,CTu"); michael@0: do_print("ca_name = " + ca_name); michael@0: test_cert_for_usages([ca_name], ca_usage1); michael@0: michael@0: // A certificate with no basicConstraints extension is considered an EE. michael@0: test_cert_for_usages(["int-no-extensions"], ee_usage1); michael@0: michael@0: // int-no-extensions is an EE (see previous case), so no certs can chain to michael@0: // it. michael@0: test_cert_for_usages(["ee-int-no-extensions", "int-no-extensions"], ""); michael@0: michael@0: // a certificate with bsaicConstraints.cA==false is considered an EE. michael@0: test_cert_for_usages(["int-not-a-ca"], ee_usage1); michael@0: michael@0: // int-not-a-ca is an EE (see previous case), so no certs can chain to it. michael@0: test_cert_for_usages(["ee-int-not-a-ca", "int-not-a-ca"], ""); michael@0: michael@0: // int-limited-depth has cA==true and a path length constraint of zero. michael@0: test_cert_for_usages(["int-limited-depth"], ca_usage1); michael@0: michael@0: // path length constraints do not affect the ability of a non-CA cert to michael@0: // chain to to the CA cert. michael@0: test_cert_for_usages(["ee-int-limited-depth", "int-limited-depth"], michael@0: ee_usage1); michael@0: michael@0: // ca michael@0: // int-limited-depth (cA==true, pathLenConstraint==0) michael@0: // int-limited-depth-invalid (cA==true) michael@0: // michael@0: // XXX: It seems the NSS code does not consider the path length of the michael@0: // certificate we're validating, but mozilla::pkix does. mozilla::pkix's michael@0: // behavior is correct. michael@0: test_cert_for_usages(["int-limited-depth-invalid", "int-limited-depth"], michael@0: useMozillaPKIX ? "" : ca_usage1); michael@0: test_cert_for_usages(["ee-int-limited-depth-invalid", michael@0: "int-limited-depth-invalid", michael@0: "int-limited-depth"], michael@0: ""); michael@0: michael@0: // int-valid-ku-no-eku has keyCertSign michael@0: test_cert_for_usages(["int-valid-ku-no-eku"], "SSL CA"); michael@0: test_cert_for_usages(["ee-int-valid-ku-no-eku", "int-valid-ku-no-eku"], michael@0: ee_usage1); michael@0: michael@0: // int-bad-ku-no-eku has basicConstraints.cA==true and has a KU extension michael@0: // but the KU extension is missing keyCertSign. Note that mozilla::pkix michael@0: // doesn't validate certificates with basicConstraints.Ca==true for non-CA michael@0: // uses, but NSS does. michael@0: test_cert_for_usages(["int-bad-ku-no-eku"], michael@0: useMozillaPKIX michael@0: ? "" michael@0: : 'Client,Server,Sign,Encrypt,Status Responder'); michael@0: test_cert_for_usages(["ee-int-bad-ku-no-eku", "int-bad-ku-no-eku"], ""); michael@0: michael@0: // int-no-ku-no-eku has basicConstraints.cA==true and no KU extension. michael@0: // We treat a missing KU as "any key usage is OK". michael@0: test_cert_for_usages(["int-no-ku-no-eku"], ca_usage1); michael@0: test_cert_for_usages(["ee-int-no-ku-no-eku", "int-no-ku-no-eku"], ee_usage1); michael@0: michael@0: // int-valid-ku-server-eku has basicConstraints.cA==true, keyCertSign in KU, michael@0: // and EKU=={id-kp-serverAuth,id-kp-clientAuth}. michael@0: test_cert_for_usages(["int-valid-ku-server-eku"], "SSL CA"); michael@0: test_cert_for_usages(["ee-int-valid-ku-server-eku", michael@0: "int-valid-ku-server-eku"], "Client,Server"); michael@0: michael@0: // int-bad-ku-server-eku has basicConstraints.cA==true, a KU without michael@0: // keyCertSign, and EKU=={id-kp-serverAuth,id-kp-clientAuth}. michael@0: test_cert_for_usages(["int-bad-ku-server-eku"], ""); michael@0: test_cert_for_usages(["ee-int-bad-ku-server-eku", "int-bad-ku-server-eku"], michael@0: ""); michael@0: michael@0: // int-bad-ku-server-eku has basicConstraints.cA==true, no KU, and michael@0: // EKU=={id-kp-serverAuth,id-kp-clientAuth}. michael@0: test_cert_for_usages(["int-no-ku-server-eku"], "SSL CA"); michael@0: test_cert_for_usages(["ee-int-no-ku-server-eku", "int-no-ku-server-eku"], michael@0: "Client,Server"); michael@0: } michael@0: michael@0: function run_test() { michael@0: run_test_in_mode(true); michael@0: run_test_in_mode(false); michael@0: }