aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Klyubin2016-01-13 12:32:47 -0600
committerAlex Klyubin2016-01-29 12:17:02 -0600
commitc2a36afd6772d9286e8071693f80648beef763a3 (patch)
tree00347526394018525a69f65c4e0fca2965c45854 /tools/releasetools/sign_target_files_apks.py
parent4a97cde443829f1a3bf40fe6e820ba5b01e3bf87 (diff)
downloadplatform-build-c2a36afd6772d9286e8071693f80648beef763a3.tar.gz
platform-build-c2a36afd6772d9286e8071693f80648beef763a3.tar.xz
platform-build-c2a36afd6772d9286e8071693f80648beef763a3.zip
Sign APKs using SHA-256 instead of SHA-1 when possible.
This changes the build system to provide the signapk tool with the minSdkVersion of the APK being signed. signapk in turn will then use SHA-256 instead of SHA-1 if minSdkVersion is 18 (JB MR2) or higher (see c2c49ed0c13846f7f96249c7419971dfcddc9215). To avoid increasing incremental OTA update package sizes for already released platforms, release build scripts disable the above logic when signing target files ZIPs for pre-N platforms. Bug: 25643280 (cherry picked from commit de5bc04717505ad0e5b55605bccf43974f4c5c7a) Change-Id: I4b100750e47788ab6ed897a0a5abfd33542e8676
Diffstat (limited to 'tools/releasetools/sign_target_files_apks.py')
-rwxr-xr-xtools/releasetools/sign_target_files_apks.py92
1 files changed, 87 insertions, 5 deletions
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index baf60f5c6..8941e3569 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -127,14 +127,34 @@ def CheckAllApksSigned(input_tf_zip, apk_key_map):
127 sys.exit(1) 127 sys.exit(1)
128 128
129 129
130def SignApk(data, keyname, pw): 130def SignApk(data, keyname, pw, platform_api_level, codename_to_api_level_map):
131 unsigned = tempfile.NamedTemporaryFile() 131 unsigned = tempfile.NamedTemporaryFile()
132 unsigned.write(data) 132 unsigned.write(data)
133 unsigned.flush() 133 unsigned.flush()
134 134
135 signed = tempfile.NamedTemporaryFile() 135 signed = tempfile.NamedTemporaryFile()
136 136
137 common.SignFile(unsigned.name, signed.name, keyname, pw) 137 # For pre-N builds, don't upgrade to SHA-256 JAR signatures based on the APK's
138 # minSdkVersion to avoid increasing incremental OTA update sizes. If an APK
139 # didn't change, we don't want its signature to change due to the switch
140 # from SHA-1 to SHA-256.
141 # By default, APK signer chooses SHA-256 signatures if the APK's minSdkVersion
142 # is 18 or higher. For pre-N builds we disable this mechanism by pretending
143 # that the APK's minSdkVersion is 1.
144 # For N+ builds, we let APK signer rely on the APK's minSdkVersion to
145 # determine whether to use SHA-256.
146 min_api_level = None
147 if platform_api_level > 23:
148 # Let APK signer choose whether to use SHA-1 or SHA-256, based on the APK's
149 # minSdkVersion attribute
150 min_api_level = None
151 else:
152 # Force APK signer to use SHA-1
153 min_api_level = 1
154
155 common.SignFile(unsigned.name, signed.name, keyname, pw,
156 min_api_level=min_api_level,
157 codename_to_api_level_map=codename_to_api_level_map)
138 158
139 data = signed.read() 159 data = signed.read()
140 unsigned.close() 160 unsigned.close()
@@ -144,7 +164,8 @@ def SignApk(data, keyname, pw):
144 164
145 165
146def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info, 166def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
147 apk_key_map, key_passwords): 167 apk_key_map, key_passwords, platform_api_level,
168 codename_to_api_level_map):
148 169
149 maxsize = max([len(os.path.basename(i.filename)) 170 maxsize = max([len(os.path.basename(i.filename))
150 for i in input_tf_zip.infolist() 171 for i in input_tf_zip.infolist()
@@ -200,7 +221,8 @@ def ProcessTargetFiles(input_tf_zip, output_tf_zip, misc_info,
200 key = apk_key_map[name] 221 key = apk_key_map[name]
201 if key not in common.SPECIAL_CERT_STRINGS: 222 if key not in common.SPECIAL_CERT_STRINGS:
202 print " signing: %-*s (%s)" % (maxsize, name, key) 223 print " signing: %-*s (%s)" % (maxsize, name, key)
203 signed_data = SignApk(data, key, key_passwords[key]) 224 signed_data = SignApk(data, key, key_passwords[key], platform_api_level,
225 codename_to_api_level_map)
204 common.ZipWriteStr(output_tf_zip, out_info, signed_data) 226 common.ZipWriteStr(output_tf_zip, out_info, signed_data)
205 else: 227 else:
206 # an APK we're not supposed to sign. 228 # an APK we're not supposed to sign.
@@ -440,6 +462,57 @@ def BuildKeyMap(misc_info, key_mapping_options):
440 OPTIONS.key_map[s] = d 462 OPTIONS.key_map[s] = d
441 463
442 464
465def GetApiLevelAndCodename(input_tf_zip):
466 data = input_tf_zip.read("SYSTEM/build.prop")
467 api_level = None
468 codename = None
469 for line in data.split("\n"):
470 line = line.strip()
471 original_line = line
472 if line and line[0] != '#' and "=" in line:
473 key, value = line.split("=", 1)
474 key = key.strip()
475 if key == "ro.build.version.sdk":
476 api_level = int(value.strip())
477 elif key == "ro.build.version.codename":
478 codename = value.strip()
479
480 if api_level is None:
481 raise ValueError("No ro.build.version.sdk in SYSTEM/build.prop")
482 if codename is None:
483 raise ValueError("No ro.build.version.codename in SYSTEM/build.prop")
484
485 return (api_level, codename)
486
487
488def GetCodenameToApiLevelMap(input_tf_zip):
489 data = input_tf_zip.read("SYSTEM/build.prop")
490 api_level = None
491 codenames = None
492 for line in data.split("\n"):
493 line = line.strip()
494 original_line = line
495 if line and line[0] != '#' and "=" in line:
496 key, value = line.split("=", 1)
497 key = key.strip()
498 if key == "ro.build.version.sdk":
499 api_level = int(value.strip())
500 elif key == "ro.build.version.all_codenames":
501 codenames = value.strip().split(",")
502
503 if api_level is None:
504 raise ValueError("No ro.build.version.sdk in SYSTEM/build.prop")
505 if codenames is None:
506 raise ValueError("No ro.build.version.all_codenames in SYSTEM/build.prop")
507
508 result = dict()
509 for codename in codenames:
510 codename = codename.strip()
511 if len(codename) > 0:
512 result[codename] = api_level
513 return result
514
515
443def main(argv): 516def main(argv):
444 517
445 key_mapping_options = [] 518 key_mapping_options = []
@@ -498,8 +571,17 @@ def main(argv):
498 CheckAllApksSigned(input_zip, apk_key_map) 571 CheckAllApksSigned(input_zip, apk_key_map)
499 572
500 key_passwords = common.GetKeyPasswords(set(apk_key_map.values())) 573 key_passwords = common.GetKeyPasswords(set(apk_key_map.values()))
574 platform_api_level, platform_codename = GetApiLevelAndCodename(input_zip)
575 codename_to_api_level_map = GetCodenameToApiLevelMap(input_zip)
576 # Android N will be API Level 24, but isn't yet.
577 # TODO: Remove this workaround once Android N is officially API Level 24.
578 if platform_api_level == 23 and platform_codename == "N":
579 platform_api_level = 24
580
501 ProcessTargetFiles(input_zip, output_zip, misc_info, 581 ProcessTargetFiles(input_zip, output_zip, misc_info,
502 apk_key_map, key_passwords) 582 apk_key_map, key_passwords,
583 platform_api_level,
584 codename_to_api_level_map)
503 585
504 common.ZipClose(input_zip) 586 common.ZipClose(input_zip)
505 common.ZipClose(output_zip) 587 common.ZipClose(output_zip)