From fe23bc40dc950051415a04c8f919b81e01aa05db Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 28 Sep 2021 10:08:40 -0700 Subject: [PATCH] Update OEM Certificate scripts for Python 3 (This is a merge from the Widevine repo of http://go/wvgerrit/131084.) This patch updates the OEM Certificate scripts to work in Python 3. Previously, the scripts were nominally Python-2-only, though I actually couldn't get them to run in either Python 2 or 3. The following changes were necessary to make the scripts work in Python 3: 1) print() is now a function, not a keyword. 2) xrange() is now range(). 3) StringIO is now part of the io package. 4) Python 3 no longer lets you mix strings and byte buffers indiscriminately. As such, the code needed to be made more crisp about when it is treating a file or other blob of data as binary vs. text. Many instances of StringIO had to become BytesIO, and several literals had to be turned into byte literals. Passphrase command-line parameters are now parsed to UTF-8 bytes during argument parsing. Bug: 151736642 Test: oem_certificate_test.py Change-Id: I8ea5d0fda2ea5a2c0289be7612be0b4e508c4abf --- .../oem_certificate.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) mode change 100644 => 100755 libwvdrmengine/oem_certificate_generator/oem_certificate.py diff --git a/libwvdrmengine/oem_certificate_generator/oem_certificate.py b/libwvdrmengine/oem_certificate_generator/oem_certificate.py old mode 100644 new mode 100755 index 8d17c98b..71e77895 --- a/libwvdrmengine/oem_certificate_generator/oem_certificate.py +++ b/libwvdrmengine/oem_certificate_generator/oem_certificate.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # Copyright 2017 Google LLC. All Rights Reserved. """OEM certificate generation tool. @@ -110,7 +111,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) @@ -134,6 +135,10 @@ class X509CertificateChain(object): return backend._read_mem_bio(bio) +# Type for argparse to accept byte buffers on the command line +def utf8_bytes(utf8_str): + return utf8_str.encode('utf-8') + def _multiple_of_1024(key_size_str): """argparse custom type function for key size.""" key_size = int(key_size_str) @@ -299,9 +304,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) @@ -403,6 +408,7 @@ def create_parser(): '--output_private_key_file', type=argparse.FileType('wb'), required=True) parser_csr.add_argument( '--passphrase', + type=utf8_bytes, 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) @@ -429,7 +435,7 @@ def create_parser(): '--root_certificate_file', type=argparse.FileType('rb'), required=True) parser_intermediate_cert.add_argument( '--root_private_key_file', type=argparse.FileType('rb'), required=True) - parser_intermediate_cert.add_argument('--root_private_key_passphrase') + parser_intermediate_cert.add_argument('--root_private_key_passphrase', type=utf8_bytes) parser_intermediate_cert.add_argument( '--output_certificate_file', type=argparse.FileType('wb'), required=True) parser_intermediate_cert.set_defaults(func=generate_intermediate_certificate) @@ -460,13 +466,14 @@ def create_parser(): '--intermediate_private_key_file', type=argparse.FileType('rb'), required=True) - parser_leaf_cert.add_argument('--intermediate_private_key_passphrase') + parser_leaf_cert.add_argument('--intermediate_private_key_passphrase', type=utf8_bytes) parser_leaf_cert.add_argument( '--output_certificate_file', type=argparse.FileType('wb'), required=True) parser_leaf_cert.add_argument( '--output_private_key_file', type=argparse.FileType('wb'), required=True) parser_leaf_cert.add_argument( '--passphrase', + type=utf8_bytes, help=('specify an optional passphrase to encrypt the private key. The ' 'private key is not encrypted if omitted.')) parser_leaf_cert.set_defaults(func=generate_leaf_certificate) @@ -497,7 +504,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)