Bug 1464869 - Run autopep8 on security/ r=fkiefer

MozReview-Commit-ID: K3aWVqsO0O8

--HG--
extra : rebase_source : 6bcf97b8b4a6e70113f36d8097f26816ce4b0acf
This commit is contained in:
Sylvestre Ledru 2018-05-26 06:47:27 -07:00
parent 288239cebe
commit 9fa6cfa8d4
11 changed files with 110 additions and 60 deletions

View File

@ -4,22 +4,25 @@
import binascii
def _file_byte_generator(filename):
with open(filename, "rb") as f:
contents = f.read()
with open(filename, "rb") as f:
contents = f.read()
# Treat empty files the same as a file containing a lone 0;
# a single-element array will fail cert verifcation just as an
# empty array would.
if not contents:
return ['\0']
# Treat empty files the same as a file containing a lone 0;
# a single-element array will fail cert verifcation just as an
# empty array would.
if not contents:
return ['\0']
return contents
return contents
def _create_header(array_name, cert_bytes):
hexified = ["0x" + binascii.hexlify(byte) for byte in cert_bytes]
substs = { 'array_name': array_name, 'bytes': ', '.join(hexified) }
return "const uint8_t %(array_name)s[] = {\n%(bytes)s\n};\n" % substs
hexified = ["0x" + binascii.hexlify(byte) for byte in cert_bytes]
substs = {'array_name': array_name, 'bytes': ', '.join(hexified)}
return "const uint8_t %(array_name)s[] = {\n%(bytes)s\n};\n" % substs
# Create functions named the same as the data arrays that we're going to
# write to the headers, so we don't have to duplicate the names like so:
@ -27,12 +30,13 @@ def _create_header(array_name, cert_bytes):
# def arrayName(header, cert_filename):
# header.write(_create_header("arrayName", cert_filename))
array_names = [
'xpcshellRoot',
'addonsPublicRoot',
'addonsStageRoot',
'privilegedPackageRoot',
'xpcshellRoot',
'addonsPublicRoot',
'addonsStageRoot',
'privilegedPackageRoot',
]
for n in array_names:
# Make sure the lambda captures the right string.
globals()[n] = lambda header, cert_filename, name=n: header.write(_create_header(name, _file_byte_generator(cert_filename)))
# Make sure the lambda captures the right string.
globals()[n] = lambda header, cert_filename, name=n: header.write(
_create_header(name, _file_byte_generator(cert_filename)))

View File

@ -7,9 +7,10 @@ import buildconfig
import os
import subprocess
def main(output, *inputs):
env=dict(os.environ)
env = dict(os.environ)
env['PERL'] = str(buildconfig.substs['PERL'])
output.write(subprocess.check_output([buildconfig.substs['PYTHON'],
inputs[0], inputs[2]], env=env))
inputs[0], inputs[2]], env=env))
return None

View File

@ -105,6 +105,7 @@ class Error(Exception):
class UnknownBaseError(Error):
"""Base class for handling unexpected input in this module."""
def __init__(self, value):
super(UnknownBaseError, self).__init__()
self.value = value
@ -222,6 +223,7 @@ def getASN1Tag(asn1Type):
type from the pyasn1 package"""
return asn1Type.tagSet.baseTag.tagId
def stringToAccessDescription(string):
"""Helper function that takes a string representing a URI
presumably identifying an OCSP authority information access
@ -234,6 +236,7 @@ def stringToAccessDescription(string):
sequence.setComponentByPosition(1, accessLocation)
return sequence
def stringToDN(string, tag=None):
"""Takes a string representing a distinguished name or directory
name and returns a Name for use by pyasn1. See the documentation
@ -291,6 +294,7 @@ def stringToDN(string, tag=None):
name.setComponentByPosition(0, rdns)
return name
def stringToAlgorithmIdentifiers(string):
"""Helper function that converts a description of an algorithm
to a representation usable by the pyasn1 package and a hash
@ -330,6 +334,7 @@ def stringToAlgorithmIdentifiers(string):
algorithmIdentifier['parameters'] = univ.Any(nullEncapsulated)
return (algorithmIdentifier, algorithmType)
def datetimeToTime(dt):
"""Takes a datetime object and returns an rfc2459.Time object with
that time as its value as a GeneralizedTime"""
@ -337,6 +342,7 @@ def datetimeToTime(dt):
time['generalTime'] = useful.GeneralizedTime(dt.strftime('%Y%m%d%H%M%SZ'))
return time
def serialBytesToString(serialBytes):
"""Takes a list of integers in the interval [0, 255] and returns
the corresponding serial number string."""
@ -347,12 +353,13 @@ def serialBytesToString(serialBytes):
stringBytes = [getASN1Tag(univ.Integer), serialBytesLen] + serialBytes
return ''.join(chr(b) for b in stringBytes)
class Certificate(object):
"""Utility class for reading a certificate specification and
generating a signed x509 certificate"""
def __init__(self, paramStream):
self.versionValue = 2 # a value of 2 is X509v3
self.versionValue = 2 # a value of 2 is X509v3
self.signature = 'sha256WithRSAEncryption'
self.issuer = 'Default Issuer'
actualNow = datetime.datetime.utcnow()

View File

@ -36,6 +36,7 @@ import pycert
import pykey
import sys
class Error(Exception):
"""Base class for exceptions in this module."""
pass
@ -133,7 +134,7 @@ class CMS(object):
rsa['algorithm'] = rfc2459.rsaEncryption
rsa['parameters'] = univ.Null()
authenticatedAttributes = self.buildAuthenticatedAttributes(digestValue,
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))
authenticatedAttributesTBS = self.buildAuthenticatedAttributes(digestValue)
signerInfo['authenticatedAttributes'] = authenticatedAttributes
signerInfo['digestEncryptionAlgorithm'] = rsa
@ -165,7 +166,7 @@ class CMS(object):
implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))
extendedCertificateOrCertificate = rfc2315.ExtendedCertificateOrCertificate()
certificate = decoder.decode(self.signer.toDER(),
asn1Spec=rfc2459.Certificate())[0]
asn1Spec=rfc2459.Certificate())[0]
extendedCertificateOrCertificate['certificate'] = certificate
certificates[0] = extendedCertificateOrCertificate
signedData['certificates'] = certificates
@ -174,10 +175,10 @@ class CMS(object):
if len(self.sha1) > 0:
signerInfos[len(signerInfos)] = self.buildSignerInfo(certificate,
pykey.HASH_SHA1, self.sha1)
pykey.HASH_SHA1, self.sha1)
if len(self.sha256) > 0:
signerInfos[len(signerInfos)] = self.buildSignerInfo(certificate,
pykey.HASH_SHA256, self.sha256)
pykey.HASH_SHA256, self.sha256)
signedData['signerInfos'] = signerInfos
encoded = encoder.encode(signedData)

View File

@ -18,8 +18,10 @@ import hashlib
import pykey
class InvalidKeyError(Exception):
"""Helper exception to handle unknown key types."""
def __init__(self, key):
self.key = key

View File

@ -48,6 +48,7 @@ HASH_SHA256 = 'hash:sha256'
HASH_SHA384 = 'hash:sha384'
HASH_SHA512 = 'hash:sha512'
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
@ -55,8 +56,10 @@ def byteStringToHexifiedBitString(string):
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):
super(UnknownBaseError, self).__init__()
self.value = value
@ -84,6 +87,7 @@ class UnknownHashAlgorithmError(UnknownBaseError):
class UnsupportedHashAlgorithmError(Exception):
"""Helper exception type for unsupported hash algorithms."""
def __init__(self, value):
super(UnsupportedHashAlgorithmError, self).__init__()
self.value = value
@ -624,46 +628,49 @@ secp256k1Params = (long('fffffffffffffffffffffffffffffffffffffffffffffffffffffff
long('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 16),
long('483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 16))
def longToEvenLengthHexString(val):
h = format(val, 'x')
if not len(h) % 2 == 0:
h = '0' + h
return h
def notRandom(n):
return n * '\x04'
class ECCKey(object):
secp256k1Encoded = str('08fd87b04fba98090100004035ee7c7289d8fef7a8'
'6afe5da66d8bc2ebb6a8543fd2fead089f45ce7acd0fa64382a9500c41dad'
'770ffd4b511bf4b492eb1238800c32c4f76c73a3f3294e7c5002067cebc20'
'8a5fa3df16ec2bb34acc59a42ab4abb0538575ca99b92b6a2149a04f')
'6afe5da66d8bc2ebb6a8543fd2fead089f45ce7acd0fa64382a9500c41dad'
'770ffd4b511bf4b492eb1238800c32c4f76c73a3f3294e7c5002067cebc20'
'8a5fa3df16ec2bb34acc59a42ab4abb0538575ca99b92b6a2149a04f')
secp224r1Encoded = str('0ee5587c4d18526f00e00038668d72cca6fd6a1b35'
'57b5366104d84408ecb637f08e8c86bbff82cc00e88f0066d7af63c3298ba'
'377348a1202b03b37fd6b1ff415aa311e001c04389459926c3296c242b83e'
'10a6cd2011c8fe2dae1b772ea5b21067')
'57b5366104d84408ecb637f08e8c86bbff82cc00e88f0066d7af63c3298ba'
'377348a1202b03b37fd6b1ff415aa311e001c04389459926c3296c242b83e'
'10a6cd2011c8fe2dae1b772ea5b21067')
secp256r1Encoded = str('cb872ac99cd31827010000404fbfbbbb61e0f8f9b1'
'a60a59ac8704e2ec050b423e3cf72e923f2c4f794b455c2a69d233456c36c'
'4119d0706e00eedc8d19390d7991b7b2d07a304eaa04aa6c000202191403d'
'5710bf15a265818cd42ed6fedf09add92d78b18e7a1e9feb95524702')
'a60a59ac8704e2ec050b423e3cf72e923f2c4f794b455c2a69d233456c36c'
'4119d0706e00eedc8d19390d7991b7b2d07a304eaa04aa6c000202191403d'
'5710bf15a265818cd42ed6fedf09add92d78b18e7a1e9feb95524702')
secp384r1Encoded = str('d3103f5ac81741e801800060a1687243362b5c7b18'
'89f379154615a1c73fb48dee863e022915db608e252de4b7132da8ce98e83'
'1534e6a9c0c0b09c8d639ade83206e5ba813473a11fa330e05da8c96e4383'
'fe27873da97103be2888cff002f05af71a1fddcc8374aa6ea9ce0030035c7'
'a1b10d9fafe837b64ad92f22f5ced0789186538669b5c6d872cec3d926122'
'b393772b57602ff31365efe1393246')
'89f379154615a1c73fb48dee863e022915db608e252de4b7132da8ce98e83'
'1534e6a9c0c0b09c8d639ade83206e5ba813473a11fa330e05da8c96e4383'
'fe27873da97103be2888cff002f05af71a1fddcc8374aa6ea9ce0030035c7'
'a1b10d9fafe837b64ad92f22f5ced0789186538669b5c6d872cec3d926122'
'b393772b57602ff31365efe1393246')
secp521r1Encoded = str('77f4b0ac81948ddc02090084014cdc9cacc4794109'
'6bc9cc66752ec27f597734fa66c62b792f88c519d6d37f0d16ea1c483a182'
'7a010b9128e3a08070ca33ef5f57835b7c1ba251f6cc3521dc42b01065345'
'1981b445d343eed3782a35d6cff0ff484f5a883d209f1b9042b726703568b'
'2f326e18b833bdd8aa0734392bcd19501e10d698a79f53e11e0a22bdd2aad'
'900042014f3284fa698dd9fe1118dd331851cdfaac5a3829278eb8994839d'
'e9471c940b858c69d2d05e8c01788a7d0b6e235aa5e783fc1bee807dcc386'
'5f920e12cf8f2d29')
'6bc9cc66752ec27f597734fa66c62b792f88c519d6d37f0d16ea1c483a182'
'7a010b9128e3a08070ca33ef5f57835b7c1ba251f6cc3521dc42b01065345'
'1981b445d343eed3782a35d6cff0ff484f5a883d209f1b9042b726703568b'
'2f326e18b833bdd8aa0734392bcd19501e10d698a79f53e11e0a22bdd2aad'
'900042014f3284fa698dd9fe1118dd331851cdfaac5a3829278eb8994839d'
'e9471c940b858c69d2d05e8c01788a7d0b6e235aa5e783fc1bee807dcc386'
'5f920e12cf8f2d29')
def __init__(self, specification=None):
if specification == 'secp256k1':
@ -748,6 +755,8 @@ def keyFromSpecification(specification):
# 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(keyFromSpecification(configStream.read().strip()).toPEM())

View File

@ -30,6 +30,7 @@ KID = 4
ALG = 1
COSE_Sign = 98
def coseAlgorithmToPykeyHash(algorithm):
"""Helper function that takes one of (ES256, ES384, ES512)
and returns the corresponding pykey.HASH_* identifier."""
@ -47,6 +48,8 @@ def coseAlgorithmToPykeyHash(algorithm):
# unprotected : {},
# signature : bstr
# ]
def coseSignature(payload, algorithm, signingKey, signingCertificate,
bodyProtected):
"""Returns a COSE_Signature structure.
@ -78,6 +81,8 @@ def coseSignature(payload, algorithm, signingKey, signingCertificate,
# payload : nil,
# signatures : [+ COSE_Signature]
# ]
def coseSig(payload, intermediates, signatures):
"""Returns the entire (tagged) COSE_Sign structure.
payload is a string representing the data to be signed
@ -96,6 +101,7 @@ def coseSig(payload, intermediates, signatures):
tagged = CBORTag(COSE_Sign, [protectedEncoded, {}, None, coseSignatures])
return dumps(tagged)
def walkDirectory(directory):
"""Given a relative path to a directory, enumerates the
files in the tree rooted at that location. Returns a list
@ -110,6 +116,7 @@ def walkDirectory(directory):
paths.append((fullPath, internalPath))
return paths
def addManifestEntry(filename, hashes, contents, entries):
"""Helper function to fill out a manifest entry.
Takes the filename, a list of (hash function, hash function name)
@ -121,6 +128,7 @@ def addManifestEntry(filename, hashes, contents, entries):
entry += '%s-Digest: %s\n' % (name, base64hash)
entries.append(entry)
def getCert(subject, keyName, issuerName, ee, issuerKey=""):
"""Helper function to create an X509 cert from a specification.
Takes the subject, the subject key name to use, the issuer name,
@ -141,6 +149,7 @@ def getCert(subject, keyName, issuerName, ee, issuerKey=""):
certSpecificationStream.seek(0)
return pycert.Certificate(certSpecificationStream)
def coseAlgorithmToSignatureParams(coseAlgorithm, issuerName):
"""Given a COSE algorithm ('ES256', 'ES384', 'ES512') and an issuer
name, returns a (algorithm id, pykey.ECCKey, encoded certificate)
@ -153,15 +162,17 @@ def coseAlgorithmToSignatureParams(coseAlgorithm, issuerName):
keyName = 'secp384r1'
algId = ES384
elif coseAlgorithm == 'ES512':
keyName = 'secp521r1' # COSE uses the hash algorithm; this is the curve
keyName = 'secp521r1' # COSE uses the hash algorithm; this is the curve
algId = ES512
else:
raise UnknownCOSEAlgorithmError(coseAlgorithm)
key = pykey.ECCKey(keyName)
# The subject must differ to avoid errors when importing into NSS later.
ee = getCert('xpcshell signed app test signer ' + keyName, keyName, issuerName, True, 'default')
ee = getCert('xpcshell signed app test signer ' + keyName,
keyName, issuerName, True, 'default')
return (algId, key, ee.toDER())
def signZip(appDirectory, outputFile, issuerName, rootName, manifestHashes,
signatureHashes, pkcs7Hashes, coseAlgorithms, emptySignerInfos):
"""Given a directory containing the files to package up,
@ -198,8 +209,8 @@ def signZip(appDirectory, outputFile, issuerName, rootName, manifestHashes,
intermediate = intermediate.toDER()
intermediates.append(intermediate)
signatures = map(lambda coseAlgorithm:
coseAlgorithmToSignatureParams(coseAlgorithm, coseIssuerName),
coseAlgorithms)
coseAlgorithmToSignatureParams(coseAlgorithm, coseIssuerName),
coseAlgorithms)
coseSignatureBytes = coseSig(coseManifest, intermediates, signatures)
outZip.writestr('META-INF/cose.sig', coseSignatureBytes)
addManifestEntry('META-INF/cose.sig', manifestHashes,
@ -230,6 +241,7 @@ def signZip(appDirectory, outputFile, issuerName, rootName, manifestHashes,
outZip.writestr('META-INF/A.SF', sfContents)
outZip.writestr('META-INF/MANIFEST.MF', mfContents)
class Error(Exception):
"""Base class for exceptions in this module."""
pass
@ -264,6 +276,7 @@ def hashNameToFunctionAndIdentifier(name):
return (sha256, 'SHA256')
raise UnknownHashAlgorithmError(name)
def main(outputFile, appPath, *args):
"""Main entrypoint. Given an already-opened file-like
object, a path to the app directory to sign, and some

View File

@ -43,6 +43,7 @@ basicConstraintsTypes = {
'BC-cA': 'extension:basicConstraints:cA,'
}
def writeCertspec(issuer, subject, fields):
filename = '%s_%s.pem.certspec' % (subject, issuer)
if issuer == subject:

View File

@ -30,12 +30,15 @@ from cryptography.x509.oid import NameOID
assert sys.version_info >= (3, 2), "Requires Python 3.2 or later"
def hex_string_for_struct(bytes):
return ["0x{:02X}".format(x) for x in bytes]
def hex_string_human_readable(bytes):
return ["{:02X}".format(x) for x in bytes]
def nameOIDtoString(oid):
if oid == NameOID.COUNTRY_NAME:
return "C"
@ -49,6 +52,7 @@ def nameOIDtoString(oid):
return "OU"
raise Exception("Unknown OID: {}".format(oid))
def print_block(pemData, identifierType="DN", crtshId=None):
substrate = pem.readPemFromFile(io.StringIO(pemData.decode("utf-8")))
cert, rest = decoder.decode(substrate, asn1Spec=rfc5280.Certificate())

View File

@ -188,6 +188,7 @@ def generate_cpp_header_file(json_data, out_file):
logs="\n".join(log_info_initializers),
operators="\n".join(operator_info_initializers)))
def patch_in_test_logs(json_data):
""" Insert Mozilla-specific test log data. """
max_id = 0
@ -195,15 +196,15 @@ def patch_in_test_logs(json_data):
if operator["id"] > max_id:
max_id = operator["id"]
mozilla_test_operator_1 = {"name": "Mozilla Test Org 1", "id": max_id + 1,
"test_only": True}
"test_only": True}
mozilla_test_operator_2 = {"name": "Mozilla Test Org 2", "id": max_id + 2,
"test_only": True}
"test_only": True}
json_data["operators"].append(mozilla_test_operator_1)
json_data["operators"].append(mozilla_test_operator_2)
# The easiest way to get this is
# `openssl x509 -noout -pubkey -in <path/to/default-ee.pem>`
mozilla_rsa_log_1 = {"description": "Mozilla Test RSA Log 1",
"key": """
"key": """
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuohRqESOFtZB/W62iAY2
ED08E9nq5DVKtOz1aFdsJHvBxyWo4NgfvbGcBptuGobya+KvWnVramRxCHqlWqdF
h/cc1SScAn7NQ/weadA4ICmTqyDDSeTbuUzCa2wO7RWCD/F+rWkasdMCOosqQe6n
@ -212,11 +213,11 @@ def patch_in_test_logs(json_data):
tIqVYR3uJtYlnauRCE42yxwkBCy/Fosv5fGPmRcxuLP+SSP6clHEMdUDrNoYCjXt
jQIDAQAB
""",
"operated_by": [max_id + 1]}
"operated_by": [max_id + 1]}
# Similarly,
# `openssl x509 -noout -pubkey -in <path/to/other-test-ca.pem>`
mozilla_rsa_log_2 = {"description": "Mozilla Test RSA Log 2",
"key": """
"key": """
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXXGUmYJn3cIKmeR8bh2
w39c5TiwbErNIrHL1G+mWtoq3UHIwkmKxKOzwfYUh/QbaYlBvYClHDwSAkTFhKTE
SDMF5ROMAQbPCL6ahidguuai6PNvI8XZgxO53683g0XazlHU1tzSpss8xwbrzTBw
@ -225,18 +226,19 @@ def patch_in_test_logs(json_data):
gys1uJMPdLqQqovHYWckKrH9bWIUDRjEwLjGj8N0hFcyStfehuZVLx0eGR1xIWjT
uwIDAQAB
""",
"operated_by": [max_id + 2]}
"operated_by": [max_id + 2]}
# `openssl x509 -noout -pubkey -in <path/to/root_secp256r1_256.pem`
mozilla_ec_log = {"description": "Mozilla Test EC Log",
"key": """
"key": """
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAET7+7u2Hg+PmxpgpZrIcE4uwFC0I+
PPcukj8sT3lLRVwqadIzRWw2xBGdBwbgDu3I0ZOQ15kbey0HowTqoEqmwA==
""",
"operated_by": [max_id + 1]}
"operated_by": [max_id + 1]}
json_data["logs"].append(mozilla_rsa_log_1)
json_data["logs"].append(mozilla_rsa_log_2)
json_data["logs"].append(mozilla_ec_log)
def run(args):
"""
Load the input JSON file and generate the C++ header according to the

View File

@ -24,6 +24,7 @@ import argparse
import itertools
import sys
def base128(value):
"""
Given an integral value, returns an array of the base-128 representation
@ -50,6 +51,7 @@ def base128(value):
return result
def dottedOIDToEncodedArray(dottedOID):
"""
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
@ -68,6 +70,7 @@ def dottedOIDToEncodedArray(dottedOID):
restBase128 = [base128(x) for x in nodes[2:]]
return [firstByte] + list(itertools.chain.from_iterable(restBase128))
def dottedOIDToCArray(dottedOID, mode):
"""
Takes a dotted OID string (e.g. '1.2.840.10045.4.3.4') as input, and
@ -86,6 +89,7 @@ def dottedOIDToCArray(dottedOID, mode):
return ", ".join(["0x%.2x" % b for b in bytes])
def specNameToCName(specName):
"""
Given an string containing an ASN.1 name, returns a string that is a valid
@ -97,6 +101,7 @@ def specNameToCName(specName):
"""
return specName.replace("-", "_")
def toCode(programName, specName, dottedOID, mode):
"""
Given an ASN.1 name and a string containing the dotted representation of an
@ -180,11 +185,12 @@ def toCode(programName, specName, dottedOID, mode):
" };\n") % (programNameWithOptions, specName, dottedOID, varName,
dottedOIDToCArray(dottedOID, mode))
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Generate code snippets to handle OIDs in C++",
epilog="example: python %s ecdsa-with-SHA1 1.2.840.10045.4.1"
% sys.argv[0])
description="Generate code snippets to handle OIDs in C++",
epilog="example: python %s ecdsa-with-SHA1 1.2.840.10045.4.1"
% sys.argv[0])
group = parser.add_mutually_exclusive_group()
group.add_argument("--tlv", action='store_true',
help="Wrap the encoded OID value with the tag and length")