1#!/usr/bin/env python 2# 3# Copyright (C) 2019 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""" 18Signs a standalone APEX file. 19 20Usage: sign_apex [flags] input_apex_file output_apex_file 21 22 --avbtool <avbtool> 23 Optional flag that specifies the AVB tool to use. Defaults to `avbtool`. 24 25 --container_key <key> 26 Mandatory flag that specifies the container signing key. 27 28 --payload_key <key> 29 Mandatory flag that specifies the payload signing key. 30 31 --payload_extra_args <args> 32 Optional flag that specifies any extra args to be passed to payload signer 33 (e.g. --payload_extra_args="--signing_helper_with_files /path/to/helper"). 34 35 -e (--extra_apks) <name,name,...=key> 36 Add extra APK name/key pairs. This is useful to sign the apk files in the 37 apex payload image. 38 39 --codename_to_api_level_map Q:29,R:30,... 40 A Mapping of codename to api level. This is useful to provide sdk targeting 41 information to APK Signer. 42 43 --sign_tool <sign_tool> 44 Optional flag that specifies a custom signing tool for the contents of the apex. 45""" 46 47import logging 48import shutil 49import sys 50 51import apex_utils 52import common 53 54logger = logging.getLogger(__name__) 55 56 57def SignApexFile(avbtool, apex_file, payload_key, container_key, no_hashtree, 58 apk_keys=None, signing_args=None, codename_to_api_level_map=None, sign_tool=None): 59 """Signs the given apex file.""" 60 with open(apex_file, 'rb') as input_fp: 61 apex_data = input_fp.read() 62 63 return apex_utils.SignApex( 64 avbtool, 65 apex_data, 66 payload_key=payload_key, 67 container_key=container_key, 68 container_pw=None, 69 codename_to_api_level_map=codename_to_api_level_map, 70 no_hashtree=no_hashtree, 71 apk_keys=apk_keys, 72 signing_args=signing_args, 73 sign_tool=sign_tool) 74 75 76def main(argv): 77 78 options = {} 79 80 def option_handler(o, a): 81 if o == '--avbtool': 82 options['avbtool'] = a 83 elif o == '--container_key': 84 # Strip the suffix if any, as common.SignFile expects no suffix. 85 DEFAULT_CONTAINER_KEY_SUFFIX = '.x509.pem' 86 if a.endswith(DEFAULT_CONTAINER_KEY_SUFFIX): 87 a = a[:-len(DEFAULT_CONTAINER_KEY_SUFFIX)] 88 options['container_key'] = a 89 elif o == '--payload_key': 90 options['payload_key'] = a 91 elif o == '--payload_extra_args': 92 options['payload_extra_args'] = a 93 elif o == '--codename_to_api_level_map': 94 versions = a.split(",") 95 for v in versions: 96 key, value = v.split(":") 97 if 'codename_to_api_level_map' not in options: 98 options['codename_to_api_level_map'] = {} 99 options['codename_to_api_level_map'].update({key: value}) 100 elif o in ("-e", "--extra_apks"): 101 names, key = a.split("=") 102 names = names.split(",") 103 for n in names: 104 if 'extra_apks' not in options: 105 options['extra_apks'] = {} 106 options['extra_apks'].update({n: key}) 107 elif o == '--sign_tool': 108 options['sign_tool'] = a 109 else: 110 return False 111 return True 112 113 args = common.ParseOptions( 114 argv, __doc__, 115 extra_opts='e:', 116 extra_long_opts=[ 117 'avbtool=', 118 'codename_to_api_level_map=', 119 'container_key=', 120 'payload_extra_args=', 121 'payload_key=', 122 'extra_apks=', 123 'sign_tool=', 124 ], 125 extra_option_handler=option_handler) 126 127 if (len(args) != 2 or 'container_key' not in options or 128 'payload_key' not in options): 129 common.Usage(__doc__) 130 sys.exit(1) 131 132 common.InitLogging() 133 134 signed_apex = SignApexFile( 135 options.get('avbtool', 'avbtool'), 136 args[0], 137 options['payload_key'], 138 options['container_key'], 139 no_hashtree=False, 140 apk_keys=options.get('extra_apks', {}), 141 signing_args=options.get('payload_extra_args'), 142 codename_to_api_level_map=options.get( 143 'codename_to_api_level_map', {}), 144 sign_tool=options.get('sign_tool', None)) 145 shutil.copyfile(signed_apex, args[1]) 146 logger.info("done.") 147 148 149if __name__ == '__main__': 150 try: 151 main(sys.argv[1:]) 152 finally: 153 common.Cleanup() 154