blob: 6420a8fa43de8709a0b8f24e21a094c66ba40ddf [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001import sys
2import os
3import struct
4import subprocess
5import shutil
6script_folder, script_name = os.path.split(os.path.realpath(__file__))
7sys.path.append(os.path.join(script_folder, "lib"))
8import gfh
9import cert
10
11def get_file_sizeb(file_path):
12 if not os.path.isfile(file_path):
13 return 0
14 file_handle = open(file_path, "rb")
15 file_handle.seek(0, 2)
16 file_size = file_handle.tell()
17 file_handle.close()
18 return file_size
19
20def concatb(file1_path, file2_path):
21 file1_size = get_file_sizeb(file1_path)
22 file2_size = get_file_sizeb(file2_path)
23 file1 = open(file1_path, "ab+")
24 file2 = open(file2_path, "rb")
25 file1.write(file2.read(file2_size))
26 file2.close()
27 file1.close()
28
29class bootloader:
30 def __init__(self, out_path, in_bootloader_file_path, out_bootloader_file_path):
31 self.m_gfh = gfh.image_gfh()
32 self.m_out_path = out_path
33 if not os.path.exists(self.m_out_path):
34 os.makedirs(self.m_out_path)
35 self.m_in_bootloader_file_path = in_bootloader_file_path
36 self.m_out_bootloader_file_path = out_bootloader_file_path
37 self.m_bootloader_is_signed = False
38 self.m_bootloader_content_offset = 0
39 #initialize content size to bootloader file size
40 self.m_bootloader_content_length = get_file_sizeb(self.m_in_bootloader_file_path)
41 self.m_bootloader_sig_size = 0
42 #generate file path for bootloader without gfh and signature
43 bootloader_path = in_bootloader_file_path.split('.')
44 self.m_bootloader_no_gfh_file_path = bootloader_path[0] + "_plain.bin"
45 self.m_sig_ver = 0
46 self.m_sw_ver = 0
47 self.m_root_prvk_path = ""
48 self.m_img_prvk_path = ""
49 self.m_ac_key = 0
50 self.m_sig_handler = None
51 def is_signed(self):
52 if self.m_in_bootloader_file_path:
53 bootloader_file = open(self.m_in_bootloader_file_path, "rb")
54 gfh_hdr_obj = gfh.gfh_header()
55 gfh_hdr_size = gfh_hdr_obj.get_size()
56 gfh_hdr_buf = bootloader_file.read(gfh_hdr_size)
57 self.m_bootloader_is_signed = gfh_hdr_obj.is_gfh(gfh_hdr_buf)
58 bootloader_file.close()
59 return self.m_bootloader_is_signed
60 def parse(self):
61 print "===parse bootloader==="
62 #image will be decomposed if it's signed
63 if self.is_signed():
64 gfh_total_size = self.m_gfh.parse(self.m_in_bootloader_file_path)
65 self.m_bootloader_content_offset = gfh_total_size
66 self.m_bootloader_content_length -= gfh_total_size
67 self.m_bootloader_content_length -= self.m_gfh.get_sig_size()
68 self.m_bootloader_sig_size = self.m_gfh.get_sig_size()
69 in_file = open(self.m_in_bootloader_file_path, "rb")
70 out_file = open(self.m_bootloader_no_gfh_file_path, "wb")
71 in_file.seek(self.m_bootloader_content_offset)
72 out_file.write(in_file.read(self.m_bootloader_content_length))
73 out_file.close()
74 in_file.close()
75 else:
76 shutil.copyfile(self.m_in_bootloader_file_path, self.m_bootloader_no_gfh_file_path)
77 print "bootloader content size = " + hex(self.m_bootloader_content_length)
78 def create_gfh(self, gfh_config):
79 self.parse()
80 if gfh_config:
81 if self.is_signed():
82 del self.m_gfh.gfhs[:]
83 self.m_gfh.load_ini(gfh_config)
84 elif not self.is_signed():
85 print "GFH_CONFIG.ini does not exist!!"
86 return -1
87 #self.m_gfh.dump()
88 return 0
89 def sign(self, key_ini_path, key_cert_path, content_config_file_path):
90 self.m_gfh.finalize(self.m_bootloader_content_length, key_ini_path)
91 #create tbs_bootloader.bin
92 tbs_bootloader_file_path = os.path.join(self.m_out_path, "tbs_preloader.bin")
93 tbs_bootloader_file = open(tbs_bootloader_file_path, "wb")
94 tbs_bootloader_file.write(self.m_gfh.pack())
95 bootloader_no_gfh_file = open(self.m_bootloader_no_gfh_file_path, "rb")
96 tbs_bootloader_file.write(bootloader_no_gfh_file.read(self.m_bootloader_content_length))
97 bootloader_no_gfh_file.close()
98 tbs_bootloader_file.close()
99 print "===sign==="
100 if self.m_gfh.get_sig_type() == "CERT_CHAIN":
101 self.m_sig_handler = cert.cert_chain_v2()
102 #create key cert if key cert does not exist
103 if key_cert_path == "":
104 key_cert_path = os.path.join(self.m_out_path, "key_cert.bin")
105 if not os.path.isfile(key_cert_path):
106 key_cert_folder_name, key_cert_file_name = os.path.split(os.path.abspath(key_cert_path))
107 self.m_sig_handler.create_key_cert(key_ini_path, self.m_out_path, key_cert_file_name)
108 key_cert_path = os.path.join(self.m_out_path, key_cert_file_name)
109 else:
110 self.m_sig_handler.set_key_cert(key_cert_path)
111 #create content cert
112 content_cert_name = "content_cert.bin"
113 self.m_sig_handler.create_content_cert(content_config_file_path, tbs_bootloader_file_path, self.m_out_path, content_cert_name)
114 #create final cert chain
115 sig_name = "preloader.sig"
116 sig_file_path = os.path.join(self.m_out_path, sig_name)
117 self.m_sig_handler.output(self.m_out_path, sig_name)
118 #output final cert chain size
119 sig_size_name = "sig_size.txt"
120 sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
121 sig_size_file = open(sig_size_file_path, 'w')
122 sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
123 sig_size_file.close()
124 #create final preloader image
125 if os.path.isfile(self.m_out_bootloader_file_path):
126 os.remove(self.m_out_bootloader_file_path)
127 concatb(self.m_out_bootloader_file_path, tbs_bootloader_file_path)
128 concatb(self.m_out_bootloader_file_path, sig_file_path)
129 #clean up
130 os.remove(os.path.join(self.m_out_path, content_cert_name))
131 elif self.m_gfh.get_sig_type() == "SINGLE_AND_PHASH":
132 self.m_sig_handler = cert.sig_single_and_phash(self.m_gfh.get_pad_type())
133 self.m_sig_handler.set_out_path(self.m_out_path)
134 self.m_sig_handler.create(key_ini_path, tbs_bootloader_file_path)
135 #signature generation
136 self.m_sig_handler.sign()
137 sig_name = "preloader.sig"
138 sig_file_path = os.path.join(self.m_out_path, sig_name)
139 self.m_sig_handler.output(self.m_out_path, sig_name)
140 #output signature size
141 sig_size_name = "sig_size.txt"
142 sig_size_file_path = os.path.join(self.m_out_path, sig_size_name)
143 sig_size_file = open(sig_size_file_path, 'w')
144 sig_size_file.write(hex(get_file_sizeb(sig_file_path)))
145 sig_size_file.close()
146 #create final preloader image
147 if os.path.isfile(self.m_out_bootloader_file_path):
148 os.remove(self.m_out_bootloader_file_path)
149 concatb(self.m_out_bootloader_file_path, tbs_bootloader_file_path)
150 concatb(self.m_out_bootloader_file_path, sig_file_path)
151 else:
152 print "unknown signature type"
153 #clean up
154 os.remove(self.m_bootloader_no_gfh_file_path)
155 os.remove(tbs_bootloader_file_path)
156 os.remove(sig_file_path)
157 return
158
159def main():
160 #parameter parsing
161 idx = 1
162 key_ini_path = ""
163 key_path = ""
164 gfh_config_ini_path = ""
165 content_config_ini_path = ""
166 key_cert_path = ""
167 in_bootloader_path = ""
168 function = "sign"
169 function_out_path = ""
170 while idx < len(sys.argv):
171 if sys.argv[idx][0] == '-':
172 if sys.argv[idx][1] == 'i':
173 print "key ini: " + sys.argv[idx + 1]
174 key_ini_path = sys.argv[idx + 1]
175 idx += 2
176 if sys.argv[idx][1] == 'j':
177 print "key(pem): " + sys.argv[idx + 1]
178 key_path = sys.argv[idx + 1]
179 idx += 2
180 elif sys.argv[idx][1] == 'g':
181 print "gfh config: " + sys.argv[idx + 1]
182 gfh_config_ini_path = sys.argv[idx + 1]
183 idx += 2
184 elif sys.argv[idx][1] == 'c':
185 print "content config: " + sys.argv[idx + 1]
186 content_config_ini_path = sys.argv[idx + 1]
187 idx += 2
188 elif sys.argv[idx][1] == 'k':
189 print "key cert: " + sys.argv[idx + 1]
190 key_cert_path = sys.argv[idx + 1]
191 idx += 2
192 elif sys.argv[idx][1:] == 'func':
193 print "function: " + sys.argv[idx + 1]
194 function = sys.argv[idx + 1]
195 idx += 2
196 elif sys.argv[idx][1] == 'o':
197 print "function output: " + sys.argv[idx + 1]
198 function_out_path = sys.argv[idx + 1]
199 idx += 2
200 else:
201 print "unknown input"
202 idx += 2
203 else:
204 in_bootloader_path = sys.argv[idx]
205 print "bootloader: " + in_bootloader_path
206 idx += 1
207
208 if (function == "sign") and (not in_bootloader_path):
209 print "bootloader path is not given!"
210 return -1
211 if (not function_out_path):
212 print "function out path is not given!"
213 return -1
214 if function == "sign":
215 if (key_ini_path == "") and (key_cert_path == ""):
216 print "key path is not given!"
217 return -1
218 else:
219 if (key_path == "" and key_ini_path == ""):
220 print "key path is not given!"
221 return -1
222
223 out_path = os.path.dirname(os.path.abspath(function_out_path))
224 if not os.path.exists(out_path):
225 os.makedirs(out_path)
226
227 if function == "sign":
228 bootloader_obj = bootloader(out_path, in_bootloader_path, function_out_path)
229 bootloader_obj.create_gfh(gfh_config_ini_path)
230 bootloader_obj.sign(key_ini_path, key_cert_path, content_config_ini_path)
231 return 0
232 elif function == "keybin_pss":
233 key = cert.ct_key("pss")
234 key.create(key_path)
235 key_bin = key.pack()
236 out_file = open(function_out_path, "wb")
237 out_file.write(key_bin)
238 out_file.close()
239 return 0
240 elif function == "keybin_legacy":
241 key = cert.ct_key("legacy")
242 key.create(key_path)
243 key_bin = key.pack()
244 out_file = open(function_out_path, "wb")
245 out_file.write(key_bin)
246 out_file.close()
247 return 0
248 elif function == "keyhash_pss":
249 key = cert.ct_key("pss")
250 key.create(key_path)
251 key_bin = key.pack()
252 tmp_key_bin_path = os.path.join(out_path, "tmp_keybin.bin")
253 out_file = open(tmp_key_bin_path, "wb")
254 out_file.write(key_bin)
255 out_file.close()
256 cert.hash_gen(tmp_key_bin_path, function_out_path)
257 os.remove(tmp_key_bin_path)
258 return 0
259 elif function == "keyhash_legacy":
260 key = cert.ct_key("legacy")
261 key.create(key_path)
262 key_bin = key.pack()
263 tmp_key_bin_path = os.path.join(out_path, "tmp_keybin.bin")
264 out_file = open(tmp_key_bin_path, "wb")
265 out_file.write(key_bin)
266 out_file.close()
267 cert.hash_gen(tmp_key_bin_path, function_out_path)
268 os.remove(tmp_key_bin_path)
269 return 0
270
271if __name__ == '__main__':
272 main()