| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python | 
 | 2 | # | 
 | 3 | # Copyright (C) 2008 The Android Open Source Project | 
 | 4 | # | 
 | 5 | # Licensed under the Apache License, Version 2.0 (the "License"); | 
 | 6 | # you may not use this file except in compliance with the License. | 
 | 7 | # You may obtain a copy of the License at | 
 | 8 | # | 
 | 9 | #      http://www.apache.org/licenses/LICENSE-2.0 | 
 | 10 | # | 
 | 11 | # Unless required by applicable law or agreed to in writing, software | 
 | 12 | # distributed under the License is distributed on an "AS IS" BASIS, | 
 | 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | 14 | # See the License for the specific language governing permissions and | 
 | 15 | # limitations under the License. | 
 | 16 |  | 
 | 17 | """ | 
 | 18 | Signs all the APK files in a target-files zipfile, producing a new | 
 | 19 | target-files zip. | 
 | 20 |  | 
 | 21 | Usage:  sign_target_files_apks [flags] input_target_files output_target_files | 
 | 22 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 23 |   -e  (--extra_apks)  <name,name,...=key> | 
 | 24 |       Add extra APK name/key pairs as though they appeared in | 
| Doug Zongker | ad88c7c | 2009-04-14 12:34:27 -0700 | [diff] [blame] | 25 |       apkcerts.txt (so mappings specified by -k and -d are applied). | 
 | 26 |       Keys specified in -e override any value for that app contained | 
 | 27 |       in the apkcerts.txt file.  Option may be repeated to give | 
 | 28 |       multiple extra packages. | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 29 |  | 
 | 30 |   -k  (--key_mapping)  <src_key=dest_key> | 
 | 31 |       Add a mapping from the key name as specified in apkcerts.txt (the | 
 | 32 |       src_key) to the real key you wish to sign the package with | 
 | 33 |       (dest_key).  Option may be repeated to give multiple key | 
 | 34 |       mappings. | 
 | 35 |  | 
 | 36 |   -d  (--default_key_mappings)  <dir> | 
 | 37 |       Set up the following key mappings: | 
 | 38 |  | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 39 |         $devkey/devkey    ==>  $dir/releasekey | 
 | 40 |         $devkey/testkey   ==>  $dir/releasekey | 
 | 41 |         $devkey/media     ==>  $dir/media | 
 | 42 |         $devkey/shared    ==>  $dir/shared | 
 | 43 |         $devkey/platform  ==>  $dir/platform | 
 | 44 |  | 
 | 45 |       where $devkey is the directory part of the value of | 
 | 46 |       default_system_dev_certificate from the input target-files's | 
 | 47 |       META/misc_info.txt.  (Defaulting to "build/target/product/security" | 
 | 48 |       if the value is not present in misc_info. | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 49 |  | 
 | 50 |       -d and -k options are added to the set of mappings in the order | 
 | 51 |       in which they appear on the command line. | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 52 |  | 
 | 53 |   -o  (--replace_ota_keys) | 
 | 54 |       Replace the certificate (public key) used by OTA package | 
 | 55 |       verification with the one specified in the input target_files | 
 | 56 |       zip (in the META/otakeys.txt file).  Key remapping (-k and -d) | 
 | 57 |       is performed on this key. | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 58 |  | 
| Doug Zongker | ae87701 | 2009-04-21 10:04:51 -0700 | [diff] [blame] | 59 |   -t  (--tag_changes)  <+tag>,<-tag>,... | 
 | 60 |       Comma-separated list of changes to make to the set of tags (in | 
 | 61 |       the last component of the build fingerprint).  Prefix each with | 
 | 62 |       '+' or '-' to indicate whether that tag should be added or | 
 | 63 |       removed.  Changes are processed in the order they appear. | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 64 |       Default value is "-test-keys,-dev-keys,+release-keys". | 
| Doug Zongker | ae87701 | 2009-04-21 10:04:51 -0700 | [diff] [blame] | 65 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 66 | """ | 
 | 67 |  | 
 | 68 | import sys | 
 | 69 |  | 
 | 70 | if sys.hexversion < 0x02040000: | 
 | 71 |   print >> sys.stderr, "Python 2.4 or newer is required." | 
 | 72 |   sys.exit(1) | 
 | 73 |  | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 74 | import cStringIO | 
 | 75 | import copy | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 76 | import os | 
 | 77 | import re | 
 | 78 | import subprocess | 
 | 79 | import tempfile | 
 | 80 | import zipfile | 
 | 81 |  | 
 | 82 | import common | 
 | 83 |  | 
 | 84 | OPTIONS = common.OPTIONS | 
 | 85 |  | 
 | 86 | OPTIONS.extra_apks = {} | 
 | 87 | OPTIONS.key_map = {} | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 88 | OPTIONS.replace_ota_keys = False | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 89 | OPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys") | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 90 |  | 
 | 91 | def GetApkCerts(tf_zip): | 
| Doug Zongker | f6a53aa | 2009-12-15 15:06:55 -0800 | [diff] [blame] | 92 |   certmap = common.ReadApkCerts(tf_zip) | 
 | 93 |  | 
 | 94 |   # apply the key remapping to the contents of the file | 
 | 95 |   for apk, cert in certmap.iteritems(): | 
 | 96 |     certmap[apk] = OPTIONS.key_map.get(cert, cert) | 
 | 97 |  | 
 | 98 |   # apply all the -e options, overriding anything in the file | 
| Doug Zongker | ad88c7c | 2009-04-14 12:34:27 -0700 | [diff] [blame] | 99 |   for apk, cert in OPTIONS.extra_apks.iteritems(): | 
| Doug Zongker | decf995 | 2009-12-15 17:27:49 -0800 | [diff] [blame] | 100 |     if not cert: | 
 | 101 |       cert = "PRESIGNED" | 
| Doug Zongker | ad88c7c | 2009-04-14 12:34:27 -0700 | [diff] [blame] | 102 |     certmap[apk] = OPTIONS.key_map.get(cert, cert) | 
| Doug Zongker | f6a53aa | 2009-12-15 15:06:55 -0800 | [diff] [blame] | 103 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 104 |   return certmap | 
 | 105 |  | 
 | 106 |  | 
| Doug Zongker | eb338ef | 2009-05-20 16:50:49 -0700 | [diff] [blame] | 107 | def CheckAllApksSigned(input_tf_zip, apk_key_map): | 
 | 108 |   """Check that all the APKs we want to sign have keys specified, and | 
 | 109 |   error out if they don't.""" | 
 | 110 |   unknown_apks = [] | 
 | 111 |   for info in input_tf_zip.infolist(): | 
 | 112 |     if info.filename.endswith(".apk"): | 
 | 113 |       name = os.path.basename(info.filename) | 
 | 114 |       if name not in apk_key_map: | 
 | 115 |         unknown_apks.append(name) | 
 | 116 |   if unknown_apks: | 
 | 117 |     print "ERROR: no key specified for:\n\n ", | 
 | 118 |     print "\n  ".join(unknown_apks) | 
 | 119 |     print "\nUse '-e <apkname>=' to specify a key (which may be an" | 
 | 120 |     print "empty string to not sign this apk)." | 
 | 121 |     sys.exit(1) | 
 | 122 |  | 
 | 123 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 124 | def SignApk(data, keyname, pw): | 
 | 125 |   unsigned = tempfile.NamedTemporaryFile() | 
 | 126 |   unsigned.write(data) | 
 | 127 |   unsigned.flush() | 
 | 128 |  | 
 | 129 |   signed = tempfile.NamedTemporaryFile() | 
 | 130 |  | 
 | 131 |   common.SignFile(unsigned.name, signed.name, keyname, pw, align=4) | 
 | 132 |  | 
 | 133 |   data = signed.read() | 
 | 134 |   unsigned.close() | 
 | 135 |   signed.close() | 
 | 136 |  | 
 | 137 |   return data | 
 | 138 |  | 
 | 139 |  | 
| Doug Zongker | eb338ef | 2009-05-20 16:50:49 -0700 | [diff] [blame] | 140 | def SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 141 |   maxsize = max([len(os.path.basename(i.filename)) | 
 | 142 |                  for i in input_tf_zip.infolist() | 
 | 143 |                  if i.filename.endswith('.apk')]) | 
 | 144 |  | 
 | 145 |   for info in input_tf_zip.infolist(): | 
 | 146 |     data = input_tf_zip.read(info.filename) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 147 |     out_info = copy.copy(info) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 148 |     if info.filename.endswith(".apk"): | 
 | 149 |       name = os.path.basename(info.filename) | 
| Doug Zongker | 43874f8 | 2009-04-14 14:05:15 -0700 | [diff] [blame] | 150 |       key = apk_key_map[name] | 
| Doug Zongker | f6a53aa | 2009-12-15 15:06:55 -0800 | [diff] [blame] | 151 |       if key not in common.SPECIAL_CERT_STRINGS: | 
| Doug Zongker | 43874f8 | 2009-04-14 14:05:15 -0700 | [diff] [blame] | 152 |         print "    signing: %-*s (%s)" % (maxsize, name, key) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 153 |         signed_data = SignApk(data, key, key_passwords[key]) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 154 |         output_tf_zip.writestr(out_info, signed_data) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 155 |       else: | 
 | 156 |         # an APK we're not supposed to sign. | 
| Doug Zongker | 43874f8 | 2009-04-14 14:05:15 -0700 | [diff] [blame] | 157 |         print "NOT signing: %s" % (name,) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 158 |         output_tf_zip.writestr(out_info, data) | 
 | 159 |     elif info.filename in ("SYSTEM/build.prop", | 
 | 160 |                            "RECOVERY/RAMDISK/default.prop"): | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 161 |       print "rewriting %s:" % (info.filename,) | 
 | 162 |       new_data = RewriteProps(data) | 
 | 163 |       output_tf_zip.writestr(out_info, new_data) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 164 |     else: | 
 | 165 |       # a non-APK file; copy it verbatim | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 166 |       output_tf_zip.writestr(out_info, data) | 
 | 167 |  | 
 | 168 |  | 
| Doug Zongker | c09abc8 | 2010-01-11 13:09:15 -0800 | [diff] [blame] | 169 | def EditTags(tags): | 
 | 170 |   """Given a string containing comma-separated tags, apply the edits | 
 | 171 |   specified in OPTIONS.tag_changes and return the updated string.""" | 
 | 172 |   tags = set(tags.split(",")) | 
 | 173 |   for ch in OPTIONS.tag_changes: | 
 | 174 |     if ch[0] == "-": | 
 | 175 |       tags.discard(ch[1:]) | 
 | 176 |     elif ch[0] == "+": | 
 | 177 |       tags.add(ch[1:]) | 
 | 178 |   return ",".join(sorted(tags)) | 
 | 179 |  | 
 | 180 |  | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 181 | def RewriteProps(data): | 
 | 182 |   output = [] | 
 | 183 |   for line in data.split("\n"): | 
 | 184 |     line = line.strip() | 
 | 185 |     original_line = line | 
 | 186 |     if line and line[0] != '#': | 
 | 187 |       key, value = line.split("=", 1) | 
 | 188 |       if key == "ro.build.fingerprint": | 
| Doug Zongker | c09abc8 | 2010-01-11 13:09:15 -0800 | [diff] [blame] | 189 |         pieces = value.split("/") | 
 | 190 |         pieces[-1] = EditTags(pieces[-1]) | 
 | 191 |         value = "/".join(pieces) | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 192 |       elif key == "ro.build.description": | 
| Doug Zongker | c09abc8 | 2010-01-11 13:09:15 -0800 | [diff] [blame] | 193 |         pieces = value.split(" ") | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 194 |         assert len(pieces) == 5 | 
| Doug Zongker | c09abc8 | 2010-01-11 13:09:15 -0800 | [diff] [blame] | 195 |         pieces[-1] = EditTags(pieces[-1]) | 
 | 196 |         value = " ".join(pieces) | 
 | 197 |       elif key == "ro.build.tags": | 
 | 198 |         value = EditTags(value) | 
 | 199 |       line = key + "=" + value | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 200 |     if line != original_line: | 
 | 201 |       print "  replace: ", original_line | 
 | 202 |       print "     with: ", line | 
 | 203 |     output.append(line) | 
 | 204 |   return "\n".join(output) + "\n" | 
 | 205 |  | 
 | 206 |  | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 207 | def ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 208 |   try: | 
 | 209 |     keylist = input_tf_zip.read("META/otakeys.txt").split() | 
 | 210 |   except KeyError: | 
 | 211 |     raise ExternalError("can't read META/otakeys.txt from input") | 
 | 212 |  | 
| Doug Zongker | e121d6a | 2011-02-01 14:13:52 -0800 | [diff] [blame] | 213 |   extra_recovery_keys = misc_info.get("extra_recovery_keys", None) | 
 | 214 |   if extra_recovery_keys: | 
 | 215 |     extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem" | 
 | 216 |                            for k in extra_recovery_keys.split()] | 
 | 217 |     if extra_recovery_keys: | 
 | 218 |       print "extra recovery-only key(s): " + ", ".join(extra_recovery_keys) | 
 | 219 |   else: | 
 | 220 |     extra_recovery_keys = [] | 
 | 221 |  | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 222 |   mapped_keys = [] | 
 | 223 |   for k in keylist: | 
 | 224 |     m = re.match(r"^(.*)\.x509\.pem$", k) | 
 | 225 |     if not m: | 
 | 226 |       raise ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) | 
 | 227 |     k = m.group(1) | 
 | 228 |     mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") | 
 | 229 |  | 
| Doug Zongker | e05628c | 2009-08-20 17:38:42 -0700 | [diff] [blame] | 230 |   if mapped_keys: | 
 | 231 |     print "using:\n   ", "\n   ".join(mapped_keys) | 
 | 232 |     print "for OTA package verification" | 
 | 233 |   else: | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 234 |     devkey = misc_info.get("default_system_dev_certificate", | 
 | 235 |                            "build/target/product/security/testkey") | 
| Doug Zongker | e05628c | 2009-08-20 17:38:42 -0700 | [diff] [blame] | 236 |     mapped_keys.append( | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 237 |         OPTIONS.key_map.get(devkey, devkey) + ".x509.pem") | 
| Doug Zongker | e05628c | 2009-08-20 17:38:42 -0700 | [diff] [blame] | 238 |     print "META/otakeys.txt has no keys; using", mapped_keys[0] | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 239 |  | 
 | 240 |   # recovery uses a version of the key that has been slightly | 
 | 241 |   # predigested (by DumpPublicKey.java) and put in res/keys. | 
| Doug Zongker | e121d6a | 2011-02-01 14:13:52 -0800 | [diff] [blame] | 242 |   # extra_recovery_keys are used only in recovery. | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 243 |  | 
| Doug Zongker | 602a84e | 2009-06-18 08:35:12 -0700 | [diff] [blame] | 244 |   p = common.Run(["java", "-jar", | 
 | 245 |                   os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] | 
| Doug Zongker | e121d6a | 2011-02-01 14:13:52 -0800 | [diff] [blame] | 246 |                  + mapped_keys + extra_recovery_keys, | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 247 |                  stdout=subprocess.PIPE) | 
 | 248 |   data, _ = p.communicate() | 
 | 249 |   if p.returncode != 0: | 
 | 250 |     raise ExternalError("failed to run dumpkeys") | 
| Doug Zongker | 048e7ca | 2009-06-15 14:31:53 -0700 | [diff] [blame] | 251 |   common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 252 |  | 
 | 253 |   # SystemUpdateActivity uses the x509.pem version of the keys, but | 
 | 254 |   # put into a zipfile system/etc/security/otacerts.zip. | 
| Doug Zongker | e121d6a | 2011-02-01 14:13:52 -0800 | [diff] [blame] | 255 |   # We DO NOT include the extra_recovery_keys (if any) here. | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 256 |  | 
 | 257 |   tempfile = cStringIO.StringIO() | 
 | 258 |   certs_zip = zipfile.ZipFile(tempfile, "w") | 
 | 259 |   for k in mapped_keys: | 
 | 260 |     certs_zip.write(k) | 
 | 261 |   certs_zip.close() | 
| Doug Zongker | 048e7ca | 2009-06-15 14:31:53 -0700 | [diff] [blame] | 262 |   common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", | 
 | 263 |                      tempfile.getvalue()) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 264 |  | 
 | 265 |  | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 266 | def BuildKeyMap(misc_info, key_mapping_options): | 
 | 267 |   for s, d in key_mapping_options: | 
 | 268 |     if s is None:   # -d option | 
 | 269 |       devkey = misc_info.get("default_system_dev_certificate", | 
 | 270 |                              "build/target/product/security/testkey") | 
 | 271 |       devkeydir = os.path.dirname(devkey) | 
 | 272 |  | 
 | 273 |       OPTIONS.key_map.update({ | 
 | 274 |           devkeydir + "/testkey":  d + "/releasekey", | 
 | 275 |           devkeydir + "/devkey":   d + "/releasekey", | 
 | 276 |           devkeydir + "/media":    d + "/media", | 
 | 277 |           devkeydir + "/shared":   d + "/shared", | 
 | 278 |           devkeydir + "/platform": d + "/platform", | 
 | 279 |           }) | 
 | 280 |     else: | 
 | 281 |       OPTIONS.key_map[s] = d | 
 | 282 |  | 
 | 283 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 284 | def main(argv): | 
 | 285 |  | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 286 |   key_mapping_options = [] | 
 | 287 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 288 |   def option_handler(o, a): | 
| Doug Zongker | 05d3dea | 2009-06-22 11:32:31 -0700 | [diff] [blame] | 289 |     if o in ("-e", "--extra_apks"): | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 290 |       names, key = a.split("=") | 
 | 291 |       names = names.split(",") | 
 | 292 |       for n in names: | 
 | 293 |         OPTIONS.extra_apks[n] = key | 
 | 294 |     elif o in ("-d", "--default_key_mappings"): | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 295 |       key_mapping_options.append((None, a)) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 296 |     elif o in ("-k", "--key_mapping"): | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 297 |       key_mapping_options.append(a.split("=", 1)) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 298 |     elif o in ("-o", "--replace_ota_keys"): | 
 | 299 |       OPTIONS.replace_ota_keys = True | 
| Doug Zongker | ae87701 | 2009-04-21 10:04:51 -0700 | [diff] [blame] | 300 |     elif o in ("-t", "--tag_changes"): | 
 | 301 |       new = [] | 
 | 302 |       for i in a.split(","): | 
 | 303 |         i = i.strip() | 
 | 304 |         if not i or i[0] not in "-+": | 
 | 305 |           raise ValueError("Bad tag change '%s'" % (i,)) | 
 | 306 |         new.append(i[0] + i[1:].strip()) | 
 | 307 |       OPTIONS.tag_changes = tuple(new) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 308 |     else: | 
 | 309 |       return False | 
 | 310 |     return True | 
 | 311 |  | 
 | 312 |   args = common.ParseOptions(argv, __doc__, | 
| Doug Zongker | 05d3dea | 2009-06-22 11:32:31 -0700 | [diff] [blame] | 313 |                              extra_opts="e:d:k:ot:", | 
 | 314 |                              extra_long_opts=["extra_apks=", | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 315 |                                               "default_key_mappings=", | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 316 |                                               "key_mapping=", | 
| Doug Zongker | 17aa944 | 2009-04-17 10:15:58 -0700 | [diff] [blame] | 317 |                                               "replace_ota_keys", | 
| Doug Zongker | ae87701 | 2009-04-21 10:04:51 -0700 | [diff] [blame] | 318 |                                               "tag_changes="], | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 319 |                              extra_option_handler=option_handler) | 
 | 320 |  | 
 | 321 |   if len(args) != 2: | 
 | 322 |     common.Usage(__doc__) | 
 | 323 |     sys.exit(1) | 
 | 324 |  | 
 | 325 |   input_zip = zipfile.ZipFile(args[0], "r") | 
 | 326 |   output_zip = zipfile.ZipFile(args[1], "w") | 
 | 327 |  | 
| Doug Zongker | 831840e | 2011-09-22 10:28:04 -0700 | [diff] [blame] | 328 |   misc_info = common.LoadInfoDict(input_zip) | 
 | 329 |  | 
 | 330 |   BuildKeyMap(misc_info, key_mapping_options) | 
 | 331 |  | 
| Doug Zongker | eb338ef | 2009-05-20 16:50:49 -0700 | [diff] [blame] | 332 |   apk_key_map = GetApkCerts(input_zip) | 
 | 333 |   CheckAllApksSigned(input_zip, apk_key_map) | 
| Doug Zongker | eb338ef | 2009-05-20 16:50:49 -0700 | [diff] [blame] | 334 |  | 
 | 335 |   key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) | 
 | 336 |   SignApks(input_zip, output_zip, apk_key_map, key_passwords) | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 337 |  | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 338 |   if OPTIONS.replace_ota_keys: | 
| Doug Zongker | b11e2d7 | 2011-10-05 11:23:06 -0700 | [diff] [blame] | 339 |     ReplaceOtaKeys(input_zip, output_zip, misc_info) | 
| Doug Zongker | 8e931bf | 2009-04-06 15:21:45 -0700 | [diff] [blame] | 340 |  | 
| Doug Zongker | eef3944 | 2009-04-02 12:14:19 -0700 | [diff] [blame] | 341 |   input_zip.close() | 
 | 342 |   output_zip.close() | 
 | 343 |  | 
 | 344 |   print "done." | 
 | 345 |  | 
 | 346 |  | 
 | 347 | if __name__ == '__main__': | 
 | 348 |   try: | 
 | 349 |     main(sys.argv[1:]) | 
 | 350 |   except common.ExternalError, e: | 
 | 351 |     print | 
 | 352 |     print "   ERROR: %s" % (e,) | 
 | 353 |     print | 
 | 354 |     sys.exit(1) |