releasetools: Fix an issue with pubkey extraction.
When calling 'openssl x509 -pubkey' to extract the public key from a
certificate, openssl 1.0 and 1.1 handle the '-out' parameter
differently. openssl 1.0 doesn't write the output into the specified
filename, which leads to the payload verification failure in
check_ota_package_signature.VerifyAbOtaPayload(). This CL addresses
the issue by always collecting the output from stdout instead.
It also refactors the two copies into common.ExtractPublicKey(), and
adds unittest. get_testdata_dir() is moved into test_utils.py that holds
common utils for running the unittests.
Bug: 72884343
Test: python -m unittest test_common
Test: python -m unittest test_ota_from_target_files
Test: Run sign_target_files_apks with '--replace_ota_keys' on marlin
target_files zip. Check the payload pubkey replacement.
Test: Trigger the tests with forrest, and tests no longer fail on
machines with openssl 1.0.1.
Change-Id: Ib0389b360f064053e9aa7cc0546d718e7b23003b
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index d09f60c..16600ed 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1804,6 +1804,31 @@
cert = "".join(cert).decode('base64')
return cert
+
+def ExtractPublicKey(cert):
+ """Extracts the public key (PEM-encoded) from the given certificate file.
+
+ Args:
+ cert: The certificate filename.
+
+ Returns:
+ The public key string.
+
+ Raises:
+ AssertionError: On non-zero return from 'openssl'.
+ """
+ # The behavior with '-out' is different between openssl 1.1 and openssl 1.0.
+ # While openssl 1.1 writes the key into the given filename followed by '-out',
+ # openssl 1.0 (both of 1.0.1 and 1.0.2) doesn't. So we collect the output from
+ # stdout instead.
+ cmd = ['openssl', 'x509', '-pubkey', '-noout', '-in', cert]
+ proc = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pubkey, stderrdata = proc.communicate()
+ assert proc.returncode == 0, \
+ 'Failed to dump public key from certificate: %s\n%s' % (cert, stderrdata)
+ return pubkey
+
+
def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
info_dict=None):
"""Generate a binary patch that creates the recovery image starting