зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 3 changesets (bug 1178988) for ocsp orange CLOSED TREE
Backed out changeset 7fb6a9114916 (bug 1178988) Backed out changeset 2700ec4adc3e (bug 1178988) Backed out changeset 07b9c2331ac1 (bug 1178988)
This commit is contained in:
Родитель
5c8d42ea2d
Коммит
b9baa34b08
|
@ -12,7 +12,6 @@ TEST_DIRS += [
|
|||
'test_cert_version',
|
||||
'test_intermediate_basic_usage_constraints',
|
||||
'test_pinning_dynamic',
|
||||
'test_ocsp_url',
|
||||
]
|
||||
|
||||
if not CONFIG['MOZ_NO_SMART_CARDS']:
|
||||
|
|
|
@ -26,7 +26,6 @@ extKeyUsage:[serverAuth,clientAuth,codeSigning,emailProtection
|
|||
nsSGC, # Netscape Server Gated Crypto
|
||||
OCSPSigning,timeStamping]
|
||||
subjectAlternativeName:[<dNSName>,...]
|
||||
authorityInformationAccess:<OCSP URI>
|
||||
|
||||
Where:
|
||||
[] indicates an optional field or component of a field
|
||||
|
@ -49,14 +48,14 @@ or as the subject public key information field, respectively.
|
|||
|
||||
from pyasn1.codec.der import decoder
|
||||
from pyasn1.codec.der import encoder
|
||||
from pyasn1.type import constraint, tag, univ, useful
|
||||
from pyasn1.type import constraint, namedtype, tag, univ, useful
|
||||
from pyasn1_modules import rfc2459
|
||||
import base64
|
||||
import binascii
|
||||
import datetime
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
import pykey
|
||||
import rsa
|
||||
|
||||
class UnknownBaseError(Exception):
|
||||
"""Base class for handling unexpected input in this module."""
|
||||
|
@ -100,6 +99,14 @@ class UnknownKeyPurposeTypeError(UnknownBaseError):
|
|||
self.category = 'keyPurpose'
|
||||
|
||||
|
||||
class UnknownKeySpecificationError(UnknownBaseError):
|
||||
"""Helper exception type to handle unknown key specifications."""
|
||||
|
||||
def __init__(self, value):
|
||||
UnknownBaseError.__init__(self, value)
|
||||
self.category = 'key specification'
|
||||
|
||||
|
||||
class UnknownKeyTargetError(UnknownBaseError):
|
||||
"""Helper exception type to handle unknown key targets."""
|
||||
|
||||
|
@ -121,18 +128,6 @@ def getASN1Tag(asn1Type):
|
|||
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
|
||||
location. Returns an AccessDescription usable by pyasn1."""
|
||||
accessMethod = rfc2459.id_ad_ocsp
|
||||
accessLocation = rfc2459.GeneralName()
|
||||
accessLocation.setComponentByName('uniformResourceIdentifier', string)
|
||||
sequence = univ.Sequence()
|
||||
sequence.setComponentByPosition(0, accessMethod)
|
||||
sequence.setComponentByPosition(1, accessLocation)
|
||||
return sequence
|
||||
|
||||
def stringToAlgorithmIdentifier(string):
|
||||
"""Helper function that converts a description of an algorithm
|
||||
to a representation usable by the pyasn1 package"""
|
||||
|
@ -171,10 +166,97 @@ def datetimeToTime(dt):
|
|||
time.setComponentByName('generalTime', useful.GeneralizedTime(dt.strftime('%Y%m%d%H%M%SZ')))
|
||||
return time
|
||||
|
||||
def byteStringToHexifiedBitString(string):
|
||||
"""Takes a string of bytes and returns a hex string representing
|
||||
those bytes for use with pyasn1.type.univ.BitString. It must be of
|
||||
the form "'<hex bytes>'H", where the trailing 'H' indicates to
|
||||
pyasn1 that the input is a hex string."""
|
||||
return "'%s'H" % binascii.hexlify(string)
|
||||
|
||||
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 Certificate:
|
||||
"""Utility class for reading a certificate specification and
|
||||
generating a signed x509 certificate"""
|
||||
|
||||
# For reference, when encoded as a subject public key info, the
|
||||
# base64-encoded sha-256 hash of this key is
|
||||
# VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=
|
||||
sharedRSA_N = long(
|
||||
'00ba8851a8448e16d641fd6eb6880636103d3c13d9eae4354ab4ecf56857'
|
||||
'6c247bc1c725a8e0d81fbdb19c069b6e1a86f26be2af5a756b6a6471087a'
|
||||
'a55aa74587f71cd5249c027ecd43fc1e69d038202993ab20c349e4dbb94c'
|
||||
'c26b6c0eed15820ff17ead691ab1d3023a8b2a41eea770e00f0d8dfd660b'
|
||||
'2bb02492a47db988617990b157903dd23bc5e0b8481fa837d38843ef2716'
|
||||
'd855b7665aaa7e02902f3a7b10800624cc1c6c97ad96615bb7e29612c075'
|
||||
'31a30c91ddb4caf7fcad1d25d309efb9170ea768e1b37b2f226f69e3b48a'
|
||||
'95611dee26d6259dab91084e36cb1c24042cbf168b2fe5f18f991731b8b3'
|
||||
'fe4923fa7251c431d503acda180a35ed8d', 16)
|
||||
sharedRSA_E = 65537L
|
||||
sharedRSA_D = long(
|
||||
'009ecbce3861a454ecb1e0fe8f85dd43c92f5825ce2e997884d0e1a949da'
|
||||
'a2c5ac559b240450e5ac9fe0c3e31c0eefa6525a65f0c22194004ee1ab46'
|
||||
'3dde9ee82287cc93e746a91929c5e6ac3d88753f6c25ba5979e73e5d8fb2'
|
||||
'39111a3cdab8a4b0cdf5f9cab05f1233a38335c64b5560525e7e3b92ad7c'
|
||||
'7504cf1dc7cb005788afcbe1e8f95df7402a151530d5808346864eb370aa'
|
||||
'79956a587862cb533791307f70d91c96d22d001a69009b923c683388c9f3'
|
||||
'6cb9b5ebe64302041c78d908206b87009cb8cabacad3dbdb2792fb911b2c'
|
||||
'f4db6603585be9ae0ca3b8e6417aa04b06e470ea1a3b581ca03a6781c931'
|
||||
'5b62b30e6011f224725946eec57c6d9441', 16)
|
||||
sharedRSA_P = long(
|
||||
'00dd6e1d4fffebf68d889c4d114cdaaa9caa63a59374286c8a5c29a717bb'
|
||||
'a60375644d5caa674c4b8bc7326358646220e4550d7608ac27d55b6db74f'
|
||||
'8d8127ef8fa09098b69147de065573447e183d22fe7d885aceb513d9581d'
|
||||
'd5e07c1a90f5ce0879de131371ecefc9ce72e9c43dc127d238190de81177'
|
||||
'3ca5d19301f48c742b', 16)
|
||||
sharedRSA_Q = long(
|
||||
'00d7a773d9ebc380a767d2fec0934ad4e8b5667240771acdebb5ad796f47'
|
||||
'8fec4d45985efbc9532968289c8d89102fadf21f34e2dd4940eba8c09d6d'
|
||||
'1f16dcc29729774c43275e9251ddbe4909e1fd3bf1e4bedf46a39b8b3833'
|
||||
'28ef4ae3b95b92f2070af26c9e7c5c9b587fedde05e8e7d86ca57886fb16'
|
||||
'5810a77b9845bc3127', 16)
|
||||
# For reference, when encoded as a subject public key info, the
|
||||
# base64-encoded sha-256 hash of this key is
|
||||
# K+uamI+1JmrxMsBxEfGOoydEDJVMa5MY/eaTj+43Lzc=
|
||||
alternateRSA_N = long(
|
||||
'00cd6e66a71b9a104c7c5f270b5869da966a52e547f8a026eef128c4d51f'
|
||||
'a7d949b1df8a1e342c59cbad0fb6ef867427bd9e76f2e9bf0b582745c646'
|
||||
'4446db7bdd4d0f2f361da724ff206d070b3d75ad87d690fa307dcccc2ad1'
|
||||
'4283921f9621f2a564e7e9f708a98556194df12fb4b0a2f0b89f76ac7e59'
|
||||
'668285aa50f14f310b6ebd8f001d0c115393bd27f3334f67780abfe0b19e'
|
||||
'5ac3414c5b4a3819fbed39198050e1c660e44cacaf108cbe1671d5a14602'
|
||||
'6090f371b2873d419eeb6de982fb493c3d4d33fb8a12bd65f1c59a3494dd'
|
||||
'd7e1131aa45e896d817bbb28e6fd4c2323ed17a26dc8e4e49281decc641e'
|
||||
'f7b7acfe65e7c0e5212fb2a9d472902c35', 16)
|
||||
alternateRSA_E = 65537L
|
||||
alternateRSA_D = long(
|
||||
'6ae6e0946550aeda9e7e059b69ceebe90a3b490542e4545e53309bfd2c13'
|
||||
'f486dd012ea6b90fbb4aba2c4b4e29f1981c9cb1d986b9dbf56bba6b8b75'
|
||||
'4c4a3b12d65ee87a88c3ca04d9a2e2df7e84166171cecfe31c13cecb194a'
|
||||
'3b9d76c271b80b498f45b93fd0b78a2e70d8e9b26598e51bae1fdb7384a2'
|
||||
'4b99b31f9bf351d9692c00d6f05c30424be4b4de55331ac77532c3fdaf74'
|
||||
'95dbf7aef601b517ed227d0efa3de443d56d8b29e556f6be938eabf4c0e4'
|
||||
'2e2fe38bec60cba5b5ff9192b68620ee4b629b9d0b64b9a8810809813b0b'
|
||||
'04e485d97fdad2961c0982a589863643974e3900dd8a75112a0fffc59f4b'
|
||||
'24c31307901dd04a848b02db32f61a01', 16)
|
||||
alternateRSA_P = long(
|
||||
'00feeacc987c0494cb5e9550eefb9dc56f9d957022a11539dae04c6361ab'
|
||||
'd5081dce2a6aec0905450886f5bb7e56e8bd2bef37cfa16fbda5ffc268ca'
|
||||
'e0499017552c37fa4a041341d67d4d69d093d8950f50672fb085b636560e'
|
||||
'2446689474b29be7abeba358ab7bc4cde3fd065d46f762adeb5c4b54ccca'
|
||||
'651a14b498311615b1', 16)
|
||||
alternateRSA_Q = long(
|
||||
'00ce4dca3fdda86b8c800c268082446633c8aaf0f20c729878092198585b'
|
||||
'd2ed134a7bdb2c93f829f99e6e9070db6598b3113627fd87bf6bc46cb2e5'
|
||||
'121777cbea9c41e74c9c2c248931dbccb5ae8a1dccfad284784cc35b8329'
|
||||
'abc420ce95640085dbf325fa7f6a2a567d487c1ef67d07a56c6beade9404'
|
||||
'd039ba01adf328ebc5', 16)
|
||||
|
||||
def __init__(self, paramStream, now=datetime.datetime.utcnow()):
|
||||
self.versionValue = 2 # a value of 2 is X509v3
|
||||
self.signature = 'sha256WithRSAEncryption'
|
||||
|
@ -185,8 +267,13 @@ class Certificate:
|
|||
self.subject = 'Default Subject'
|
||||
self.signatureAlgorithm = 'sha256WithRSAEncryption'
|
||||
self.extensions = None
|
||||
self.subjectKey = pykey.RSAKey()
|
||||
self.issuerKey = pykey.RSAKey()
|
||||
self.subjectRSA_N = self.sharedRSA_N
|
||||
self.subjectRSA_E = self.sharedRSA_E
|
||||
self.issuerRSA_N = self.sharedRSA_N
|
||||
self.issuerRSA_E = self.sharedRSA_E
|
||||
self.issuerRSA_D = self.sharedRSA_D
|
||||
self.issuerRSA_P = self.sharedRSA_P
|
||||
self.issuerRSA_Q = self.sharedRSA_Q
|
||||
self.decodeParams(paramStream)
|
||||
self.serialNumber = self.generateSerialNumber()
|
||||
|
||||
|
@ -260,18 +347,24 @@ class Certificate:
|
|||
self.addExtKeyUsage(value)
|
||||
elif extensionType == 'subjectAlternativeName':
|
||||
self.addSubjectAlternativeName(value)
|
||||
elif extensionType == 'authorityInformationAccess':
|
||||
self.addAuthorityInformationAccess(value)
|
||||
else:
|
||||
raise UnknownExtensionTypeError(extensionType)
|
||||
|
||||
def setupKey(self, subjectOrIssuer, value):
|
||||
if subjectOrIssuer == 'subject':
|
||||
self.subjectKey = pykey.RSAKey(value)
|
||||
elif subjectOrIssuer == 'issuer':
|
||||
self.issuerKey = pykey.RSAKey(value)
|
||||
if value == 'alternate':
|
||||
if subjectOrIssuer == 'subject':
|
||||
self.subjectRSA_N = self.alternateRSA_N
|
||||
self.subjectRSA_E = self.alternateRSA_E
|
||||
elif subjectOrIssuer == 'issuer':
|
||||
self.issuerRSA_N = self.alternateRSA_N
|
||||
self.issuerRSA_E = self.alternateRSA_E
|
||||
self.issuerRSA_D = self.alternateRSA_D
|
||||
self.issuerRSA_P = self.alternateRSA_P
|
||||
self.issuerRSA_Q = self.alternateRSA_Q
|
||||
else:
|
||||
raise UnknownKeyTargetError(subjectOrIssuer)
|
||||
else:
|
||||
raise UnknownKeyTargetError(subjectOrIssuer)
|
||||
raise UnknownKeySpecificationError(value)
|
||||
|
||||
def addExtension(self, extensionType, extensionValue):
|
||||
if not self.extensions:
|
||||
|
@ -336,12 +429,6 @@ class Certificate:
|
|||
count += 1
|
||||
self.addExtension(rfc2459.id_ce_subjectAltName, subjectAlternativeName)
|
||||
|
||||
def addAuthorityInformationAccess(self, ocspURI):
|
||||
sequence = univ.Sequence()
|
||||
accessDescription = stringToAccessDescription(ocspURI)
|
||||
sequence.setComponentByPosition(0, accessDescription)
|
||||
self.addExtension(rfc2459.id_pe_authorityInfoAccess, sequence)
|
||||
|
||||
def getVersion(self):
|
||||
return rfc2459.Version(self.versionValue).subtype(
|
||||
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))
|
||||
|
@ -373,6 +460,21 @@ class Certificate:
|
|||
def getSignatureAlgorithm(self):
|
||||
return stringToAlgorithmIdentifier(self.signature)
|
||||
|
||||
def getSubjectPublicKey(self):
|
||||
rsaKey = RSAPublicKey()
|
||||
rsaKey.setComponentByName('N', univ.Integer(self.subjectRSA_N))
|
||||
rsaKey.setComponentByName('E', univ.Integer(self.subjectRSA_E))
|
||||
return univ.BitString(byteStringToHexifiedBitString(encoder.encode(rsaKey)))
|
||||
|
||||
def getSubjectPublicKeyInfo(self):
|
||||
algorithmIdentifier = rfc2459.AlgorithmIdentifier()
|
||||
algorithmIdentifier.setComponentByName('algorithm', rfc2459.rsaEncryption)
|
||||
algorithmIdentifier.setComponentByName('parameters', univ.Null())
|
||||
spki = rfc2459.SubjectPublicKeyInfo()
|
||||
spki.setComponentByName('algorithm', algorithmIdentifier)
|
||||
spki.setComponentByName('subjectPublicKey', self.getSubjectPublicKey())
|
||||
return spki
|
||||
|
||||
def toDER(self):
|
||||
tbsCertificate = rfc2459.TBSCertificate()
|
||||
tbsCertificate.setComponentByName('version', self.getVersion())
|
||||
|
@ -381,8 +483,7 @@ class Certificate:
|
|||
tbsCertificate.setComponentByName('issuer', self.getIssuer())
|
||||
tbsCertificate.setComponentByName('validity', self.getValidity())
|
||||
tbsCertificate.setComponentByName('subject', self.getSubject())
|
||||
tbsCertificate.setComponentByName('subjectPublicKeyInfo',
|
||||
self.subjectKey.asSubjectPublicKeyInfo())
|
||||
tbsCertificate.setComponentByName('subjectPublicKeyInfo', self.getSubjectPublicKeyInfo())
|
||||
if self.extensions:
|
||||
extensions = rfc2459.Extensions().subtype(
|
||||
explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 3))
|
||||
|
@ -391,11 +492,14 @@ class Certificate:
|
|||
extensions.setComponentByPosition(count, extension)
|
||||
count += 1
|
||||
tbsCertificate.setComponentByName('extensions', extensions)
|
||||
tbsDER = encoder.encode(tbsCertificate)
|
||||
rsaPrivateKey = rsa.PrivateKey(self.issuerRSA_N, self.issuerRSA_E, self.issuerRSA_D,
|
||||
self.issuerRSA_P, self.issuerRSA_Q)
|
||||
signature = rsa.sign(tbsDER, rsaPrivateKey, 'SHA-256')
|
||||
certificate = rfc2459.Certificate()
|
||||
certificate.setComponentByName('tbsCertificate', tbsCertificate)
|
||||
certificate.setComponentByName('signatureAlgorithm', self.getSignatureAlgorithm())
|
||||
tbsDER = encoder.encode(tbsCertificate)
|
||||
certificate.setComponentByName('signatureValue', self.issuerKey.sign(tbsDER))
|
||||
certificate.setComponentByName('signatureValue', byteStringToHexifiedBitString(signature))
|
||||
return encoder.encode(certificate)
|
||||
|
||||
def toPEM(self):
|
||||
|
|
|
@ -1,282 +0,0 @@
|
|||
#!/usr/bin/env 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/.
|
||||
|
||||
"""
|
||||
Reads a key specification from stdin or a file and outputs a
|
||||
PKCS #8 file representing the (private) key. Also provides
|
||||
methods for signing data and representing the key as a subject
|
||||
public key info for use with pyasn1.
|
||||
|
||||
The key specification format is currently very simple. If it is
|
||||
empty, one RSA key is used. If it consists of the string
|
||||
'alternate', a different RSA key is used. In the future it will
|
||||
be possible to specify other properties of the key (type,
|
||||
strength, signature algorithm, etc.).
|
||||
"""
|
||||
|
||||
from pyasn1.codec.der import encoder
|
||||
from pyasn1.type import univ, namedtype
|
||||
from pyasn1_modules import rfc2459
|
||||
import base64
|
||||
import binascii
|
||||
import rsa
|
||||
import sys
|
||||
|
||||
def byteStringToHexifiedBitString(string):
|
||||
"""Takes a string of bytes and returns a hex string representing
|
||||
those bytes for use with pyasn1.type.univ.BitString. It must be of
|
||||
the form "'<hex bytes>'H", where the trailing 'H' indicates to
|
||||
pyasn1 that the input is a hex string."""
|
||||
return "'%s'H" % binascii.hexlify(string)
|
||||
|
||||
class UnknownBaseError(Exception):
|
||||
"""Base class for handling unexpected input in this module."""
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
self.category = 'input'
|
||||
|
||||
def __str__(self):
|
||||
return 'Unknown %s type "%s"' % (self.category, repr(self.value))
|
||||
|
||||
|
||||
class UnknownKeySpecificationError(UnknownBaseError):
|
||||
"""Helper exception type to handle unknown key specifications."""
|
||||
|
||||
def __init__(self, value):
|
||||
UnknownBaseError.__init__(self, value)
|
||||
self.category = 'key specification'
|
||||
|
||||
|
||||
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):
|
||||
"""Helper type for encoding an RSA private key"""
|
||||
componentType = namedtype.NamedTypes(
|
||||
namedtype.NamedType('version', univ.Integer()),
|
||||
namedtype.NamedType('modulus', univ.Integer()),
|
||||
namedtype.NamedType('publicExponent', univ.Integer()),
|
||||
namedtype.NamedType('privateExponent', univ.Integer()),
|
||||
namedtype.NamedType('prime1', univ.Integer()),
|
||||
namedtype.NamedType('prime2', univ.Integer()),
|
||||
namedtype.NamedType('exponent1', univ.Integer()),
|
||||
namedtype.NamedType('exponent2', univ.Integer()),
|
||||
namedtype.NamedType('coefficient', univ.Integer()),
|
||||
)
|
||||
|
||||
|
||||
class PrivateKeyInfo(univ.Sequence):
|
||||
"""Helper type for encoding a PKCS #8 private key info"""
|
||||
componentType = namedtype.NamedTypes(
|
||||
namedtype.NamedType('version', univ.Integer()),
|
||||
namedtype.NamedType('privateKeyAlgorithm', rfc2459.AlgorithmIdentifier()),
|
||||
namedtype.NamedType('privateKey', univ.OctetString())
|
||||
)
|
||||
|
||||
|
||||
class RSAKey:
|
||||
# For reference, when encoded as a subject public key info, the
|
||||
# base64-encoded sha-256 hash of this key is
|
||||
# VCIlmPM9NkgFQtrs4Oa5TeFcDu6MWRTKSNdePEhOgD8=
|
||||
sharedRSA_N = long(
|
||||
'00ba8851a8448e16d641fd6eb6880636103d3c13d9eae4354ab4ecf56857'
|
||||
'6c247bc1c725a8e0d81fbdb19c069b6e1a86f26be2af5a756b6a6471087a'
|
||||
'a55aa74587f71cd5249c027ecd43fc1e69d038202993ab20c349e4dbb94c'
|
||||
'c26b6c0eed15820ff17ead691ab1d3023a8b2a41eea770e00f0d8dfd660b'
|
||||
'2bb02492a47db988617990b157903dd23bc5e0b8481fa837d38843ef2716'
|
||||
'd855b7665aaa7e02902f3a7b10800624cc1c6c97ad96615bb7e29612c075'
|
||||
'31a30c91ddb4caf7fcad1d25d309efb9170ea768e1b37b2f226f69e3b48a'
|
||||
'95611dee26d6259dab91084e36cb1c24042cbf168b2fe5f18f991731b8b3'
|
||||
'fe4923fa7251c431d503acda180a35ed8d', 16)
|
||||
sharedRSA_E = 65537L
|
||||
sharedRSA_D = long(
|
||||
'009ecbce3861a454ecb1e0fe8f85dd43c92f5825ce2e997884d0e1a949da'
|
||||
'a2c5ac559b240450e5ac9fe0c3e31c0eefa6525a65f0c22194004ee1ab46'
|
||||
'3dde9ee82287cc93e746a91929c5e6ac3d88753f6c25ba5979e73e5d8fb2'
|
||||
'39111a3cdab8a4b0cdf5f9cab05f1233a38335c64b5560525e7e3b92ad7c'
|
||||
'7504cf1dc7cb005788afcbe1e8f95df7402a151530d5808346864eb370aa'
|
||||
'79956a587862cb533791307f70d91c96d22d001a69009b923c683388c9f3'
|
||||
'6cb9b5ebe64302041c78d908206b87009cb8cabacad3dbdb2792fb911b2c'
|
||||
'f4db6603585be9ae0ca3b8e6417aa04b06e470ea1a3b581ca03a6781c931'
|
||||
'5b62b30e6011f224725946eec57c6d9441', 16)
|
||||
sharedRSA_P = long(
|
||||
'00dd6e1d4fffebf68d889c4d114cdaaa9caa63a59374286c8a5c29a717bb'
|
||||
'a60375644d5caa674c4b8bc7326358646220e4550d7608ac27d55b6db74f'
|
||||
'8d8127ef8fa09098b69147de065573447e183d22fe7d885aceb513d9581d'
|
||||
'd5e07c1a90f5ce0879de131371ecefc9ce72e9c43dc127d238190de81177'
|
||||
'3ca5d19301f48c742b', 16)
|
||||
sharedRSA_Q = long(
|
||||
'00d7a773d9ebc380a767d2fec0934ad4e8b5667240771acdebb5ad796f47'
|
||||
'8fec4d45985efbc9532968289c8d89102fadf21f34e2dd4940eba8c09d6d'
|
||||
'1f16dcc29729774c43275e9251ddbe4909e1fd3bf1e4bedf46a39b8b3833'
|
||||
'28ef4ae3b95b92f2070af26c9e7c5c9b587fedde05e8e7d86ca57886fb16'
|
||||
'5810a77b9845bc3127', 16)
|
||||
sharedRSA_exp1 = long(
|
||||
'0096472b41a610c0ade1af2266c1600e3671355ba42d4b5a0eb4e9d7eb35'
|
||||
'81400ba5dd132cdb1a5e9328c7bbc0bbb0155ea192972edf97d12751d8fc'
|
||||
'f6ae572a30b1ea309a8712dd4e33241db1ee455fc093f5bc9b592d756e66'
|
||||
'21474f32c07af22fb275d340792b32ba2590bbb261aefb95a258eea53765'
|
||||
'5315be9c24d191992d', 16)
|
||||
sharedRSA_exp2 = long(
|
||||
'28b450a7a75a856413b2bda6f7a63e3d964fb9ecf50e3823ef6cc8e8fa26'
|
||||
'ee413f8b9d1205540f12bbe7a0c76828b7ba65ad83cca4d0fe2a220114e1'
|
||||
'b35d03d5a85bfe2706bd50fce6cfcdd571b46ca621b8ed47d605bbe765b0'
|
||||
'aa4a0665ac25364da20154032e1204b8559d3e34fb5b177c9a56ff93510a'
|
||||
'5a4a6287c151de2d', 16)
|
||||
sharedRSA_coef = long(
|
||||
'28067b9355801d2ef52dfa96d8adb589673cf8ee8a9c6ff72aeeabe9ef6b'
|
||||
'e58a4f4abf05f788947dc851fdaa34542147a71a246bfb054ee76aa346ab'
|
||||
'cd2692cfc9e44c51e6f069c735e073ba019f6a7214961c91b26871caeabf'
|
||||
'8f064418a02690e39a8d5ff3067b7cdb7f50b1f53418a703966c4fc774bf'
|
||||
'7402af6c43247f43', 16)
|
||||
|
||||
# For reference, when encoded as a subject public key info, the
|
||||
# base64-encoded sha-256 hash of this key is
|
||||
# MQj2tt1yGAfwFpWETYUCVrZxk2CD2705NKBQUlAaKJI=
|
||||
alternateRSA_N = long(
|
||||
'00c175c65266099f77082a6791f1b876c37f5ce538b06c4acd22b1cbd46f'
|
||||
'a65ada2add41c8c2498ac4a3b3c1f61487f41b698941bd80a51c3c120244'
|
||||
'c584a4c4483305e5138c0106cf08be9a862760bae6a2e8f36f23c5d98313'
|
||||
'b9dfaf378345dace51d4d6dcd2a6cb3cc706ebcd3070ec98cce40aa591d7'
|
||||
'295a7f71c5be66691d2b2dfec84944590bc5a3ea49fd93b1d753405f1773'
|
||||
'7699958666254797ed426908880811422069988a43fee48ce68781dd22b6'
|
||||
'a69cd28375131f932b128ce286fa7d251c062ad27ef016f187cdd54e832b'
|
||||
'35b8930f74ba90aa8bc76167242ab1fd6d62140d18c4c0b8c68fc3748457'
|
||||
'324ad7de86e6552f1d1e191d712168d3bb', 16)
|
||||
alternateRSA_E = 65537L
|
||||
alternateRSA_D = long(
|
||||
'7e3f6d7cb839ef66ae5d7dd92ff5410bb341dc14728d39034570e1a37079'
|
||||
'0f30f0681355fff41e2ad4e9a9d9fcebfbd127bdfab8c00affb1f3cea732'
|
||||
'7ead47aa1621f2ac1ee14ca02f04b3b2786017980b181a449d03b03e69d1'
|
||||
'12b83571e55434f012056575d2832ed6731dce799e37c83f6d51c55ab71e'
|
||||
'b58015af05e1af15c747603ef7f27d03a6ff049d96bbf854c1e4e50ef5b0'
|
||||
'58d0fb08180e0ac7f7be8f2ff1673d97fc9e55dba838077bbf8a7cff2962'
|
||||
'857785269cd9d5bad2b57469e4afcd33c4ca2d2f699f11e7c8fbdcd484f0'
|
||||
'8d8efb8a3cb8a972eb24bed972efaae4bb712093e48fe94a46eb629a8750'
|
||||
'78c4021a9a2c93c9a70390e9d0a54401', 16)
|
||||
alternateRSA_P = long(
|
||||
'00e63fc725a6ba76925a7ff8cb59c4f56dd7ec83fe85bf1f53e11cac9a81'
|
||||
'258bcfc0ae819077b0f2d1477aaf868de6a8ecbeaf7bb22b196f2a9ad82d'
|
||||
'3286f0d0cc29de719e5f2be8e509b7284d5963edd362f927887a4c4a8979'
|
||||
'9d340d51b301ac7601ab27179024fcaadd38bf6522af63eb16461ec02a7f'
|
||||
'27b06fe09ddda7c0a1', 16)
|
||||
alternateRSA_Q = long(
|
||||
'00d718b1fe9f8f99f00e832ae1fbdc6fe2ab27f34e049c498010fa0eb708'
|
||||
'4852182346083b5c96c3eee5592c014a410c6b930b165c13b5c26aa32eac'
|
||||
'6e7c925a8551c25134f2f4a72c6421f19a73148a0edfaba5d3a6888b35cb'
|
||||
'a18c00fd38ee5aaf0b545731d720761bbccdee744a52ca415e98e4de01cd'
|
||||
'fe764c1967b3e8cadb', 16)
|
||||
alternateRSA_exp1 = long(
|
||||
'01e5aca266c94a88d22e13c2b92ea247116c657a076817bdfd30db4b3a9d'
|
||||
'3095b9a4b6749647e2f84e7a784fc7838b08c85971cf7a036fa30e3b91c3'
|
||||
'c4d0df278f80c1b6e859d8456adb137defaa9f1f0ac5bac9a9184fd4ea27'
|
||||
'9d722ea626f160d78aad7bc83845ccb29df115c83f61b7622b99bd439c60'
|
||||
'9b5790a63c595181', 16)
|
||||
alternateRSA_exp2 = long(
|
||||
'0080cc45d10d2484ee0d1297fc07bf80b3beff461ea27e1f38f371789c3a'
|
||||
'f66b4a0edd2192c227791db4f1c77ae246bf342f31856b0f56581b58a95b'
|
||||
'1131c0c5396db2a8c3c6f39ea2e336bc205ae6a2a0b36869fca98cbba733'
|
||||
'cf01319a6f9bb26b7ca23d3017fc551cd8da8afdd17f6fa2e30d34868798'
|
||||
'1cd6234d571e90b7df', 16)
|
||||
alternateRSA_coef = long(
|
||||
'6f77c0c1f2ae7ac169561cca499c52bdfbe04cddccdbdc12aec5a85691e8'
|
||||
'594b7ee29908f30e7b96aa6254b80ed4aeec9b993782bdfc79b69d8d58c6'
|
||||
'8870fa4be1bc0c3527288c5c82bb4aebaf15edff110403fc78e6ace6a828'
|
||||
'27bf42f0cfa751e507651c5638db9393dd23dd1f6b295151de44b77fe55a'
|
||||
'7b0df271e19a65c0', 16)
|
||||
|
||||
def __init__(self, specification = None):
|
||||
if not specification:
|
||||
self.RSA_N = self.sharedRSA_N
|
||||
self.RSA_E = self.sharedRSA_E
|
||||
self.RSA_D = self.sharedRSA_D
|
||||
self.RSA_P = self.sharedRSA_P
|
||||
self.RSA_Q = self.sharedRSA_Q
|
||||
self.RSA_exp1 = self.sharedRSA_exp1
|
||||
self.RSA_exp2 = self.sharedRSA_exp2
|
||||
self.RSA_coef = self.sharedRSA_coef
|
||||
elif specification == 'alternate':
|
||||
self.RSA_N = self.alternateRSA_N
|
||||
self.RSA_E = self.alternateRSA_E
|
||||
self.RSA_D = self.alternateRSA_D
|
||||
self.RSA_P = self.alternateRSA_P
|
||||
self.RSA_Q = self.alternateRSA_Q
|
||||
self.RSA_exp1 = self.alternateRSA_exp1
|
||||
self.RSA_exp2 = self.alternateRSA_exp2
|
||||
self.RSA_coef = self.alternateRSA_coef
|
||||
else:
|
||||
raise UnknownKeySpecificationError(specification)
|
||||
|
||||
def toDER(self):
|
||||
privateKeyInfo = PrivateKeyInfo()
|
||||
privateKeyInfo.setComponentByName('version', 0)
|
||||
algorithmIdentifier = rfc2459.AlgorithmIdentifier()
|
||||
algorithmIdentifier.setComponentByName('algorithm', rfc2459.rsaEncryption)
|
||||
algorithmIdentifier.setComponentByName('parameters', univ.Null())
|
||||
privateKeyInfo.setComponentByName('privateKeyAlgorithm', algorithmIdentifier)
|
||||
rsaPrivateKey = RSAPrivateKey()
|
||||
rsaPrivateKey.setComponentByName('version', 0)
|
||||
rsaPrivateKey.setComponentByName('modulus', self.RSA_N)
|
||||
rsaPrivateKey.setComponentByName('publicExponent', self.RSA_E)
|
||||
rsaPrivateKey.setComponentByName('privateExponent', self.RSA_D)
|
||||
rsaPrivateKey.setComponentByName('prime1', self.RSA_P)
|
||||
rsaPrivateKey.setComponentByName('prime2', self.RSA_Q)
|
||||
rsaPrivateKey.setComponentByName('exponent1', self.RSA_exp1)
|
||||
rsaPrivateKey.setComponentByName('exponent2', self.RSA_exp2)
|
||||
rsaPrivateKey.setComponentByName('coefficient', self.RSA_coef)
|
||||
rsaPrivateKeyEncoded = encoder.encode(rsaPrivateKey)
|
||||
privateKeyInfo.setComponentByName('privateKey', univ.OctetString(rsaPrivateKeyEncoded))
|
||||
return encoder.encode(privateKeyInfo)
|
||||
|
||||
def toPEM(self):
|
||||
output = '-----BEGIN PRIVATE KEY-----'
|
||||
der = self.toDER()
|
||||
b64 = base64.b64encode(der)
|
||||
while b64:
|
||||
output += '\n' + b64[:64]
|
||||
b64 = b64[64:]
|
||||
output += '\n-----END PRIVATE KEY-----'
|
||||
return output
|
||||
|
||||
def asSubjectPublicKeyInfo(self):
|
||||
"""Returns a subject public key info representing
|
||||
this key for use by pyasn1."""
|
||||
algorithmIdentifier = rfc2459.AlgorithmIdentifier()
|
||||
algorithmIdentifier.setComponentByName('algorithm', rfc2459.rsaEncryption)
|
||||
algorithmIdentifier.setComponentByName('parameters', univ.Null())
|
||||
spki = rfc2459.SubjectPublicKeyInfo()
|
||||
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):
|
||||
"""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, 'SHA-256')
|
||||
return byteStringToHexifiedBitString(signature)
|
||||
|
||||
|
||||
# The build harness will call this function with an output file-like
|
||||
# object and a path to a file containing a specification. This will
|
||||
# read the specification and output the key as ASCII-encoded PKCS #8.
|
||||
def main(output, inputPath):
|
||||
with open(inputPath) as configStream:
|
||||
output.write(RSAKey(configStream.read()).toPEM())
|
||||
|
||||
# When run as a standalone program, this will read a specification from
|
||||
# stdin and output the certificate as PEM to stdout.
|
||||
if __name__ == '__main__':
|
||||
print RSAKey(sys.stdin.read()).toPEM()
|
|
@ -25,14 +25,14 @@ function start_ocsp_responder(expectedCertNames, expectedPaths) {
|
|||
}
|
||||
|
||||
function check_cert_err(cert_name, expected_error) {
|
||||
let cert = constructCertFromFile("test_ocsp_url/" + cert_name + ".pem");
|
||||
let cert = constructCertFromFile("test_ocsp_url/" + cert_name + ".der");
|
||||
return checkCertErrorGeneric(certdb, cert, expected_error,
|
||||
certificateUsageSSLServer);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
addCertFromFile(certdb, "test_ocsp_url/ca.pem", 'CTu,CTu,CTu');
|
||||
addCertFromFile(certdb, "test_ocsp_url/int.pem", ',,');
|
||||
addCertFromFile(certdb, "test_ocsp_url/ca.der", 'CTu,CTu,CTu');
|
||||
addCertFromFile(certdb, "test_ocsp_url/int.der", ',,');
|
||||
|
||||
// Enabled so that we can force ocsp failure responses.
|
||||
Services.prefs.setBoolPref("security.OCSP.require", true);
|
||||
|
@ -44,7 +44,7 @@ function run_test() {
|
|||
add_test(function() {
|
||||
clearOCSPCache();
|
||||
let ocspResponder = failingOCSPResponder();
|
||||
check_cert_err("bad-scheme", SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
|
||||
check_cert_err("bad-scheme",SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
|
||||
ocspResponder.stop(run_next_test);
|
||||
});
|
||||
|
||||
|
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:bad-scheme
|
||||
extension:authorityInformationAccess:/www.example.com
|
Двоичный файл не отображается.
|
@ -1,4 +0,0 @@
|
|||
issuer:ca
|
||||
subject:ca
|
||||
extension:basicConstraints:cA,
|
||||
extension:keyUsage:keyCertSign,cRLSign
|
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:empty-port
|
||||
extension:authorityInformationAccess:http://www.example.com:/
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:empty-scheme-url
|
||||
extension:authorityInformationAccess:://www.example.com:8888/
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:ftp-url
|
||||
extension:authorityInformationAccess:ftp://www.example.com:8888/
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import tempfile, os, sys
|
||||
|
||||
libpath = os.path.abspath('../psm_common_py')
|
||||
sys.path.append(libpath)
|
||||
import CertUtils
|
||||
|
||||
srcdir = os.getcwd()
|
||||
db = tempfile.mkdtemp()
|
||||
|
||||
def generate_ca_cert(db_dir, dest_dir, noise_file, name):
|
||||
return CertUtils.generate_ca_cert(db_dir, dest_dir, noise_file, name,
|
||||
3, True)
|
||||
|
||||
def generate_child_cert(db_dir, dest_dir, noise_file, name, ca_nick, is_ee,
|
||||
ocsp_url):
|
||||
return CertUtils.generate_child_cert(db_dir, dest_dir, noise_file, name,
|
||||
ca_nick, 3, True, is_ee, ocsp_url)
|
||||
|
||||
def generate_certs():
|
||||
[noise_file, pwd_file] = CertUtils.init_nss_db(srcdir)
|
||||
generate_ca_cert(srcdir, srcdir, noise_file, 'ca')
|
||||
generate_child_cert(srcdir, srcdir, noise_file, 'int', 'ca', False, '')
|
||||
nick_baseurl = { 'no-path-url': "http://www.example.com:8888",
|
||||
'ftp-url': "ftp://www.example.com:8888/",
|
||||
'no-scheme-url': "www.example.com:8888/",
|
||||
'empty-scheme-url': "://www.example.com:8888/",
|
||||
'no-host-url': "http://:8888/",
|
||||
'hTTp-url': "hTTp://www.example.com:8888/hTTp-url",
|
||||
'https-url': "https://www.example.com:8888/https-url",
|
||||
'bad-scheme': "/www.example.com",
|
||||
'empty-port': "http://www.example.com:/",
|
||||
'unknown-scheme': "ttp://www.example.com",
|
||||
'negative-port': "http://www.example.com:-1",
|
||||
'no-scheme-host-port': "/" }
|
||||
for nick, url in nick_baseurl.iteritems():
|
||||
generate_child_cert(srcdir, srcdir, noise_file, nick, 'int', True, url)
|
||||
|
||||
generate_certs()
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:hTTp-url
|
||||
extension:authorityInformationAccess:hTTp://www.example.com:8888/hTTp-url
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:https-url
|
||||
extension:authorityInformationAccess:https://www.example.com:8888/https-url
|
Двоичный файл не отображается.
|
@ -1,4 +0,0 @@
|
|||
issuer:ca
|
||||
subject:int
|
||||
extension:basicConstraints:cA,
|
||||
extension:keyUsage:keyCertSign,cRLSign
|
Двоичный файл не отображается.
|
@ -1,42 +0,0 @@
|
|||
# -*- 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/.
|
||||
|
||||
test_certificates = (
|
||||
'bad-scheme.pem',
|
||||
'ca.pem',
|
||||
'empty-port.pem',
|
||||
'empty-scheme-url.pem',
|
||||
'ftp-url.pem',
|
||||
'hTTp-url.pem',
|
||||
'https-url.pem',
|
||||
'int.pem',
|
||||
'negative-port.pem',
|
||||
'no-host-url.pem',
|
||||
'no-path-url.pem',
|
||||
'no-scheme-host-port.pem',
|
||||
'no-scheme-url.pem',
|
||||
'unknown-scheme.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, '!/config/buildid']
|
||||
TEST_HARNESS_FILES.xpcshell.security.manager.ssl.tests.unit.test_ocsp_url += ['!%s' % test_certificate]
|
||||
|
||||
test_keys = (
|
||||
'int.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.test_ocsp_url += ['!%s' % test_key]
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:negative-port
|
||||
extension:authorityInformationAccess:http://www.example.com:-1
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:no-host-url
|
||||
extension:authorityInformationAccess:http://:8888/
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:no-path-url
|
||||
extension:authorityInformationAccess:http://www.example.com:8888
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:no-scheme-host-port
|
||||
extension:authorityInformationAccess:/
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:no-scheme-url
|
||||
extension:authorityInformationAccess:www.example.com:8888/
|
|
@ -0,0 +1,5 @@
|
|||
library=
|
||||
name=NSS Internal PKCS #11 Module
|
||||
parameters=configdir='sql:./security/manager/ssl/tests/unit/test_ocsp_url' 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})
|
||||
|
Двоичный файл не отображается.
|
@ -1,3 +0,0 @@
|
|||
issuer:int
|
||||
subject:unknown-scheme-url
|
||||
extension:authorityInformationAccess:ttp://www.example.com
|
|
@ -10,13 +10,9 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "base64.h"
|
||||
#include "cert.h"
|
||||
#include "nspr.h"
|
||||
#include "nss.h"
|
||||
#include "plarenas.h"
|
||||
|
@ -70,8 +66,9 @@ const static OCSPResponseName kOCSPResponseNameList[] = {
|
|||
// two years old
|
||||
};
|
||||
|
||||
|
||||
bool
|
||||
StringToOCSPResponseType(const char* respText,
|
||||
stringToOCSPResponseType(const char* respText,
|
||||
/*out*/ OCSPResponseType* OCSPType)
|
||||
{
|
||||
if (!OCSPType) {
|
||||
|
@ -110,216 +107,7 @@ 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 PR_ReadDir (more
|
||||
// specifically, something is causing PR_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.
|
||||
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[])
|
||||
|
@ -332,9 +120,12 @@ main(int argc, char* argv[])
|
|||
argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
SECStatus rv = InitializeNSS(argv[1]);
|
||||
const char* dbdir = argv[1];
|
||||
|
||||
SECStatus rv;
|
||||
rv = NSS_Init(dbdir);
|
||||
if (rv != SECSuccess) {
|
||||
PR_fprintf(PR_STDERR, "Failed to initialize NSS\n");
|
||||
PrintPRError("Failed to initialize NSS");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
PLArenaPool* arena = PORT_NewArena(256 * argc);
|
||||
|
@ -350,15 +141,15 @@ main(int argc, char* argv[])
|
|||
const char* filename = argv[i + 3];
|
||||
|
||||
OCSPResponseType ORT;
|
||||
if (!StringToOCSPResponseType(ocspTypeText, &ORT)) {
|
||||
if (!stringToOCSPResponseType(ocspTypeText, &ORT)) {
|
||||
PR_fprintf(PR_STDERR, "Cannot generate OCSP response of type %s\n",
|
||||
ocspTypeText);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ScopedCERTCertificate cert(PK11_FindCertFromNickname(certNick, nullptr));
|
||||
ScopedCERTCertificate cert;
|
||||
cert = PK11_FindCertFromNickname(certNick, nullptr);
|
||||
if (!cert) {
|
||||
PrintPRError("PK11_FindCertFromNickname failed");
|
||||
PR_fprintf(PR_STDERR, "Failed to find certificate with nick '%s'\n",
|
||||
certNick);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
Загрузка…
Ссылка в новой задаче