diff --git a/tools/releasetools/check_target_files_signatures b/tools/releasetools/check_target_files_signatures index ae372ba4ea..45d30a651c 100755 --- a/tools/releasetools/check_target_files_signatures +++ b/tools/releasetools/check_target_files_signatures @@ -135,7 +135,7 @@ class CertDB(object): for i in to_load: f = open(i) - cert = ParseCertificate(f.read()) + cert = common.ParseCertificate(f.read()) f.close() name, _ = os.path.splitext(i) name, _ = os.path.splitext(name) @@ -144,21 +144,6 @@ class CertDB(object): ALL_CERTS = CertDB() -def ParseCertificate(data): - """Parse a PEM-format certificate.""" - cert = [] - save = False - for line in data.split("\n"): - if "--END CERTIFICATE--" in line: - break - if save: - cert.append(line) - if "--BEGIN CERTIFICATE--" in line: - save = True - cert = "".join(cert).decode('base64') - return cert - - def CertFromPKCS7(data, filename): """Read the cert out of a PKCS#7-format file (which is what is stored in a signed .apk).""" @@ -175,7 +160,7 @@ def CertFromPKCS7(data, filename): AddProblem("error reading cert:\n" + err) return None - cert = ParseCertificate(out) + cert = common.ParseCertificate(out) if not cert: AddProblem("error parsing cert output") return None diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py index 58582ba690..a3217dd9a3 100644 --- a/tools/releasetools/common.py +++ b/tools/releasetools/common.py @@ -954,3 +954,18 @@ def GetTypeAndDevice(mount_point, info): return PARTITION_TYPES[fstab[mount_point].fs_type], fstab[mount_point].device else: return None + + +def ParseCertificate(data): + """Parse a PEM-format certificate.""" + cert = [] + save = False + for line in data.split("\n"): + if "--END CERTIFICATE--" in line: + break + if save: + cert.append(line) + if "--BEGIN CERTIFICATE--" in line: + save = True + cert = "".join(cert).decode('base64') + return cert diff --git a/tools/releasetools/sign_target_files_apks b/tools/releasetools/sign_target_files_apks index 9fb1008938..fe6f8209a7 100755 --- a/tools/releasetools/sign_target_files_apks +++ b/tools/releasetools/sign_target_files_apks @@ -71,8 +71,10 @@ if sys.hexversion < 0x02040000: print >> sys.stderr, "Python 2.4 or newer is required." sys.exit(1) +import base64 import cStringIO import copy +import errno import os import re import subprocess @@ -161,11 +163,45 @@ def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): print "rewriting %s:" % (info.filename,) new_data = RewriteProps(data) output_tf_zip.writestr(out_info, new_data) + elif info.filename.endswith("mac_permissions.xml"): + print "rewriting %s with new keys." % (info.filename,) + new_data = ReplaceCerts(data) + output_tf_zip.writestr(out_info, new_data) else: # a non-APK file; copy it verbatim output_tf_zip.writestr(out_info, data) +def ReplaceCerts(data): + """Given a string of data, replace all occurences of a set + of X509 certs with a newer set of X509 certs and return + the updated data string.""" + for old, new in OPTIONS.key_map.iteritems(): + try: + if OPTIONS.verbose: + print " Replacing %s.x509.pem with %s.x509.pem" % (old, new) + f = open(old + ".x509.pem") + old_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower() + f.close() + f = open(new + ".x509.pem") + new_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower() + f.close() + # Only match entire certs. + pattern = "\\b"+old_cert16+"\\b" + (data, num) = re.subn(pattern, new_cert16, data, flags=re.IGNORECASE) + if OPTIONS.verbose: + print " Replaced %d occurence(s) of %s.x509.pem with " \ + "%s.x509.pem" % (num, old, new) + except IOError, e: + if (e.errno == errno.ENOENT and not OPTIONS.verbose): + continue + + print " Error accessing %s. %s. Skip replacing %s.x509.pem " \ + "with %s.x509.pem." % (e.filename, e.strerror, old, new) + + return data + + def EditTags(tags): """Given a string containing comma-separated tags, apply the edits specified in OPTIONS.tag_changes and return the updated string."""