1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python 2*9e94795aSAndroid Build Coastguard Worker# 3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2019 The Android Open Source Project 4*9e94795aSAndroid Build Coastguard Worker# 5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 6*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 7*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at 8*9e94795aSAndroid Build Coastguard Worker# 9*9e94795aSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 10*9e94795aSAndroid Build Coastguard Worker# 11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 13*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 15*9e94795aSAndroid Build Coastguard Worker# limitations under the License. 16*9e94795aSAndroid Build Coastguard Worker 17*9e94795aSAndroid Build Coastguard Worker""" 18*9e94795aSAndroid Build Coastguard WorkerSigns a standalone APEX file. 19*9e94795aSAndroid Build Coastguard Worker 20*9e94795aSAndroid Build Coastguard WorkerUsage: sign_apex [flags] input_apex_file output_apex_file 21*9e94795aSAndroid Build Coastguard Worker 22*9e94795aSAndroid Build Coastguard Worker --avbtool <avbtool> 23*9e94795aSAndroid Build Coastguard Worker Optional flag that specifies the AVB tool to use. Defaults to `avbtool`. 24*9e94795aSAndroid Build Coastguard Worker 25*9e94795aSAndroid Build Coastguard Worker --container_key <key> 26*9e94795aSAndroid Build Coastguard Worker Mandatory flag that specifies the container signing key. 27*9e94795aSAndroid Build Coastguard Worker 28*9e94795aSAndroid Build Coastguard Worker --payload_key <key> 29*9e94795aSAndroid Build Coastguard Worker Mandatory flag that specifies the payload signing key. 30*9e94795aSAndroid Build Coastguard Worker 31*9e94795aSAndroid Build Coastguard Worker --payload_extra_args <args> 32*9e94795aSAndroid Build Coastguard Worker Optional flag that specifies any extra args to be passed to payload signer 33*9e94795aSAndroid Build Coastguard Worker (e.g. --payload_extra_args="--signing_helper_with_files /path/to/helper"). 34*9e94795aSAndroid Build Coastguard Worker 35*9e94795aSAndroid Build Coastguard Worker -e (--extra_apks) <name,name,...=key> 36*9e94795aSAndroid Build Coastguard Worker Add extra APK name/key pairs. This is useful to sign the apk files in the 37*9e94795aSAndroid Build Coastguard Worker apex payload image. 38*9e94795aSAndroid Build Coastguard Worker 39*9e94795aSAndroid Build Coastguard Worker --codename_to_api_level_map Q:29,R:30,... 40*9e94795aSAndroid Build Coastguard Worker A Mapping of codename to api level. This is useful to provide sdk targeting 41*9e94795aSAndroid Build Coastguard Worker information to APK Signer. 42*9e94795aSAndroid Build Coastguard Worker 43*9e94795aSAndroid Build Coastguard Worker --sign_tool <sign_tool> 44*9e94795aSAndroid Build Coastguard Worker Optional flag that specifies a custom signing tool for the contents of the apex. 45*9e94795aSAndroid Build Coastguard Worker 46*9e94795aSAndroid Build Coastguard Worker --container_pw <name1=passwd,name2=passwd> 47*9e94795aSAndroid Build Coastguard Worker A mapping of key_name to password 48*9e94795aSAndroid Build Coastguard Worker""" 49*9e94795aSAndroid Build Coastguard Worker 50*9e94795aSAndroid Build Coastguard Workerimport logging 51*9e94795aSAndroid Build Coastguard Workerimport shutil 52*9e94795aSAndroid Build Coastguard Workerimport re 53*9e94795aSAndroid Build Coastguard Workerimport sys 54*9e94795aSAndroid Build Coastguard Worker 55*9e94795aSAndroid Build Coastguard Workerimport apex_utils 56*9e94795aSAndroid Build Coastguard Workerimport common 57*9e94795aSAndroid Build Coastguard Worker 58*9e94795aSAndroid Build Coastguard Workerlogger = logging.getLogger(__name__) 59*9e94795aSAndroid Build Coastguard Worker 60*9e94795aSAndroid Build Coastguard Worker 61*9e94795aSAndroid Build Coastguard Workerdef SignApexFile(avbtool, apex_file, payload_key, container_key, no_hashtree, 62*9e94795aSAndroid Build Coastguard Worker apk_keys=None, signing_args=None, codename_to_api_level_map=None, sign_tool=None, container_pw=None): 63*9e94795aSAndroid Build Coastguard Worker """Signs the given apex file.""" 64*9e94795aSAndroid Build Coastguard Worker with open(apex_file, 'rb') as input_fp: 65*9e94795aSAndroid Build Coastguard Worker apex_data = input_fp.read() 66*9e94795aSAndroid Build Coastguard Worker 67*9e94795aSAndroid Build Coastguard Worker return apex_utils.SignApex( 68*9e94795aSAndroid Build Coastguard Worker avbtool, 69*9e94795aSAndroid Build Coastguard Worker apex_data, 70*9e94795aSAndroid Build Coastguard Worker payload_key=payload_key, 71*9e94795aSAndroid Build Coastguard Worker container_key=container_key, 72*9e94795aSAndroid Build Coastguard Worker container_pw=container_pw, 73*9e94795aSAndroid Build Coastguard Worker codename_to_api_level_map=codename_to_api_level_map, 74*9e94795aSAndroid Build Coastguard Worker no_hashtree=no_hashtree, 75*9e94795aSAndroid Build Coastguard Worker apk_keys=apk_keys, 76*9e94795aSAndroid Build Coastguard Worker signing_args=signing_args, 77*9e94795aSAndroid Build Coastguard Worker sign_tool=sign_tool) 78*9e94795aSAndroid Build Coastguard Worker 79*9e94795aSAndroid Build Coastguard Worker 80*9e94795aSAndroid Build Coastguard Workerdef main(argv): 81*9e94795aSAndroid Build Coastguard Worker 82*9e94795aSAndroid Build Coastguard Worker options = {} 83*9e94795aSAndroid Build Coastguard Worker 84*9e94795aSAndroid Build Coastguard Worker def option_handler(o, a): 85*9e94795aSAndroid Build Coastguard Worker if o == '--avbtool': 86*9e94795aSAndroid Build Coastguard Worker options['avbtool'] = a 87*9e94795aSAndroid Build Coastguard Worker elif o == '--container_key': 88*9e94795aSAndroid Build Coastguard Worker # Strip the suffix if any, as common.SignFile expects no suffix. 89*9e94795aSAndroid Build Coastguard Worker DEFAULT_CONTAINER_KEY_SUFFIX = '.x509.pem' 90*9e94795aSAndroid Build Coastguard Worker if a.endswith(DEFAULT_CONTAINER_KEY_SUFFIX): 91*9e94795aSAndroid Build Coastguard Worker a = a[:-len(DEFAULT_CONTAINER_KEY_SUFFIX)] 92*9e94795aSAndroid Build Coastguard Worker options['container_key'] = a 93*9e94795aSAndroid Build Coastguard Worker elif o == '--payload_key': 94*9e94795aSAndroid Build Coastguard Worker options['payload_key'] = a 95*9e94795aSAndroid Build Coastguard Worker elif o == '--payload_extra_args': 96*9e94795aSAndroid Build Coastguard Worker options['payload_extra_args'] = a 97*9e94795aSAndroid Build Coastguard Worker elif o == '--codename_to_api_level_map': 98*9e94795aSAndroid Build Coastguard Worker versions = a.split(",") 99*9e94795aSAndroid Build Coastguard Worker for v in versions: 100*9e94795aSAndroid Build Coastguard Worker key, value = v.split(":") 101*9e94795aSAndroid Build Coastguard Worker if 'codename_to_api_level_map' not in options: 102*9e94795aSAndroid Build Coastguard Worker options['codename_to_api_level_map'] = {} 103*9e94795aSAndroid Build Coastguard Worker options['codename_to_api_level_map'].update({key: value}) 104*9e94795aSAndroid Build Coastguard Worker elif o in ("-e", "--extra_apks"): 105*9e94795aSAndroid Build Coastguard Worker names, key = a.split("=") 106*9e94795aSAndroid Build Coastguard Worker names = names.split(",") 107*9e94795aSAndroid Build Coastguard Worker for n in names: 108*9e94795aSAndroid Build Coastguard Worker if 'extra_apks' not in options: 109*9e94795aSAndroid Build Coastguard Worker options['extra_apks'] = {} 110*9e94795aSAndroid Build Coastguard Worker options['extra_apks'].update({n: key}) 111*9e94795aSAndroid Build Coastguard Worker elif o == '--sign_tool': 112*9e94795aSAndroid Build Coastguard Worker options['sign_tool'] = a 113*9e94795aSAndroid Build Coastguard Worker elif o == '--container_pw': 114*9e94795aSAndroid Build Coastguard Worker passwords = {} 115*9e94795aSAndroid Build Coastguard Worker pairs = a.split() 116*9e94795aSAndroid Build Coastguard Worker for pair in pairs: 117*9e94795aSAndroid Build Coastguard Worker if "=" not in pair: 118*9e94795aSAndroid Build Coastguard Worker continue 119*9e94795aSAndroid Build Coastguard Worker tokens = pair.split("=", maxsplit=1) 120*9e94795aSAndroid Build Coastguard Worker passwords[tokens[0].strip()] = tokens[1].strip() 121*9e94795aSAndroid Build Coastguard Worker options['container_pw'] = passwords 122*9e94795aSAndroid Build Coastguard Worker else: 123*9e94795aSAndroid Build Coastguard Worker return False 124*9e94795aSAndroid Build Coastguard Worker return True 125*9e94795aSAndroid Build Coastguard Worker 126*9e94795aSAndroid Build Coastguard Worker args = common.ParseOptions( 127*9e94795aSAndroid Build Coastguard Worker argv, __doc__, 128*9e94795aSAndroid Build Coastguard Worker extra_opts='e:', 129*9e94795aSAndroid Build Coastguard Worker extra_long_opts=[ 130*9e94795aSAndroid Build Coastguard Worker 'avbtool=', 131*9e94795aSAndroid Build Coastguard Worker 'codename_to_api_level_map=', 132*9e94795aSAndroid Build Coastguard Worker 'container_key=', 133*9e94795aSAndroid Build Coastguard Worker 'payload_extra_args=', 134*9e94795aSAndroid Build Coastguard Worker 'payload_key=', 135*9e94795aSAndroid Build Coastguard Worker 'extra_apks=', 136*9e94795aSAndroid Build Coastguard Worker 'sign_tool=', 137*9e94795aSAndroid Build Coastguard Worker 'container_pw=', 138*9e94795aSAndroid Build Coastguard Worker ], 139*9e94795aSAndroid Build Coastguard Worker extra_option_handler=option_handler) 140*9e94795aSAndroid Build Coastguard Worker 141*9e94795aSAndroid Build Coastguard Worker if (len(args) != 2 or 'container_key' not in options or 142*9e94795aSAndroid Build Coastguard Worker 'payload_key' not in options): 143*9e94795aSAndroid Build Coastguard Worker common.Usage(__doc__) 144*9e94795aSAndroid Build Coastguard Worker sys.exit(1) 145*9e94795aSAndroid Build Coastguard Worker 146*9e94795aSAndroid Build Coastguard Worker common.InitLogging() 147*9e94795aSAndroid Build Coastguard Worker 148*9e94795aSAndroid Build Coastguard Worker signed_apex = SignApexFile( 149*9e94795aSAndroid Build Coastguard Worker options.get('avbtool', 'avbtool'), 150*9e94795aSAndroid Build Coastguard Worker args[0], 151*9e94795aSAndroid Build Coastguard Worker options['payload_key'], 152*9e94795aSAndroid Build Coastguard Worker options['container_key'], 153*9e94795aSAndroid Build Coastguard Worker no_hashtree=False, 154*9e94795aSAndroid Build Coastguard Worker apk_keys=options.get('extra_apks', {}), 155*9e94795aSAndroid Build Coastguard Worker signing_args=options.get('payload_extra_args'), 156*9e94795aSAndroid Build Coastguard Worker codename_to_api_level_map=options.get( 157*9e94795aSAndroid Build Coastguard Worker 'codename_to_api_level_map', {}), 158*9e94795aSAndroid Build Coastguard Worker sign_tool=options.get('sign_tool', None), 159*9e94795aSAndroid Build Coastguard Worker container_pw=options.get('container_pw'), 160*9e94795aSAndroid Build Coastguard Worker ) 161*9e94795aSAndroid Build Coastguard Worker shutil.copyfile(signed_apex, args[1]) 162*9e94795aSAndroid Build Coastguard Worker logger.info("done.") 163*9e94795aSAndroid Build Coastguard Worker 164*9e94795aSAndroid Build Coastguard Worker 165*9e94795aSAndroid Build Coastguard Workerif __name__ == '__main__': 166*9e94795aSAndroid Build Coastguard Worker try: 167*9e94795aSAndroid Build Coastguard Worker main(sys.argv[1:]) 168*9e94795aSAndroid Build Coastguard Worker finally: 169*9e94795aSAndroid Build Coastguard Worker common.Cleanup() 170