xref: /aosp_15_r20/build/make/tools/releasetools/sign_apex.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
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