Update to support OEMCrypto v16 with ODK

This commit is contained in:
KongQun Yang
2020-09-21 15:54:04 -07:00
parent 93265ab9d1
commit 69d813f0f1
203 changed files with 16337 additions and 2290 deletions

View File

@@ -7,27 +7,42 @@
################################################################################
# Build file for OEM certificate generation tool.
package(default_visibility = ["//visibility:public"])
py_binary(
name = "oem_certificate",
srcs = ["oem_certificate.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
":oem_certificate_main_lib",
],
)
py_library(
name = "oem_certificate_main_lib",
srcs = ["oem_certificate.py"],
srcs_version = "PY3",
deps = [
],
)
py_library(
name = "oem_certificate_test_helper",
srcs = ["oem_certificate_test_helper.py"],
srcs_version = "PY3",
deps = [
":oem_certificate",
],
)
py_test(
name = "oem_certificate_test",
srcs = ["oem_certificate_test.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
":oem_certificate",
":oem_certificate_main_lib",
":oem_certificate_test_helper",
],
)

View File

@@ -1,3 +1,4 @@
# Lint as: python2, python3
################################################################################
# Copyright 2016 Google LLC.
#
@@ -5,12 +6,11 @@
# License Agreement. For a copy of this agreement, please contact
# widevine-licensing@google.com.
################################################################################
"""OEM certificate generation tool.
Supports:
- Generating CSR (certificate signing request)
- Generating OEM intermediate certificate
- Generating OEM intermediate certificate (for testing only)
- Generating OEM leaf certificate chain
- Erasing file securely
- Getting CSR/certificate/certificate chain information
@@ -31,11 +31,11 @@ example, if file "location.cfg" is,
-OU=Some Unit
A command of
"python oem_certificate.py generate_csr @location.cfg "
"python oem_certificate.py generate_csr @location.cfg -CN TestDevice1 "
"--output_csr_file=csr.pem --output_private_key_file=key.der",
is equivalent to
"python oem_certificate.py generate_csr -C=US -ST=CA -L=Kirkland "
"-O='Some Company' -OU='Some Unit' --output_csr_file=csr.pem "
"python oem_certificate.py generate_csr -CN TestDevice1 -C=US -ST=CA "
"-L=Kirkland -O='Some Company' -OU='Some Unit' --output_csr_file=csr.pem "
"--output_private_key_file=key.der".
Note that (1) the arguments in the config file must be one per line; (2) the
@@ -45,6 +45,10 @@ The script uses a default configuration file 'oem_certificate.cfg', which will
be loaded automatically if exists.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import datetime
import os
@@ -63,6 +67,7 @@ from pyasn1.codec.der import decoder
from pyasn1.codec.der import encoder
from pyasn1.type import univ
import six
from six.moves import range
class WidevineSystemId(x509.UnrecognizedExtension):
@@ -116,7 +121,7 @@ class X509CertificateChain(object):
x509_stack = pkcs7.d.sign.cert
certificates = []
for i in xrange(backend._lib.sk_X509_num(x509_stack)):
for i in range(backend._lib.sk_X509_num(x509_stack)):
x509_value = backend._ffi.gc(
backend._lib.X509_dup(backend._lib.sk_X509_value(x509_stack, i)),
backend._lib.X509_free)
@@ -188,8 +193,9 @@ def generate_csr(args):
six.text_type(args.organizational_unit_name)),
]
if args.common_name:
x509_name.append(x509.NameAttribute(oid.NameOID.COMMON_NAME,
six.text_type(args.common_name)))
x509_name.append(
x509.NameAttribute(oid.NameOID.COMMON_NAME,
six.text_type(args.common_name)))
csr = x509.CertificateSigningRequestBuilder().subject_name(
x509.Name(x509_name)).sign(key, hashes.SHA256(),
backends.default_backend())
@@ -243,8 +249,8 @@ def generate_intermediate_certificate(args):
csr = x509.load_pem_x509_csr(args.csr_file.read(), backends.default_backend())
certificate = build_certificate(csr.subject, root_cert.subject,
args.system_id, args.not_valid_before,
args.valid_duration,
args.system_id,
args.not_valid_before, args.valid_duration,
csr.public_key(), root_private_key, True)
args.output_certificate_file.write(
certificate.public_bytes(serialization.Encoding.DER))
@@ -305,9 +311,9 @@ def generate_leaf_certificate(args):
def secure_erase(args):
"""Subparser handler for secure erasing of a file."""
length = args.file.tell()
for _ in xrange(args.passes):
for _ in range(args.passes):
args.file.seek(0)
for _ in xrange(length):
for _ in range(length):
args.file.write(os.urandom(1))
args.file.close()
os.remove(args.file.name)
@@ -388,7 +394,6 @@ def create_parser():
"""Command line parsing."""
parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
subparsers = parser.add_subparsers()
# Subparser for certificate signing request generation.
parser_csr = subparsers.add_parser(
'generate_csr', help='generate certificate signing request')
@@ -412,7 +417,6 @@ def create_parser():
help=('specify an optional passphrase to encrypt the private key. The '
'private key is not encrypted if omitted.'))
parser_csr.set_defaults(func=generate_csr)
# Subparser for intermediate certificate generation.
parser_intermediate_cert = subparsers.add_parser(
'generate_intermediate_certificate',
@@ -495,7 +499,6 @@ def create_parser():
parser_info.add_argument(
'-F', '--file', type=argparse.FileType('rb'), required=True)
parser_info.set_defaults(func=get_info)
return parser
@@ -503,7 +506,7 @@ def main():
args = sys.argv[1:]
config_file_name = 'oem_certificate.cfg'
if os.path.isfile(config_file_name):
print 'Load from args default configuration file: ', config_file_name
print('Load from args default configuration file: ', config_file_name)
args.append('@' + config_file_name)
parser_args = create_parser().parse_args(args)
parser_args.func(parser_args)

View File

@@ -1,3 +1,4 @@
# Lint as: python2, python3
################################################################################
# Copyright 2016 Google LLC.
#
@@ -10,7 +11,7 @@ import base64
import datetime
import os
import shutil
import StringIO
import sys
import tempfile
import textwrap
import unittest
@@ -20,6 +21,7 @@ from cryptography.hazmat import backends
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.x509 import oid
import six
import oem_certificate
import oem_certificate_test_helper as oem_cert_test_helper
@@ -49,8 +51,9 @@ class OemCertificateTest(unittest.TestCase):
subject.get_attributes_for_oid(oid.NameOID.COUNTRY_NAME)[0].value,
args.country_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.STATE_OR_PROVINCE_NAME)[0]
.value, args.state_or_province_name)
subject.get_attributes_for_oid(
oid.NameOID.STATE_OR_PROVINCE_NAME)[0].value,
args.state_or_province_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.LOCALITY_NAME)[0].value,
args.locality_name)
@@ -58,8 +61,9 @@ class OemCertificateTest(unittest.TestCase):
subject.get_attributes_for_oid(oid.NameOID.ORGANIZATION_NAME)[0].value,
args.organization_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.ORGANIZATIONAL_UNIT_NAME)[0]
.value, args.organizational_unit_name)
subject.get_attributes_for_oid(
oid.NameOID.ORGANIZATIONAL_UNIT_NAME)[0].value,
args.organizational_unit_name)
self.assertEqual(
len(subject.get_attributes_for_oid(oid.NameOID.COMMON_NAME)), 0)
@@ -84,8 +88,9 @@ class OemCertificateTest(unittest.TestCase):
subject.get_attributes_for_oid(oid.NameOID.COUNTRY_NAME)[0].value,
args.country_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.STATE_OR_PROVINCE_NAME)[0]
.value, args.state_or_province_name)
subject.get_attributes_for_oid(
oid.NameOID.STATE_OR_PROVINCE_NAME)[0].value,
args.state_or_province_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.LOCALITY_NAME)[0].value,
args.locality_name)
@@ -93,11 +98,12 @@ class OemCertificateTest(unittest.TestCase):
subject.get_attributes_for_oid(oid.NameOID.ORGANIZATION_NAME)[0].value,
args.organization_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.ORGANIZATIONAL_UNIT_NAME)[0]
.value, args.organizational_unit_name)
subject.get_attributes_for_oid(
oid.NameOID.ORGANIZATIONAL_UNIT_NAME)[0].value,
args.organizational_unit_name)
self.assertEqual(
subject.get_attributes_for_oid(oid.NameOID.COMMON_NAME)[0]
.value, args.common_name)
subject.get_attributes_for_oid(oid.NameOID.COMMON_NAME)[0].value,
args.common_name)
private_key = serialization.load_der_private_key(
args.output_private_key_file.getvalue(),
@@ -111,11 +117,11 @@ class OemCertificateTest(unittest.TestCase):
def test_generate_csr_with_keysize4096_and_passphrase(self):
args = oem_cert_test_helper.setup_csr_args(
key_size=4096, passphrase='passphrase_4096')
key_size=4096, passphrase=b'passphrase_4096')
oem_certificate.generate_csr(args)
private_key = serialization.load_der_private_key(
args.output_private_key_file.getvalue(),
'passphrase_4096',
b'passphrase_4096',
backend=backends.default_backend())
csr = x509.load_pem_x509_csr(args.output_csr_file.getvalue(),
backends.default_backend())
@@ -156,15 +162,14 @@ class OemCertificateTest(unittest.TestCase):
cert.signature_hash_algorithm)
def test_generate_intermediate_with_cert_mismatch_root_cert_and_key(self):
root_key1, _ = (
oem_cert_test_helper.create_root_certificate_and_key())
root_key1, _ = (oem_cert_test_helper.create_root_certificate_and_key())
_, root_certificate2 = oem_cert_test_helper.create_root_certificate_and_key(
)
args = oem_cert_test_helper.setup_intermediate_cert_args(
'some csr data', root_key1, root_certificate2)
b'some csr data', root_key1, root_certificate2)
with self.assertRaises(ValueError) as context:
oem_certificate.generate_intermediate_certificate(args)
self.assertTrue('certificate does not match' in str(context.exception))
self.assertIn('certificate does not match', str(context.exception))
def test_generate_leaf_certificate_from_pem_intermediate_cert(self):
intermediate_key_bytes, intermediate_certificate_bytes = (
@@ -195,8 +200,7 @@ class OemCertificateTest(unittest.TestCase):
system_id_raw_bytes = leaf_cert.extensions.get_extension_for_oid(
oem_certificate.WidevineSystemId.oid).value.value
self.assertEqual(
oem_certificate.WidevineSystemId(system_id_raw_bytes).int_value(),
2001)
oem_certificate.WidevineSystemId(system_id_raw_bytes).int_value(), 2001)
leaf_key = serialization.load_der_private_key(
args.output_private_key_file.getvalue(),
@@ -238,75 +242,81 @@ class OemCertificateTest(unittest.TestCase):
intermediate_key_bytes,
intermediate_certificate_bytes,
key_size=4096,
passphrase='leaf passphrase')
passphrase=b'leaf passphrase')
oem_certificate.generate_leaf_certificate(args)
leaf_key = serialization.load_der_private_key(
args.output_private_key_file.getvalue(),
'leaf passphrase',
b'leaf passphrase',
backend=backends.default_backend())
self.assertEqual(4096, leaf_key.key_size)
def test_get_csr_info(self):
args = oem_cert_test_helper.setup_csr_args()
oem_certificate.generate_csr(args)
args.file = StringIO.StringIO(args.output_csr_file.getvalue())
output = StringIO.StringIO()
args.file = six.BytesIO(args.output_csr_file.getvalue())
output = six.StringIO()
oem_certificate.get_info(args, output)
expected_info = """\
CSR Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Key Size: 4096"""
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
# Remove unicode marker for Python2 backwards compatibility.
output_value = output.getvalue().replace("u'", "'")
self.assertEqual(output_value, textwrap.dedent(expected_info))
def test_get_pem_certificate_info(self):
_, intermediate_certificate_bytes = (
oem_cert_test_helper.create_intermediate_certificate_and_key_bytes(
pem_format=True))
args = ArgParseObject()
args.file = StringIO.StringIO(intermediate_certificate_bytes)
output = StringIO.StringIO()
args.file = six.BytesIO(intermediate_certificate_bytes)
output = six.StringIO()
oem_certificate.get_info(args, output)
expected_info = """\
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='root_cert')>
Key Size: 4096
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2001-11-17 00:00:00"""
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
# Remove unicode marker for Python2 backwards compatibility.
output_value = output.getvalue().replace("u'", "'")
self.assertEqual(output_value, textwrap.dedent(expected_info))
def test_get_der_certificate_info(self):
_, intermediate_certificate_bytes = (
oem_cert_test_helper.create_intermediate_certificate_and_key_bytes(
pem_format=False))
args = ArgParseObject()
args.file = StringIO.StringIO(intermediate_certificate_bytes)
output = StringIO.StringIO()
args.file = six.BytesIO(intermediate_certificate_bytes)
output = six.StringIO()
oem_certificate.get_info(args, output)
expected_info = """\
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='root_cert')>
Key Size: 4096
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2001-11-17 00:00:00"""
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
# Remove unicode marker for Python2 backwards compatibility.
output_value = output.getvalue().replace("u'", "'")
self.assertEqual(output_value, textwrap.dedent(expected_info))
def test_get_certificate_chain_info(self):
intermediate_key_bytes, intermediate_certificate_bytes = (
@@ -314,41 +324,43 @@ class OemCertificateTest(unittest.TestCase):
args = oem_cert_test_helper.setup_leaf_cert_args(
intermediate_key_bytes, intermediate_certificate_bytes)
oem_certificate.generate_leaf_certificate(args)
args.file = StringIO.StringIO(args.output_certificate_file.getvalue())
output = StringIO.StringIO()
args.file = six.BytesIO(args.output_certificate_file.getvalue())
output = six.StringIO()
oem_certificate.get_info(args, output)
expected_info = """\
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'2001-leaf')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='2001-leaf')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Key Size: 1024
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2023-07-05 00:00:00
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='root_cert')>
Key Size: 4096
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2001-11-17 00:00:00"""
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
# Remove unicode marker for Python2 backwards compatibility.
output_value = output.getvalue().replace("u'", "'")
self.assertEqual(output_value, textwrap.dedent(expected_info))
def test_get_certificate_chain_info_fixed_input(self):
# This was generated from args.output_certificate_file in the test above.
@@ -400,41 +412,43 @@ class OemCertificateTest(unittest.TestCase):
'nm0mTbNTgcC673L5YA8qpQkAzk9vLg4UaslMbPfeKM8rqduJFcjTyVY3C4jBC0qxf6z6'
'vpWbEO7UpHHdfvWe9DEBODFbyXMxAA==')
args = oem_cert_test_helper.ArgParseObject()
args.file = StringIO.StringIO(base64.b64decode(data_b64))
output = StringIO.StringIO()
args.file = six.BytesIO(base64.b64decode(data_b64))
output = six.StringIO()
oem_certificate.get_info(args, output)
expected_info = """\
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'2001-leaf')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='2001-leaf')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Key Size: 1024
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2023-07-05 00:00:00
Certificate Subject Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value=u'US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value=u'WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value=u'Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value=u'CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value=u'ContentProtection')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.6, name=countryName)>, value='US')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.8, name=stateOrProvinceName)>, value='WA')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.7, name=localityName)>, value='Kirkland')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.10, name=organizationName)>, value='CompanyXYZ')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.11, name=organizationalUnitName)>, value='ContentProtection')>
Issuer Name:
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value=u'root_cert')>
<NameAttribute(oid=<ObjectIdentifier(oid=2.5.4.3, name=commonName)>, value='root_cert')>
Key Size: 4096
Widevine System Id: 2001
Not valid before: 2001-08-09 00:00:00
Not valid after: 2001-11-17 00:00:00"""
self.assertEqual(output.getvalue(), textwrap.dedent(expected_info))
# Remove unicode marker for Python2 backwards compatibility.
output_value = output.getvalue().replace("u'", "'")
self.assertEqual(output_value, textwrap.dedent(expected_info))
def test_secure_erase(self):
args = ArgParseObject()
@@ -448,10 +462,12 @@ class OemCertificateTest(unittest.TestCase):
class OemCertificateArgParseTest(unittest.TestCase):
def setUp(self):
super(OemCertificateArgParseTest, self).setUp()
self.parser = oem_certificate.create_parser()
self.test_dir = tempfile.mkdtemp()
def tearDown(self):
super(OemCertificateArgParseTest, self).tearDown()
shutil.rmtree(self.test_dir)
def test_generate_csr(self):
@@ -506,7 +522,7 @@ class OemCertificateArgParseTest(unittest.TestCase):
def _fill_file_with_dummy_contents(self, file_name):
with open(file_name, 'wb') as f:
f.write('dummy')
f.write(b'dummy')
def test_generate_csr_invalid_key_size(self):
cmds = ('generate_csr --key_size unknown -C USA -ST WA '
@@ -601,7 +617,7 @@ class OemCertificateArgParseTest(unittest.TestCase):
self.assertEqual(args.func, oem_certificate.generate_leaf_certificate)
def test_generate_leaf_cert_invalid_date(self):
cmds = ('generate_leaf_certificate --not_valid_before invaid-date '
cmds = ('generate_leaf_certificate --not_valid_before invalid-date '
'--valid_duration 10').split()
intermediate_certificate_file = os.path.join(self.test_dir,
@@ -651,9 +667,12 @@ class OemCertificateArgParseTest(unittest.TestCase):
self.assertEqual(context.exception.code, 2)
def test_no_argument(self):
with self.assertRaises(SystemExit) as context:
self.parser.parse_args([])
self.assertEqual(context.exception.code, 2)
# Only valid for python2.
# Python3 does not throw error when missing required
if sys.version_info[0] == 2:
with self.assertRaises(SystemExit) as context:
self.parser.parse_args([])
self.assertEqual(context.exception.code, 2)
if __name__ == '__main__':

View File

@@ -1,3 +1,4 @@
# Lint as: python2, python3
################################################################################
# Copyright 2017 Google LLC.
#
@@ -5,17 +6,16 @@
# License Agreement. For a copy of this agreement, please contact
# widevine-licensing@google.com.
################################################################################
"""Common test utility functions for OEM certificate generation."""
import datetime
import StringIO
from cryptography import x509
from cryptography.hazmat import backends
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509 import oid
import six
import oem_certificate
@@ -25,7 +25,6 @@ _LOCALITY_NAME = 'Kirkland'
_ORGANIZATION_NAME = 'CompanyXYZ'
_ORGANIZATIONAL_UNIT_NAME = 'ContentProtection'
_NOT_VALID_BEFORE = datetime.datetime(2001, 8, 9)
_VALID_DURATION = 100
_LEAF_CERT_VALID_DURATION = 8000
@@ -40,14 +39,14 @@ class ArgParseObject(object):
def create_root_certificate_and_key():
"""Creates a root certificate and key."""
key = rsa.generate_private_key(
public_exponent=65537,
key_size=3072,
backend=backends.default_backend())
public_exponent=65537, key_size=3072, backend=backends.default_backend())
subject_name = x509.Name(
[x509.NameAttribute(oid.NameOID.COMMON_NAME, u'root_cert')])
certificate = oem_certificate.build_certificate(
subject_name, subject_name, None,
datetime.datetime(2001, 8, 9), 1000, key.public_key(), key, True)
certificate = oem_certificate.build_certificate(subject_name, subject_name,
None,
datetime.datetime(2001, 8,
9), 1000,
key.public_key(), key, True)
return (key, certificate)
@@ -73,18 +72,22 @@ def setup_csr_args(country_name=_COUNTRY_NAME,
if output_csr_file:
args.output_csr_file = output_csr_file
else:
args.output_csr_file = StringIO.StringIO()
args.output_csr_file = six.BytesIO()
if output_private_key_file:
args.output_private_key_file = output_private_key_file
else:
args.output_private_key_file = StringIO.StringIO()
args.output_private_key_file = six.BytesIO()
args.passphrase = passphrase
return args
def setup_intermediate_cert_args(
csr_bytes, root_key, root_certificate, not_valid_before=_NOT_VALID_BEFORE,
valid_duration=_VALID_DURATION, system_id=_SYSTEM_ID,
csr_bytes,
root_key,
root_certificate,
not_valid_before=_NOT_VALID_BEFORE,
valid_duration=_VALID_DURATION,
system_id=_SYSTEM_ID,
root_private_key_passphrase=_ROOT_PRIVATE_KEY_PASSPHRASE,
output_certificate_file=None):
"""Sets up args to OEM Cert generator for generating intermediate cert."""
@@ -92,12 +95,12 @@ def setup_intermediate_cert_args(
args.not_valid_before = not_valid_before
args.valid_duration = valid_duration
args.system_id = system_id
args.csr_file = StringIO.StringIO(csr_bytes)
args.root_private_key_passphrase = root_private_key_passphrase
args.csr_file = six.BytesIO(csr_bytes)
args.root_private_key_passphrase = root_private_key_passphrase.encode('utf-8')
if output_certificate_file:
args.output_certificate_file = output_certificate_file
else:
args.output_certificate_file = StringIO.StringIO()
args.output_certificate_file = six.BytesIO()
serialized_private_key = root_key.private_bytes(
serialization.Encoding.DER,
@@ -106,8 +109,8 @@ def setup_intermediate_cert_args(
args.root_private_key_passphrase))
serialized_certificate = root_certificate.public_bytes(
serialization.Encoding.DER)
args.root_certificate_file = StringIO.StringIO(serialized_certificate)
args.root_private_key_file = StringIO.StringIO(serialized_private_key)
args.root_certificate_file = six.BytesIO(serialized_certificate)
args.root_private_key_file = six.BytesIO(serialized_private_key)
return args
@@ -128,16 +131,15 @@ def setup_leaf_cert_args(intermediate_key_bytes,
if output_certificate_file:
args.output_certificate_file = output_certificate_file
else:
args.output_certificate_file = StringIO.StringIO()
args.output_certificate_file = six.BytesIO()
if output_private_key_file:
args.output_private_key_file = output_private_key_file
else:
args.output_private_key_file = StringIO.StringIO()
args.output_private_key_file = six.BytesIO()
args.passphrase = passphrase
args.intermediate_private_key_file = StringIO.StringIO(
intermediate_key_bytes)
args.intermediate_certificate_file = StringIO.StringIO(
args.intermediate_private_key_file = six.BytesIO(intermediate_key_bytes)
args.intermediate_certificate_file = six.BytesIO(
intermediate_certificate_bytes)
return args