1eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker#!/usr/bin/env python 2eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 3eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Copyright (C) 2008 The Android Open Source Project 4eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 5eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Licensed under the Apache License, Version 2.0 (the "License"); 6eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# you may not use this file except in compliance with the License. 7eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# You may obtain a copy of the License at 8eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 9eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# http://www.apache.org/licenses/LICENSE-2.0 10eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# 11eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# Unless required by applicable law or agreed to in writing, software 12eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# distributed under the License is distributed on an "AS IS" BASIS, 13eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# See the License for the specific language governing permissions and 15eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker# limitations under the License. 16eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 17eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker""" 18eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerSigns all the APK files in a target-files zipfile, producing a new 19eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkertarget-files zip. 20eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 21eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerUsage: sign_target_files_apks [flags] input_target_files output_target_files 22eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 23eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker -e (--extra_apks) <name,name,...=key> 24eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker Add extra APK name/key pairs as though they appeared in 25ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker apkcerts.txt (so mappings specified by -k and -d are applied). 26ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker Keys specified in -e override any value for that app contained 27ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker in the apkcerts.txt file. Option may be repeated to give 28ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker multiple extra packages. 29eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 30eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker -k (--key_mapping) <src_key=dest_key> 31eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker Add a mapping from the key name as specified in apkcerts.txt (the 32eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker src_key) to the real key you wish to sign the package with 33eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker (dest_key). Option may be repeated to give multiple key 34eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker mappings. 35eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 36eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker -d (--default_key_mappings) <dir> 37eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker Set up the following key mappings: 38eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 39831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker $devkey/devkey ==> $dir/releasekey 40831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker $devkey/testkey ==> $dir/releasekey 41831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker $devkey/media ==> $dir/media 42831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker $devkey/shared ==> $dir/shared 43831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker $devkey/platform ==> $dir/platform 44831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 45831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker where $devkey is the directory part of the value of 46831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker default_system_dev_certificate from the input target-files's 47831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker META/misc_info.txt. (Defaulting to "build/target/product/security" 48831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker if the value is not present in misc_info. 49eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 50eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker -d and -k options are added to the set of mappings in the order 51eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker in which they appear on the command line. 528e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 538e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker -o (--replace_ota_keys) 548e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker Replace the certificate (public key) used by OTA package 558e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker verification with the one specified in the input target_files 568e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker zip (in the META/otakeys.txt file). Key remapping (-k and -d) 578e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker is performed on this key. 5817aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker 59ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker -t (--tag_changes) <+tag>,<-tag>,... 60ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker Comma-separated list of changes to make to the set of tags (in 61ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker the last component of the build fingerprint). Prefix each with 62ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker '+' or '-' to indicate whether that tag should be added or 63ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker removed. Changes are processed in the order they appear. 64831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker Default value is "-test-keys,-dev-keys,+release-keys". 65ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker 66eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker""" 67eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 68eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport sys 69eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 70eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerif sys.hexversion < 0x02040000: 71eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print >> sys.stderr, "Python 2.4 or newer is required." 72eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 73eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 748e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongkerimport cStringIO 758e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongkerimport copy 76eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport os 77eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport re 78eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport subprocess 79eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport tempfile 80eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport zipfile 81eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 82eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerimport common 83eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 84eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS = common.OPTIONS 85eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 86eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.extra_apks = {} 87eef3944eb3673329b5e89cf188ac592805a0b08dDoug ZongkerOPTIONS.key_map = {} 888e931bf999693cac54c99deb1ef668d0e6164ecfDoug ZongkerOPTIONS.replace_ota_keys = False 89831840e51b0403671f746ebc32090b7d6e548c08Doug ZongkerOPTIONS.tag_changes = ("-test-keys", "-dev-keys", "+release-keys") 90eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 91eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef GetApkCerts(tf_zip): 92f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker certmap = common.ReadApkCerts(tf_zip) 93f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker 94f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # apply the key remapping to the contents of the file 95f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker for apk, cert in certmap.iteritems(): 96f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker certmap[apk] = OPTIONS.key_map.get(cert, cert) 97f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker 98f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker # apply all the -e options, overriding anything in the file 99ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker for apk, cert in OPTIONS.extra_apks.iteritems(): 100decf995c5956e6f64f858d1c4e51a3f3b9829a51Doug Zongker if not cert: 101decf995c5956e6f64f858d1c4e51a3f3b9829a51Doug Zongker cert = "PRESIGNED" 102ad88c7ce4f3a65827d4cd5b5ed01324b3b368dd9Doug Zongker certmap[apk] = OPTIONS.key_map.get(cert, cert) 103f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker 104eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return certmap 105eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 106eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 107eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongkerdef CheckAllApksSigned(input_tf_zip, apk_key_map): 108eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker """Check that all the APKs we want to sign have keys specified, and 109eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker error out if they don't.""" 110eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker unknown_apks = [] 111eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker for info in input_tf_zip.infolist(): 112eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker if info.filename.endswith(".apk"): 113eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker name = os.path.basename(info.filename) 114eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker if name not in apk_key_map: 115eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker unknown_apks.append(name) 116eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker if unknown_apks: 117eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker print "ERROR: no key specified for:\n\n ", 118eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker print "\n ".join(unknown_apks) 119eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker print "\nUse '-e <apkname>=' to specify a key (which may be an" 120eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker print "empty string to not sign this apk)." 121eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker sys.exit(1) 122eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker 123eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker 124eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef SignApk(data, keyname, pw): 125eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker unsigned = tempfile.NamedTemporaryFile() 126eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker unsigned.write(data) 127eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker unsigned.flush() 128eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 129eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker signed = tempfile.NamedTemporaryFile() 130eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 131eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker common.SignFile(unsigned.name, signed.name, keyname, pw, align=4) 132eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 133eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker data = signed.read() 134eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker unsigned.close() 135eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker signed.close() 136eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 137eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return data 138eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 139eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 140eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongkerdef SignApks(input_tf_zip, output_tf_zip, apk_key_map, key_passwords): 141eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker maxsize = max([len(os.path.basename(i.filename)) 142eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for i in input_tf_zip.infolist() 143eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if i.filename.endswith('.apk')]) 144eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 145eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for info in input_tf_zip.infolist(): 146eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker data = input_tf_zip.read(info.filename) 1478e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker out_info = copy.copy(info) 148eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if info.filename.endswith(".apk"): 149eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker name = os.path.basename(info.filename) 15043874f8c864972b9dae7e4927aa347455b774c94Doug Zongker key = apk_key_map[name] 151f6a53aa5f24878ad9098409ed3d3f41bb5c63fb5Doug Zongker if key not in common.SPECIAL_CERT_STRINGS: 15243874f8c864972b9dae7e4927aa347455b774c94Doug Zongker print " signing: %-*s (%s)" % (maxsize, name, key) 153eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker signed_data = SignApk(data, key, key_passwords[key]) 1548e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker output_tf_zip.writestr(out_info, signed_data) 155eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 156eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # an APK we're not supposed to sign. 15743874f8c864972b9dae7e4927aa347455b774c94Doug Zongker print "NOT signing: %s" % (name,) 1588e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker output_tf_zip.writestr(out_info, data) 1598e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker elif info.filename in ("SYSTEM/build.prop", 1608e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker "RECOVERY/RAMDISK/default.prop"): 16117aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker print "rewriting %s:" % (info.filename,) 16217aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker new_data = RewriteProps(data) 16317aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker output_tf_zip.writestr(out_info, new_data) 164eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 165eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker # a non-APK file; copy it verbatim 1668e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker output_tf_zip.writestr(out_info, data) 1678e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 1688e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 169c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongkerdef EditTags(tags): 170c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker """Given a string containing comma-separated tags, apply the edits 171c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker specified in OPTIONS.tag_changes and return the updated string.""" 172c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker tags = set(tags.split(",")) 173c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker for ch in OPTIONS.tag_changes: 174c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker if ch[0] == "-": 175c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker tags.discard(ch[1:]) 176c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker elif ch[0] == "+": 177c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker tags.add(ch[1:]) 178c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker return ",".join(sorted(tags)) 179c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker 180c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker 18117aa944001e7ae2425beec75d3ebc280413631eeDoug Zongkerdef RewriteProps(data): 18217aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker output = [] 18317aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker for line in data.split("\n"): 18417aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker line = line.strip() 18517aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker original_line = line 18617aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker if line and line[0] != '#': 18717aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker key, value = line.split("=", 1) 18817aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker if key == "ro.build.fingerprint": 189c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker pieces = value.split("/") 190c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker pieces[-1] = EditTags(pieces[-1]) 191c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker value = "/".join(pieces) 19217aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker elif key == "ro.build.description": 193c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker pieces = value.split(" ") 19417aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker assert len(pieces) == 5 195c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker pieces[-1] = EditTags(pieces[-1]) 196c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker value = " ".join(pieces) 197c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker elif key == "ro.build.tags": 198c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker value = EditTags(value) 199a8608a7f7cee388192780f8988b5dc5966423eefDoug Zongker elif key == "ro.build.display.id": 200a8608a7f7cee388192780f8988b5dc5966423eefDoug Zongker # change, eg, "JWR66N dev-keys" to "JWR66N" 201a8608a7f7cee388192780f8988b5dc5966423eefDoug Zongker value = value.split() 202a8608a7f7cee388192780f8988b5dc5966423eefDoug Zongker if len(value) == 2 and value[1].endswith("-keys"): 203a8608a7f7cee388192780f8988b5dc5966423eefDoug Zongker value = value[0] 204c09abc8103a4c029cc2c6d59226a2a74be57d082Doug Zongker line = key + "=" + value 20517aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker if line != original_line: 20617aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker print " replace: ", original_line 20717aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker print " with: ", line 20817aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker output.append(line) 20917aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker return "\n".join(output) + "\n" 21017aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker 21117aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker 212831840e51b0403671f746ebc32090b7d6e548c08Doug Zongkerdef ReplaceOtaKeys(input_tf_zip, output_tf_zip, misc_info): 2138e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker try: 2148e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker keylist = input_tf_zip.read("META/otakeys.txt").split() 2158e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker except KeyError: 216a28acc6972ce35e9dfab061f175e229859d3e4dbT.R. Fullhart raise common.ExternalError("can't read META/otakeys.txt from input") 2178e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 218e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker extra_recovery_keys = misc_info.get("extra_recovery_keys", None) 219e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker if extra_recovery_keys: 220e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem" 221e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker for k in extra_recovery_keys.split()] 222e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker if extra_recovery_keys: 223e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker print "extra recovery-only key(s): " + ", ".join(extra_recovery_keys) 224e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker else: 225e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker extra_recovery_keys = [] 226e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker 2278e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker mapped_keys = [] 2288e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker for k in keylist: 2298e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker m = re.match(r"^(.*)\.x509\.pem$", k) 2308e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker if not m: 231a28acc6972ce35e9dfab061f175e229859d3e4dbT.R. Fullhart raise common.ExternalError("can't parse \"%s\" from META/otakeys.txt" % (k,)) 2328e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker k = m.group(1) 2338e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem") 2348e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 235e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker if mapped_keys: 236e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker print "using:\n ", "\n ".join(mapped_keys) 237e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker print "for OTA package verification" 238e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker else: 239831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkey = misc_info.get("default_system_dev_certificate", 240831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker "build/target/product/security/testkey") 241e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker mapped_keys.append( 242831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker OPTIONS.key_map.get(devkey, devkey) + ".x509.pem") 243e05628cc8df4ec4b69befa9652d81eb81f0ab008Doug Zongker print "META/otakeys.txt has no keys; using", mapped_keys[0] 2448e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 2458e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker # recovery uses a version of the key that has been slightly 2468e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker # predigested (by DumpPublicKey.java) and put in res/keys. 247e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker # extra_recovery_keys are used only in recovery. 2488e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 249602a84e0bbf1807a9403cfa50184241f6fc035c4Doug Zongker p = common.Run(["java", "-jar", 250602a84e0bbf1807a9403cfa50184241f6fc035c4Doug Zongker os.path.join(OPTIONS.search_path, "framework", "dumpkey.jar")] 251e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker + mapped_keys + extra_recovery_keys, 2528e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker stdout=subprocess.PIPE) 2538e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker data, _ = p.communicate() 2548e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker if p.returncode != 0: 255a28acc6972ce35e9dfab061f175e229859d3e4dbT.R. Fullhart raise common.ExternalError("failed to run dumpkeys") 256048e7ca15f6391681490ce564bc71194adf146aaDoug Zongker common.ZipWriteStr(output_tf_zip, "RECOVERY/RAMDISK/res/keys", data) 2578e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 2588e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker # SystemUpdateActivity uses the x509.pem version of the keys, but 2598e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker # put into a zipfile system/etc/security/otacerts.zip. 260e121d6acf47c3056e079ff62c82171e889cec3e0Doug Zongker # We DO NOT include the extra_recovery_keys (if any) here. 2618e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 2628e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker tempfile = cStringIO.StringIO() 2638e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker certs_zip = zipfile.ZipFile(tempfile, "w") 2648e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker for k in mapped_keys: 2658e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker certs_zip.write(k) 2668e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker certs_zip.close() 267048e7ca15f6391681490ce564bc71194adf146aaDoug Zongker common.ZipWriteStr(output_tf_zip, "SYSTEM/etc/security/otacerts.zip", 268048e7ca15f6391681490ce564bc71194adf146aaDoug Zongker tempfile.getvalue()) 269eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 270eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 271831840e51b0403671f746ebc32090b7d6e548c08Doug Zongkerdef BuildKeyMap(misc_info, key_mapping_options): 272831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker for s, d in key_mapping_options: 273831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker if s is None: # -d option 274831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkey = misc_info.get("default_system_dev_certificate", 275831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker "build/target/product/security/testkey") 276831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir = os.path.dirname(devkey) 277831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 278831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker OPTIONS.key_map.update({ 279831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir + "/testkey": d + "/releasekey", 280831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir + "/devkey": d + "/releasekey", 281831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir + "/media": d + "/media", 282831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir + "/shared": d + "/shared", 283831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker devkeydir + "/platform": d + "/platform", 284831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker }) 285831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker else: 286831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker OPTIONS.key_map[s] = d 287831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 288831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 289eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerdef main(argv): 290eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 291831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker key_mapping_options = [] 292831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 293eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker def option_handler(o, a): 29405d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker if o in ("-e", "--extra_apks"): 295eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker names, key = a.split("=") 296eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker names = names.split(",") 297eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker for n in names: 298eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker OPTIONS.extra_apks[n] = key 299eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker elif o in ("-d", "--default_key_mappings"): 300831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker key_mapping_options.append((None, a)) 301eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker elif o in ("-k", "--key_mapping"): 302831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker key_mapping_options.append(a.split("=", 1)) 3038e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker elif o in ("-o", "--replace_ota_keys"): 3048e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker OPTIONS.replace_ota_keys = True 305ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker elif o in ("-t", "--tag_changes"): 306ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker new = [] 307ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker for i in a.split(","): 308ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker i = i.strip() 309ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker if not i or i[0] not in "-+": 310ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker raise ValueError("Bad tag change '%s'" % (i,)) 311ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker new.append(i[0] + i[1:].strip()) 312ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker OPTIONS.tag_changes = tuple(new) 313eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker else: 314eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return False 315eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker return True 316eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 317eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker args = common.ParseOptions(argv, __doc__, 31805d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker extra_opts="e:d:k:ot:", 31905d3dea519688b61d86e30c2d4b99ff494aeca73Doug Zongker extra_long_opts=["extra_apks=", 320eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker "default_key_mappings=", 3218e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker "key_mapping=", 32217aa944001e7ae2425beec75d3ebc280413631eeDoug Zongker "replace_ota_keys", 323ae877013ab8d87b9f0da111adcb7621f477451c6Doug Zongker "tag_changes="], 324eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker extra_option_handler=option_handler) 325eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 326eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker if len(args) != 2: 327eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker common.Usage(__doc__) 328eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 329eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 330eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker input_zip = zipfile.ZipFile(args[0], "r") 331eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker output_zip = zipfile.ZipFile(args[1], "w") 332eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 333831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker misc_info = common.LoadInfoDict(input_zip) 334831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 335831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker BuildKeyMap(misc_info, key_mapping_options) 336831840e51b0403671f746ebc32090b7d6e548c08Doug Zongker 337eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker apk_key_map = GetApkCerts(input_zip) 338eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker CheckAllApksSigned(input_zip, apk_key_map) 339eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker 340eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) 341eb338efd2eae20962c7ca75baf161be540b3d664Doug Zongker SignApks(input_zip, output_zip, apk_key_map, key_passwords) 342eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 3438e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker if OPTIONS.replace_ota_keys: 344b11e2d78ecc3eac29b259bc10a466d65d50ac653Doug Zongker ReplaceOtaKeys(input_zip, output_zip, misc_info) 3458e931bf999693cac54c99deb1ef668d0e6164ecfDoug Zongker 346eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker input_zip.close() 347eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker output_zip.close() 348eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 349eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print "done." 350eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 351eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker 352eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongkerif __name__ == '__main__': 353eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker try: 354eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker main(sys.argv[1:]) 355eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker except common.ExternalError, e: 356eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print 357eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print " ERROR: %s" % (e,) 358eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker print 359eef3944eb3673329b5e89cf188ac592805a0b08dDoug Zongker sys.exit(1) 360