WXK
2024-12-20 51135221cd73a2b3a6ce4b5ec906396d5a33b4c7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
#!/usr/bin/env python3
#
# Copyright (c) 2020-2022 Shanghai Panchip Microelectronics Co.,Ltd.
#
# SPDX-License-Identifier: Apache-2.0
#
 
"""
PAN1080 Image Encrypt Tool
 
This script is used for encrypting the PAN1080 Image by AES ECB algorithm,
which is indispensable for SoC that has enabled the Hardware Secure Flow.
 
@author: limi@panchip.com
         lihui@panchip.com
 
@change-history:
  v1.0.0: * (Apr/14/2020) Initial version
  v1.1.0: * (Apr/13/2022) Add several enhancements for easier use
"""
 
import sys
import os
import binascii
from Crypto.Cipher import AES
from binascii import b2a_hex
from intelhex import IntelHex
import yaml
 
#Get from input hex
image_start_addr = None
image_size = None
 
# Get from input yaml
encrypt_flash_offset = None
encrypt_key = None
expected_image_start_addr = None
 
usage = '''
Usage:
 
CMD Syntax:
   python %s <input_hex_image_file> <encrypt_info_yaml_file>
 
Notes:
1. Currently the tool only support HEX format file as input image.
2. The tool currently gets "encrypt_flash_offset", "encrypt_key"
   and "expected_start_addr" from the <encrypt_info_yaml_file> for
   checking and encrypting use.
3. Once encryption done, the tool generate 2 output files in the
   same folder: a hex file and a bin file, and each file has a
   '_enc' name suffix.
 
e.g.
Provided we have a <input_hex_image_file> named "path/to/input_file.hex",
and a <encrypt_info_yaml_file> named "path2/to/encrypt_info.yaml", and
now we open a cmd prompt and type:
 
   python %s path/to/input_file.hex path2/to/encrypt_info.yaml
 
Soon we can find 2 output files in the input image file folder:
  1. "path/to/input_file_enc.hex"
  2. "path/to/input_file_enc.bin"
''' % (os.path.basename(__file__), os.path.basename(__file__))
 
# Check input parameters
if len(sys.argv) != 3:
    print(usage)
    sys.exit(1)
 
# Input image file with Intel HEX format
input_hex_image_file = sys.argv[1]
# Encrypt information file with YAML format
encrypt_info_yaml_file = sys.argv[2]
 
print('Image Encryption start..')
print("Input image file: '{:s}'".format(input_hex_image_file))
print("Encrypt information file: '{:s}'".format(encrypt_info_yaml_file))
 
#------------------ Hex file processing ------------------
ihi = IntelHex(input_hex_image_file)
segments = ihi.segments()
segment_num = len(segments)
 
# Currently we don't support to parse hex file with multiple segments
if segment_num != 1:
    print("Error: Input file has multiple segments!")
    sys.exit(1)
 
print("Hex Image Entry Address Info:", ihi.start_addr)
 
for s in segments:
    image_start_addr = s[0]
    image_size = s[1]-s[0]
    print("Hex Segment: {{ start: 0x{:08X}, end: 0x{:08X}, length: 0x{:08X} ({:d}) }}"
        .format(s[0], s[1]-1, s[1]-s[0], s[1]-s[0]))
 
# Check if the image start address is 256-bytes align
if image_start_addr % 256 != 0:
    print('Error: The start address in hex file is not 256-bytes align!')
    sys.exit(1)
 
#------------------ Yaml file processing ------------------
with open(encrypt_info_yaml_file, encoding='utf-8') as f:
    enc_info_list = yaml.safe_load(f)
    # print(enc_info_list)
    encrypt_flash_offset = enc_info_list['encrypt_info']['encrypt_flash_offset']
    encrypt_key = enc_info_list['encrypt_info']['encrypt_key']
    expected_image_start_addr = enc_info_list['image_info']['expected_start_addr']
    print('encrypt flash offset: 0x{:X} ({:d})'.format(encrypt_flash_offset, encrypt_flash_offset))
    print('encrypt key:', encrypt_key)
    print('expected image start addr: 0x{:X}'.format(expected_image_start_addr))
 
# Check if the image start address read from the input HEX file is
# same with expected start address read from the input YAML file.
if expected_image_start_addr != image_start_addr:
    print('Error: Start address in input HEX file is not same as expected in encrypt info YAML file!')
    sys.exit(1)
 
# Check if the encrypt addr is larger than image start address
if (encrypt_flash_offset * 256 < image_start_addr or
        encrypt_flash_offset * 256 + 256 > image_start_addr + image_size):
    print('Error: Encrypt flash offset is out of image range!')
    sys.exit(1)
 
#----------------------------- Encrypt params ---------------------------
# offset in binary file
offset = encrypt_flash_offset - image_start_addr / 256
offset = int(offset)
# AES key for the following encrypt flow use
key    = encrypt_key
 
#------------------------- Processing binary data ----------------------
text_aes = ihi.tobinarray()
 
text_aes_128_1  = b2a_hex(text_aes[(  0+int(offset)*256):( 16+int(offset)*256)])
text_aes_128_2  = b2a_hex(text_aes[( 16+int(offset)*256):( 32+int(offset)*256)])
text_aes_128_3  = b2a_hex(text_aes[( 32+int(offset)*256):( 48+int(offset)*256)])
text_aes_128_4  = b2a_hex(text_aes[( 48+int(offset)*256):( 64+int(offset)*256)])
text_aes_128_5  = b2a_hex(text_aes[( 64+int(offset)*256):( 80+int(offset)*256)])
text_aes_128_6  = b2a_hex(text_aes[( 80+int(offset)*256):( 96+int(offset)*256)])
text_aes_128_7  = b2a_hex(text_aes[( 96+int(offset)*256):(112+int(offset)*256)])
text_aes_128_8  = b2a_hex(text_aes[(112+int(offset)*256):(128+int(offset)*256)])
text_aes_128_9  = b2a_hex(text_aes[(128+int(offset)*256):(144+int(offset)*256)])
text_aes_128_10 = b2a_hex(text_aes[(144+int(offset)*256):(160+int(offset)*256)])
text_aes_128_11 = b2a_hex(text_aes[(160+int(offset)*256):(176+int(offset)*256)])
text_aes_128_12 = b2a_hex(text_aes[(176+int(offset)*256):(192+int(offset)*256)])
text_aes_128_13 = b2a_hex(text_aes[(192+int(offset)*256):(208+int(offset)*256)])
text_aes_128_14 = b2a_hex(text_aes[(208+int(offset)*256):(224+int(offset)*256)])
text_aes_128_15 = b2a_hex(text_aes[(224+int(offset)*256):(240+int(offset)*256)])
text_aes_128_16 = b2a_hex(text_aes[(240+int(offset)*256):(256+int(offset)*256)])
 
def big_2_small_endian(data):
    return binascii.hexlify(binascii.unhexlify(data)[::-1])
 
text_aes_128_1 = big_2_small_endian(text_aes_128_1)
text_aes_128_2 = big_2_small_endian(text_aes_128_2)
text_aes_128_3 = big_2_small_endian(text_aes_128_3)
text_aes_128_4 = big_2_small_endian(text_aes_128_4)
text_aes_128_5 = big_2_small_endian(text_aes_128_5)
text_aes_128_6 = big_2_small_endian(text_aes_128_6)
text_aes_128_7 = big_2_small_endian(text_aes_128_7)
text_aes_128_8 = big_2_small_endian(text_aes_128_8)
text_aes_128_9 = big_2_small_endian(text_aes_128_9)
text_aes_128_10 = big_2_small_endian(text_aes_128_10)
text_aes_128_11 = big_2_small_endian(text_aes_128_11)
text_aes_128_12 = big_2_small_endian(text_aes_128_12)
text_aes_128_13 = big_2_small_endian(text_aes_128_13)
text_aes_128_14 = big_2_small_endian(text_aes_128_14)
text_aes_128_15 = big_2_small_endian(text_aes_128_15)
text_aes_128_16 = big_2_small_endian(text_aes_128_16)
 
def str_2_ascii(string):
    string_hex = string.zfill(32)
#    print('string_hex value is:',string_hex)
    string_ascii = binascii.a2b_hex(string_hex)
#    print('string_ascii value is: ',string_ascii)
    return string_ascii
 
def encrypt(key_ascii,text_ascii):
#    print('key_ascii value is :',key_ascii)
#    print('text_ascii value is:',text_ascii)
    mode     = AES.MODE_ECB
    aes      = AES.new(key_ascii,mode)
    en_text = aes.encrypt(text_ascii)
    # print('en_text value is:',en_text)
    # encrypt_data = b2a_hex(en_text)
    # print('encrypt value data is:',encrypt_data)
    return en_text
 
#------------------------- Encryption Flow ----------------------
 
text = text_aes_128_1
text_ascii      = str_2_ascii(text)
#print('text_aes_1 text_ascii value is ',text_ascii)
#print('text_aes_1 hex value is',b2a_hex(text_ascii))
key_ascii       = str_2_ascii(key)
encrypt_text_1  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_2
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_2  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_3
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_3  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_4
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_4  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_5
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_5  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_6
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_6  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_7
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_7  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_8
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_8  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_9
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_9  = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_10
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_10 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_11
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_11 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_12
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_12 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_13
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_13 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_14
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_14 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_15
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_15 = encrypt(key_ascii,text_ascii)
 
text = text_aes_128_16
text_ascii      = str_2_ascii(text)
#text_ascii     = text
key_ascii       = str_2_ascii(key)
encrypt_text_16 = encrypt(key_ascii,text_ascii)
 
#---------------------------- Re-combine data -----------------------------
encrypt_text_1 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_1))))
encrypt_text_2 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_2))))
encrypt_text_3 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_3))))
encrypt_text_4 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_4))))
encrypt_text_5 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_5))))
encrypt_text_6 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_6))))
encrypt_text_7 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_7))))
encrypt_text_8 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_8))))
encrypt_text_9 = str_2_ascii((big_2_small_endian(b2a_hex(encrypt_text_9))))
encrypt_text_10 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_10))))
encrypt_text_11 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_11))))
encrypt_text_12 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_12))))
encrypt_text_13 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_13))))
encrypt_text_14 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_14))))
encrypt_text_15 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_15))))
encrypt_text_16 = str_2_ascii(big_2_small_endian((b2a_hex(encrypt_text_16))))
 
text_aes_new = text_aes[0:(0+int(offset)*256)].tobytes()    \
                + encrypt_text_1    \
                + encrypt_text_2    \
                + encrypt_text_3    \
                + encrypt_text_4    \
                + encrypt_text_5    \
                + encrypt_text_6    \
                + encrypt_text_7    \
                + encrypt_text_8    \
                + encrypt_text_9    \
                + encrypt_text_10   \
                + encrypt_text_11   \
                + encrypt_text_12   \
                + encrypt_text_13   \
                + encrypt_text_14   \
                + encrypt_text_15   \
                + encrypt_text_16   \
                + text_aes[(256+int(offset)*256):].tobytes()
 
#---------------------------- Generate output files -----------------------------
iho = IntelHex()
iho.frombytes(text_aes_new, image_start_addr) # keep start address (offset) unchanged
 
# Output files name
output_bin_file = os.path.splitext(input_hex_image_file)[0] + '_enc.bin'
output_hex_file = os.path.splitext(input_hex_image_file)[0] + '_enc.hex'
 
# Generate binrary output file
try:
    iho.tobinfile(output_bin_file)
except IOError:
    e = sys.exc_info()[1]     # current exception
    print("ERROR: Could not write to file: %s: %s" % (output_bin_file, str(e)))
    sys.exit(1)
 
# Generate Intel Hex output file
try:
    # iho.start_addr = ihi.start_addr # keep start address (entry) unchanged
    iho.write_hex_file(output_hex_file)
except IOError:
    e = sys.exc_info()[1]     # current exception
    print("ERROR: Could not write to file: %s: %s" % (output_hex_file, str(e)))
    sys.exit(1)
 
print("Output bin file: '{:s}'".format(output_bin_file))
print("Output hex file: '{:s}'".format(output_hex_file))
 
print('Image encryption finish!')