Backed out changeset a08287c70962 (bug 1203312) for b2g xpcshell failures

This commit is contained in:
Wes Kocher 2015-09-18 12:53:24 -07:00
parent 2df062e513
commit 21a9e609d5
89 changed files with 758 additions and 769 deletions

View File

@ -81,7 +81,7 @@ static const char kDigiCert_High_Assurance_EV_Root_CAFingerprint[] =
/* End Entity Test Cert */
static const char kEnd_Entity_Test_CertFingerprint[] =
"VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
"lzCakFt+nADIfIkgk+UE/EQ9SaT2nay2yu2iykVbvV8=";
/* Entrust Root Certification Authority */
static const char kEntrust_Root_Certification_AuthorityFingerprint[] =
@ -1096,4 +1096,4 @@ static const TransportSecurityPreload kPublicKeyPinningPreloadList[] = {
static const int32_t kUnknownId = -1;
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1450902702049000);
static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1450521025692000);

View File

@ -435,7 +435,7 @@ 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.pem", "CTu,u,u");
addCertFromFile(certdb, "tlsserver/test-ca.der", "CTu,u,u");
const CALLBACK_PORT = 8444;
@ -639,8 +639,9 @@ FakeSSLStatus.prototype = {
// Utility functions for adding tests relating to certificate error overrides
// Helper function for add_cert_override_test. Probably doesn't need to be
// called directly.
// Helper function for add_cert_override_test and
// add_prevented_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;
@ -667,28 +668,6 @@ function add_cert_override_test(aHost, aExpectedBits, aExpectedError) {
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
@ -697,6 +676,6 @@ function attempt_adding_cert_override(aHost, aExpectedBits, aSecurityInfo) {
// 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,
attempt_adding_cert_override.bind(this, aHost, aExpectedBits));
add_cert_override.bind(this, aHost, aExpectedBits));
add_connection_test(aHost, aExpectedError);
}

View File

@ -16,8 +16,7 @@ subject:<subject distinguished name specification>
[validity:<YYYYMMDD-YYYYMMDD|duration in days>]
[issuerKey:<key specification>]
[subjectKey:<key specification>]
[signature:{sha256WithRSAEncryption,sha1WithRSAEncryption,
md5WithRSAEncryption,ecdsaWithSHA256}]
[signature:{sha1WithRSAEncryption,sha256WithRSAEncryption,ecdsaWithSHA256}]
[extension:<extension name:<extension-specific data>>]
[...]
@ -32,7 +31,6 @@ 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
@ -66,9 +64,6 @@ 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
@ -183,14 +178,6 @@ class UnknownDNTypeError(UnknownBaseError):
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"""
@ -267,29 +254,27 @@ def stringToDN(string, tag=None):
name.setComponentByPosition(0, rdns)
return name
def stringToAlgorithmIdentifiers(string):
def stringToAlgorithmIdentifier(string):
"""Helper function that converts a description of an algorithm
to a representation usable by the pyasn1 package and a hash
algorithm name for use by pykey."""
to a representation usable by the pyasn1 package"""
algorithmIdentifier = rfc2459.AlgorithmIdentifier()
algorithmName = None
algorithm = None
name = None
if string == 'sha1WithRSAEncryption':
algorithmName = 'SHA-1'
name = 'SHA-1'
algorithm = rfc2459.sha1WithRSAEncryption
elif string == 'sha256WithRSAEncryption':
algorithmName = 'SHA-256'
name = 'SHA-256'
algorithm = univ.ObjectIdentifier('1.2.840.113549.1.1.11')
elif string == 'md5WithRSAEncryption':
algorithmName = 'MD5'
algorithm = rfc2459.md5WithRSAEncryption
elif string == 'ecdsaWithSHA256':
algorithmName = 'sha256'
# 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'
algorithm = univ.ObjectIdentifier('1.2.840.10045.4.3.2')
else:
raise UnknownAlgorithmTypeError(string)
algorithmIdentifier.setComponentByName('algorithm', algorithm)
return (algorithmIdentifier, algorithmName)
return (algorithmIdentifier, name)
def datetimeToTime(dt):
"""Takes a datetime object and returns an rfc2459.Time object with
@ -395,28 +380,22 @@ class Certificate:
self.notAfter = self.now + delta
def decodeExtension(self, extension):
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)
extensionType = extension.split(':')[0]
value = ':'.join(extension.split(':')[1:])
if extensionType == 'basicConstraints':
self.addBasicConstraints(value, critical)
self.addBasicConstraints(value)
elif extensionType == 'keyUsage':
self.addKeyUsage(value, critical)
self.addKeyUsage(value)
elif extensionType == 'extKeyUsage':
self.addExtKeyUsage(value, critical)
self.addExtKeyUsage(value)
elif extensionType == 'subjectAlternativeName':
self.addSubjectAlternativeName(value, critical)
self.addSubjectAlternativeName(value)
elif extensionType == 'authorityInformationAccess':
self.addAuthorityInformationAccess(value, critical)
self.addAuthorityInformationAccess(value)
elif extensionType == 'certificatePolicies':
self.addCertificatePolicies(value, critical)
self.addCertificatePolicies(value)
elif extensionType == 'nameConstraints':
self.addNameConstraints(value, critical)
elif extensionType == 'nsCertType':
self.addNSCertType(value, critical)
self.addNameConstraints(value)
else:
raise UnknownExtensionTypeError(extensionType)
@ -428,20 +407,16 @@ class Certificate:
else:
raise UnknownKeyTargetError(subjectOrIssuer)
def addExtension(self, extensionType, extensionValue, critical):
def addExtension(self, extensionType, extensionValue):
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, critical):
def addBasicConstraints(self, basicConstraints):
cA = basicConstraints.split(',')[0]
pathLenConstraint = basicConstraints.split(',')[1]
basicConstraintsExtension = rfc2459.BasicConstraints()
@ -452,11 +427,11 @@ class Certificate:
subtypeSpec=constraint.ValueRangeConstraint(0, 64))
basicConstraintsExtension.setComponentByName('pathLenConstraint',
pathLenConstraintValue)
self.addExtension(rfc2459.id_ce_basicConstraints, basicConstraintsExtension, critical)
self.addExtension(rfc2459.id_ce_basicConstraints, basicConstraintsExtension)
def addKeyUsage(self, keyUsage, critical):
def addKeyUsage(self, keyUsage):
keyUsageExtension = rfc2459.KeyUsage(keyUsage)
self.addExtension(rfc2459.id_ce_keyUsage, keyUsageExtension, critical)
self.addExtension(rfc2459.id_ce_keyUsage, keyUsageExtension)
def keyPurposeToOID(self, keyPurpose):
if keyPurpose == 'serverAuth':
@ -477,15 +452,15 @@ class Certificate:
return rfc2459.id_kp_timeStamping
raise UnknownKeyPurposeTypeError(keyPurpose)
def addExtKeyUsage(self, extKeyUsage, critical):
def addExtKeyUsage(self, extKeyUsage):
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, critical)
self.addExtension(rfc2459.id_ce_extKeyUsage, extKeyUsageExtension)
def addSubjectAlternativeName(self, dNSNames, critical):
def addSubjectAlternativeName(self, dNSNames):
subjectAlternativeName = rfc2459.SubjectAltName()
count = 0
for dNSName in dNSNames.split(','):
@ -496,15 +471,15 @@ class Certificate:
generalName.setComponentByName('dNSName', dNSName.decode(encoding='string_escape'))
subjectAlternativeName.setComponentByPosition(count, generalName)
count += 1
self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName, critical)
self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName)
def addAuthorityInformationAccess(self, ocspURI, critical):
def addAuthorityInformationAccess(self, ocspURI):
sequence = univ.Sequence()
accessDescription = stringToAccessDescription(ocspURI)
sequence.setComponentByPosition(0, accessDescription)
self.addExtension(rfc2459.id_pe_authorityInfoAccess, sequence, critical)
self.addExtension(rfc2459.id_pe_authorityInfoAccess, sequence)
def addCertificatePolicies(self, policyOID, critical):
def addCertificatePolicies(self, policyOID):
policies = rfc2459.CertificatePolicies()
policy = rfc2459.PolicyInformation()
if policyOID == 'any':
@ -512,9 +487,9 @@ class Certificate:
policyIdentifier = rfc2459.CertPolicyId(policyOID)
policy.setComponentByName('policyIdentifier', policyIdentifier)
policies.setComponentByPosition(0, policy)
self.addExtension(rfc2459.id_ce_certificatePolicies, policies, critical)
self.addExtension(rfc2459.id_ce_certificatePolicies, policies)
def addNameConstraints(self, constraints, critical):
def addNameConstraints(self, constraints):
nameConstraints = NameConstraints()
if constraints.startswith('permitted:'):
(subtreesType, subtreesTag) = ('permittedSubtrees', 0)
@ -539,13 +514,7 @@ class Certificate:
generalSubtrees.setComponentByPosition(pos, generalSubtree)
pos = pos + 1
nameConstraints.setComponentByName(subtreesType, generalSubtrees)
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)
self.addExtension(rfc2459.id_ce_nameConstraints, nameConstraints)
def getVersion(self):
return rfc2459.Version(self.versionValue).subtype(
@ -554,6 +523,9 @@ class Certificate:
def getSerialNumber(self):
return decoder.decode(self.serialNumber)[0]
def getSignature(self):
return stringToAlgorithmIdentifier(self.signature)
def getIssuer(self):
return stringToDN(self.issuer)
@ -573,7 +545,8 @@ class Certificate:
return stringToDN(self.subject)
def toDER(self):
(signatureOID, hashName) = stringToAlgorithmIdentifiers(self.signature)
(signatureOID, hashAlg) = self.getSignature()
tbsCertificate = rfc2459.TBSCertificate()
tbsCertificate.setComponentByName('version', self.getVersion())
tbsCertificate.setComponentByName('serialNumber', self.getSerialNumber())
@ -595,7 +568,8 @@ class Certificate:
certificate.setComponentByName('tbsCertificate', tbsCertificate)
certificate.setComponentByName('signatureAlgorithm', signatureOID)
tbsDER = encoder.encode(tbsCertificate)
certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashName))
certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER, hashAlg))
return encoder.encode(certificate)
def toPEM(self):

View File

@ -66,6 +66,13 @@ class UnknownKeySpecificationError(UnknownBaseError):
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(
@ -553,12 +560,12 @@ class RSAKey:
spki.setComponentByName('subjectPublicKey', subjectPublicKey)
return spki
def sign(self, data, hashAlgorithmName):
def sign(self, data, digest):
"""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, hashAlgorithmName)
signature = rsa.sign(data, rsaPrivateKey, digest)
return byteStringToHexifiedBitString(signature)
@ -664,10 +671,14 @@ class ECCKey:
spki.setComponentByName('subjectPublicKey', subjectPublicKey)
return spki
def sign(self, data, hashAlgorithmName):
def sign(self, data, digest):
"""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):
@ -677,9 +688,9 @@ class ECCKey:
# 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, hashAlgorithmName))
x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
else:
x, y = encoding.dec_point(self.key.sign(data, hashAlgorithmName))
x, y = encoding.dec_point(self.key.sign(data, 'sha256'))
point = ECPoint()
point.setComponentByName('x', x)
point.setComponentByName('y', y)

View File

@ -94,15 +94,15 @@ var blocklist_contents =
"<serialNumber>and serial</serialNumber></certItem>" +
// some mixed
// In this case, the issuer name and the valid serialNumber correspond
// to test-int.pem in tlsserver/
"<certItem issuerName='MBIxEDAOBgNVBAMMB1Rlc3QgQ0E='>" +
// to test-int.der in tlsserver/
"<certItem issuerName='MBIxEDAOBgNVBAMTB1Rlc3QgQ0E='>" +
"<serialNumber>oops! more nonsense.</serialNumber>" +
"<serialNumber>Y1HQqXGtw7ek2v/QAqBL8jf6rbA=</serialNumber></certItem>" +
"<serialNumber>X1o=</serialNumber></certItem>" +
// ... and some good
// In this case, the issuer name and the valid serialNumber correspond
// to other-test-ca.pem in tlsserver/ (for testing root revocation)
"<certItem issuerName='MBgxFjAUBgNVBAMMDU90aGVyIHRlc3QgQ0E='>" +
"<serialNumber>Szin5enUEn9TnVq29c4IMPNFuqE=</serialNumber></certItem>" +
// to other-test-ca.der in tlsserver/ (for testing root revocation)
"<certItem issuerName='MBgxFjAUBgNVBAMTDU90aGVyIHRlc3QgQ0E='>" +
"<serialNumber>AKEIivg=</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:
@ -113,9 +113,8 @@ var blocklist_contents =
"<certItem issuerName='YW5vdGhlciBpbWFnaW5hcnkgaXNzdWVy'>" +
"<serialNumber>c2VyaWFsMi4=</serialNumber>" +
"<serialNumber>YW5vdGhlciBzZXJpYWwu</serialNumber>" +
// This item revokes same-issuer-ee.pem by subject and serial number.
"</certItem><certItem subject='MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5'"+
" pubKeyHash='VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8='>" +
"</certItem><certItem subject='MCIxIDAeBgNVBAMTF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5'"+
" pubKeyHash='2ETEb0QP574JkM+35JVwS899PLUmt1rrJyWOV6GRfAE='>" +
"</certItem></certItems></blocklist>";
testserver.registerPathHandler("/push_blocked_cert/",
function serveResponse(request, response) {
@ -137,12 +136,13 @@ var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
converter.charset = "UTF-8";
function verify_cert(file, expectedError) {
let ee = constructCertFromFile(file);
let cert_der = readFile(do_get_file(file));
let ee = certDB.constructX509(cert_der, cert_der.length);
checkCertErrorGeneric(certDB, ee, expectedError, certificateUsageSSLServer);
}
function load_cert(cert, trust) {
let file = "tlsserver/" + cert + ".pem";
let file = "tlsserver/" + cert + ".der";
addCertFromFile(certDB, file, trust);
}
@ -201,20 +201,20 @@ function run_test() {
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.pem, which issued
// test-int-ee.pem.
// Soon we'll load a blocklist which revokes test-int.der, which issued
// test-int-ee.der.
// Check the cert validates before we load the blocklist
let file = "tlsserver/test-int-ee.pem";
let file = "tlsserver/test-int-ee.der";
verify_cert(file, PRErrorCodeSuccess);
// The blocklist also revokes other-test-ca.pem, which issued other-ca-ee.pem.
// The blocklist also revokes other-test-ca.der, which issued other-ca-ee.der.
// Check the cert validates before we load the blocklist
file = "tlsserver/other-issuer-ee.pem";
file = "tlsserver/other-issuer-ee.der";
verify_cert(file, PRErrorCodeSuccess);
// The blocklist will revoke same-issuer-ee.pem via subject / pubKeyHash.
// The blocklist will revoke same-issuer-ee.der via subject / pubKeyHash.
// Check the cert validates before we load the blocklist
file = "tlsserver/same-issuer-ee.pem";
file = "tlsserver/same-issuer-ee.der";
verify_cert(file, PRErrorCodeSuccess);
// blocklist load is async so we must use add_test from here
@ -271,35 +271,35 @@ function run_test() {
contents = contents + (contents.length == 0 ? "" : "\n") + line.value;
} while (hasmore);
let expected = "# Auto generated contents. Do not edit.\n" +
"MCIxIDAeBgNVBAMMF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5\n"+
"\tVCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=\n"+
"MBIxEDAOBgNVBAMMB1Rlc3QgQ0E=\n" +
" Y1HQqXGtw7ek2v/QAqBL8jf6rbA=\n" +
"MBgxFjAUBgNVBAMMDU90aGVyIHRlc3QgQ0E=\n" +
" Szin5enUEn9TnVq29c4IMPNFuqE=\n" +
"MCIxIDAeBgNVBAMTF0Fub3RoZXIgVGVzdCBFbmQtZW50aXR5\n"+
"\t2ETEb0QP574JkM+35JVwS899PLUmt1rrJyWOV6GRfAE=\n"+
"MBgxFjAUBgNVBAMTDU90aGVyIHRlc3QgQ0E=\n" +
" AKEIivg=\n" +
"MBIxEDAOBgNVBAMTB1Rlc3QgQ0E=\n" +
" X1o=\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.pem";
let file = "tlsserver/test-int-ee.der";
verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
// Check the ee with the blocklisted root also causes a failure
file = "tlsserver/other-issuer-ee.pem";
file = "tlsserver/other-issuer-ee.der";
verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
// Check the ee blocked by subject / pubKey causes a failure
file = "tlsserver/same-issuer-ee.pem";
file = "tlsserver/same-issuer-ee.der";
verify_cert(file, SEC_ERROR_REVOKED_CERTIFICATE);
// Check a non-blocklisted chain still validates OK
file = "tlsserver/default-ee.pem";
file = "tlsserver/default-ee.der";
verify_cert(file, PRErrorCodeSuccess);
// Check a bad cert is still bad (unknown issuer)
file = "tlsserver/unknownissuer.pem";
file = "tlsserver/unknown-issuer.der";
verify_cert(file, SEC_ERROR_UNKNOWN_ISSUER);
// check that save with no further update is a no-op

View File

@ -9,16 +9,16 @@ 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 + ".pem");
let cert = constructCertFromFile("tlsserver/" + certName + ".der");
certList.addCert(cert);
});
return certList;
}
function test_cert_equals() {
let certA = constructCertFromFile("tlsserver/default-ee.pem");
let certB = constructCertFromFile("tlsserver/default-ee.pem");
let certC = constructCertFromFile("tlsserver/expired-ee.pem");
let certA = constructCertFromFile("tlsserver/default-ee.der");
let certB = constructCertFromFile("tlsserver/default-ee.der");
let certC = constructCertFromFile("tlsserver/expired-ee.der");
ok(certA != certB,
"Cert objects constructed from the same file should not be equal" +

View File

@ -13,6 +13,20 @@
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)
@ -56,11 +70,11 @@ function check_telemetry() {
.snapshot();
equal(keySizeHistogram.counts[0], 0,
"Actual and expected unchecked key size counts should match");
equal(keySizeHistogram.counts[1], 12,
equal(keySizeHistogram.counts[1], 0,
"Actual and expected successful verifications of 2048-bit keys should match");
equal(keySizeHistogram.counts[2], 0,
equal(keySizeHistogram.counts[2], 12,
"Actual and expected successful verifications of 1024-bit keys should match");
equal(keySizeHistogram.counts[3], 54,
equal(keySizeHistogram.counts[3], 48,
"Actual and expected key size verification failures should match");
run_next_test();
@ -133,24 +147,22 @@ function add_simple_tests() {
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
SEC_ERROR_UNKNOWN_ISSUER);
add_prevented_cert_override_test("inadequatekeyusage.example.com",
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
SEC_ERROR_INADEQUATE_KEY_USAGE);
add_non_overridable_test("inadequatekeyusage.example.com",
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.pem");
let rootCert = constructCertFromFile("tlsserver/test-ca.der");
setCertTrust(rootCert, ",,");
run_next_test();
});
add_prevented_cert_override_test("nsCertTypeCritical.example.com",
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
add_non_overridable_test("nsCertTypeCritical.example.com",
SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
add_test(function() {
let rootCert = constructCertFromFile("tlsserver/test-ca.pem");
let rootCert = constructCertFromFile("tlsserver/test-ca.der");
setCertTrust(rootCert, "CTu,,");
run_next_test();
});
@ -176,7 +188,7 @@ function add_simple_tests() {
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.pem");
let v1Cert = constructCertFromFile("tlsserver/v1Cert.der");
setCertTrust(v1Cert, "CTu,,");
clearSessionCache();
run_next_test();
@ -185,7 +197,7 @@ function add_simple_tests() {
PRErrorCodeSuccess);
// Reset the trust for that certificate.
add_test(function() {
let v1Cert = constructCertFromFile("tlsserver/v1Cert.pem");
let v1Cert = constructCertFromFile("tlsserver/v1Cert.der");
setCertTrust(v1Cert, ",,");
clearSessionCache();
run_next_test();
@ -197,11 +209,10 @@ function add_simple_tests() {
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
SEC_ERROR_CA_CERT_INVALID);
// This host presents a 1016-bit RSA key. NSS determines this key is too
// This host presents a 1008-bit RSA key. NSS determines this key is too
// small and terminates the connection. The error is not overridable.
add_prevented_cert_override_test("inadequate-key-size-ee.example.com",
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
SSL_ERROR_WEAK_SERVER_CERT_KEY);
add_non_overridable_test("inadequate-key-size-ee.example.com",
SSL_ERROR_WEAK_SERVER_CERT_KEY);
add_cert_override_test("ipAddressAsDNSNameInSAN.example.com",
Ci.nsICertOverrideService.ERROR_MISMATCH,
@ -252,13 +263,13 @@ 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.pem", "untrusted.example.com",
add_distrust_test("tlsserver/default-ee.der", "untrusted.example.com",
SEC_ERROR_UNTRUSTED_CERT);
add_distrust_test("tlsserver/other-test-ca.pem",
add_distrust_test("tlsserver/other-test-ca.der",
"untrustedissuer.example.com", SEC_ERROR_UNTRUSTED_ISSUER);
add_distrust_test("tlsserver/test-ca.pem",
add_distrust_test("tlsserver/test-ca.der",
"ca-used-as-end-entity.example.com",
SEC_ERROR_UNTRUSTED_ISSUER);
}
@ -272,9 +283,7 @@ function add_distrust_test(certFileName, hostName, expectedResult) {
clearSessionCache();
run_next_test();
});
add_prevented_cert_override_test(hostName,
Ci.nsICertOverrideService.ERROR_UNTRUSTED,
expectedResult);
add_non_overridable_test(hostName, expectedResult);
add_test(function () {
setCertTrust(certToDistrust, "u,,");
run_next_test();

View File

@ -24,7 +24,7 @@ function respondWithSHA1OCSP(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/ocsp-response");
let args = [ ["good-delegated", "default-ee", "delegatedSHA1Signer" ] ];
let args = [ ["good-delegated", "localhostAndExampleCom", "delegatedSHA1Signer" ] ];
let responses = generateOCSPResponses(args, "tlsserver");
response.write(responses[0]);
}
@ -37,7 +37,7 @@ function respondWithError(request, response) {
}
function generateGoodOCSPResponse() {
let args = [ ["good", "default-ee", "unused" ] ];
let args = [ ["good", "localhostAndExampleCom", "unused" ] ];
let responses = generateOCSPResponses(args, "tlsserver");
return responses[0];
}
@ -54,7 +54,7 @@ function add_ocsp_test(aHost, aExpectedResult, aResponses, aMessage) {
// 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");
});
}
@ -134,10 +134,6 @@ function add_tests() {
respondWithError,
respondWithError,
respondWithError,
respondWithError,
respondWithError,
respondWithError,
respondWithError,
],
"No stapled response -> a fetch should have been attempted");

View File

@ -16,7 +16,7 @@ function run_test() {
// get a TLS connection.
add_tls_server_setup("OCSPStaplingServer");
let args = [["good", "default-ee", "unused"]];
let args = [["good", "localhostAndExampleCom", "unused"]];
let ocspResponses = generateOCSPResponses(args, "tlsserver");
let goodOCSPResponse = ocspResponses[0];

View File

@ -20,7 +20,7 @@ function run_test() {
// get a TLS connection.
add_tls_server_setup("OCSPStaplingServer");
let args = [["bad-signature", "default-ee", "unused"]];
let args = [["bad-signature", "localhostAndExampleCom", "unused"]];
let ocspResponses = generateOCSPResponses(args, "tlsserver");
let ocspResponseBadSignature = ocspResponses[0];

View File

@ -21,7 +21,7 @@ function add_ocsp_test(aHost, aExpectedResult, aStaplingEnabled) {
});
}
function add_tests() {
function add_tests(certDB, otherTestCA) {
// In the absence of OCSP stapling, these should actually all work.
add_ocsp_test("ocsp-stapling-good.example.com",
PRErrorCodeSuccess, false);
@ -73,9 +73,6 @@ function add_tests() {
// 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);
@ -189,6 +186,11 @@ function check_ocsp_stapling_telemetry() {
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) {
@ -200,7 +202,7 @@ function run_test() {
add_tls_server_setup("OCSPStaplingServer");
add_tests();
add_tests(certDB, otherTestCA);
add_test(function () {
fakeOCSPResponder.stop(check_ocsp_stapling_telemetry);

View File

@ -24,18 +24,18 @@ function add_ocsp_test(aHost, aExpectedResult, aOCSPResponseToServe,
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", "default-ee", "unused"],
["expiredresponse", "default-ee", "unused"],
["oldvalidperiod", "default-ee", "unused"],
["revoked", "default-ee", "unused"],
["unknown", "default-ee", "unused"],
var args = [["good", "localhostAndExampleCom", "unused"],
["expiredresponse", "localhostAndExampleCom", "unused"],
["oldvalidperiod", "localhostAndExampleCom", "unused"],
["revoked", "localhostAndExampleCom", "unused"],
["unknown", "localhostAndExampleCom", "unused"],
];
var ocspResponses = generateOCSPResponses(args, "tlsserver");
// Fresh response, certificate is good.
@ -53,9 +53,9 @@ var ocspResponseUnknown = ocspResponses[4];
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 8 requests because various hash algorithm and key size combinations
// are tried.
var willRetry = 8;
// means 4 requests because various hash algorithm combinations are tried
// (for sha-1 telemetry)
var willRetry = 4;
function run_test() {
let ocspResponder = new HttpServer();

View File

@ -249,7 +249,7 @@ function run_test() {
add_tls_server_setup("BadCertServer");
// Add a user-specified trust anchor.
addCertFromFile(certdb, "tlsserver/other-test-ca.pem", "CTu,u,u");
addCertFromFile(certdb, "tlsserver/other-test-ca.der", "CTu,u,u");
test_strict();
test_mitm();

View File

@ -1,3 +0,0 @@
issuer:Test CA
subject:EE with bad subjectAltNames
extension:subjectAlternativeName:*.*.example.com

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Before UNIX Epoch Test End-entity
validity:19460214-20310101
extension:subjectAlternativeName:before-epoch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Before UNIX Epoch Test Intermediate
validity:19460214-20310101
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -1,4 +0,0 @@
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/

View File

@ -1,5 +0,0 @@
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

Binary file not shown.

View File

@ -27,7 +27,7 @@ struct BadCertHost
// Hostname, cert nickname pairs.
const BadCertHost sBadCertHosts[] =
{
{ "expired.example.com", "expired-ee" },
{ "expired.example.com", "expired" },
{ "notyetvalid.example.com", "notYetValid" },
{ "before-epoch.example.com", "beforeEpoch" },
{ "selfsigned.example.com", "selfsigned" },
@ -38,7 +38,7 @@ const BadCertHost sBadCertHosts[] =
{ "notyetvalidissuer.example.com", "notYetValidIssuer" },
{ "before-epoch-issuer.example.com", "beforeEpochIssuer" },
{ "md5signature.example.com", "md5signature" },
{ "untrusted.example.com", "default-ee" },
{ "untrusted.example.com", "localhostAndExampleCom" },
{ "untrustedissuer.example.com", "untrustedissuer" },
{ "mismatch-expired.example.com", "mismatch-expired" },
{ "mismatch-notYetValid.example.com", "mismatch-notYetValid" },
@ -46,23 +46,23 @@ const BadCertHost sBadCertHosts[] =
{ "untrusted-expired.example.com", "untrusted-expired" },
{ "md5signature-expired.example.com", "md5signature-expired" },
{ "mismatch-untrusted-expired.example.com", "mismatch-untrusted-expired" },
{ "inadequatekeyusage.example.com", "inadequatekeyusage-ee" },
{ "inadequatekeyusage.example.com", "inadequatekeyusage" },
{ "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 default-ee. Any other nick will only
// Test Cert with nick localhostAndExampleCom. 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", "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" },
{ "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" },
{ "unknownissuer.include-subdomains.pinning.example.com", "unknownissuer" },
{ "unknownissuer.test-mode.pinning.example.com", "unknownissuer" },
{ "nsCertTypeNotCritical.example.com", "nsCertTypeNotCritical" },
@ -78,37 +78,13 @@ const BadCertHost sBadCertHosts[] =
};
int32_t
DoSNISocketConfigBySubjectCN(PRFileDesc* aFd, const SECItem* aSrvNameArr,
uint32_t aSrvNameArrSize)
DoSNISocketConfig(PRFileDesc *aFd, const SECItem *aSrvNameArr,
uint32_t aSrvNameArrSize, void *aArg)
{
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,
const BadCertHost *host = GetHostForSNI(aSrvNameArr, aSrvNameArrSize,
sBadCertHosts);
if (!host) {
// 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);
return SSL_SNI_SEND_ALERT;
}
if (gDebugLevel >= DEBUG_VERBOSE) {

View File

@ -110,6 +110,219 @@ WriteResponse(const char* filename, const SECItem* item)
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[])
{

View File

@ -27,7 +27,7 @@ const OCSPHost sOCSPHosts[] =
{ "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, "other-test-ca" },
{ "ocsp-stapling-good-other-ca.example.com", ORTGoodOtherCA, "otherCA" },
{ "ocsp-stapling-expired.example.com", ORTExpired, nullptr },
{ "ocsp-stapling-expired-fresh-ca.example.com", ORTExpiredFreshCA, nullptr },
{ "ocsp-stapling-none.example.com", ORTNone, nullptr },
@ -52,7 +52,7 @@ const OCSPHost sOCSPHosts[] =
{ "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-1016-keysizeDelegatedSigner" },
{ "keysize-ocsp-delegated.example.com", ORTDelegatedIncluded, "rsa-1008-keysizeDelegatedSigner" },
{ "revoked-ca-cert-used-as-end-entity.example.com", ORTRevoked, "ca-used-as-end-entity" },
{ nullptr, ORTNull, nullptr }
};

View File

@ -1,4 +0,0 @@
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/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Test SHA1 Delegated Responder
subjectKey:alternate
signature:sha1WithRSAEncryption
extension:extKeyUsage:OCSPSigning

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Test Delegated Responder
subjectKey:alternate
extension:extKeyUsage:OCSPSigning

View File

@ -1,4 +0,0 @@
issuer:Test End-entity
subject:EE Issued by non-CA
extension:subjectAlternativeName:localhost,*.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,3 +0,0 @@
issuer:V1 Cert
subject:EE Issued by V1 Cert
extension:subjectAlternativeName:localhost,*.example.com

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Expired Test End-entity
validity:20130101-20140101
extension:subjectAlternativeName:expired.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Expired Test Intermediate
validity:20110101-20130101
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -1,4 +0,0 @@
issuer:Expired Test Intermediate
subject:Test End-entity with expired issuer
extension:subjectAlternativeName:expiredissuer.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -0,0 +1,354 @@
#!/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

View File

@ -1,5 +0,0 @@
issuer:Test Intermediate
subject:Inadequate Key Size End-Entity
subjectKey:rsa1016
extension:subjectAlternativeName:inadequate-key-size-ee.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Inadequate Key Usage Test End-entity
extension:keyUsage:cRLSign
extension:subjectAlternativeName:inadequatekeyusage.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,4 +0,0 @@
issuer:Test Intermediate
subject:Test Invalid Delegated Responder From Intermediate
subjectKey:alternate
extension:extKeyUsage:OCSPSigning

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Test Invalid Delegated Responder keyUsage crlSigning
subjectKey:alternate
extension:keyUsage:cRLSign

View File

@ -1,3 +0,0 @@
issuer:Test CA
subject:Test Invalid Delegated Responder No extKeyUsage
subjectKey:alternate

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Test Invalid Delegated Responder Wrong extKeyUsage
subjectKey:alternate
extension:extKeyUsage:codeSigning

View File

@ -1,3 +0,0 @@
issuer:Test CA
subject:127.0.0.1
extension:subjectAlternativeName:127.0.0.1

Binary file not shown.

View File

@ -5,11 +5,7 @@
#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"
@ -26,7 +22,7 @@ static const uint16_t LISTEN_PORT = 8443;
DebugLevel gDebugLevel = DEBUG_ERRORS;
uint16_t gCallbackPort = 0;
const char DEFAULT_CERT_NICKNAME[] = "default-ee";
const char DEFAULT_CERT_NICKNAME[] = "localhostAndExampleCom";
struct Connection
{
@ -64,222 +60,6 @@ PrintPRError(const char *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)
{
@ -459,10 +239,9 @@ ConfigSecureServerWithNamedCert(PRFileDesc *fd, const char *certName,
certList->len = 2;
}
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
ScopedSECKEYPrivateKey key(PK11_FindKeyByDERCert(slot, cert, nullptr));
ScopedSECKEYPrivateKey key(PK11_FindKeyByAnyCert(cert, nullptr));
if (!key) {
PrintPRError("PK11_FindKeyByDERCert failed");
PrintPRError("PK11_FindKeyByAnyCert failed");
return SECFailure;
}
@ -507,8 +286,8 @@ StartServer(const char *nssCertDBDir, SSLSNISocketConfig sniSocketConfig,
gCallbackPort = atoi(callbackPort);
}
if (InitializeNSS(nssCertDBDir) != SECSuccess) {
PR_fprintf(PR_STDERR, "InitializeNSS failed");
if (NSS_Init(nssCertDBDir) != SECSuccess) {
PrintPRError("NSS_Init failed");
return 1;
}

View File

@ -19,13 +19,6 @@
#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
@ -49,9 +42,6 @@ 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);

View File

@ -1,6 +0,0 @@
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/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Test End-entity with MD5 signature
signature:md5WithRSAEncryption
extension:subjectAlternativeName:md5signature.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Mismatch-Expired Test End-entity
validity:20130101-20140101
extension:subjectAlternativeName:doesntmatch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Mismatch-Not Yet Valid Test End-entity
validity:20330101-20340101
extension:subjectAlternativeName:doesntmatch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Other test CA
subject:Mismatch-Untrusted-Expired Test End-entity
validity:20110101-20130101
extension:subjectAlternativeName:doesntmatch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,4 +0,0 @@
issuer:Other test CA
subject:Mismatch-Untrusted Test End-entity
extension:subjectAlternativeName:doesntmatch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Mismatch Test End-entity
extension:subjectAlternativeName:doesntmatch.example.com,*.alsodoesntmatch.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,2 +0,0 @@
issuer:Test CA
subject:doesntmatch.example.com

View File

@ -6,79 +6,3 @@
# 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]

View File

@ -1,3 +0,0 @@
issuer:Test CA
subject:End-entity with no valid names
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Not Yet Valid Test End-entity
validity:20310101-20320101
extension:subjectAlternativeName:notyetvalid.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Not Yet Valid Test Intermediate
validity:20310101-20330101
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -1,4 +0,0 @@
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/

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:nsCertType Critical
extension:subjectAlternativeName:localhost,*.example.com
extension:nsCertType[critical]:sslServer

View File

@ -1,6 +0,0 @@
issuer:Test CA
subject:nsCertType Critical With extKeyUsage
extension:subjectAlternativeName:localhost,*.example.com
extension:nsCertType[critical]:sslServer
extension:basicConstraints:,
extension:extKeyUsage:serverAuth

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:nsCertType Not Critical
extension:subjectAlternativeName:localhost,*.example.com
extension:nsCertType:sslServer

View File

@ -1,4 +0,0 @@
issuer:Test Intermediate
subject:Test End-entity with Intermediate
extension:subjectAlternativeName:localhost,*.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Other Cert
extension:subjectAlternativeName:localhost,*.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,6 +0,0 @@
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/

View File

@ -1,7 +0,0 @@
issuer:Other test CA
subject:Other test CA
issuerKey:alternate
subjectKey:alternate
validity:20150101-20250101
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -0,0 +1,5 @@
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})

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:RSA 1016 Key Size Test Delegated Responder
subjectKey:rsa1016
extension:extKeyUsage:OCSPSigning

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Another Test End-entity
extension:subjectAlternativeName:localhost,*.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,5 +0,0 @@
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

View File

@ -1,6 +0,0 @@
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/

View File

@ -1,4 +0,0 @@
issuer:Self-signed Test End-entity
subject:Self-signed Test End-entity
extension:subjectAlternativeName:selfsigned.example.com
extension:authorityInformationAccess:http://localhost:8888/

Binary file not shown.

View File

@ -1,4 +0,0 @@
issuer:Test CA
subject:Test CA
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -1,3 +0,0 @@
issuer:Test Intermediate
subject:EE issued by intermediate
extension:subjectAlternativeName:localhost

Binary file not shown.

View File

@ -1,5 +0,0 @@
issuer:Test CA
subject:Test Intermediate
validity:20150101-20250101
extension:basicConstraints:cA,
extension:keyUsage:cRLSign,keyCertSign

View File

@ -1,4 +0,0 @@
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/

View File

@ -1,5 +0,0 @@
issuer:Other test CA
subject:Untrusted-Expired Test End-entity
validity:20110101-20130101
extension:subjectAlternativeName:untrusted-expired.example.com
extension:authorityInformationAccess:http://localhost:8888/

View File

@ -1,4 +0,0 @@
issuer:Other test CA
subject:Test End-entity with untrusted issuer
extension:subjectAlternativeName:untrustedissuer.example.com
extension:authorityInformationAccess:http://localhost:8888/

Binary file not shown.

View File

@ -1,3 +0,0 @@
issuer:Test CA
subject:V1 Cert
version:1

View File

@ -8,13 +8,13 @@
// 3. run `[path to]/run-mozilla.sh [path to]/xpcshell \
// [path to]/genHPKPStaticpins.js \
// [absolute path to]/PreloadedHPKPins.json \
// [an unused argument - see bug 1205406] \
// [absolute path to]/default-ee.der \
// [absolute path to]/StaticHPKPins.h
if (arguments.length != 3) {
throw "Usage: genHPKPStaticPins.js " +
"<absolute path to PreloadedHPKPins.json> " +
"<an unused argument - see bug 1205406> " +
"<absolute path to default-ee.der> " +
"<absolute path to StaticHPKPins.h>";
}
@ -68,8 +68,7 @@ const PINSETDEF = "/* Pinsets are each an ordered list by the actual value of th
// Command-line arguments
var gStaticPins = parseJson(arguments[0]);
// arguments[1] is ignored for now. See bug 1205406.
var gTestCertFile = arguments[1];
// Open the output file.
var file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
@ -351,7 +350,7 @@ function downloadAndParseChromePins(filename,
// Returns a pair of maps [certNameToSKD, certSKDToName] between cert
// nicknames and digests of the SPKInfo for the mozilla trust store
function loadNSSCertinfo(extraCertificates) {
function loadNSSCertinfo(derTestFile, extraCertificates) {
let allCerts = gCertDB.getCerts();
let enumerator = allCerts.getEnumerator();
let certNameToSKD = {};
@ -375,10 +374,13 @@ function loadNSSCertinfo(extraCertificates) {
}
{
// This is the pinning test certificate. The key hash identifies the
// default RSA key from pykey.
// 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.
let name = "End Entity Test Cert";
let SKD = "VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=";
let SKD = testCert.sha256SubjectPublicKeyInfoDigest;
certNameToSKD[name] = SKD;
certSKDToName[SKD] = name;
}
@ -597,7 +599,8 @@ function loadExtraCertificates(certStringList) {
}
var extraCertificates = loadExtraCertificates(gStaticPins.extra_certificates);
var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(extraCertificates);
var [ certNameToSKD, certSKDToName ] = loadNSSCertinfo(gTestCertFile,
extraCertificates);
var [ chromeNameToHash, chromeNameToMozName ] = downloadAndParseChromeCerts(
gStaticPins.chromium_data.cert_file_url, certSKDToName);
var [ chromeImportedPinsets, chromeImportedEntries ] =