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 <signer>".
The signer will be called with "-inkey <path_to_private_key>",
"-in <input_file>" and "-out <output_file>" parameters.
Test: Use a dummy signer, call 'ota_from_target_files.py --payload_signer <signer> <target_files.zip> <ota.zip>' and verify the signatures in the generated package.
Bug: 28701652
Change-Id: I26cfdd3fdba6fc90799221741b75426988e46fd3
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index bb3a009..0a0173d 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -113,6 +113,14 @@
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 <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 <path_to_key>",
+ "-in <input_file>" and "-out <output_file>" parameters.
"""
import sys
@@ -160,6 +168,7 @@
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 @@
"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 @@
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 @@
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 @@
"stash_threshold=",
"gen_verify",
"log_diff=",
+ "payload_signer=",
], extra_option_handler=option_handler)
if len(args) != 2: