update the cert used for OTA verification when signing

The build system now (in donut) produces builds that use the testkey
cert for OTA package verification.  Change the app-signing script to
also optionally substitute the "real" cert in both the recovery and
system images.  Also fix bug where the build fingerprint and
description were not getting properly updated in the recovery
partition.
This commit is contained in:
Doug Zongker
2009-04-06 15:21:45 -07:00
parent eef3944eb3
commit 8e931bf999
2 changed files with 64 additions and 8 deletions

View File

@@ -28,6 +28,7 @@ if not hasattr(os, "SEEK_SET"):
class Options(object): pass class Options(object): pass
OPTIONS = Options() OPTIONS = Options()
OPTIONS.signapk_jar = "out/host/linux-x86/framework/signapk.jar" OPTIONS.signapk_jar = "out/host/linux-x86/framework/signapk.jar"
OPTIONS.dumpkey_jar = "out/host/linux-x86/framework/dumpkey.jar"
OPTIONS.max_image_size = {} OPTIONS.max_image_size = {}
OPTIONS.verbose = False OPTIONS.verbose = False
OPTIONS.tempfiles = [] OPTIONS.tempfiles = []

View File

@@ -45,6 +45,12 @@ Usage: sign_target_files_apks [flags] input_target_files output_target_files
-d and -k options are added to the set of mappings in the order -d and -k options are added to the set of mappings in the order
in which they appear on the command line. in which they appear on the command line.
-o (--replace_ota_keys)
Replace the certificate (public key) used by OTA package
verification with the one specified in the input target_files
zip (in the META/otakeys.txt file). Key remapping (-k and -d)
is performed on this key.
""" """
import sys import sys
@@ -53,6 +59,8 @@ if sys.hexversion < 0x02040000:
print >> sys.stderr, "Python 2.4 or newer is required." print >> sys.stderr, "Python 2.4 or newer is required."
sys.exit(1) sys.exit(1)
import cStringIO
import copy
import os import os
import re import re
import subprocess import subprocess
@@ -65,7 +73,7 @@ OPTIONS = common.OPTIONS
OPTIONS.extra_apks = {} OPTIONS.extra_apks = {}
OPTIONS.key_map = {} OPTIONS.key_map = {}
OPTIONS.replace_ota_keys = False
def GetApkCerts(tf_zip): def GetApkCerts(tf_zip):
certmap = OPTIONS.extra_apks.copy() certmap = OPTIONS.extra_apks.copy()
@@ -107,18 +115,20 @@ def SignApks(input_tf_zip, output_tf_zip):
for info in input_tf_zip.infolist(): for info in input_tf_zip.infolist():
data = input_tf_zip.read(info.filename) data = input_tf_zip.read(info.filename)
out_info = copy.copy(info)
if info.filename.endswith(".apk"): if info.filename.endswith(".apk"):
name = os.path.basename(info.filename) name = os.path.basename(info.filename)
key = apk_key_map.get(name, None) key = apk_key_map.get(name, None)
if key is not None: if key is not None:
print "signing: %-*s (%s)" % (maxsize, name, key) print "signing: %-*s (%s)" % (maxsize, name, key)
signed_data = SignApk(data, key, key_passwords[key]) signed_data = SignApk(data, key, key_passwords[key])
output_tf_zip.writestr(info, signed_data) output_tf_zip.writestr(out_info, signed_data)
else: else:
# an APK we're not supposed to sign. # an APK we're not supposed to sign.
print "skipping: %s" % (name,) print "skipping: %s" % (name,)
output_tf_zip.writestr(info, data) output_tf_zip.writestr(out_info, data)
elif info.filename == "SYSTEM/build.prop": elif info.filename in ("SYSTEM/build.prop",
"RECOVERY/RAMDISK/default.prop"):
# Change build fingerprint to reflect the fact that apps are signed. # Change build fingerprint to reflect the fact that apps are signed.
m = re.search(r"ro\.build\.fingerprint=.*\b(test-keys)\b.*", data) m = re.search(r"ro\.build\.fingerprint=.*\b(test-keys)\b.*", data)
if not m: if not m:
@@ -130,10 +140,49 @@ def SignApks(input_tf_zip, output_tf_zip):
print 'WARNING: ro.build.description does not contain "test-keys"' print 'WARNING: ro.build.description does not contain "test-keys"'
else: else:
data = data[:m.start(1)] + "release-keys" + data[m.end(1):] data = data[:m.start(1)] + "release-keys" + data[m.end(1):]
output_tf_zip.writestr(info, data) output_tf_zip.writestr(out_info, data)
else: else:
# a non-APK file; copy it verbatim # a non-APK file; copy it verbatim
output_tf_zip.writestr(info, data) output_tf_zip.writestr(out_info, data)
def ReplaceOtaKeys(input_tf_zip, output_tf_zip):
try:
keylist = input_tf_zip.read("META/otakeys.txt").split()
except KeyError:
raise ExternalError("can't read META/otakeys.txt from input")
mapped_keys = []
for k in keylist:
m = re.match(r"^(.*)\.x509\.pem$", k)
if not m:
raise ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,))
k = m.group(1)
mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem")
print "using:\n ", "\n ".join(mapped_keys)
print "for OTA package verification"
# recovery uses a version of the key that has been slightly
# predigested (by DumpPublicKey.java) and put in res/keys.
p = common.Run(["java", "-jar", OPTIONS.dumpkey_jar] + mapped_keys,
stdout=subprocess.PIPE)
data, _ = p.communicate()
if p.returncode != 0:
raise ExternalError("failed to run dumpkeys")
output_tf_zip.writestr("RECOVERY/RAMDISK/res/keys", data)
# SystemUpdateActivity uses the x509.pem version of the keys, but
# put into a zipfile system/etc/security/otacerts.zip.
tempfile = cStringIO.StringIO()
certs_zip = zipfile.ZipFile(tempfile, "w")
for k in mapped_keys:
certs_zip.write(k)
certs_zip.close()
output_tf_zip.writestr("SYSTEM/etc/security/otacerts.zip",
tempfile.getvalue())
def main(argv): def main(argv):
@@ -156,16 +205,19 @@ def main(argv):
elif o in ("-k", "--key_mapping"): elif o in ("-k", "--key_mapping"):
s, d = a.split("=") s, d = a.split("=")
OPTIONS.key_map[s] = d OPTIONS.key_map[s] = d
elif o in ("-o", "--replace_ota_keys"):
OPTIONS.replace_ota_keys = True
else: else:
return False return False
return True return True
args = common.ParseOptions(argv, __doc__, args = common.ParseOptions(argv, __doc__,
extra_opts="s:e:d:k:", extra_opts="s:e:d:k:o",
extra_long_opts=["signapk_jar=", extra_long_opts=["signapk_jar=",
"extra_apks=", "extra_apks=",
"default_key_mappings=", "default_key_mappings=",
"key_mapping="], "key_mapping=",
"replace_ota_keys"],
extra_option_handler=option_handler) extra_option_handler=option_handler)
if len(args) != 2: if len(args) != 2:
@@ -177,6 +229,9 @@ def main(argv):
SignApks(input_zip, output_zip) SignApks(input_zip, output_zip)
if OPTIONS.replace_ota_keys:
ReplaceOtaKeys(input_zip, output_zip)
input_zip.close() input_zip.close()
output_zip.close() output_zip.close()