bug 1203312 - convert tlsserver to generate certificates at build time r=Cykesiopka,mgoodwin
☠☠ backed out by 1d45333a4690 ☠ ☠
authorDavid Keeler <dkeeler@mozilla.com>
Mon, 24 Aug 2015 15:53:07 -0700
changeset 295909 a08287c70962145364545c1a72135f9338544e9e
parent 295908 28161d563685be3cafcc1a47dc08aed4dec67cdc
child 295910 b4851ce6637da13db086a93bad3a0faa5fde579b
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCykesiopka, mgoodwin
bugs1203312
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1203312 - convert tlsserver to generate certificates at build time r=Cykesiopka,mgoodwin
security/manager/ssl/StaticHPKPins.h
security/manager/ssl/tests/unit/head_psm.js
security/manager/ssl/tests/unit/pycert.py
security/manager/ssl/tests/unit/pykey.py
security/manager/ssl/tests/unit/test_cert_blocklist.js
security/manager/ssl/tests/unit/test_cert_chains.js
security/manager/ssl/tests/unit/test_cert_overrides.js
security/manager/ssl/tests/unit/test_ocsp_caching.js
security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
security/manager/ssl/tests/unit/test_ocsp_required.js
security/manager/ssl/tests/unit/test_ocsp_stapling.js
security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
security/manager/ssl/tests/unit/test_pinning.js
security/manager/ssl/tests/unit/tlsserver/badSubjectAltNames.pem.certspec
security/manager/ssl/tests/unit/tlsserver/beforeEpoch.pem.certspec
security/manager/ssl/tests/unit/tlsserver/beforeEpochINT.pem.certspec
security/manager/ssl/tests/unit/tlsserver/beforeEpochIssuer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/ca-used-as-end-entity.pem.certspec
security/manager/ssl/tests/unit/tlsserver/cert9.db
security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
security/manager/ssl/tests/unit/tlsserver/default-ee.der
security/manager/ssl/tests/unit/tlsserver/default-ee.key.keyspec
security/manager/ssl/tests/unit/tlsserver/default-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/delegatedSHA1Signer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/delegatedSigner.pem.certspec
security/manager/ssl/tests/unit/tlsserver/eeIssuedByNonCA.pem.certspec
security/manager/ssl/tests/unit/tlsserver/eeIssuedByV1Cert.pem.certspec
security/manager/ssl/tests/unit/tlsserver/expired-ee.der
security/manager/ssl/tests/unit/tlsserver/expired-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/expiredINT.pem.certspec
security/manager/ssl/tests/unit/tlsserver/expiredissuer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
security/manager/ssl/tests/unit/tlsserver/inadequateKeySizeEE.pem.certspec
security/manager/ssl/tests/unit/tlsserver/inadequatekeyusage-ee.der
security/manager/ssl/tests/unit/tlsserver/inadequatekeyusage-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerFromIntermediate.pem.certspec
security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerKeyUsageCrlSigning.pem.certspec
security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerNoExtKeyUsage.pem.certspec
security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerWrongExtKeyUsage.pem.certspec
security/manager/ssl/tests/unit/tlsserver/ipAddressAsDNSNameInSAN.pem.certspec
security/manager/ssl/tests/unit/tlsserver/key4.db
security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.cpp
security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.h
security/manager/ssl/tests/unit/tlsserver/md5signature-expired.pem.certspec
security/manager/ssl/tests/unit/tlsserver/md5signature.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatch-expired.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatch-notYetValid.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatch-untrusted-expired.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatch-untrusted.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatch.pem.certspec
security/manager/ssl/tests/unit/tlsserver/mismatchCN.pem.certspec
security/manager/ssl/tests/unit/tlsserver/moz.build
security/manager/ssl/tests/unit/tlsserver/noValidNames.pem.certspec
security/manager/ssl/tests/unit/tlsserver/notYetValid.pem.certspec
security/manager/ssl/tests/unit/tlsserver/notYetValidINT.pem.certspec
security/manager/ssl/tests/unit/tlsserver/notYetValidIssuer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/nsCertTypeCritical.pem.certspec
security/manager/ssl/tests/unit/tlsserver/nsCertTypeCriticalWithExtKeyUsage.pem.certspec
security/manager/ssl/tests/unit/tlsserver/nsCertTypeNotCritical.pem.certspec
security/manager/ssl/tests/unit/tlsserver/ocspEEWithIntermediate.pem.certspec
security/manager/ssl/tests/unit/tlsserver/ocspOtherEndEntity.pem.certspec
security/manager/ssl/tests/unit/tlsserver/other-issuer-ee.der
security/manager/ssl/tests/unit/tlsserver/other-issuer-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/other-test-ca.der
security/manager/ssl/tests/unit/tlsserver/other-test-ca.key.keyspec
security/manager/ssl/tests/unit/tlsserver/other-test-ca.pem.certspec
security/manager/ssl/tests/unit/tlsserver/pkcs11.txt
security/manager/ssl/tests/unit/tlsserver/rsa-1016-keysizeDelegatedSigner.key.keyspec
security/manager/ssl/tests/unit/tlsserver/rsa-1016-keysizeDelegatedSigner.pem.certspec
security/manager/ssl/tests/unit/tlsserver/same-issuer-ee.der
security/manager/ssl/tests/unit/tlsserver/same-issuer-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/self-signed-EE-with-cA-true.pem.certspec
security/manager/ssl/tests/unit/tlsserver/selfsigned-inadequateEKU.pem.certspec
security/manager/ssl/tests/unit/tlsserver/selfsigned.pem.certspec
security/manager/ssl/tests/unit/tlsserver/test-ca.der
security/manager/ssl/tests/unit/tlsserver/test-ca.pem.certspec
security/manager/ssl/tests/unit/tlsserver/test-int-ee.der
security/manager/ssl/tests/unit/tlsserver/test-int-ee.pem.certspec
security/manager/ssl/tests/unit/tlsserver/test-int.der
security/manager/ssl/tests/unit/tlsserver/test-int.pem.certspec
security/manager/ssl/tests/unit/tlsserver/unknown-issuer.der
security/manager/ssl/tests/unit/tlsserver/unknownissuer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/untrusted-expired.pem.certspec
security/manager/ssl/tests/unit/tlsserver/untrustedissuer.pem.certspec
security/manager/ssl/tests/unit/tlsserver/v1Cert.der
security/manager/ssl/tests/unit/tlsserver/v1Cert.pem.certspec
security/manager/tools/genHPKPStaticPins.js
--- a/security/manager/ssl/StaticHPKPins.h
+++ b/security/manager/ssl/StaticHPKPins.h
@@ -76,17 +76,17 @@ static const char kDigiCert_Global_Root_
   "r/mIkG3eEpVdm+u/ko/cwxzOMo1bk4TyHIlByibiA5E=";
 
 /* DigiCert High Assurance EV Root CA */
 static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[] =
   "WoiWRyIOVNa9ihaBciRSC7XHjliYS9VwUGOIud4PB18=";
 
 /* End Entity Test Cert */
 static const char kEnd_Entity_Test_CertFingerprint[] =
-  "lzCakFt+nADIfIkgk+UE/EQ9SaT2nay2yu2iykVbvV8=";
+  "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
 
 /* Entrust Root Certification Authority */
 static const char kEntrust_Root_Certification_AuthorityFingerprint[] =
   "bb+uANN7nNc/j7R95lkXrwDg3d9C286sIMF8AnXuIJU=";
 
 /* Entrust Root Certification Authority - EC1 */
 static const char kEntrust_Root_Certification_Authority___EC1Fingerprint[] =
   "/qK31kX7pz11PB7Jp4cMQOH3sMVh6Se5hb9xGGbjbyI=";
@@ -1091,9 +1091,9 @@ static const TransportSecurityPreload kP
   { "youtube.com", true, false, false, -1, &kPinset_google_root_pems },
   { "ytimg.com", true, false, false, -1, &kPinset_google_root_pems },
 };
 
 // Pinning Preload List Length = 363;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1450521025692000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1450902702049000);
--- a/security/manager/ssl/tests/unit/head_psm.js
+++ b/security/manager/ssl/tests/unit/head_psm.js
@@ -430,17 +430,17 @@ function _getBinaryUtil(binaryUtilName) 
 }
 
 // Do not call this directly; use add_tls_server_setup
 function _setupTLSServerTest(serverBinName)
 {
   let certdb = Cc["@mozilla.org/security/x509certdb;1"]
                   .getService(Ci.nsIX509CertDB);
   // The trusted CA that is typically used for "good" certificates.
-  addCertFromFile(certdb, "tlsserver/test-ca.der", "CTu,u,u");
+  addCertFromFile(certdb, "tlsserver/test-ca.pem", "CTu,u,u");
 
   const CALLBACK_PORT = 8444;
 
   let directoryService = Cc["@mozilla.org/file/directory_service;1"]
                            .getService(Ci.nsIProperties);
   let envSvc = Cc["@mozilla.org/process/environment;1"]
                  .getService(Ci.nsIEnvironment);
   let greBinDir = directoryService.get("GreBinD", Ci.nsIFile);
@@ -634,19 +634,18 @@ FakeSSLStatus.prototype = {
       return this;
     }
     throw Components.results.NS_ERROR_NO_INTERFACE;
   },
 }
 
 // Utility functions for adding tests relating to certificate error overrides
 
-// Helper function for add_cert_override_test and
-// add_prevented_cert_override_test. Probably doesn't need to be called
-// directly.
+// Helper function for add_cert_override_test. Probably doesn't need to be
+// called directly.
 function add_cert_override(aHost, aExpectedBits, aSecurityInfo) {
   let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
                                .SSLStatus;
   let bits =
     (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) |
     (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) |
     (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
   Assert.equal(bits, aExpectedBits,
@@ -663,19 +662,41 @@ function add_cert_override(aHost, aExpec
 // with the expected errors and that adding an override results in a subsequent
 // connection succeeding.
 function add_cert_override_test(aHost, aExpectedBits, aExpectedError) {
   add_connection_test(aHost, aExpectedError, null,
                       add_cert_override.bind(this, aHost, aExpectedBits));
   add_connection_test(aHost, PRErrorCodeSuccess);
 }
 
+// Helper function for add_prevented_cert_override_test. This is much like
+// add_cert_override except it may not be the case that the connection has an
+// SSLStatus set on it. In this case, the error was not overridable anyway, so
+// we consider it a success.
+function attempt_adding_cert_override(aHost, aExpectedBits, aSecurityInfo) {
+  let sslstatus = aSecurityInfo.QueryInterface(Ci.nsISSLStatusProvider)
+                               .SSLStatus;
+  if (sslstatus) {
+    let bits =
+      (sslstatus.isUntrusted ? Ci.nsICertOverrideService.ERROR_UNTRUSTED : 0) |
+      (sslstatus.isDomainMismatch ? Ci.nsICertOverrideService.ERROR_MISMATCH : 0) |
+      (sslstatus.isNotValidAtThisTime ? Ci.nsICertOverrideService.ERROR_TIME : 0);
+    Assert.equal(bits, aExpectedBits,
+                 "Actual and expected override bits should match");
+    let cert = sslstatus.serverCert;
+    let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
+                                .getService(Ci.nsICertOverrideService);
+    certOverrideService.rememberValidityOverride(aHost, 8443, cert, aExpectedBits,
+                                                 true);
+  }
+}
+
 // Given a host, expected error bits (see nsICertOverrideService.idl), and
 // an expected error code, tests that an initial connection to the host fails
 // with the expected errors and that adding an override does not result in a
 // subsequent connection succeeding (i.e. the same error code is encountered).
 // The idea here is that for HSTS hosts or hosts with key pins, no error is
 // overridable, even if an entry is added to the override service.
 function add_prevented_cert_override_test(aHost, aExpectedBits, aExpectedError) {
   add_connection_test(aHost, aExpectedError, null,
-                      add_cert_override.bind(this, aHost, aExpectedBits));
+                      attempt_adding_cert_override.bind(this, aHost, aExpectedBits));
   add_connection_test(aHost, aExpectedError);
 }
--- a/security/manager/ssl/tests/unit/pycert.py
+++ b/security/manager/ssl/tests/unit/pycert.py
@@ -11,31 +11,33 @@ signed x509 certificate with the desired
 The input format is as follows:
 
 issuer:<issuer distinguished name specification>
 subject:<subject distinguished name specification>
 [version:{1,2,3,4}]
 [validity:<YYYYMMDD-YYYYMMDD|duration in days>]
 [issuerKey:<key specification>]
 [subjectKey:<key specification>]
-[signature:{sha1WithRSAEncryption,sha256WithRSAEncryption,ecdsaWithSHA256}]
+[signature:{sha256WithRSAEncryption,sha1WithRSAEncryption,
+            md5WithRSAEncryption,ecdsaWithSHA256}]
 [extension:<extension name:<extension-specific data>>]
 [...]
 
 Known extensions are:
 basicConstraints:[cA],[pathLenConstraint]
 keyUsage:[digitalSignature,nonRepudiation,keyEncipherment,
           dataEncipherment,keyAgreement,keyCertSign,cRLSign]
 extKeyUsage:[serverAuth,clientAuth,codeSigning,emailProtection
              nsSGC, # Netscape Server Gated Crypto
              OCSPSigning,timeStamping]
 subjectAlternativeName:[<dNSName>,...]
 authorityInformationAccess:<OCSP URI>
 certificatePolicies:<policy OID>
 nameConstraints:{permitted,excluded}:[<dNSName|directoryName>,...]
+nsCertType:sslServer
 
 Where:
   [] indicates an optional field or component of a field
   <> indicates a required component of a field
   {} indicates a choice of exactly one value among a set of values
   [a,b,c] indicates a list of potential values, of which zero or more
           may be used
 
@@ -59,16 +61,19 @@ Issuer and subject distinguished name sp
 '[stringEncoding]/C=XX/O=Example/CN=example.com'. C (country name), ST
 (state or province name), L (locality name), O (organization name), OU
 (organizational unit name), CN (common name) and emailAddress (email
 address) are currently supported. The optional stringEncoding field may
 be 'utf8String' or 'printableString'. If the given string does not
 contain a '/', it is assumed to represent a common name.
 DirectoryNames also use this format. When specifying a directoryName in
 a nameConstraints extension, the implicit form may not be used.
+
+If an extension name has '[critical]' after it, it will be marked as
+critical. Otherwise (by default), it will not be marked as critical.
 """
 
 from pyasn1.codec.der import decoder
 from pyasn1.codec.der import encoder
 from pyasn1.type import constraint, namedtype, tag, univ, useful
 from pyasn1_modules import rfc2459
 import base64
 import datetime
@@ -173,16 +178,24 @@ class UnknownNameConstraintsSpecificatio
 class UnknownDNTypeError(UnknownBaseError):
     """Helper exception type to handle unknown DN types."""
 
     def __init__(self, value):
         UnknownBaseError.__init__(self, value)
         self.category = 'DN'
 
 
+class UnknownNSCertTypeError(UnknownBaseError):
+    """Helper exception type to handle unknown nsCertType types."""
+
+    def __init__(self, value):
+        UnknownBaseError.__init__(self, value)
+        self.category = 'nsCertType'
+
+
 def getASN1Tag(asn1Type):
     """Helper function for returning the base tag value of a given
     type from the pyasn1 package"""
     return asn1Type.baseTagSet.getBaseTag().asTuple()[2]
 
 def stringToAccessDescription(string):
     """Helper function that takes a string representing a URI
     presumably identifying an OCSP authority information access
@@ -249,37 +262,39 @@ def stringToDN(string, tag=None):
         pos = pos + 1
     if tag:
         name = rfc2459.Name().subtype(implicitTag=tag)
     else:
         name = rfc2459.Name()
     name.setComponentByPosition(0, rdns)
     return name
 
-def stringToAlgorithmIdentifier(string):
+def stringToAlgorithmIdentifiers(string):
     """Helper function that converts a description of an algorithm
-    to a representation usable by the pyasn1 package"""
+    to a representation usable by the pyasn1 package and a hash
+    algorithm name for use by pykey."""
     algorithmIdentifier = rfc2459.AlgorithmIdentifier()
+    algorithmName = None
     algorithm = None
-    name = None
     if string == 'sha1WithRSAEncryption':
-        name = 'SHA-1'
+        algorithmName = 'SHA-1'
         algorithm = rfc2459.sha1WithRSAEncryption
     elif string == 'sha256WithRSAEncryption':
-        name = 'SHA-256'
+        algorithmName = 'SHA-256'
         algorithm = univ.ObjectIdentifier('1.2.840.113549.1.1.11')
+    elif string == 'md5WithRSAEncryption':
+        algorithmName = 'MD5'
+        algorithm = rfc2459.md5WithRSAEncryption
     elif string == 'ecdsaWithSHA256':
-        # Note that this value is only used by pykey.py to tell if
-        # ECDSA is allowed.  It does not conform to the pyECC syntax.
-        name = 'SHA-256'
+        algorithmName = 'sha256'
         algorithm = univ.ObjectIdentifier('1.2.840.10045.4.3.2')
     else:
         raise UnknownAlgorithmTypeError(string)
     algorithmIdentifier.setComponentByName('algorithm', algorithm)
-    return (algorithmIdentifier, name)
+    return (algorithmIdentifier, algorithmName)
 
 def datetimeToTime(dt):
     """Takes a datetime object and returns an rfc2459.Time object with
     that time as its value as a GeneralizedTime"""
     time = rfc2459.Time()
     time.setComponentByName('generalTime', useful.GeneralizedTime(dt.strftime('%Y%m%d%H%M%SZ')))
     return time
 
@@ -375,68 +390,78 @@ class Certificate:
             self.notBefore = datetime.datetime.strptime(match.group(1), '%Y%m%d')
             self.notAfter = datetime.datetime.strptime(match.group(2), '%Y%m%d')
         else:
             delta = datetime.timedelta(days=(int(duration) / 2))
             self.notBefore = self.now - delta
             self.notAfter = self.now + delta
 
     def decodeExtension(self, extension):
-        extensionType = extension.split(':')[0]
-        value = ':'.join(extension.split(':')[1:])
+        match = re.search('([a-zA-Z]+)(\[critical\])?:(.*)', extension)
+        if not match:
+            raise UnknownExtensionTypeError(extension)
+        extensionType = match.group(1)
+        critical = match.group(2)
+        value = match.group(3)
         if extensionType == 'basicConstraints':
-            self.addBasicConstraints(value)
+            self.addBasicConstraints(value, critical)
         elif extensionType == 'keyUsage':
-            self.addKeyUsage(value)
+            self.addKeyUsage(value, critical)
         elif extensionType == 'extKeyUsage':
-            self.addExtKeyUsage(value)
+            self.addExtKeyUsage(value, critical)
         elif extensionType == 'subjectAlternativeName':
-            self.addSubjectAlternativeName(value)
+            self.addSubjectAlternativeName(value, critical)
         elif extensionType == 'authorityInformationAccess':
-            self.addAuthorityInformationAccess(value)
+            self.addAuthorityInformationAccess(value, critical)
         elif extensionType == 'certificatePolicies':
-            self.addCertificatePolicies(value)
+            self.addCertificatePolicies(value, critical)
         elif extensionType == 'nameConstraints':
-            self.addNameConstraints(value)
+            self.addNameConstraints(value, critical)
+        elif extensionType == 'nsCertType':
+            self.addNSCertType(value, critical)
         else:
             raise UnknownExtensionTypeError(extensionType)
 
     def setupKey(self, subjectOrIssuer, value):
         if subjectOrIssuer == 'subject':
             self.subjectKey = pykey.keyFromSpecification(value)
         elif subjectOrIssuer == 'issuer':
             self.issuerKey = pykey.keyFromSpecification(value)
         else:
             raise UnknownKeyTargetError(subjectOrIssuer)
 
-    def addExtension(self, extensionType, extensionValue):
+    def addExtension(self, extensionType, extensionValue, critical):
         if not self.extensions:
             self.extensions = []
         encapsulated = univ.OctetString(encoder.encode(extensionValue))
         extension = rfc2459.Extension()
         extension.setComponentByName('extnID', extensionType)
+        # critical is either the string '[critical]' or None.
+        # We only care whether or not it is truthy.
+        if critical:
+            extension.setComponentByName('critical', True)
         extension.setComponentByName('extnValue', encapsulated)
         self.extensions.append(extension)
 
-    def addBasicConstraints(self, basicConstraints):
+    def addBasicConstraints(self, basicConstraints, critical):
         cA = basicConstraints.split(',')[0]
         pathLenConstraint = basicConstraints.split(',')[1]
         basicConstraintsExtension = rfc2459.BasicConstraints()
         basicConstraintsExtension.setComponentByName('cA', cA == 'cA')
         if pathLenConstraint:
             pathLenConstraintValue = \
                 univ.Integer(int(pathLenConstraint)).subtype(
                     subtypeSpec=constraint.ValueRangeConstraint(0, 64))
             basicConstraintsExtension.setComponentByName('pathLenConstraint',
                                                          pathLenConstraintValue)
-        self.addExtension(rfc2459.id_ce_basicConstraints, basicConstraintsExtension)
+        self.addExtension(rfc2459.id_ce_basicConstraints, basicConstraintsExtension, critical)
 
-    def addKeyUsage(self, keyUsage):
+    def addKeyUsage(self, keyUsage, critical):
         keyUsageExtension = rfc2459.KeyUsage(keyUsage)
-        self.addExtension(rfc2459.id_ce_keyUsage, keyUsageExtension)
+        self.addExtension(rfc2459.id_ce_keyUsage, keyUsageExtension, critical)
 
     def keyPurposeToOID(self, keyPurpose):
         if keyPurpose == 'serverAuth':
             # the OID for id_kp_serverAuth is incorrect in the
             # pyasn1-modules implementation
             return univ.ObjectIdentifier('1.3.6.1.5.5.7.3.1')
         if keyPurpose == 'clientAuth':
             return rfc2459.id_kp_clientAuth
@@ -447,54 +472,54 @@ class Certificate:
         if keyPurpose == 'nsSGC':
             return univ.ObjectIdentifier('2.16.840.1.113730.4.1')
         if keyPurpose == 'OCSPSigning':
             return univ.ObjectIdentifier('1.3.6.1.5.5.7.3.9')
         if keyPurpose == 'timeStamping':
             return rfc2459.id_kp_timeStamping
         raise UnknownKeyPurposeTypeError(keyPurpose)
 
-    def addExtKeyUsage(self, extKeyUsage):
+    def addExtKeyUsage(self, extKeyUsage, critical):
         extKeyUsageExtension = rfc2459.ExtKeyUsageSyntax()
         count = 0
         for keyPurpose in extKeyUsage.split(','):
             extKeyUsageExtension.setComponentByPosition(count, self.keyPurposeToOID(keyPurpose))
             count += 1
-        self.addExtension(rfc2459.id_ce_extKeyUsage, extKeyUsageExtension)
+        self.addExtension(rfc2459.id_ce_extKeyUsage, extKeyUsageExtension, critical)
 
-    def addSubjectAlternativeName(self, dNSNames):
+    def addSubjectAlternativeName(self, dNSNames, critical):
         subjectAlternativeName = rfc2459.SubjectAltName()
         count = 0
         for dNSName in dNSNames.split(','):
             generalName = rfc2459.GeneralName()
             # The string may have things like '\0' (i.e. a slash
             # followed by the number zero) that have to be decoded into
             # the resulting '\x00' (i.e. a byte with value zero).
             generalName.setComponentByName('dNSName', dNSName.decode(encoding='string_escape'))
             subjectAlternativeName.setComponentByPosition(count, generalName)
             count += 1
-        self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName)
+        self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName, critical)
 
-    def addAuthorityInformationAccess(self, ocspURI):
+    def addAuthorityInformationAccess(self, ocspURI, critical):
         sequence = univ.Sequence()
         accessDescription = stringToAccessDescription(ocspURI)
         sequence.setComponentByPosition(0, accessDescription)
-        self.addExtension(rfc2459.id_pe_authorityInfoAccess, sequence)
+        self.addExtension(rfc2459.id_pe_authorityInfoAccess, sequence, critical)
 
-    def addCertificatePolicies(self, policyOID):
+    def addCertificatePolicies(self, policyOID, critical):
         policies = rfc2459.CertificatePolicies()
         policy = rfc2459.PolicyInformation()
         if policyOID == 'any':
             policyOID = '2.5.29.32.0'
         policyIdentifier = rfc2459.CertPolicyId(policyOID)
         policy.setComponentByName('policyIdentifier', policyIdentifier)
         policies.setComponentByPosition(0, policy)
-        self.addExtension(rfc2459.id_ce_certificatePolicies, policies)
+        self.addExtension(rfc2459.id_ce_certificatePolicies, policies, critical)
 
-    def addNameConstraints(self, constraints):
+    def addNameConstraints(self, constraints, critical):
         nameConstraints = NameConstraints()
         if constraints.startswith('permitted:'):
             (subtreesType, subtreesTag) = ('permittedSubtrees', 0)
         elif constraints.startswith('excluded:'):
             (subtreesType, subtreesTag) = ('excludedSubtrees', 1)
         else:
             raise UnknownNameConstraintsSpecificationError(constraints)
         generalSubtrees = rfc2459.GeneralSubtrees().subtype(
@@ -509,28 +534,31 @@ class Certificate:
                 generalName.setComponentByName('directoryName', directoryName)
             else:
                 generalName.setComponentByName('dNSName', name)
             generalSubtree = GeneralSubtree()
             generalSubtree.setComponentByName('base', generalName)
             generalSubtrees.setComponentByPosition(pos, generalSubtree)
             pos = pos + 1
         nameConstraints.setComponentByName(subtreesType, generalSubtrees)
-        self.addExtension(rfc2459.id_ce_nameConstraints, nameConstraints)
+        self.addExtension(rfc2459.id_ce_nameConstraints, nameConstraints, critical)
+
+    def addNSCertType(self, certType, critical):
+        if certType != 'sslServer':
+            raise UnknownNSCertTypeError(certType)
+        self.addExtension(univ.ObjectIdentifier('2.16.840.1.113730.1.1'), univ.BitString("'01'B"),
+            critical)
 
     def getVersion(self):
         return rfc2459.Version(self.versionValue).subtype(
             explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))
 
     def getSerialNumber(self):
         return decoder.decode(self.serialNumber)[0]
 
-    def getSignature(self):
-        return stringToAlgorithmIdentifier(self.signature)
-
     def getIssuer(self):
         return stringToDN(self.issuer)
 
     def getValidity(self):
         validity = rfc2459.Validity()
         validity.setComponentByName('notBefore', self.getNotBefore())
         validity.setComponentByName('notAfter', self.getNotAfter())
         return validity
@@ -540,18 +568,17 @@ class Certificate:
 
     def getNotAfter(self):
         return datetimeToTime(self.notAfter)
 
     def getSubject(self):
         return stringToDN(self.subject)
 
     def toDER(self):
-        (signatureOID, hashAlg) = self.getSignature()
-
+        (signatureOID, hashName) = stringToAlgorithmIdentifiers(self.signature)
         tbsCertificate = rfc2459.TBSCertificate()
         tbsCertificate.setComponentByName('version', self.getVersion())
         tbsCertificate.setComponentByName('serialNumber', self.getSerialNumber())
         tbsCertificate.setComponentByName('signature', signatureOID)
         tbsCertificate.setComponentByName('issuer', self.getIssuer())
         tbsCertificate.setComponentByName('validity', self.getValidity())
         tbsCertificate.setComponentByName('subject', self.getSubject())
         tbsCertificate.setComponentByName('subjectPublicKeyInfo',
@@ -563,18 +590,17 @@ class Certificate:
             for extension in self.extensions:
                 extensions.setComponentByPosition(count, extension)
                 count += 1
             tbsCertificate.setComponentByName('extensions', extensions)
         certificate = rfc2459.Certificate()
         certificate.setComponentByName('tbsCertificate', tbsCertificate)
         certificate.setComponentByName('signatureAlgorithm', signatureOID)
         tbsDER = encoder.encode(tbsCertificate)
-
-        certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashAlg))
+        certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashName))
         return encoder.encode(certificate)
 
     def toPEM(self):
         output = '-----BEGIN CERTIFICATE-----'
         der = self.toDER()
         b64 = base64.b64encode(der)
         while b64:
             output += '\n' + b64[:64]
--- a/security/manager/ssl/tests/unit/pykey.py
+++ b/security/manager/ssl/tests/unit/pykey.py
@@ -61,23 +61,16 @@ class UnknownBaseError(Exception):
 
 class UnknownKeySpecificationError(UnknownBaseError):
     """Helper exception type to handle unknown key specifications."""
 
     def __init__(self, value):
         UnknownBaseError.__init__(self, value)
         self.category = 'key specification'
 
-class ParameterError(UnknownBaseError):
-    """Exception type indicating that the key was misconfigured"""
-
-    def __init__(self, value):
-        UnknownBaseError.__init__(self, value)
-        self.category = 'key parameter'
-
 class RSAPublicKey(univ.Sequence):
     """Helper type for encoding an RSA public key"""
     componentType = namedtype.NamedTypes(
         namedtype.NamedType('N', univ.Integer()),
         namedtype.NamedType('E', univ.Integer()))
 
 
 class RSAPrivateKey(univ.Sequence):
@@ -555,22 +548,22 @@ class RSAKey:
         spki.setComponentByName('algorithm', algorithmIdentifier)
         rsaKey = RSAPublicKey()
         rsaKey.setComponentByName('N', univ.Integer(self.RSA_N))
         rsaKey.setComponentByName('E', univ.Integer(self.RSA_E))
         subjectPublicKey = univ.BitString(byteStringToHexifiedBitString(encoder.encode(rsaKey)))
         spki.setComponentByName('subjectPublicKey', subjectPublicKey)
         return spki
 
-    def sign(self, data, digest):
+    def sign(self, data, hashAlgorithmName):
         """Returns a hexified bit string representing a
         signature by this key over the specified data.
         Intended for use with pyasn1.type.univ.BitString"""
         rsaPrivateKey = rsa.PrivateKey(self.RSA_N, self.RSA_E, self.RSA_D, self.RSA_P, self.RSA_Q)
-        signature = rsa.sign(data, rsaPrivateKey, digest)
+        signature = rsa.sign(data, rsaPrivateKey, hashAlgorithmName)
         return byteStringToHexifiedBitString(signature)
 
 
 ecPublicKey = univ.ObjectIdentifier('1.2.840.10045.2.1')
 secp256k1 = univ.ObjectIdentifier('1.3.132.0.10')
 secp224r1 = univ.ObjectIdentifier('1.3.132.0.33')
 secp256r1 = univ.ObjectIdentifier('1.2.840.10045.3.1.7')
 secp384r1 = univ.ObjectIdentifier('1.3.132.0.34')
@@ -666,36 +659,32 @@ class ECCKey:
         _, _, points = encoding.Decoder(encoded).int(8).int(2).point(2).out()
         # '04' indicates that the points are in uncompressed form.
         hexifiedBitString = "'%s%s%s'H" % ('04', longToEvenLengthHexString(points[0]),
                                            longToEvenLengthHexString(points[1]))
         subjectPublicKey = univ.BitString(hexifiedBitString)
         spki.setComponentByName('subjectPublicKey', subjectPublicKey)
         return spki
 
-    def sign(self, data, digest):
+    def sign(self, data, hashAlgorithmName):
         """Returns a hexified bit string representing a
         signature by this key over the specified data.
         Intended for use with pyasn1.type.univ.BitString"""
-        # This should really only be used with SHA-256
-        if digest != "SHA-256":
-            raise ParameterError(digest)
-
         # There is some non-determinism in ECDSA signatures. Work around
         # this by patching ecc.ecdsa.urandom to not be random.
         with mock.patch('ecc.ecdsa.urandom', side_effect=notRandom):
             # For some reason Key.sign returns an encoded point.
             # Decode it so we can encode it as a BITSTRING consisting
             # of a SEQUENCE of two INTEGERs.
             # Also patch in secp256k1 if applicable.
             if self.keyOID == secp256k1:
                 with mock.patch('ecc.curves.DOMAINS', {256: secp256k1Params}):
-                    x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
+                    x, y = encoding.dec_point(self.key.sign(data, hashAlgorithmName))
             else:
-                x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
+                x, y = encoding.dec_point(self.key.sign(data, hashAlgorithmName))
             point = ECPoint()
             point.setComponentByName('x', x)
             point.setComponentByName('y', y)
             return byteStringToHexifiedBitString(encoder.encode(point))
 
 
 def keyFromSpecification(specification):
     """Pass in a specification, get the appropriate key back."""
--- a/security/manager/ssl/tests/unit/test_cert_blocklist.js
+++ b/security/manager/ssl/tests/unit/test_cert_blocklist.js
@@ -89,37 +89,38 @@ var blocklist_contents =
     "<certItems><certItem issuerName='Some nonsense in issuer'>" +
     "<serialNumber>AkHVNA==</serialNumber>" +
     "</certItem><certItem issuerName='MA0xCzAJBgNVBAMMAmNh'>" +
     "<serialNumber>some nonsense in serial</serialNumber>" +
     "</certItem><certItem issuerName='some nonsense in both issuer'>" +
     "<serialNumber>and serial</serialNumber></certItem>" +
     // some mixed
     // In this case, the issuer name and the valid serialNumber correspond
-    // to test-int.der in tlsserver/
-    "<certItem issuerName='MBIxEDAOBgNVBAMTB1Rlc3QgQ0E='>" +
+    // to test-int.pem in tlsserver/
+    "<certItem issuerName='MBIxEDAOBgNVBAMMB1Rlc3QgQ0E='>" +
     "<serialNumber>oops! more nonsense.</serialNumber>" +
-    "<serialNumber>X1o=</serialNumber></certItem>" +
+    "<serialNumber>Y1HQqXGtw7ek2v/QAqBL8jf6rbA=</serialNumber></certItem>" +
     // ... and some good
     // In this case, the issuer name and the valid serialNumber correspond
-    // to other-test-ca.der in tlsserver/ (for testing root revocation)
-    "<certItem issuerName='MBgxFjAUBgNVBAMTDU90aGVyIHRlc3QgQ0E='>" +
-    "<serialNumber>AKEIivg=</serialNumber></certItem>" +
+    // to other-test-ca.pem in tlsserver/ (for testing root revocation)
+    "<certItem issuerName='MBgxFjAUBgNVBAMMDU90aGVyIHRlc3QgQ0E='>" +
+    "<serialNumber>Szin5enUEn9TnVq29c4IMPNFuqE=</serialNumber></certItem>" +
     // This item corresponds to an entry in sample_revocations.txt where:
     // isser name is "another imaginary issuer" base-64 encoded, and
     // serialNumbers are:
     // "serial2." base-64 encoded, and
     // "another serial." base-64 encoded
     // We need this to ensure that existing items are retained if they're
     // also in the blocklist
     "<certItem issuerName='YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy'>" +
     "<serialNumber>c2VyaWFsMi4=</serialNumber>" +
     "<serialNumber>YW5vdGhlciBzZXJpYWwu</serialNumber>" +
-    "</certItem><certItem subject='MCIxIDAeBgNVBAMTF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5'"+
-    " pubKeyHash='2ETEb0QP574JkM+35JVwS899PLUmt1rrJyWOV6GRfAE='>" +
+    // This item revokes same-issuer-ee.pem by subject and serial number.
+    "</certItem><certItem subject='MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5'"+
+    " pubKeyHash='VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8='>" +
     "</certItem></certItems></blocklist>";
 testserver.registerPathHandler("/push_blocked_cert/",
   function serveResponse(request, response) {
     response.write(blocklist_contents);
   });
 
 // start the test server
 testserver.start(-1);
@@ -131,23 +132,22 @@ var addonManager = Cc["@mozilla.org/addo
                      .QueryInterface(Ci.nsITimerCallback);
 addonManager.observe(null, "addons-startup", null);
 
 var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                   .createInstance(Ci.nsIScriptableUnicodeConverter);
 converter.charset = "UTF-8";
 
 function verify_cert(file, expectedError) {
-  let cert_der = readFile(do_get_file(file));
-  let ee = certDB.constructX509(cert_der, cert_der.length);
+  let ee = constructCertFromFile(file);
   checkCertErrorGeneric(certDB, ee, expectedError, certificateUsageSSLServer);
 }
 
 function load_cert(cert, trust) {
-  let file = "tlsserver/" + cert + ".der";
+  let file = "tlsserver/" + cert + ".pem";
   addCertFromFile(certDB, file, trust);
 }
 
 function test_is_revoked(certList, issuerString, serialString, subjectString,
                          pubKeyString) {
   let issuer = converter.convertToByteArray(issuerString ? issuerString : '',
                                             {});
 
@@ -196,30 +196,30 @@ function run_test() {
 
   // And this test corresponds to:
   // issuer: YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy
   // serial: c2VyaWFsMi4=
   // (we test this issuer twice to ensure we can read multiple serials)
   ok(test_is_revoked(certList, "another imaginary issuer", "serial2."),
      "issuer / serial pair should be blocked");
 
-  // Soon we'll load a blocklist which revokes test-int.der, which issued
-  // test-int-ee.der.
+  // Soon we'll load a blocklist which revokes test-int.pem, which issued
+  // test-int-ee.pem.
   // Check the cert validates before we load the blocklist
-  let file = "tlsserver/test-int-ee.der";
+  let file = "tlsserver/test-int-ee.pem";
   verify_cert(file, PRErrorCodeSuccess);
 
-  // The blocklist also revokes other-test-ca.der, which issued other-ca-ee.der.
+  // The blocklist also revokes other-test-ca.pem, which issued other-ca-ee.pem.
   // Check the cert validates before we load the blocklist
-  file = "tlsserver/other-issuer-ee.der";
+  file = "tlsserver/other-issuer-ee.pem";
   verify_cert(file, PRErrorCodeSuccess);
 
-  // The blocklist will revoke same-issuer-ee.der via subject / pubKeyHash.
+  // The blocklist will revoke same-issuer-ee.pem via subject / pubKeyHash.
   // Check the cert validates before we load the blocklist
-  file = "tlsserver/same-issuer-ee.der";
+  file = "tlsserver/same-issuer-ee.pem";
   verify_cert(file, PRErrorCodeSuccess);
 
   // blocklist load is async so we must use add_test from here
   add_test(function() {
     let certblockObserver = {
       observe: function(aSubject, aTopic, aData) {
         Services.obs.removeObserver(this, "blocklist-updated");
         run_next_test();
@@ -266,45 +266,45 @@ function run_test() {
     let contents = "";
     let hasmore = false;
     do {
       var line = {};
       hasmore = inputStream.readLine(line);
       contents = contents + (contents.length == 0 ? "" : "\n") + line.value;
     } while (hasmore);
     let expected = "# Auto generated contents. Do not edit.\n" +
-                  "MCIxIDAeBgNVBAMTF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5\n"+
-                  "\t2ETEb0QP574JkM+35JVwS899PLUmt1rrJyWOV6GRfAE=\n"+
-                  "MBgxFjAUBgNVBAMTDU90aGVyIHRlc3QgQ0E=\n" +
-                  " AKEIivg=\n" +
-                  "MBIxEDAOBgNVBAMTB1Rlc3QgQ0E=\n" +
-                  " X1o=\n" +
+                  "MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5\n"+
+                  "\tVCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=\n"+
+                  "MBIxEDAOBgNVBAMMB1Rlc3QgQ0E=\n" +
+                  " Y1HQqXGtw7ek2v/QAqBL8jf6rbA=\n" +
+                  "MBgxFjAUBgNVBAMMDU90aGVyIHRlc3QgQ0E=\n" +
+                  " Szin5enUEn9TnVq29c4IMPNFuqE=\n" +
                   "YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy\n" +
                   " YW5vdGhlciBzZXJpYWwu\n" +
                   " c2VyaWFsMi4=";
     equal(contents, expected, "revocations.txt should be as expected");
 
     // Check the blocklisted intermediate now causes a failure
-    let file = "tlsserver/test-int-ee.der";
+    let file = "tlsserver/test-int-ee.pem";
     verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
 
     // Check the ee with the blocklisted root also causes a failure
-    file = "tlsserver/other-issuer-ee.der";
+    file = "tlsserver/other-issuer-ee.pem";
     verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
 
     // Check the ee blocked by subject / pubKey causes a failure
-    file = "tlsserver/same-issuer-ee.der";
+    file = "tlsserver/same-issuer-ee.pem";
     verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
 
     // Check a non-blocklisted chain still validates OK
-    file = "tlsserver/default-ee.der";
+    file = "tlsserver/default-ee.pem";
     verify_cert(file, PRErrorCodeSuccess);
 
     // Check a bad cert is still bad (unknown issuer)
-    file = "tlsserver/unknown-issuer.der";
+    file = "tlsserver/unknownissuer.pem";
     verify_cert(file, SEC_ERROR_UNKNOWN_ISSUER);
 
     // check that save with no further update is a no-op
     let lastModified = revocations.lastModifiedTime;
     // add an already existing entry
     certList.revokeCertByIssuerAndSerial("YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy",
                                          "c2VyaWFsMi4=");
     certList.saveEntries();
--- a/security/manager/ssl/tests/unit/test_cert_chains.js
+++ b/security/manager/ssl/tests/unit/test_cert_chains.js
@@ -4,26 +4,26 @@
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 "use strict";
 
 function build_cert_chain(certNames) {
   let certList = Cc["@mozilla.org/security/x509certlist;1"]
                    .createInstance(Ci.nsIX509CertList);
   certNames.forEach(function(certName) {
-    let cert = constructCertFromFile("tlsserver/" + certName + ".der");
+    let cert = constructCertFromFile("tlsserver/" + certName + ".pem");
     certList.addCert(cert);
   });
   return certList;
 }
 
 function test_cert_equals() {
-  let certA = constructCertFromFile("tlsserver/default-ee.der");
-  let certB = constructCertFromFile("tlsserver/default-ee.der");
-  let certC = constructCertFromFile("tlsserver/expired-ee.der");
+  let certA = constructCertFromFile("tlsserver/default-ee.pem");
+  let certB = constructCertFromFile("tlsserver/default-ee.pem");
+  let certC = constructCertFromFile("tlsserver/expired-ee.pem");
 
   ok(certA != certB,
      "Cert objects constructed from the same file should not be equal" +
      " according to the equality operators");
   ok(certA.equals(certB),
      "equals() on cert objects constructed from the same cert file should" +
      " return true");
   ok(!certA.equals(certC),
--- a/security/manager/ssl/tests/unit/test_cert_overrides.js
+++ b/security/manager/ssl/tests/unit/test_cert_overrides.js
@@ -8,30 +8,16 @@
 // add_cert_override_test will queue a test that does the following:
 // 1. Attempt to connect to the given host. This should fail with the
 //    given error and override bits.
 // 2. Add an override for that host/port/certificate/override bits.
 // 3. Connect again. This should succeed.
 
 do_get_profile();
 
-function add_non_overridable_test(aHost, aExpectedError) {
-  add_connection_test(
-    aHost, aExpectedError, null,
-    function (securityInfo) {
-      // bug 754369 - no SSLStatus probably means this is a non-overridable
-      // error, which is what we're testing (although it would be best to test
-      // this directly).
-      securityInfo.QueryInterface(Ci.nsISSLStatusProvider);
-      equal(securityInfo.SSLStatus, null,
-            "As a proxy to checking that the connection error is" +
-            " non-overridable, SSLStatus should be null");
-    });
-}
-
 function check_telemetry() {
   let histogram = Cc["@mozilla.org/base/telemetry;1"]
                     .getService(Ci.nsITelemetry)
                     .getHistogramById("SSL_CERT_ERROR_OVERRIDES")
                     .snapshot();
   equal(histogram.counts[ 0], 0, "Should have 0 unclassified counts");
   equal(histogram.counts[ 2], 7,
         "Actual and expected SEC_ERROR_UNKNOWN_ISSUER counts should match");
@@ -65,21 +51,21 @@ function check_telemetry() {
         "Actual and expected SEC_ERROR_INVALID_TIME counts should match");
 
   let keySizeHistogram = Cc["@mozilla.org/base/telemetry;1"]
                            .getService(Ci.nsITelemetry)
                            .getHistogramById("CERT_CHAIN_KEY_SIZE_STATUS")
                            .snapshot();
   equal(keySizeHistogram.counts[0], 0,
         "Actual and expected unchecked key size counts should match");
-  equal(keySizeHistogram.counts[1], 0,
+  equal(keySizeHistogram.counts[1], 12,
         "Actual and expected successful verifications of 2048-bit keys should match");
-  equal(keySizeHistogram.counts[2], 12,
+  equal(keySizeHistogram.counts[2], 0,
         "Actual and expected successful verifications of 1024-bit keys should match");
-  equal(keySizeHistogram.counts[3], 48,
+  equal(keySizeHistogram.counts[3], 54,
         "Actual and expected key size verification failures should match");
 
   run_next_test();
 }
 
 function run_test() {
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
   add_tls_server_setup("BadCertServer");
@@ -142,32 +128,34 @@ function add_simple_tests() {
 
   // A Microsoft IIS utility generates self-signed certificates with
   // properties similar to the one this "host" will present (see
   // tlsserver/generate_certs.sh).
   add_cert_override_test("selfsigned-inadequateEKU.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          SEC_ERROR_UNKNOWN_ISSUER);
 
-  add_non_overridable_test("inadequatekeyusage.example.com",
-                           SEC_ERROR_INADEQUATE_KEY_USAGE);
+  add_prevented_cert_override_test("inadequatekeyusage.example.com",
+                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                                   SEC_ERROR_INADEQUATE_KEY_USAGE);
 
   // This is intended to test the case where a verification has failed for one
   // overridable reason (e.g. unknown issuer) but then, in the process of
   // reporting that error, a non-overridable error is encountered. The
   // non-overridable error should be prioritized.
   add_test(function() {
-    let rootCert = constructCertFromFile("tlsserver/test-ca.der");
+    let rootCert = constructCertFromFile("tlsserver/test-ca.pem");
     setCertTrust(rootCert, ",,");
     run_next_test();
   });
-  add_non_overridable_test("nsCertTypeCritical.example.com",
-                           SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
+  add_prevented_cert_override_test("nsCertTypeCritical.example.com",
+                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                                   SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
   add_test(function() {
-    let rootCert = constructCertFromFile("tlsserver/test-ca.der");
+    let rootCert = constructCertFromFile("tlsserver/test-ca.pem");
     setCertTrust(rootCert, "CTu,,");
     run_next_test();
   });
 
   // Bug 990603: Apache documentation has recommended generating a self-signed
   // test certificate with basic constraints: CA:true. For compatibility, this
   // is a scenario in which an override is allowed.
   add_cert_override_test("self-signed-end-entity-with-cA-true.example.com",
@@ -183,41 +171,42 @@ function add_simple_tests() {
   add_cert_override_test("end-entity-issued-by-v1-cert.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          MOZILLA_PKIX_ERROR_V1_CERT_USED_AS_CA);
   // If we make that certificate a trust anchor, the connection will succeed.
   add_test(function() {
     let certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
                                 .getService(Ci.nsICertOverrideService);
     certOverrideService.clearValidityOverride("end-entity-issued-by-v1-cert.example.com", 8443);
-    let v1Cert = constructCertFromFile("tlsserver/v1Cert.der");
+    let v1Cert = constructCertFromFile("tlsserver/v1Cert.pem");
     setCertTrust(v1Cert, "CTu,,");
     clearSessionCache();
     run_next_test();
   });
   add_connection_test("end-entity-issued-by-v1-cert.example.com",
                       PRErrorCodeSuccess);
   // Reset the trust for that certificate.
   add_test(function() {
-    let v1Cert = constructCertFromFile("tlsserver/v1Cert.der");
+    let v1Cert = constructCertFromFile("tlsserver/v1Cert.pem");
     setCertTrust(v1Cert, ",,");
     clearSessionCache();
     run_next_test();
   });
 
   // Due to compatibility issues, we allow overrides for certificates issued by
   // certificates that are not valid CAs.
   add_cert_override_test("end-entity-issued-by-non-CA.example.com",
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          SEC_ERROR_CA_CERT_INVALID);
 
-  // This host presents a 1008-bit RSA key. NSS determines this key is too
+  // This host presents a 1016-bit RSA key. NSS determines this key is too
   // small and terminates the connection. The error is not overridable.
-  add_non_overridable_test("inadequate-key-size-ee.example.com",
-                           SSL_ERROR_WEAK_SERVER_CERT_KEY);
+  add_prevented_cert_override_test("inadequate-key-size-ee.example.com",
+                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                                   SSL_ERROR_WEAK_SERVER_CERT_KEY);
 
   add_cert_override_test("ipAddressAsDNSNameInSAN.example.com",
                          Ci.nsICertOverrideService.ERROR_MISMATCH,
                          SSL_ERROR_BAD_CERT_DOMAIN);
   add_cert_override_test("noValidNames.example.com",
                          Ci.nsICertOverrideService.ERROR_MISMATCH,
                          SSL_ERROR_BAD_CERT_DOMAIN);
   add_cert_override_test("badSubjectAltNames.example.com",
@@ -258,34 +247,36 @@ function add_combo_tests() {
                          Ci.nsICertOverrideService.ERROR_UNTRUSTED,
                          MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY);
 }
 
 function add_distrust_tests() {
   // Before we specifically distrust this certificate, it should be trusted.
   add_connection_test("untrusted.example.com", PRErrorCodeSuccess);
 
-  add_distrust_test("tlsserver/default-ee.der", "untrusted.example.com",
+  add_distrust_test("tlsserver/default-ee.pem", "untrusted.example.com",
                     SEC_ERROR_UNTRUSTED_CERT);
 
-  add_distrust_test("tlsserver/other-test-ca.der",
+  add_distrust_test("tlsserver/other-test-ca.pem",
                     "untrustedissuer.example.com", SEC_ERROR_UNTRUSTED_ISSUER);
 
-  add_distrust_test("tlsserver/test-ca.der",
+  add_distrust_test("tlsserver/test-ca.pem",
                     "ca-used-as-end-entity.example.com",
                     SEC_ERROR_UNTRUSTED_ISSUER);
 }
 
 function add_distrust_test(certFileName, hostName, expectedResult) {
   let certToDistrust = constructCertFromFile(certFileName);
 
   add_test(function () {
     // Add an entry to the NSS certDB that says to distrust the cert
     setCertTrust(certToDistrust, "pu,,");
     clearSessionCache();
     run_next_test();
   });
-  add_non_overridable_test(hostName, expectedResult);
+  add_prevented_cert_override_test(hostName,
+                                   Ci.nsICertOverrideService.ERROR_UNTRUSTED,
+                                   expectedResult);
   add_test(function () {
     setCertTrust(certToDistrust, "u,,");
     run_next_test();
   });
 }
--- a/security/manager/ssl/tests/unit/test_ocsp_caching.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_caching.js
@@ -19,47 +19,47 @@ function respondWithGoodOCSP(request, re
   response.write(gGoodOCSPResponse);
 }
 
 function respondWithSHA1OCSP(request, response) {
   do_print("returning 200 OK with sha-1 delegated response");
   response.setStatusLine(request.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "application/ocsp-response");
 
-  let args = [ ["good-delegated", "localhostAndExampleCom", "delegatedSHA1Signer" ] ];
+  let args = [ ["good-delegated", "default-ee", "delegatedSHA1Signer" ] ];
   let responses = generateOCSPResponses(args, "tlsserver");
   response.write(responses[0]);
 }
 
 function respondWithError(request, response) {
   do_print("returning 500 Internal Server Error");
   response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
   let body = "Refusing to return a response";
   response.bodyOutputStream.write(body, body.length);
 }
 
 function generateGoodOCSPResponse() {
-  let args = [ ["good", "localhostAndExampleCom", "unused" ] ];
+  let args = [ ["good", "default-ee", "unused" ] ];
   let responses = generateOCSPResponses(args, "tlsserver");
   return responses[0];
 }
 
 function add_ocsp_test(aHost, aExpectedResult, aResponses, aMessage) {
   add_connection_test(aHost, aExpectedResult,
       function() {
         clearSessionCache();
         gFetchCount = 0;
         gResponsePattern = aResponses;
         gMessage = aMessage;
       },
       function() {
         // check the number of requests matches the size of aResponses
         equal(gFetchCount, aResponses.length,
               "should have made " + aResponses.length +
-              " OCSP request" + aResponses.length == 1 ? "" : "s");
+              " OCSP request" + (aResponses.length == 1 ? "" : "s"));
       });
 }
 
 function run_test() {
   do_get_profile();
   Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
   add_tls_server_setup("OCSPStaplingServer");
@@ -129,16 +129,20 @@ function add_tests() {
   // A failure to retrieve an OCSP response must result in the cached Unknown
   // response being recognized and honored.
   add_ocsp_test("ocsp-stapling-none.example.com", SEC_ERROR_OCSP_UNKNOWN_CERT,
                 [
                   respondWithError,
                   respondWithError,
                   respondWithError,
                   respondWithError,
+                  respondWithError,
+                  respondWithError,
+                  respondWithError,
+                  respondWithError,
                 ],
                 "No stapled response -> a fetch should have been attempted");
 
   // A valid Good response from the OCSP responder must override the cached
   // Unknown response.
   //
   // Note that We need to make sure that the Unknown response and the Good
   // response have different thisUpdate timestamps; otherwise, the Good
--- a/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_no_hsts_upgrade.js
@@ -11,17 +11,17 @@ function run_test() {
   do_get_profile();
   // OCSP required means this test will only pass if the request succeeds.
   Services.prefs.setBoolPref("security.OCSP.require", true);
 
   // We don't actually make use of stapling in this test. This is just how we
   // get a TLS connection.
   add_tls_server_setup("OCSPStaplingServer");
 
-  let args = [["good", "localhostAndExampleCom", "unused"]];
+  let args = [["good", "default-ee", "unused"]];
   let ocspResponses = generateOCSPResponses(args, "tlsserver");
   let goodOCSPResponse = ocspResponses[0];
 
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 200, "OK");
     response.setHeader("Content-Type", "application/ocsp-response");
     response.write(goodOCSPResponse);
--- a/security/manager/ssl/tests/unit/test_ocsp_required.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_required.js
@@ -15,17 +15,17 @@ function run_test() {
   do_get_profile();
   Services.prefs.setBoolPref("security.OCSP.require", true);
   Services.prefs.setIntPref("security.OCSP.enabled", 1);
 
   // We don't actually make use of stapling in this test. This is just how we
   // get a TLS connection.
   add_tls_server_setup("OCSPStaplingServer");
 
-  let args = [["bad-signature", "localhostAndExampleCom", "unused"]];
+  let args = [["bad-signature", "default-ee", "unused"]];
   let ocspResponses = generateOCSPResponses(args, "tlsserver");
   let ocspResponseBadSignature = ocspResponses[0];
 
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 200, "OK");
     response.setHeader("Content-Type", "application/ocsp-response");
     response.write(ocspResponseBadSignature);
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling.js
@@ -16,17 +16,17 @@ function add_ocsp_test(aHost, aExpectedR
       gExpectOCSPRequest = !aStaplingEnabled;
       clearOCSPCache();
       clearSessionCache();
       Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling",
                                  aStaplingEnabled);
     });
 }
 
-function add_tests(certDB, otherTestCA) {
+function add_tests() {
   // In the absence of OCSP stapling, these should actually all work.
   add_ocsp_test("ocsp-stapling-good.example.com",
                 PRErrorCodeSuccess, false);
   add_ocsp_test("ocsp-stapling-revoked.example.com",
                 PRErrorCodeSuccess, false);
   add_ocsp_test("ocsp-stapling-good-other-ca.example.com",
                 PRErrorCodeSuccess, false);
   add_ocsp_test("ocsp-stapling-malformed.example.com",
@@ -68,16 +68,19 @@ function add_tests(certDB, otherTestCA) 
 
   // SEC_ERROR_OCSP_INVALID_SIGNING_CERT vs SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
   // depends on whether the CA that signed the response is a trusted CA
   // (but only with the classic implementation - mozilla::pkix always
   // results in the error SEC_ERROR_OCSP_INVALID_SIGNING_CERT).
 
   // This stapled response is from a CA that is untrusted and did not issue
   // the server's certificate.
+  let certDB = Cc["@mozilla.org/security/x509certdb;1"]
+                  .getService(Ci.nsIX509CertDB);
+  let otherTestCA = constructCertFromFile("tlsserver/other-test-ca.pem");
   add_test(function() {
     certDB.setCertTrust(otherTestCA, Ci.nsIX509Cert.CA_CERT,
                         Ci.nsIX509CertDB.UNTRUSTED);
     run_next_test();
   });
   add_ocsp_test("ocsp-stapling-good-other-ca.example.com",
                 SEC_ERROR_OCSP_INVALID_SIGNING_CERT, true);
 
@@ -181,32 +184,27 @@ function check_ocsp_stapling_telemetry()
   equal(histogram.counts[4], 21,
         "Actual and expected connections with bad responses should match");
   run_next_test();
 }
 
 function run_test() {
   do_get_profile();
 
-  let certDB = Cc["@mozilla.org/security/x509certdb;1"]
-                  .getService(Ci.nsIX509CertDB);
-  let otherTestCAFile = do_get_file("tlsserver/other-test-ca.der", false);
-  let otherTestCADER = readFile(otherTestCAFile);
-  let otherTestCA = certDB.constructX509(otherTestCADER, otherTestCADER.length);
 
   let fakeOCSPResponder = new HttpServer();
   fakeOCSPResponder.registerPrefixHandler("/", function (request, response) {
     response.setStatusLine(request.httpVersion, 500, "Internal Server Error");
     ok(gExpectOCSPRequest,
        "Should be getting an OCSP request only when expected");
   });
   fakeOCSPResponder.start(8888);
 
   add_tls_server_setup("OCSPStaplingServer");
 
-  add_tests(certDB, otherTestCA);
+  add_tests();
 
   add_test(function () {
     fakeOCSPResponder.stop(check_ocsp_stapling_telemetry);
   });
 
   run_next_test();
 }
--- a/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
+++ b/security/manager/ssl/tests/unit/test_ocsp_stapling_expired.js
@@ -19,28 +19,28 @@ function add_ocsp_test(aHost, aExpectedR
       clearOCSPCache();
       clearSessionCache();
       gCurrentOCSPResponse = aOCSPResponseToServe;
       gOCSPRequestCount = 0;
     },
     function() {
       equal(gOCSPRequestCount, aExpectedRequestCount,
             "Should have made " + aExpectedRequestCount +
-            " fallback OCSP request" + aExpectedRequestCount == 1 ? "" : "s");
+            " fallback OCSP request" + (aExpectedRequestCount == 1 ? "" : "s"));
     });
 }
 
 do_get_profile();
 Services.prefs.setBoolPref("security.ssl.enable_ocsp_stapling", true);
 Services.prefs.setIntPref("security.OCSP.enabled", 1);
-var args = [["good", "localhostAndExampleCom", "unused"],
-             ["expiredresponse", "localhostAndExampleCom", "unused"],
-             ["oldvalidperiod", "localhostAndExampleCom", "unused"],
-             ["revoked", "localhostAndExampleCom", "unused"],
-             ["unknown", "localhostAndExampleCom", "unused"],
+var args = [["good", "default-ee", "unused"],
+             ["expiredresponse", "default-ee", "unused"],
+             ["oldvalidperiod", "default-ee", "unused"],
+             ["revoked", "default-ee", "unused"],
+             ["unknown", "default-ee", "unused"],
             ];
 var ocspResponses = generateOCSPResponses(args, "tlsserver");
 // Fresh response, certificate is good.
 var ocspResponseGood = ocspResponses[0];
 // Expired response, certificate is good.
 var expiredOCSPResponseGood = ocspResponses[1];
 // Fresh signature, old validity period, certificate is good.
 var oldValidityPeriodOCSPResponseGood = ocspResponses[2];
@@ -48,19 +48,19 @@ var oldValidityPeriodOCSPResponseGood = 
 var ocspResponseRevoked = ocspResponses[3];
 // Fresh signature, certificate is unknown.
 var ocspResponseUnknown = ocspResponses[4];
 
 // sometimes we expect a result without re-fetch
 var willNotRetry = 1;
 // but sometimes, since a bad response is in the cache, OCSP fetch will be
 // attempted for each validation - in practice, for these test certs, this
-// means 4 requests because various hash algorithm combinations are tried
-// (for sha-1 telemetry)
-var willRetry = 4;
+// means 8 requests because various hash algorithm and key size combinations
+// are tried.
+var willRetry = 8;
 
 function run_test() {
   let ocspResponder = new HttpServer();
   ocspResponder.registerPrefixHandler("/", function(request, response) {
     if (gCurrentOCSPResponse) {
       response.setStatusLine(request.httpVersion, 200, "OK");
       response.setHeader("Content-Type", "application/ocsp-response");
       response.write(gCurrentOCSPResponse);
--- a/security/manager/ssl/tests/unit/test_pinning.js
+++ b/security/manager/ssl/tests/unit/test_pinning.js
@@ -244,17 +244,17 @@ function check_pinning_telemetry() {
         "Actual and expected per host (Mozilla) success count should match");
   run_next_test();
 }
 
 function run_test() {
   add_tls_server_setup("BadCertServer");
 
   // Add a user-specified trust anchor.
-  addCertFromFile(certdb, "tlsserver/other-test-ca.der", "CTu,u,u");
+  addCertFromFile(certdb, "tlsserver/other-test-ca.pem", "CTu,u,u");
 
   test_strict();
   test_mitm();
   test_disabled();
   test_enforce_test_mode();
 
   add_test(function () {
     check_pinning_telemetry();
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/badSubjectAltNames.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test CA
+subject:EE with bad subjectAltNames
+extension:subjectAlternativeName:*.*.example.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/beforeEpoch.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Before UNIX Epoch Test End-entity
+validity:19460214-20310101
+extension:subjectAlternativeName:before-epoch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/beforeEpochINT.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Before UNIX Epoch Test Intermediate
+validity:19460214-20310101
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/beforeEpochIssuer.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Before UNIX Epoch Test Intermediate
+subject:Test End-entity with Before UNIX Epoch issuer
+extension:subjectAlternativeName:before-epoch-issuer.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/ca-used-as-end-entity.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Test Intermediate used as End-Entity
+extension:basicConstraints:cA,
+extension:authorityInformationAccess:http://localhost:8888/
+extension:subjectAlternativeName:ca-used-as-end-entity.example.com
deleted file mode 100644
index ecc9900149d2b8e3277e64d3ac05c851c41c1a00..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/BadCertServer.cpp
@@ -22,74 +22,98 @@ struct BadCertHost
 {
   const char *mHostName;
   const char *mCertName;
 };
 
 // Hostname, cert nickname pairs.
 const BadCertHost sBadCertHosts[] =
 {
-  { "expired.example.com", "expired" },
+  { "expired.example.com", "expired-ee" },
   { "notyetvalid.example.com", "notYetValid" },
   { "before-epoch.example.com", "beforeEpoch" },
   { "selfsigned.example.com", "selfsigned" },
   { "unknownissuer.example.com", "unknownissuer" },
   { "mismatch.example.com", "mismatch" },
   { "mismatch-CN.example.com", "mismatchCN" },
   { "expiredissuer.example.com", "expiredissuer" },
   { "notyetvalidissuer.example.com", "notYetValidIssuer" },
   { "before-epoch-issuer.example.com", "beforeEpochIssuer" },
   { "md5signature.example.com", "md5signature" },
-  { "untrusted.example.com", "localhostAndExampleCom" },
+  { "untrusted.example.com", "default-ee" },
   { "untrustedissuer.example.com", "untrustedissuer" },
   { "mismatch-expired.example.com", "mismatch-expired" },
   { "mismatch-notYetValid.example.com", "mismatch-notYetValid" },
   { "mismatch-untrusted.example.com", "mismatch-untrusted" },
   { "untrusted-expired.example.com", "untrusted-expired" },
   { "md5signature-expired.example.com", "md5signature-expired" },
   { "mismatch-untrusted-expired.example.com", "mismatch-untrusted-expired" },
-  { "inadequatekeyusage.example.com", "inadequatekeyusage" },
+  { "inadequatekeyusage.example.com", "inadequatekeyusage-ee" },
   { "selfsigned-inadequateEKU.example.com", "selfsigned-inadequateEKU" },
   { "self-signed-end-entity-with-cA-true.example.com", "self-signed-EE-with-cA-true" },
   { "ca-used-as-end-entity.example.com", "ca-used-as-end-entity" },
   { "ca-used-as-end-entity-name-mismatch.example.com", "ca-used-as-end-entity" },
   // All of include-subdomains.pinning.example.com is pinned to End Entity
-  // Test Cert with nick localhostAndExampleCom. Any other nick will only
+  // Test Cert with nick default-ee. Any other nick will only
   // pass pinning when security.cert_pinning.enforcement.level != strict and
   // otherCA is added as a user-specified trust anchor. See StaticHPKPins.h.
-  { "include-subdomains.pinning.example.com", "localhostAndExampleCom" },
-  { "good.include-subdomains.pinning.example.com", "localhostAndExampleCom" },
-  { "bad.include-subdomains.pinning.example.com", "otherIssuerEE" },
-  { "bad.include-subdomains.pinning.example.com.", "otherIssuerEE" },
-  { "bad.include-subdomains.pinning.example.com..", "otherIssuerEE" },
-  { "exclude-subdomains.pinning.example.com", "localhostAndExampleCom" },
-  { "sub.exclude-subdomains.pinning.example.com", "otherIssuerEE" },
-  { "test-mode.pinning.example.com", "otherIssuerEE" },
+  { "include-subdomains.pinning.example.com", "default-ee" },
+  { "good.include-subdomains.pinning.example.com", "default-ee" },
+  { "bad.include-subdomains.pinning.example.com", "other-issuer-ee" },
+  { "bad.include-subdomains.pinning.example.com.", "other-issuer-ee" },
+  { "bad.include-subdomains.pinning.example.com..", "other-issuer-ee" },
+  { "exclude-subdomains.pinning.example.com", "default-ee" },
+  { "sub.exclude-subdomains.pinning.example.com", "other-issuer-ee" },
+  { "test-mode.pinning.example.com", "other-issuer-ee" },
   { "unknownissuer.include-subdomains.pinning.example.com", "unknownissuer" },
   { "unknownissuer.test-mode.pinning.example.com", "unknownissuer" },
   { "nsCertTypeNotCritical.example.com", "nsCertTypeNotCritical" },
   { "nsCertTypeCriticalWithExtKeyUsage.example.com", "nsCertTypeCriticalWithExtKeyUsage" },
   { "nsCertTypeCritical.example.com", "nsCertTypeCritical" },
   { "end-entity-issued-by-v1-cert.example.com", "eeIssuedByV1Cert" },
   { "end-entity-issued-by-non-CA.example.com", "eeIssuedByNonCA" },
   { "inadequate-key-size-ee.example.com", "inadequateKeySizeEE" },
   { "badSubjectAltNames.example.com", "badSubjectAltNames" },
   { "ipAddressAsDNSNameInSAN.example.com", "ipAddressAsDNSNameInSAN" },
   { "noValidNames.example.com", "noValidNames" },
   { nullptr, nullptr }
 };
 
 int32_t
-DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
-                  uint32_t aSrvNameArrSize, void *aArg)
+DoSNISocketConfigBySubjectCN(PRFileDesc* aFd, const SECItem* aSrvNameArr,
+                             uint32_t aSrvNameArrSize)
 {
-  const BadCertHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
+  for (uint32_t i = 0; i < aSrvNameArrSize; i++) {
+    ScopedPORTString name((char*)PORT_ZAlloc(aSrvNameArr[i].len + 1));
+    if (name) {
+      PORT_Memcpy(name, aSrvNameArr[i].data, aSrvNameArr[i].len);
+      if (SECSuccess == ConfigSecureServerWithNamedCert(aFd, name,
+                                                        nullptr, nullptr)) {
+        return 0;
+      }
+    }
+  }
+
+  return SSL_SNI_SEND_ALERT;
+}
+
+int32_t
+DoSNISocketConfig(PRFileDesc* aFd, const SECItem* aSrvNameArr,
+                  uint32_t aSrvNameArrSize, void* aArg)
+{
+  const BadCertHost* host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
                                           sBadCertHosts);
   if (!host) {
-    return SSL_SNI_SEND_ALERT;
+    // No static cert <-> hostname mapping found. This happens when we use a
+    // collection of certificates in a given directory and build a cert DB at
+    // runtime, rather than using an NSS cert DB populated at build time.
+    // (This will be the default in the future.)
+    // For all given server names, check if the runtime-built cert DB contains
+    // a certificate with a matching subject CN.
+    return DoSNISocketConfigBySubjectCN(aFd, aSrvNameArr, aSrvNameArrSize);
   }
 
   if (gDebugLevel >= DEBUG_VERBOSE) {
     fprintf(stderr, "found pre-defined host '%s'\n", host->mHostName);
   }
 
   ScopedCERTCertificate cert;
   SSLKEAType certKEA;
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/GenerateOCSPResponse.cpp
@@ -105,229 +105,16 @@ WriteResponse(const char* filename, cons
   if (rv < 0 || (uint32_t) rv != item->len) {
     PrintPRError("File write failure");
     return false;
   }
 
   return true;
 }
 
-template <size_t N>
-SECStatus
-ReadFileToBuffer(const char* basePath, const char* filename, char (&buf)[N])
-{
-  static_assert(N > 0, "input buffer too small for ReadFileToBuffer");
-  if (PR_snprintf(buf, N - 1, "%s/%s", basePath, filename) == 0) {
-    PrintPRError("PR_snprintf failed");
-    return SECFailure;
-  }
-  ScopedPRFileDesc fd(PR_OpenFile(buf, PR_RDONLY, 0));
-  if (!fd) {
-    PrintPRError("PR_Open failed");
-    return SECFailure;
-  }
-  int32_t fileSize = PR_Available(fd);
-  if (fileSize < 0) {
-    PrintPRError("PR_Available failed");
-    return SECFailure;
-  }
-  if (static_cast<size_t>(fileSize) > N - 1) {
-    PR_fprintf(PR_STDERR, "file too large - not reading\n");
-    return SECFailure;
-  }
-  int32_t bytesRead = PR_Read(fd, buf, fileSize);
-  if (bytesRead != fileSize) {
-    PrintPRError("PR_Read failed");
-    return SECFailure;
-  }
-  buf[bytesRead] = 0;
-  return SECSuccess;
-}
-
-namespace mozilla {
-
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRDir, PRDir, PR_CloseDir);
-MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPORTString, unsigned char, PORT_Free);
-
-};
-
-void
-AddKeyFromFile(const char* basePath, const char* filename)
-{
-  const char* PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
-  const char* PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----";
-
-  char buf[16384] = { 0 };
-  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
-  if (rv != SECSuccess) {
-    return;
-  }
-  if (strncmp(buf, PRIVATE_KEY_HEADER, strlen(PRIVATE_KEY_HEADER)) != 0) {
-    PR_fprintf(PR_STDERR, "invalid key - not importing\n");
-    return;
-  }
-  const char* bufPtr = buf + strlen(PRIVATE_KEY_HEADER);
-  size_t bufLen = strlen(buf);
-  char base64[16384] = { 0 };
-  char* base64Ptr = base64;
-  while (bufPtr < buf + bufLen) {
-    if (strncmp(bufPtr, PRIVATE_KEY_FOOTER, strlen(PRIVATE_KEY_FOOTER)) == 0) {
-      break;
-    }
-    if (*bufPtr != '\r' && *bufPtr != '\n') {
-      *base64Ptr = *bufPtr;
-      base64Ptr++;
-    }
-    bufPtr++;
-  }
-
-  unsigned int binLength;
-  ScopedPORTString bin(ATOB_AsciiToData(base64, &binLength));
-  if (!bin || binLength == 0) {
-    PrintPRError("ATOB_AsciiToData failed");
-    return;
-  }
-  ScopedSECItem secitem(SECITEM_AllocItem(nullptr, nullptr, binLength));
-  if (!secitem) {
-    PrintPRError("SECITEM_AllocItem failed");
-    return;
-  }
-  memcpy(secitem->data, bin, binLength);
-  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
-  if (!slot) {
-    PrintPRError("PK11_GetInternalKeySlot failed");
-    return;
-  }
-  if (PK11_NeedUserInit(slot)) {
-    if (PK11_InitPin(slot, nullptr, nullptr) != SECSuccess) {
-      PrintPRError("PK11_InitPin failed");
-      return;
-    }
-  }
-  SECKEYPrivateKey* privateKey;
-  if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secitem, nullptr, nullptr,
-                                               true, false, KU_ALL,
-                                               &privateKey, nullptr)
-        != SECSuccess) {
-    PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed");
-    return;
-  }
-  SECKEY_DestroyPrivateKey(privateKey);
-}
-
-SECStatus
-DecodeCertCallback(void* arg, SECItem** certs, int numcerts)
-{
-  if (numcerts != 1) {
-    PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
-    return SECFailure;
-  }
-  SECItem* certDEROut = static_cast<SECItem*>(arg);
-  return SECITEM_CopyItem(nullptr, certDEROut, *certs);
-}
-
-void
-AddCertificateFromFile(const char* basePath, const char* filename)
-{
-  char buf[16384] = { 0 };
-  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
-  if (rv != SECSuccess) {
-    return;
-  }
-  SECItem certDER;
-  rv = CERT_DecodeCertPackage(buf, strlen(buf), DecodeCertCallback, &certDER);
-  if (rv != SECSuccess) {
-    PrintPRError("CERT_DecodeCertPackage failed");
-    return;
-  }
-  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
-                                                     &certDER, nullptr, false,
-                                                     true));
-  PORT_Free(certDER.data);
-  if (!cert) {
-    PrintPRError("CERT_NewTempCertificate failed");
-    return;
-  }
-  const char* extension = strstr(filename, ".pem");
-  if (!extension) {
-    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
-    return;
-  }
-  size_t nicknameLength = extension - filename;
-  memset(buf, 0, sizeof(buf));
-  memcpy(buf, filename, nicknameLength);
-  buf[nicknameLength] = 0;
-  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
-  if (!slot) {
-    PrintPRError("PK11_GetInternalKeySlot failed");
-    return;
-  }
-  rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, buf, false);
-  if (rv != SECSuccess) {
-    PrintPRError("PK11_ImportCert failed");
-  }
-}
-
-SECStatus
-InitializeNSS(const char* nssCertDBDir)
-{
-  // First attempt to initialize NSS in read-only mode, in case the specified
-  // directory contains NSS DBs that are tracked by revision control.
-  // If this succeeds, we're done.
-  if (NSS_Initialize(nssCertDBDir, "", "", SECMOD_DB, NSS_INIT_READONLY)
-        == SECSuccess) {
-    return SECSuccess;
-  }
-  // Otherwise, create a new read-write DB and load all .pem and .key files.
-  if (NSS_Initialize(nssCertDBDir, "", "", SECMOD_DB, 0) != SECSuccess) {
-    PrintPRError("NSS_Initialize failed");
-    return SECFailure;
-  }
-  const char* basePath = nssCertDBDir;
-  // The NSS cert DB path could have been specified as "sql:path". Trim off
-  // the leading "sql:" if so.
-  if (strncmp(basePath, "sql:", 4) == 0) {
-    basePath = basePath + 4;
-  }
-  ScopedPRDir fdDir(PR_OpenDir(basePath));
-  if (!fdDir) {
-    PrintPRError("PR_OpenDir failed");
-    return SECFailure;
-  }
-  // On the B2G ICS emulator, operations taken in AddCertificateFromFile or
-  // AddKeyFromFile appear to interact poorly with readdir (more specifically,
-  // something is causing readdir to never return null - it indefinitely loops
-  // through every file in the directory, which causes timeouts). Rather than
-  // waste more time chasing this down, loading certificates and keys happens in
-  // two phases: filename collection and then loading. (This is probably a good
-  // idea anyway because readdir isn't reentrant. Something could change later
-  // such that it gets called as a result of calling AddCertificateFromFile or
-  // AddKeyFromFile.)
-  std::vector<std::string> certificates;
-  std::vector<std::string> keys;
-  for (PRDirEntry* dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH); dirEntry;
-       dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH)) {
-    size_t nameLength = strlen(dirEntry->name);
-    if (nameLength > 4) {
-      if (strncmp(dirEntry->name + nameLength - 4, ".pem", 4) == 0) {
-        certificates.push_back(dirEntry->name);
-      } else if (strncmp(dirEntry->name + nameLength - 4, ".key", 4) == 0) {
-        keys.push_back(dirEntry->name);
-      }
-    }
-  }
-  for (std::string& certificate : certificates) {
-    AddCertificateFromFile(basePath, certificate.c_str());
-  }
-  for (std::string& key : keys) {
-    AddKeyFromFile(basePath, key.c_str());
-  }
-  return SECSuccess;
-}
-
 int
 main(int argc, char* argv[])
 {
 
   if (argc < 6 || (argc - 6) % 4 != 0) {
     PR_fprintf(PR_STDERR, "usage: %s <NSS DB directory> <responsetype> "
                           "<cert_nick> <extranick> <outfilename> [<resptype> "
                           "<cert_nick> <extranick> <outfilename>]* \n",
--- a/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/cmd/OCSPStaplingServer.cpp
@@ -22,17 +22,17 @@ using namespace mozilla::test;
 const OCSPHost sOCSPHosts[] =
 {
   { "ocsp-stapling-good.example.com", ORTGood, nullptr },
   { "ocsp-stapling-revoked.example.com", ORTRevoked, nullptr },
   { "ocsp-stapling-revoked-old.example.com", ORTRevokedOld, nullptr },
   { "ocsp-stapling-unknown.example.com", ORTUnknown, nullptr },
   { "ocsp-stapling-unknown-old.example.com", ORTUnknownOld, nullptr },
   { "ocsp-stapling-good-other.example.com", ORTGoodOtherCert, "ocspOtherEndEntity" },
-  { "ocsp-stapling-good-other-ca.example.com", ORTGoodOtherCA, "otherCA" },
+  { "ocsp-stapling-good-other-ca.example.com", ORTGoodOtherCA, "other-test-ca" },
   { "ocsp-stapling-expired.example.com", ORTExpired, nullptr },
   { "ocsp-stapling-expired-fresh-ca.example.com", ORTExpiredFreshCA, nullptr },
   { "ocsp-stapling-none.example.com", ORTNone, nullptr },
   { "ocsp-stapling-empty.example.com", ORTEmpty, nullptr },
   { "ocsp-stapling-malformed.example.com", ORTMalformed, nullptr },
   { "ocsp-stapling-srverr.example.com", ORTSrverr, nullptr },
   { "ocsp-stapling-trylater.example.com", ORTTryLater, nullptr },
   { "ocsp-stapling-needssig.example.com", ORTNeedsSig, nullptr },
@@ -47,17 +47,17 @@ const OCSPHost sOCSPHosts[] =
   { "ocsp-stapling-delegated-included-last.example.com", ORTDelegatedIncludedLast, "delegatedSigner" },
   { "ocsp-stapling-delegated-missing.example.com", ORTDelegatedMissing, "delegatedSigner" },
   { "ocsp-stapling-delegated-missing-multiple.example.com", ORTDelegatedMissingMultiple, "delegatedSigner" },
   { "ocsp-stapling-delegated-no-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerNoExtKeyUsage" },
   { "ocsp-stapling-delegated-from-intermediate.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerFromIntermediate" },
   { "ocsp-stapling-delegated-keyUsage-crlSigning.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerKeyUsageCrlSigning" },
   { "ocsp-stapling-delegated-wrong-extKeyUsage.example.com", ORTDelegatedIncluded, "invalidDelegatedSignerWrongExtKeyUsage" },
   { "ocsp-stapling-ancient-valid.example.com", ORTAncientAlmostExpired, nullptr},
-  { "keysize-ocsp-delegated.example.com", ORTDelegatedIncluded, "rsa-1008-keysizeDelegatedSigner" },
+  { "keysize-ocsp-delegated.example.com", ORTDelegatedIncluded, "rsa-1016-keysizeDelegatedSigner" },
   { "revoked-ca-cert-used-as-end-entity.example.com", ORTRevoked, "ca-used-as-end-entity" },
   { nullptr, ORTNull, nullptr }
 };
 
 int32_t
 DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
                   uint32_t aSrvNameArrSize, void *aArg)
 {
index 7f89b7e37c393fcfaad3d327f859be9ea460c135..3a9b8fa9bc0418d36bc7ea8c66727483a02c25d3
GIT binary patch
literal 190
zc$_WF%MHRn420o(s+bC*gjWxop@AhkAuEC%t!<!uARx_U4*z$ais3WSCz2o}j2UB@
z+2ZKntC$;H!DNI_#GqPpk>o`M7y6SFTshpd$$W6u<xX*UCGA7zHA>-n|0PAnn#^kq
o9`#EmM-4G7tVMGf5KB%@Ynu~^OI*=!y6v{#tlIzYcio|F-sjgsvj6}9
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/default-ee.key.keyspec
@@ -0,0 +1,1 @@
+default
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/default-ee.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Test End-entity
+extension:subjectAlternativeName:localhost,*.example.com,*.pinning.example.com,*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/delegatedSHA1Signer.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Test SHA1 Delegated Responder
+subjectKey:alternate
+signature:sha1WithRSAEncryption
+extension:extKeyUsage:OCSPSigning
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/delegatedSigner.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Test Delegated Responder
+subjectKey:alternate
+extension:extKeyUsage:OCSPSigning
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/eeIssuedByNonCA.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test End-entity
+subject:EE Issued by non-CA
+extension:subjectAlternativeName:localhost,*.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/eeIssuedByV1Cert.pem.certspec
@@ -0,0 +1,3 @@
+issuer:V1 Cert
+subject:EE Issued by V1 Cert
+extension:subjectAlternativeName:localhost,*.example.com
deleted file mode 100644
index fd9e7e9e940b712ac7337700a8ce57a600e05625..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/expired-ee.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Expired Test End-entity
+validity:20130101-20140101
+extension:subjectAlternativeName:expired.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/expiredINT.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Expired Test Intermediate
+validity:20110101-20130101
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/expiredissuer.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Expired Test Intermediate
+subject:Test End-entity with expired issuer
+extension:subjectAlternativeName:expiredissuer.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100755
--- a/security/manager/ssl/tests/unit/tlsserver/generate_certs.sh
+++ /dev/null
@@ -1,354 +0,0 @@
-#!/bin/bash
-#
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-#
-# Usage: ./generate_certs.sh <path to objdir> <output directory> [--clobber]
-# e.g. (from the root of mozilla-central)
-# `./security/manager/ssl/tests/unit/tlsserver/generate_certs.sh \
-#  obj-x86_64-unknown-linux-gnu/ \
-#  security/manager/ssl/tests/unit/tlsserver/`
-#
-# The --clobber switch is optional. If specified, the existing database of
-# keys and certificates is removed and repopulated. By default, existing
-# databases are preserved and only keys and certificates that don't already
-# exist in the database are added.
-# NB: If --clobber is specified, the following files to be overwritten if they
-# are in the output directory:
-#  cert9.db, key4.db, pkcs11.txt, test-ca.der, other-test-ca.der, default-ee.der
-# (if --clobber is not specified, then only cert9.db and key4.db are modified)
-# NB: If --clobber is specified, you must run genHPKPStaticPins.js after
-# running this file, since its output (StaticHPKPins.h) depends on
-# default-ee.der
-
-set -x
-set -e
-
-if [ $# -lt 2 ]; then
-  echo "Usage: `basename ${0}` <path to objdir> <output directory> [--clobber]"
-  exit $E_BADARGS
-fi
-
-OBJDIR=${1}
-OUTPUT_DIR=${2}
-CLOBBER=0
-if [ "${3}" == "--clobber" ]; then
-  CLOBBER=1
-fi
-# Use the SQL DB so we can run tests on Android.
-DB_ARGUMENT="sql:$OUTPUT_DIR"
-RUN_MOZILLA="$OBJDIR/dist/bin/run-mozilla.sh"
-CERTUTIL="$OBJDIR/dist/bin/certutil"
-# On BSD, mktemp requires either a template or a prefix.
-MKTEMP="mktemp temp.XXXX"
-
-NOISE_FILE=`$MKTEMP`
-# Make a good effort at putting something unique in the noise file.
-date +%s%N  > "$NOISE_FILE"
-PASSWORD_FILE=`$MKTEMP`
-
-function cleanup {
-  rm -f "$NOISE_FILE" "$PASSWORD_FILE"
-}
-
-if [ ! -f "$RUN_MOZILLA" ]; then
-  echo "Could not find run-mozilla.sh at \'$RUN_MOZILLA\' - I'll try without it"
-  RUN_MOZILLA=""
-fi
-
-if [ ! -f "$CERTUTIL" ]; then
-  echo "Could not find certutil at \'$CERTUTIL\'"
-  exit $E_BADARGS
-fi
-
-if [ ! -d "$OUTPUT_DIR" ]; then
-  echo "Could not find output directory at \'$OUTPUT_DIR\'"
-  exit $E_BADARGS
-fi
-
-if [ -f "$OUTPUT_DIR/cert9.db" -o -f "$OUTPUT_DIR/key4.db" -o -f "$OUTPUT_DIR/pkcs11.txt" ]; then
-  if [ $CLOBBER -eq 1 ]; then
-    echo "Found pre-existing NSS DBs. Clobbering old certificates."
-    rm -f "$OUTPUT_DIR/cert9.db" "$OUTPUT_DIR/key4.db" "$OUTPUT_DIR/pkcs11.txt"
-    $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -N -f $PASSWORD_FILE
-  else
-    echo "Found pre-existing NSS DBs. Only generating newly added certificates."
-    echo "(re-run with --clobber to remove and regenerate old certificates)"
-  fi
-else
-  echo "No pre-existing NSS DBs found. Creating new ones."
-  $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -N -f $PASSWORD_FILE
-fi
-
-COMMON_ARGS="-v 360 -w -1 -2 -z $NOISE_FILE"
-
-function export_cert {
-  NICKNAME="${1}"
-  DERFILE="${2}"
-
-  $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -L -n $NICKNAME -r > $OUTPUT_DIR/$DERFILE
-}
-
-# Bash doesn't actually allow return values in a sane way, so just use a
-# global variable.
-function cert_already_exists {
-  NICKNAME="${1}"
-  ALREADY_EXISTS=1
-  $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -L -n $NICKNAME || ALREADY_EXISTS=0
-}
-
-function make_CA {
-  CA_RESPONSES="y\n1\ny"
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  DERFILE="${3}"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  echo -e "$CA_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                                                   -n $NICKNAME \
-                                                   -s "$SUBJECT" \
-                                                   -t "CT,," \
-                                                   -x $COMMON_ARGS
-  export_cert $NICKNAME $DERFILE
-}
-
-SERIALNO=$RANDOM
-
-function make_INT {
-  INT_RESPONSES="y\n0\ny\n2\n7\nhttp://localhost:8888/\n\nn\nn\n"
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  CA="${3}"
-  EXTRA_ARGS="${4}"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  echo -e "$INT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                                                    -n $NICKNAME \
-                                                    -s "$SUBJECT" \
-                                                    -c $CA \
-                                                    -t ",," \
-                                                    -m $SERIALNO \
-                                                    --extAIA \
-                                                    $COMMON_ARGS \
-                                                    $EXTRA_ARGS
-  SERIALNO=$(($SERIALNO + 1))
-}
-
-# This creates an X.509 version 1 certificate (note --certVersion 1 and a lack
-# of extensions).
-function make_V1 {
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  CA="${3}"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                         -n $NICKNAME \
-                         -s "$SUBJECT" \
-                         -c $CA \
-                         -t ",," \
-                         -m $SERIALNO \
-                         --certVersion 1 \
-                         -v 360 -w -1 -z $NOISE_FILE
-
-  SERIALNO=$(($SERIALNO + 1))
-}
-
-function make_EE {
-  CERT_RESPONSES="n\n\ny\n2\n7\nhttp://localhost:8888/\n\nn\nn\n"
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  CA="${3}"
-  SUBJECT_ALT_NAME="${4}"
-  EXTRA_ARGS="${5} ${6}"
-
-  [ -z "$SUBJECT_ALT_NAME" ] && SUBJECT_ALT_NAME_PART="" || SUBJECT_ALT_NAME_PART="-8 $SUBJECT_ALT_NAME"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                                                     -n $NICKNAME \
-                                                     -s "$SUBJECT" \
-                                                     $SUBJECT_ALT_NAME_PART \
-                                                     -c $CA \
-                                                     -t ",," \
-                                                     -m $SERIALNO \
-                                                     --extAIA \
-                                                     $COMMON_ARGS \
-                                                     $EXTRA_ARGS
-  SERIALNO=$(($SERIALNO + 1))
-}
-
-function make_EE_with_nsCertType {
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  CA="${3}"
-  SUBJECT_ALT_NAME="${4}"
-  NS_CERT_TYPE_CRITICAL="${5}"
-  EXTRA_ARGS="${6}"
-  # This adds the Netscape certificate type extension with the "sslServer"
-  # bit asserted. Its criticality depends on if "y" or "n" was passed as
-  # an argument to this function.
-  CERT_RESPONSES="n\n\ny\n1\n8\n$NS_CERT_TYPE_CRITICAL\n"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                                                     -n $NICKNAME \
-                                                     -s "$SUBJECT" \
-                                                     -8 $SUBJECT_ALT_NAME \
-                                                     -c $CA \
-                                                     -t ",," \
-                                                     -m $SERIALNO \
-                                                     -5 \
-                                                     $COMMON_ARGS \
-                                                     $EXTRA_ARGS
-  SERIALNO=$(($SERIALNO + 1))
-}
-
-function make_delegated {
-  CERT_RESPONSES="n\n\ny\n"
-  NICKNAME="${1}"
-  SUBJECT="${2}"
-  CA="${3}"
-  EXTRA_ARGS="${4}"
-
-  cert_already_exists $NICKNAME
-  if [ $ALREADY_EXISTS -eq 1 ]; then
-    echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
-    return
-  fi
-
-  echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
-                                                     -n $NICKNAME \
-                                                     -s "$SUBJECT" \
-                                                     -c $CA \
-                                                     -t ",," \
-                                                     -m $SERIALNO \
-                                                     $COMMON_ARGS \
-                                                     $EXTRA_ARGS
-  SERIALNO=$(($SERIALNO + 1))
-}
-
-make_CA testCA 'CN=Test CA' test-ca.der
-make_CA otherCA 'CN=Other test CA' other-test-ca.der
-
-make_EE localhostAndExampleCom 'CN=Test End-entity' testCA "localhost,*.example.com,*.pinning.example.com,*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com"
-# Make another EE cert using testCA for subject / pubkey revocation
-make_EE sameIssuerEE 'CN=Another Test End-entity' testCA "localhost,*.example.com"
-# Make an EE cert issued by otherCA
-make_EE otherIssuerEE 'CN=Wrong CA Pin Test End-Entity' otherCA "*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com,*.pinning.example.com"
-
-export_cert localhostAndExampleCom default-ee.der
-export_cert sameIssuerEE same-issuer-ee.der
-export_cert otherIssuerEE other-issuer-ee.der
-
-# A cert that is like localhostAndExampleCom, but with a different serial number for
-# testing the "OCSP response is from the right issuer, but it is for the wrong cert"
-# case.
-make_EE ocspOtherEndEntity 'CN=Other Cert' testCA "localhost,*.example.com"
-
-make_INT testINT 'CN=Test Intermediate' testCA
-export_cert testINT test-int.der
-make_EE ocspEEWithIntermediate 'CN=Test End-entity with Intermediate' testINT "localhost,*.example.com"
-make_EE expired 'CN=Expired Test End-entity' testCA "expired.example.com" "-w -400"
-export_cert expired expired-ee.der
-make_EE notYetValid 'CN=Not Yet Valid Test End-entity' testCA "notyetvalid.example.com" "-w 400"
-make_EE mismatch 'CN=Mismatch Test End-entity' testCA "doesntmatch.example.com,*.alsodoesntmatch.example.com"
-make_EE mismatchCN 'CN=doesntmatch.example.com' testCA
-make_EE ipAddressAsDNSNameInSAN 'CN=127.0.0.1' testCA "127.0.0.1"
-make_EE noValidNames 'CN=End-entity with no valid names' testCA
-make_EE selfsigned 'CN=Self-signed Test End-entity' testCA "selfsigned.example.com" "-x"
-# If the certificate 'CN=Test Intermediate' isn't loaded into memory,
-# this certificate will have an unknown issuer.
-# deletedINT is never kept in the database, so it always gets regenerated.
-# That's ok, because if unknownissuer was already in the database, it won't
-# get regenerated. Either way, deletedINT will then be removed again.
-make_INT deletedINT 'CN=Test Intermediate to delete' testCA
-make_EE unknownissuer 'CN=Test End-entity from unknown issuer' deletedINT "unknownissuer.example.com,unknownissuer.include-subdomains.pinning.example.com,unknownissuer.test-mode.pinning.example.com"
-export_cert unknownissuer unknown-issuer.der
-
-$RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -D -n deletedINT
-
-# certutil doesn't expose a way to directly specify a notBefore time.
-# Workaround this by just providing a large enough warp that the notBefore time
-# falls before the UNIX Epoch.
-make_EE beforeEpoch 'CN=Before UNIX Epoch Test End-entity' testCA "before-epoch.example.com" "-w -720 -v 960"
-make_INT beforeEpochINT 'CN=Before UNIX Epoch Test Intermediate' testCA "-w -720 -v 960"
-make_EE beforeEpochIssuer 'CN=Test End-entity with Before UNIX Epoch issuer' beforeEpochINT "before-epoch-issuer.example.com"
-
-make_INT expiredINT 'CN=Expired Test Intermediate' testCA "-w -400"
-make_EE expiredissuer 'CN=Test End-entity with expired issuer' expiredINT "expiredissuer.example.com"
-make_INT notYetValidINT 'CN=Not Yet Valid Test Intermediate' testCA "-w 400"
-make_EE notYetValidIssuer 'CN=Test End-entity with not yet valid issuer' notYetValidINT "notyetvalidissuer.example.com"
-NSS_ALLOW_WEAK_SIGNATURE_ALG=1 make_EE md5signature 'CN=Test End-entity with MD5 signature' testCA "md5signature.example.com" "-Z MD5"
-make_EE untrustedissuer 'CN=Test End-entity with untrusted issuer' otherCA "untrustedissuer.example.com"
-
-make_EE mismatch-expired 'CN=Mismatch-Expired Test End-entity' testCA "doesntmatch.example.com" "-w -400"
-make_EE mismatch-notYetValid 'CN=Mismatch-Not Yet Valid Test End-entity' testCA "doesntmatch.example.com" "-w 400"
-make_EE mismatch-untrusted 'CN=Mismatch-Untrusted Test End-entity' otherCA "doesntmatch.example.com"
-make_EE untrusted-expired 'CN=Untrusted-Expired Test End-entity' otherCA "untrusted-expired.example.com" "-w -400"
-make_EE mismatch-untrusted-expired 'CN=Mismatch-Untrusted-Expired Test End-entity' otherCA "doesntmatch.example.com" "-w -400"
-NSS_ALLOW_WEAK_SIGNATURE_ALG=1 make_EE md5signature-expired 'CN=Test MD5Signature-Expired End-entity' testCA "md5signature-expired.example.com" "-Z MD5" "-w -400"
-
-make_EE inadequatekeyusage 'CN=Inadequate Key Usage Test End-entity' testCA "inadequatekeyusage.example.com" "--keyUsage crlSigning"
-export_cert inadequatekeyusage inadequatekeyusage-ee.der
-make_EE selfsigned-inadequateEKU 'CN=Self-signed Inadequate EKU Test End-entity' unused "selfsigned-inadequateEKU.example.com" "--keyUsage keyEncipherment,dataEncipherment --extKeyUsage serverAuth" "-x"
-
-make_delegated delegatedSigner 'CN=Test Delegated Responder' testCA "--extKeyUsage ocspResponder"
-make_delegated delegatedSHA1Signer 'CN=Test SHA1 Delegated Responder' testCA "--extKeyUsage ocspResponder -Z SHA1"
-make_delegated invalidDelegatedSignerNoExtKeyUsage 'CN=Test Invalid Delegated Responder No extKeyUsage' testCA
-make_delegated invalidDelegatedSignerFromIntermediate 'CN=Test Invalid Delegated Responder From Intermediate' testINT "--extKeyUsage ocspResponder"
-make_delegated invalidDelegatedSignerKeyUsageCrlSigning 'CN=Test Invalid Delegated Responder keyUsage crlSigning' testCA "--keyUsage crlSigning"
-make_delegated invalidDelegatedSignerWrongExtKeyUsage 'CN=Test Invalid Delegated Responder Wrong extKeyUsage' testCA "--extKeyUsage codeSigning"
-
-make_INT self-signed-EE-with-cA-true 'CN=Test Self-signed End-entity with CA true' unused "-x -8 self-signed-end-entity-with-cA-true.example.com"
-make_INT ca-used-as-end-entity 'CN=Test Intermediate used as End-Entity' testCA "-8 ca-used-as-end-entity.example.com"
-
-make_delegated rsa-1008-keysizeDelegatedSigner 'CN=RSA 1008 Key Size Test Delegated Responder' testCA "--extKeyUsage ocspResponder -g 1008"
-make_EE inadequateKeySizeEE 'CN=Inadequate Key Size End-Entity' testINT "inadequate-key-size-ee.example.com" "-g 1008"
-
-make_EE_with_nsCertType nsCertTypeCritical 'CN=nsCertType Critical' testCA "localhost,*.example.com" "y"
-make_EE_with_nsCertType nsCertTypeNotCritical 'CN=nsCertType Not Critical' testCA "localhost,*.example.com" "n"
-make_EE_with_nsCertType nsCertTypeCriticalWithExtKeyUsage 'CN=nsCertType Critical With extKeyUsage' testCA "localhost,*.example.com" "y" "--extKeyUsage serverAuth"
-
-# Make an X.509 version 1 certificate that will issue another certificate.
-# By default, this causes an error in verification that we allow overrides for.
-# However, if the v1 certificate is a trust anchor, then verification succeeds.
-make_V1 v1Cert 'CN=V1 Cert' testCA
-export_cert v1Cert v1Cert.der
-make_EE eeIssuedByV1Cert 'CN=EE Issued by V1 Cert' v1Cert "localhost,*.example.com"
-
-make_EE eeIssuedByNonCA 'CN=EE Issued by non-CA' localhostAndExampleCom "localhost,*.example.com"
-
-# Make a valid EE using testINT to test OneCRL revocation of testINT
-make_EE eeIssuedByIntermediate 'CN=EE issued by intermediate' testINT "localhost"
-export_cert eeIssuedByIntermediate test-int-ee.der
-
-make_EE badSubjectAltNames 'CN=EE with bad subjectAltNames' testCA "*.*.example.com"
-
-cleanup
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/inadequateKeySizeEE.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test Intermediate
+subject:Inadequate Key Size End-Entity
+subjectKey:rsa1016
+extension:subjectAlternativeName:inadequate-key-size-ee.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100644
index 4daa9a5eaa1e2575ed47c5dd86a4754a3ab01214..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/inadequatekeyusage-ee.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Inadequate Key Usage Test End-entity
+extension:keyUsage:cRLSign
+extension:subjectAlternativeName:inadequatekeyusage.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerFromIntermediate.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test Intermediate
+subject:Test Invalid Delegated Responder From Intermediate
+subjectKey:alternate
+extension:extKeyUsage:OCSPSigning
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerKeyUsageCrlSigning.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Test Invalid Delegated Responder keyUsage crlSigning
+subjectKey:alternate
+extension:keyUsage:cRLSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerNoExtKeyUsage.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test CA
+subject:Test Invalid Delegated Responder No extKeyUsage
+subjectKey:alternate
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/invalidDelegatedSignerWrongExtKeyUsage.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Test Invalid Delegated Responder Wrong extKeyUsage
+subjectKey:alternate
+extension:extKeyUsage:codeSigning
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/ipAddressAsDNSNameInSAN.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test CA
+subject:127.0.0.1
+extension:subjectAlternativeName:127.0.0.1
deleted file mode 100644
index c3e06ff70995c36474b407bf0b6a5fe23b88071b..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.cpp
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.cpp
@@ -1,33 +1,37 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "TLSServer.h"
 
 #include <stdio.h>
+#include <string>
+#include <vector>
+
 #include "ScopedNSSTypes.h"
+#include "base64.h"
 #include "nspr.h"
 #include "nss.h"
 #include "plarenas.h"
 #include "prenv.h"
 #include "prerror.h"
 #include "prnetdb.h"
 #include "prtime.h"
 #include "ssl.h"
 
 namespace mozilla { namespace test {
 
 static const uint16_t LISTEN_PORT = 8443;
 
 DebugLevel gDebugLevel = DEBUG_ERRORS;
 uint16_t gCallbackPort = 0;
 
-const char DEFAULT_CERT_NICKNAME[] = "localhostAndExampleCom";
+const char DEFAULT_CERT_NICKNAME[] = "default-ee";
 
 struct Connection
 {
   PRFileDesc *mSocket;
   char mByte;
 
   explicit Connection(PRFileDesc *aSocket);
   ~Connection();
@@ -55,16 +59,232 @@ PrintPRError(const char *aPrefix)
     }
   } else {
     if (gDebugLevel >= DEBUG_ERRORS) {
       fprintf(stderr, "%s\n", aPrefix);
     }
   }
 }
 
+template <size_t N>
+SECStatus
+ReadFileToBuffer(const char* basePath, const char* filename, char (&buf)[N])
+{
+  static_assert(N > 0, "input buffer too small for ReadFileToBuffer");
+  if (PR_snprintf(buf, N - 1, "%s/%s", basePath, filename) == 0) {
+    PrintPRError("PR_snprintf failed");
+    return SECFailure;
+  }
+  ScopedPRFileDesc fd(PR_OpenFile(buf, PR_RDONLY, 0));
+  if (!fd) {
+    PrintPRError("PR_Open failed");
+    return SECFailure;
+  }
+  int32_t fileSize = PR_Available(fd);
+  if (fileSize < 0) {
+    PrintPRError("PR_Available failed");
+    return SECFailure;
+  }
+  if (static_cast<size_t>(fileSize) > N - 1) {
+    PR_fprintf(PR_STDERR, "file too large - not reading\n");
+    return SECFailure;
+  }
+  int32_t bytesRead = PR_Read(fd, buf, fileSize);
+  if (bytesRead != fileSize) {
+    PrintPRError("PR_Read failed");
+    return SECFailure;
+  }
+  buf[bytesRead] = 0;
+  return SECSuccess;
+}
+
+SECStatus
+AddKeyFromFile(const char* basePath, const char* filename)
+{
+  const char* PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
+  const char* PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----";
+
+  char buf[16384] = { 0 };
+  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
+  if (rv != SECSuccess) {
+    return rv;
+  }
+  if (strncmp(buf, PRIVATE_KEY_HEADER, strlen(PRIVATE_KEY_HEADER)) != 0) {
+    PR_fprintf(PR_STDERR, "invalid key - not importing\n");
+    return SECFailure;
+  }
+  const char* bufPtr = buf + strlen(PRIVATE_KEY_HEADER);
+  size_t bufLen = strlen(buf);
+  char base64[16384] = { 0 };
+  char* base64Ptr = base64;
+  while (bufPtr < buf + bufLen) {
+    if (strncmp(bufPtr, PRIVATE_KEY_FOOTER, strlen(PRIVATE_KEY_FOOTER)) == 0) {
+      break;
+    }
+    if (*bufPtr != '\r' && *bufPtr != '\n') {
+      *base64Ptr = *bufPtr;
+      base64Ptr++;
+    }
+    bufPtr++;
+  }
+
+  unsigned int binLength;
+  ScopedPORTString bin((char*)ATOB_AsciiToData(base64, &binLength));
+  if (!bin || binLength == 0) {
+    PrintPRError("ATOB_AsciiToData failed");
+    return SECFailure;
+  }
+  ScopedSECItem secitem(::SECITEM_AllocItem(nullptr, nullptr, binLength));
+  if (!secitem) {
+    PrintPRError("SECITEM_AllocItem failed");
+    return SECFailure;
+  }
+  PORT_Memcpy(secitem->data, bin, binLength);
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  if (!slot) {
+    PrintPRError("PK11_GetInternalKeySlot failed");
+    return SECFailure;
+  }
+  if (PK11_NeedUserInit(slot)) {
+    if (PK11_InitPin(slot, nullptr, nullptr) != SECSuccess) {
+      PrintPRError("PK11_InitPin failed");
+      return SECFailure;
+    }
+  }
+  SECKEYPrivateKey* privateKey;
+  if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secitem, nullptr, nullptr,
+                                               true, false, KU_ALL,
+                                               &privateKey, nullptr)
+        != SECSuccess) {
+    PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed");
+    return SECFailure;
+  }
+  SECKEY_DestroyPrivateKey(privateKey);
+  return SECSuccess;
+}
+
+SECStatus
+DecodeCertCallback(void* arg, SECItem** certs, int numcerts)
+{
+  if (numcerts != 1) {
+    PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
+    return SECFailure;
+  }
+
+  SECItem* certDEROut = static_cast<SECItem*>(arg);
+  return SECITEM_CopyItem(nullptr, certDEROut, *certs);
+}
+
+SECStatus
+AddCertificateFromFile(const char* basePath, const char* filename)
+{
+  char buf[16384] = { 0 };
+  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
+  if (rv != SECSuccess) {
+    return rv;
+  }
+  SECItem certDER;
+  rv = CERT_DecodeCertPackage(buf, strlen(buf), DecodeCertCallback, &certDER);
+  if (rv != SECSuccess) {
+    PrintPRError("CERT_DecodeCertPackage failed");
+    return rv;
+  }
+  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
+                                                     &certDER, nullptr, false,
+                                                     true));
+  PORT_Free(certDER.data);
+  if (!cert) {
+    PrintPRError("CERT_NewTempCertificate failed");
+    return SECFailure;
+  }
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  if (!slot) {
+    PrintPRError("PK11_GetInternalKeySlot failed");
+    return SECFailure;
+  }
+  // The nickname is the filename without '.pem'.
+  std::string nickname(filename, strlen(filename) - 4);
+  rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, nickname.c_str(), false);
+  if (rv != SECSuccess) {
+    PrintPRError("PK11_ImportCert failed");
+    return rv;
+  }
+  return SECSuccess;
+}
+
+SECStatus
+LoadCertificatesAndKeys(const char* basePath)
+{
+  // The NSS cert DB path could have been specified as "sql:path". Trim off
+  // the leading "sql:" if so.
+  if (strncmp(basePath, "sql:", 4) == 0) {
+    basePath = basePath + 4;
+  }
+
+  ScopedPRDir fdDir(PR_OpenDir(basePath));
+  if (!fdDir) {
+    PrintPRError("PR_OpenDir failed");
+    return SECFailure;
+  }
+  // On the B2G ICS emulator, operations taken in AddCertificateFromFile
+  // appear to interact poorly with readdir (more specifically, something is
+  // causing readdir to never return null - it indefinitely loops through every
+  // file in the directory, which causes timeouts). Rather than waste more time
+  // chasing this down, loading certificates and keys happens in two phases:
+  // filename collection and then loading. (This is probably a good
+  // idea anyway because readdir isn't reentrant. Something could change later
+  // such that it gets called as a result of calling AddCertificateFromFile or
+  // AddKeyFromFile.)
+  std::vector<std::string> certificates;
+  std::vector<std::string> keys;
+  for (PRDirEntry* dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH); dirEntry;
+       dirEntry = PR_ReadDir(fdDir, PR_SKIP_BOTH)) {
+    size_t nameLength = strlen(dirEntry->name);
+    if (nameLength > 4) {
+      if (strncmp(dirEntry->name + nameLength - 4, ".pem", 4) == 0) {
+        certificates.push_back(dirEntry->name);
+      } else if (strncmp(dirEntry->name + nameLength - 4, ".key", 4) == 0) {
+        keys.push_back(dirEntry->name);
+      }
+    }
+  }
+  SECStatus rv;
+  for (std::string& certificate : certificates) {
+    rv = AddCertificateFromFile(basePath, certificate.c_str());
+    if (rv != SECSuccess) {
+      return rv;
+    }
+  }
+  for (std::string& key : keys) {
+    rv = AddKeyFromFile(basePath, key.c_str());
+    if (rv != SECSuccess) {
+      return rv;
+    }
+  }
+  return SECSuccess;
+}
+
+SECStatus
+InitializeNSS(const char* nssCertDBDir)
+{
+  // Try initializing an existing DB.
+  if (NSS_Init(nssCertDBDir) == SECSuccess) {
+    return SECSuccess;
+  }
+
+  // Create a new DB if there is none...
+  SECStatus rv = NSS_Initialize(nssCertDBDir, nullptr, nullptr, nullptr, 0);
+  if (rv != SECSuccess) {
+    return rv;
+  }
+
+  // ...and load all certificates into it.
+  return LoadCertificatesAndKeys(nssCertDBDir);
+}
+
 nsresult
 SendAll(PRFileDesc *aSocket, const char *aData, size_t aDataLen)
 {
   if (gDebugLevel >= DEBUG_VERBOSE) {
     fprintf(stderr, "sending '%s'\n", aData);
   }
 
   while (aDataLen > 0) {
@@ -234,19 +454,20 @@ ConfigSecureServerWithNamedCert(PRFileDe
     if (SECITEM_CopyItem(certList->arena, certList->certs + 1,
                          &issuerCert->derCert) != SECSuccess) {
       PrintPRError("SECITEM_CopyItem failed");
       return SECFailure;
     }
     certList->len = 2;
   }
 
-  ScopedSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert, nullptr));
+  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
+  ScopedSECKEYPrivateKey key(PK11_FindKeyByDERCert(slot, cert, nullptr));
   if (!key) {
-    PrintPRError("PK11_FindKeyByAnyCert failed");
+    PrintPRError("PK11_FindKeyByDERCert failed");
     return SECFailure;
   }
 
   SSLKEAType certKEA = NSS_FindCertKEAType(cert);
 
   if (SSL_ConfigSecureServerWithCertChain(fd, cert, certList, key, certKEA)
         != SECSuccess) {
     PrintPRError("SSL_ConfigSecureServer failed");
@@ -281,18 +502,18 @@ StartServer(const char *nssCertDBDir, SS
     }
   }
 
   const char *callbackPort = PR_GetEnv("MOZ_TLS_SERVER_CALLBACK_PORT");
   if (callbackPort) {
     gCallbackPort = atoi(callbackPort);
   }
 
-  if (NSS_Init(nssCertDBDir) != SECSuccess) {
-    PrintPRError("NSS_Init failed");
+  if (InitializeNSS(nssCertDBDir) != SECSuccess) {
+    PR_fprintf(PR_STDERR, "InitializeNSS failed");
     return 1;
   }
 
   if (NSS_SetDomesticPolicy() != SECSuccess) {
     PrintPRError("NSS_SetDomesticPolicy failed");
     return 1;
   }
 
--- a/security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.h
+++ b/security/manager/ssl/tests/unit/tlsserver/lib/TLSServer.h
@@ -14,16 +14,23 @@
 // it will connect to a specified port and issue a simple HTTP request.
 
 #include <stdint.h>
 #include "prio.h"
 #include "ScopedNSSTypes.h"
 #include "secerr.h"
 #include "ssl.h"
 
+namespace mozilla {
+
+MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRDir, PRDir, PR_CloseDir);
+MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPORTString, char, PORT_Free);
+
+} // namespace mozilla
+
 namespace mozilla { namespace test {
 
 enum DebugLevel
 {
   DEBUG_ERRORS = 1,
   DEBUG_WARNINGS  = 2,
   DEBUG_VERBOSE = 3
 };
@@ -37,16 +44,19 @@ extern const char DEFAULT_CERT_NICKNAME[
 
 // Pass DEFAULT_CERT_NICKNAME as certName unless you need a specific
 // certificate.
 SECStatus
 ConfigSecureServerWithNamedCert(PRFileDesc *fd, const char *certName,
                                 /*optional*/ ScopedCERTCertificate *cert,
                                 /*optional*/ SSLKEAType *kea);
 
+SECStatus
+InitializeNSS(const char* nssCertDBDir);
+
 int
 StartServer(const char *nssCertDBDir, SSLSNISocketConfig sniSocketConfig,
             void *sniSocketConfigArg);
 
 template <typename Host>
 inline const Host *
 GetHostForSNI(const SECItem *aSrvNameArr, uint32_t aSrvNameArrSize,
               const Host *hosts)
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/md5signature-expired.pem.certspec
@@ -0,0 +1,6 @@
+issuer:Test CA
+subject:Test MD5Signature-Expired End-entity
+validity:20110101-20130101
+signature:md5WithRSAEncryption
+extension:subjectAlternativeName:md5signature-expired.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/md5signature.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Test End-entity with MD5 signature
+signature:md5WithRSAEncryption
+extension:subjectAlternativeName:md5signature.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatch-expired.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Mismatch-Expired Test End-entity
+validity:20130101-20140101
+extension:subjectAlternativeName:doesntmatch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatch-notYetValid.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Mismatch-Not Yet Valid Test End-entity
+validity:20330101-20340101
+extension:subjectAlternativeName:doesntmatch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatch-untrusted-expired.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Other test CA
+subject:Mismatch-Untrusted-Expired Test End-entity
+validity:20110101-20130101
+extension:subjectAlternativeName:doesntmatch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatch-untrusted.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Other test CA
+subject:Mismatch-Untrusted Test End-entity
+extension:subjectAlternativeName:doesntmatch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatch.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Mismatch Test End-entity
+extension:subjectAlternativeName:doesntmatch.example.com,*.alsodoesntmatch.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/mismatchCN.pem.certspec
@@ -0,0 +1,2 @@
+issuer:Test CA
+subject:doesntmatch.example.com
--- a/security/manager/ssl/tests/unit/tlsserver/moz.build
+++ b/security/manager/ssl/tests/unit/tlsserver/moz.build
@@ -1,8 +1,84 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # lib must be first, because cmd depends on its output
 DIRS += ['lib', 'cmd']
+
+test_certificates = (
+    'badSubjectAltNames.pem',
+    'beforeEpochINT.pem',
+    'beforeEpochIssuer.pem',
+    'beforeEpoch.pem',
+    'ca-used-as-end-entity.pem',
+    'default-ee.pem',
+    'delegatedSHA1Signer.pem',
+    'delegatedSigner.pem',
+    'eeIssuedByNonCA.pem',
+    'eeIssuedByV1Cert.pem',
+    'expired-ee.pem',
+    'expiredINT.pem',
+    'expiredissuer.pem',
+    'inadequateKeySizeEE.pem',
+    'inadequatekeyusage-ee.pem',
+    'invalidDelegatedSignerFromIntermediate.pem',
+    'invalidDelegatedSignerKeyUsageCrlSigning.pem',
+    'invalidDelegatedSignerNoExtKeyUsage.pem',
+    'invalidDelegatedSignerWrongExtKeyUsage.pem',
+    'ipAddressAsDNSNameInSAN.pem',
+    'md5signature-expired.pem',
+    'md5signature.pem',
+    'mismatchCN.pem',
+    'mismatch-expired.pem',
+    'mismatch-notYetValid.pem',
+    'mismatch.pem',
+    'mismatch-untrusted-expired.pem',
+    'mismatch-untrusted.pem',
+    'notYetValidINT.pem',
+    'notYetValidIssuer.pem',
+    'notYetValid.pem',
+    'noValidNames.pem',
+    'nsCertTypeCritical.pem',
+    'nsCertTypeCriticalWithExtKeyUsage.pem',
+    'nsCertTypeNotCritical.pem',
+    'ocspEEWithIntermediate.pem',
+    'ocspOtherEndEntity.pem',
+    'other-test-ca.pem',
+    'other-issuer-ee.pem',
+    'rsa-1016-keysizeDelegatedSigner.pem',
+    'same-issuer-ee.pem',
+    'self-signed-EE-with-cA-true.pem',
+    'selfsigned-inadequateEKU.pem',
+    'selfsigned.pem',
+    'test-ca.pem',
+    'test-int-ee.pem',
+    'test-int.pem',
+    'unknownissuer.pem',
+    'untrusted-expired.pem',
+    'untrustedissuer.pem',
+    'v1Cert.pem',
+)
+
+for test_certificate in test_certificates:
+    input_file = test_certificate + '.certspec'
+    GENERATED_FILES += [test_certificate]
+    props = GENERATED_FILES[test_certificate]
+    props.script = '../pycert.py'
+    props.inputs = [input_file]
+    TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.tlsserver += ['!%s' % test_certificate]
+
+test_keys = (
+    'default-ee.key',
+    'other-test-ca.key',
+    'rsa-1016-keysizeDelegatedSigner.key',
+)
+
+for test_key in test_keys:
+    input_file = test_key + '.keyspec'
+    GENERATED_FILES += [test_key]
+    props = GENERATED_FILES[test_key]
+    props.script = '../pykey.py'
+    props.inputs = [input_file]
+    TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.tlsserver += ['!%s' % test_key]
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/noValidNames.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test CA
+subject:End-entity with no valid names
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/notYetValid.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Not Yet Valid Test End-entity
+validity:20310101-20320101
+extension:subjectAlternativeName:notyetvalid.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/notYetValidINT.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Not Yet Valid Test Intermediate
+validity:20310101-20330101
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/notYetValidIssuer.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Not Yet Valid Test Intermediate
+subject:Test End-entity with not yet valid issuer
+extension:subjectAlternativeName:notyetvalidissuer.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/nsCertTypeCritical.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:nsCertType Critical
+extension:subjectAlternativeName:localhost,*.example.com
+extension:nsCertType[critical]:sslServer
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/nsCertTypeCriticalWithExtKeyUsage.pem.certspec
@@ -0,0 +1,6 @@
+issuer:Test CA
+subject:nsCertType Critical With extKeyUsage
+extension:subjectAlternativeName:localhost,*.example.com
+extension:nsCertType[critical]:sslServer
+extension:basicConstraints:,
+extension:extKeyUsage:serverAuth
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/nsCertTypeNotCritical.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:nsCertType Not Critical
+extension:subjectAlternativeName:localhost,*.example.com
+extension:nsCertType:sslServer
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/ocspEEWithIntermediate.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test Intermediate
+subject:Test End-entity with Intermediate
+extension:subjectAlternativeName:localhost,*.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/ocspOtherEndEntity.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Other Cert
+extension:subjectAlternativeName:localhost,*.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100644
index a82b2910c5cbb1aa242de9e4398a16833e3296b6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/other-issuer-ee.pem.certspec
@@ -0,0 +1,6 @@
+issuer:Other test CA
+subject:Wrong CA Pin Test End-Entity
+issuerKey:alternate
+subjectKey:alternate
+extension:subjectAlternativeName:*.include-subdomains.pinning.example.com,*.exclude-subdomains.pinning.example.com,*.pinning.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100644
index 4da6f3bf6b2ccc7f23527eea12f48e7902b4642f..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.key.keyspec
@@ -0,0 +1,1 @@
+alternate
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/other-test-ca.pem.certspec
@@ -0,0 +1,7 @@
+issuer:Other test CA
+subject:Other test CA
+issuerKey:alternate
+subjectKey:alternate
+validity:20150101-20250101
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
deleted file mode 100644
--- a/security/manager/ssl/tests/unit/tlsserver/pkcs11.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-library=
-name=NSS Internal PKCS #11 Module
-parameters=configdir='sql:security/manager/ssl/tests/unit/tlsserver' certPrefix='' keyPrefix='' secmod='secmod.db' flags= updatedir='' updateCertPrefix='' updateKeyPrefix='' updateid='' updateTokenDescription='' 
-NSS=Flags=internal,critical trustOrder=75 cipherOrder=100 slotParams=(1={slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512] askpw=any timeout=30})
-
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/rsa-1016-keysizeDelegatedSigner.key.keyspec
@@ -0,0 +1,1 @@
+rsa1016
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/rsa-1016-keysizeDelegatedSigner.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:RSA 1016 Key Size Test Delegated Responder
+subjectKey:rsa1016
+extension:extKeyUsage:OCSPSigning
deleted file mode 100644
index 62d959834b0a02080ccaf96986fb19f582a678dc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/same-issuer-ee.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Another Test End-entity
+extension:subjectAlternativeName:localhost,*.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/self-signed-EE-with-cA-true.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test Self-signed End-entity with CA true
+subject:Test Self-signed End-entity with CA true
+extension:basicConstraints:cA,
+extension:authorityInformationAccess:http://localhost:8888/
+extension:subjectAlternativeName:self-signed-end-entity-with-cA-true.example.com
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/selfsigned-inadequateEKU.pem.certspec
@@ -0,0 +1,6 @@
+issuer:Self-signed Inadequate EKU Test End-entity
+subject:Self-signed Inadequate EKU Test End-entity
+extension:keyUsage:keyEncipherment,dataEncipherment
+extension:extKeyUsage:serverAuth
+extension:subjectAlternativeName:selfsigned-inadequateEKU.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/selfsigned.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Self-signed Test End-entity
+subject:Self-signed Test End-entity
+extension:subjectAlternativeName:selfsigned.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100644
index a46410db966439bf7640bbfae9460cde418af401..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/test-ca.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test CA
+subject:Test CA
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
deleted file mode 100644
index d1c019f78d34a9454c22fd5b23b642482f72e74c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/test-int-ee.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test Intermediate
+subject:EE issued by intermediate
+extension:subjectAlternativeName:localhost
deleted file mode 100644
index afac61f517454353e10a1896f32699104d78266d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/test-int.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Test CA
+subject:Test Intermediate
+validity:20150101-20250101
+extension:basicConstraints:cA,
+extension:keyUsage:cRLSign,keyCertSign
deleted file mode 100644
index 7457064ebd9d5597e06ccbd38cac0082366e54e2..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/unknownissuer.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Test Intermediate to delete
+subject:Test End-entity from unknown issuer
+extension:subjectAlternativeName:unknownissuer.example.com,unknownissuer.include-subdomains.pinning.example.com,unknownissuer.test-mode.pinning.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/untrusted-expired.pem.certspec
@@ -0,0 +1,5 @@
+issuer:Other test CA
+subject:Untrusted-Expired Test End-entity
+validity:20110101-20130101
+extension:subjectAlternativeName:untrusted-expired.example.com
+extension:authorityInformationAccess:http://localhost:8888/
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/untrustedissuer.pem.certspec
@@ -0,0 +1,4 @@
+issuer:Other test CA
+subject:Test End-entity with untrusted issuer
+extension:subjectAlternativeName:untrustedissuer.example.com
+extension:authorityInformationAccess:http://localhost:8888/
deleted file mode 100644
index 3a69e645a10689e8269e4633816e6d9735b64909..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/unit/tlsserver/v1Cert.pem.certspec
@@ -0,0 +1,3 @@
+issuer:Test CA
+subject:V1 Cert
+version:1
--- a/security/manager/tools/genHPKPStaticPins.js
+++ b/security/manager/tools/genHPKPStaticPins.js
@@ -3,23 +3,23 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // How to run this file:
 // 1. [obtain firefox source code]
 // 2. [build/obtain firefox binaries]
 // 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \
 //                                  [path to]/genHPKPStaticpins.js \
 //                                  [absolute path to]/PreloadedHPKPins.json \
-//                                  [absolute path to]/default-ee.der \
+//                                  [an unused argument - see bug 1205406] \
 //                                  [absolute path to]/StaticHPKPins.h
 
 if (arguments.length != 3) {
   throw "Usage: genHPKPStaticPins.js " +
         "<absolute path to PreloadedHPKPins.json> " +
-        "<absolute path to default-ee.der> " +
+        "<an unused argument - see bug 1205406> " +
         "<absolute path to StaticHPKPins.h>";
 }
 
 const { 'classes': Cc, 'interfaces': Ci, 'utils': Cu, 'results': Cr } = Components;
 
 var { NetUtil } = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 var { FileUtils } = Cu.import("resource://gre/modules/FileUtils.jsm", {});
 var { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
@@ -63,17 +63,18 @@ const PINSETDEF = "/* Pinsets are each a
   "};\n\n" +
   "struct StaticPinset {\n" +
   "  const StaticFingerprints* sha1;\n" +
   "  const StaticFingerprints* sha256;\n" +
   "};\n\n";
 
 // Command-line arguments
 var gStaticPins = parseJson(arguments[0]);
-var gTestCertFile = arguments[1];
+
+// arguments[1] is ignored for now. See bug 1205406.
 
 // Open the output file.
 var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
 file.initWithPath(arguments[2]);
 var gFileOutputStream = FileUtils.openSafeFileOutputStream(file);
 
 function writeString(string) {
   gFileOutputStream.write(string, string.length);
@@ -345,17 +346,17 @@ function downloadAndParseChromePins(file
         pins: pinsetName });
     }
   });
   return [ chromeImportedPinsets, chromeImportedEntries ];
 }
 
 // Returns a pair of maps [certNameToSKD, certSKDToName] between cert
 // nicknames and digests of the SPKInfo for the mozilla trust store
-function loadNSSCertinfo(derTestFile, extraCertificates) {
+function loadNSSCertinfo(extraCertificates) {
   let allCerts = gCertDB.getCerts();
   let enumerator = allCerts.getEnumerator();
   let certNameToSKD = {};
   let certSKDToName = {};
   while (enumerator.hasMoreElements()) {
     let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
     if (!isCertBuiltIn(cert)) {
       continue;
@@ -369,23 +370,20 @@ function loadNSSCertinfo(derTestFile, ex
   for (let cert of extraCertificates) {
     let name = cert.commonName;
     let SKD = cert.sha256SubjectPublicKeyInfoDigest;
     certNameToSKD[name] = SKD;
     certSKDToName[SKD] = name;
   }
 
   {
-    // A certificate for *.example.com.
-    let der = readFileToString(derTestFile);
-    let testCert = gCertDB.constructX509(der, der.length);
-    // We can't include this cert in the previous loop, because it skips
-    // non-builtin certs and the nickname is not built-in to the cert.
+    // This is the pinning test certificate. The key hash identifies the
+    // default RSA key from pykey.
     let name = "End Entity Test Cert";
-    let SKD  = testCert.sha256SubjectPublicKeyInfoDigest;
+    let SKD = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
     certNameToSKD[name] = SKD;
     certSKDToName[SKD] = name;
   }
   return [certNameToSKD, certSKDToName];
 }
 
 function parseJson(filename) {
   let json = stripComments(readFileToString(filename));
@@ -594,18 +592,17 @@ function loadExtraCertificates(certStrin
   let constructedCerts = [];
   for (let certString of certStringList) {
     constructedCerts.push(gCertDB.constructX509FromBase64(certString));
   }
   return constructedCerts;
 }
 
 var extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates);
-var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile,
-                                                       extraCertificates);
+var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(extraCertificates);
 var [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
   gStaticPins.chromium_data.cert_file_url, certSKDToName);
 var [ chromeImportedPinsets, chromeImportedEntries ] =
   downloadAndParseChromePins(gStaticPins.chromium_data.json_file_url,
     chromeNameToHash, chromeNameToMozName, certNameToSKD, certSKDToName);
 
 writeFile(certNameToSKD, certSKDToName, chromeImportedPinsets,
           chromeImportedEntries);