From dea0f8bfed01fa620d23d7dd8ff533246f26e8a0 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 20 Jun 2016 17:55:06 -0700 Subject: [PATCH] releasetools: Support using payload_signer. For A/B OTAs, by default it calls 'openssl pkeyutl' to sign the payload and metadata with the package private key. If the private key cannot be accessed directly, a payload signer that knows how to do that should be supplied via "--payload_signer ". The signer will be called with "-inkey ", "-in " and "-out " parameters. Test: Use a dummy signer, call 'ota_from_target_files.py --payload_signer ' and verify the signatures in the generated package. Bug: 28701652 Change-Id: I26cfdd3fdba6fc90799221741b75426988e46fd3 --- tools/releasetools/ota_from_target_files.py | 62 ++++++++++++++------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py index bb3a009cba..0a0173dcd3 100755 --- a/tools/releasetools/ota_from_target_files.py +++ b/tools/releasetools/ota_from_target_files.py @@ -113,6 +113,14 @@ Usage: ota_from_target_files [flags] input_target_files output_ota_package Generate a log file that shows the differences in the source and target builds for an incremental package. This option is only meaningful when -i is specified. + + --payload_signer + Specify the signer when signing the payload and metadata for A/B OTAs. + By default (i.e. without this flag), it calls 'openssl pkeyutl' to sign + with the package private key. If the private key cannot be accessed + directly, a payload signer that knows how to do that should be specified. + The signer will be supplied with "-inkey ", + "-in " and "-out " parameters. """ import sys @@ -160,6 +168,7 @@ OPTIONS.cache_size = None OPTIONS.stash_threshold = 0.8 OPTIONS.gen_verify = False OPTIONS.log_diff = None +OPTIONS.payload_signer = None def MostPopularKey(d, default): """Given a dict, return the key corresponding to the largest @@ -1163,17 +1172,19 @@ def WriteABOTAPackageWithBrilloScript(target_file, output_file, "default_system_dev_certificate", "build/target/product/security/testkey") - # A/B updater expects key in RSA format. - cmd = ["openssl", "pkcs8", - "-in", OPTIONS.package_key + OPTIONS.private_key_suffix, - "-inform", "DER", "-nocrypt"] - rsa_key = common.MakeTempFile(prefix="key-", suffix=".key") - cmd.extend(["-out", rsa_key]) - p1 = common.Run(cmd, stdout=subprocess.PIPE) - p1.wait() - assert p1.returncode == 0, "openssl pkcs8 failed" + # A/B updater expects a signing key in RSA format. Gets the key ready for + # later use in step 3, unless a payload_signer has been specified. + if OPTIONS.payload_signer is None: + cmd = ["openssl", "pkcs8", + "-in", OPTIONS.package_key + OPTIONS.private_key_suffix, + "-inform", "DER", "-nocrypt"] + rsa_key = common.MakeTempFile(prefix="key-", suffix=".key") + cmd.extend(["-out", rsa_key]) + p1 = common.Run(cmd, stdout=subprocess.PIPE) + p1.wait() + assert p1.returncode == 0, "openssl pkcs8 failed" - # Stage the output zip package for signing. + # Stage the output zip package for package signing. temp_zip_file = tempfile.NamedTemporaryFile() output_zip = zipfile.ZipFile(temp_zip_file, "w", compression=zipfile.ZIP_DEFLATED) @@ -1234,21 +1245,29 @@ def WriteABOTAPackageWithBrilloScript(target_file, output_file, signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-", suffix=".bin") # 3a. Sign the payload hash. - cmd = ["openssl", "pkeyutl", "-sign", - "-inkey", rsa_key, - "-pkeyopt", "digest:sha256", - "-in", payload_sig_file, - "-out", signed_payload_sig_file] + if OPTIONS.payload_signer is not None: + cmd = [OPTIONS.payload_signer, + "-inkey", OPTIONS.package_key + OPTIONS.private_key_suffix] + else: + cmd = ["openssl", "pkeyutl", "-sign", + "-inkey", rsa_key, + "-pkeyopt", "digest:sha256"] + cmd.extend(["-in", payload_sig_file, + "-out", signed_payload_sig_file]) p1 = common.Run(cmd, stdout=subprocess.PIPE) p1.wait() assert p1.returncode == 0, "openssl sign payload failed" # 3b. Sign the metadata hash. - cmd = ["openssl", "pkeyutl", "-sign", - "-inkey", rsa_key, - "-pkeyopt", "digest:sha256", - "-in", metadata_sig_file, - "-out", signed_metadata_sig_file] + if OPTIONS.payload_signer is not None: + cmd = [OPTIONS.payload_signer, + "-inkey", OPTIONS.package_key + OPTIONS.private_key_suffix] + else: + cmd = ["openssl", "pkeyutl", "-sign", + "-inkey", rsa_key, + "-pkeyopt", "digest:sha256"] + cmd.extend(["-in", metadata_sig_file, + "-out", signed_metadata_sig_file]) p1 = common.Run(cmd, stdout=subprocess.PIPE) p1.wait() assert p1.returncode == 0, "openssl sign metadata failed" @@ -1905,6 +1924,8 @@ def main(argv): OPTIONS.gen_verify = True elif o == "--log_diff": OPTIONS.log_diff = a + elif o == "--payload_signer": + OPTIONS.payload_signer = a else: return False return True @@ -1934,6 +1955,7 @@ def main(argv): "stash_threshold=", "gen_verify", "log_diff=", + "payload_signer=", ], extra_option_handler=option_handler) if len(args) != 2: