1
1
#! /usr/bin/env python3
2
2
#
3
3
# Copyright 2017 Linaro Limited
4
- # Copyright (c) 2018, Arm Limited.
4
+ # Copyright (c) 2018-2019 , Arm Limited.
5
5
#
6
6
# Licensed under the Apache License, Version 2.0 (the "License");
7
7
# you may not use this file except in compliance with the License.
24
24
from .imgtool_lib import version
25
25
import sys
26
26
27
+ sign_bin_size_re = re .compile (r"^\s*RE_SIGN_BIN_SIZE\s*=\s*(.*)" )
28
+ image_load_address_re = re .compile (r"^\s*RE_IMAGE_LOAD_ADDRESS\s*=\s*(.*)" )
29
+
27
30
def find_load_address (args ):
28
31
load_address_re = re .compile (r"^#define\sIMAGE_LOAD_ADDRESS\s+(0x[0-9a-fA-F]+)" )
29
32
@@ -60,30 +63,37 @@ def get_last_version(path):
60
63
61
64
def next_version_number (args , defaultVersion , path ):
62
65
newVersion = None
66
+ versionProvided = False
63
67
if (version .compare (args .version , defaultVersion ) == 0 ): # Default version
64
68
lastVersion = get_last_version (path )
65
69
if (lastVersion is not None ):
66
70
newVersion = version .increment_build_num (lastVersion )
67
71
else :
68
72
newVersion = version .increment_build_num (defaultVersion )
69
73
else : # Version number has been explicitly provided (not using the default)
74
+ versionProvided = True
70
75
newVersion = args .version
71
76
versionString = "{a}.{b}.{c}+{d}" .format (
72
77
a = str (newVersion .major ),
73
78
b = str (newVersion .minor ),
74
79
c = str (newVersion .revision ),
75
80
d = str (newVersion .build )
76
81
)
77
- with open (path , "w" ) as newFile :
78
- newFile .write (versionString )
82
+ if not versionProvided :
83
+ with open (path , "w" ) as newFile :
84
+ newFile .write (versionString )
79
85
print ("**[INFO]** Image version number set to " + versionString )
80
86
return newVersion
81
87
82
88
def gen_rsa2048 (args ):
83
- keys .RSA2048 .generate ().export_private (args .key )
89
+ keys .RSAutil .generate ().export_private (args .key )
90
+
91
+ def gen_rsa3072 (args ):
92
+ keys .RSAutil .generate (key_size = 3072 ).export_private (args .key )
84
93
85
94
keygens = {
86
- 'rsa-2048' : gen_rsa2048 , }
95
+ 'rsa-2048' : gen_rsa2048 ,
96
+ 'rsa-3072' : gen_rsa3072 , }
87
97
88
98
def do_keygen (args ):
89
99
if args .type not in keygens :
@@ -102,18 +112,38 @@ def do_getpub(args):
102
112
def do_sign (args ):
103
113
if args .rsa_pkcs1_15 :
104
114
keys .sign_rsa_pss = False
115
+
116
+ version_num = next_version_number (args ,
117
+ version .decode_version ("0" ),
118
+ "lastVerNum.txt" )
119
+
120
+ if args .security_counter is None :
121
+ # Security counter has not been explicitly provided,
122
+ # generate it from the version number
123
+ args .security_counter = ((version_num .major << 24 )
124
+ + (version_num .minor << 16 )
125
+ + version_num .revision )
126
+
127
+ if "_s.c" in args .layout :
128
+ sw_type = "SPE"
129
+ elif "_ns.c" in args .layout :
130
+ sw_type = "NSPE"
131
+ else :
132
+ sw_type = "NSPE_SPE"
133
+
134
+ pad_size = args .pad
105
135
img = image .Image .load (args .infile ,
106
- version = next_version_number ( args ,
107
- version . decode_version ( "0" ) ,
108
- "lastVerNum.txt" ) ,
109
- header_size = args .header_size ,
110
- included_header = args . included_header ,
111
- pad = args .pad )
112
- key = keys . load (args . key ) if args . key else None
113
- img .sign (key , find_load_address ( args ) )
114
-
115
- if args . pad :
116
- img .pad_to (args . pad , args .align )
136
+ version = version_num ,
137
+ header_size = args . header_size ,
138
+ security_cnt = args . security_counter ,
139
+ included_header = args .included_header ,
140
+ pad = pad_size )
141
+ key = keys . load ( args . key , args . public_key_format ) if args .key else None
142
+ ram_load_address = find_load_address (args )
143
+ img .sign (sw_type , key , ram_load_address , args . dependencies )
144
+
145
+ if pad_size :
146
+ img .pad_to (pad_size , args .align )
117
147
118
148
img .save (args .outfile )
119
149
@@ -122,6 +152,30 @@ def do_sign(args):
122
152
'getpub' : do_getpub ,
123
153
'sign' : do_sign , }
124
154
155
+
156
+ def get_dependencies (text ):
157
+ if text is not None :
158
+ versions = []
159
+ images = re .findall (r"\((\d+)" , text )
160
+ if len (images ) == 0 :
161
+ msg = "Image dependency format is invalid: {}" .format (text )
162
+ raise argparse .ArgumentTypeError (msg )
163
+ raw_versions = re .findall (r",\s*([0-9.+]+)\)" , text )
164
+ if len (images ) != len (raw_versions ):
165
+ msg = '''There's a mismatch between the number of dependency images
166
+ and versions in: {}''' .format (text )
167
+ raise argparse .ArgumentTypeError (msg )
168
+ for raw_version in raw_versions :
169
+ try :
170
+ versions .append (version .decode_version (raw_version ))
171
+ except ValueError as e :
172
+ print (e )
173
+ dependencies = dict ()
174
+ dependencies [image .DEP_IMAGES_KEY ] = images
175
+ dependencies [image .DEP_VERSIONS_KEY ] = versions
176
+ return dependencies
177
+
178
+
125
179
def alignment_value (text ):
126
180
value = int (text )
127
181
if value not in [1 , 2 , 4 , 8 ]:
@@ -149,17 +203,23 @@ def args():
149
203
getpub .add_argument ('-l' , '--lang' , metavar = 'lang' , default = 'c' )
150
204
151
205
sign = subs .add_parser ('sign' , help = 'Sign an image with a private key' )
152
- sign .add_argument ('--layout' , required = True ,
153
- help = 'Location of the memory layout file ' )
206
+ sign .add_argument ('-l' , '- -layout' , required = True ,
207
+ help = 'Location of the file that contains preprocessed macros ' )
154
208
sign .add_argument ('-k' , '--key' , metavar = 'filename' )
209
+ sign .add_argument ("-K" , "--public-key-format" ,
210
+ help = 'In what format to add the public key to the image manifest: full or hash' ,
211
+ metavar = 'pub_key_format' , choices = ['full' , 'hash' ], default = 'hash' )
155
212
sign .add_argument ("--align" , type = alignment_value , required = True )
156
213
sign .add_argument ("-v" , "--version" , type = version .decode_version ,
157
214
default = "0.0.0+0" )
215
+ sign .add_argument ("-d" , "--dependencies" , type = get_dependencies ,
216
+ required = False , help = '''Add dependence on another image,
217
+ format: "(<image_ID>,<image_version>), ... "''' )
218
+ sign .add_argument ("-s" , "--security-counter" , type = intparse ,
219
+ help = 'Specify explicitly the security counter value' )
158
220
sign .add_argument ("-H" , "--header-size" , type = intparse , required = True )
159
221
sign .add_argument ("--included-header" , default = False , action = 'store_true' ,
160
222
help = 'Image has gap for header' )
161
- sign .add_argument ("--pad" , type = intparse ,
162
- help = 'Pad image to this many bytes, adding trailer magic' )
163
223
sign .add_argument ("--rsa-pkcs1-15" ,
164
224
help = 'Use old PKCS#1 v1.5 signature algorithm' ,
165
225
default = False , action = 'store_true' )
@@ -174,4 +234,4 @@ def args():
174
234
subcmds [args .subcmd ](args )
175
235
176
236
if __name__ == '__main__' :
177
- args ()
237
+ args ()
0 commit comments