OLD | NEW |
| (Empty) |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | |
2 * Use of this source code is governed by a BSD-style license that can be | |
3 * found in the LICENSE file. | |
4 * | |
5 * Functions for generating and manipulating a verified boot firmware image. | |
6 */ | |
7 | |
8 #include "firmware_image.h" | |
9 | |
10 #include <sys/types.h> | |
11 #include <sys/stat.h> | |
12 #include <fcntl.h> | |
13 #include <unistd.h> | |
14 | |
15 #include "cryptolib.h" | |
16 #include "file_keys.h" | |
17 #include "signature_digest.h" | |
18 #include "stateful_util.h" | |
19 | |
20 /* Macro to determine the size of a field structure in the FirmwareImage | |
21 * structure. */ | |
22 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field)) | |
23 | |
24 FirmwareImage* FirmwareImageNew(void) { | |
25 FirmwareImage* image = (FirmwareImage*) Malloc(sizeof(FirmwareImage)); | |
26 if (image) { | |
27 image->firmware_sign_key = NULL; | |
28 image->kernel_subkey_sign_key = NULL; | |
29 image->preamble_signature = NULL; | |
30 image->firmware_signature = NULL; | |
31 image->firmware_data = NULL; | |
32 } | |
33 return image; | |
34 } | |
35 | |
36 void FirmwareImageFree(FirmwareImage* image) { | |
37 if (image) { | |
38 Free(image->firmware_sign_key); | |
39 Free(image->kernel_subkey_sign_key); | |
40 Free(image->preamble_signature); | |
41 Free(image->firmware_signature); | |
42 Free(image->firmware_data); | |
43 Free(image); | |
44 } | |
45 } | |
46 | |
47 FirmwareImage* ReadFirmwareImage(const char* input_file) { | |
48 uint64_t file_size; | |
49 int image_len = 0; /* Total size of the firmware image. */ | |
50 int header_len = 0; | |
51 int firmware_sign_key_len; | |
52 int signature_len; | |
53 uint8_t* firmware_buf; | |
54 uint8_t header_checksum[FIELD_LEN(header_checksum)]; | |
55 MemcpyState st; | |
56 FirmwareImage* image = FirmwareImageNew(); | |
57 | |
58 if (!image) | |
59 return NULL; | |
60 | |
61 firmware_buf = BufferFromFile(input_file, &file_size); | |
62 image_len = file_size; | |
63 | |
64 st.remaining_len = image_len; | |
65 st.remaining_buf = firmware_buf; | |
66 st.overrun = 0; | |
67 | |
68 /* Read and compare magic bytes. */ | |
69 StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE); | |
70 if (SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) { | |
71 debug("Wrong Firmware Magic.\n"); | |
72 Free(firmware_buf); | |
73 return NULL; | |
74 } | |
75 StatefulMemcpy(&st, &image->header_len, FIELD_LEN(header_len)); | |
76 StatefulMemcpy(&st, &image->firmware_sign_algorithm, | |
77 FIELD_LEN(firmware_sign_algorithm)); | |
78 | |
79 /* Valid Algorithm? */ | |
80 if (image->firmware_sign_algorithm >= kNumAlgorithms) { | |
81 Free(firmware_buf); | |
82 return NULL; | |
83 } | |
84 | |
85 /* Compute size of pre-processed RSA public key and signature. */ | |
86 firmware_sign_key_len = RSAProcessedKeySize(image->firmware_sign_algorithm); | |
87 signature_len = siglen_map[image->firmware_sign_algorithm]; | |
88 | |
89 /* Check whether the header length is correct. */ | |
90 header_len = GetFirmwareHeaderLen(image); | |
91 if (header_len != image->header_len) { | |
92 debug("Header length mismatch. Got: %d Expected: %d\n", | |
93 image->header_len, header_len); | |
94 Free(firmware_buf); | |
95 return NULL; | |
96 } | |
97 | |
98 /* Read pre-processed public half of the sign key. */ | |
99 StatefulMemcpy(&st, &image->firmware_key_version, | |
100 FIELD_LEN(firmware_key_version)); | |
101 image->firmware_sign_key = (uint8_t*) Malloc(firmware_sign_key_len); | |
102 StatefulMemcpy(&st, image->firmware_sign_key, firmware_sign_key_len); | |
103 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); | |
104 | |
105 /* Check whether the header checksum matches. */ | |
106 CalculateFirmwareHeaderChecksum(image, header_checksum); | |
107 if (SafeMemcmp(header_checksum, image->header_checksum, | |
108 FIELD_LEN(header_checksum))) { | |
109 debug("Invalid firmware header checksum!\n"); | |
110 Free(firmware_buf); | |
111 return NULL; | |
112 } | |
113 | |
114 /* Read key signature. */ | |
115 StatefulMemcpy(&st, image->firmware_key_signature, | |
116 FIELD_LEN(firmware_key_signature)); | |
117 | |
118 /* Read the firmware preamble. */ | |
119 StatefulMemcpy(&st,&image->firmware_version, FIELD_LEN(firmware_version)); | |
120 StatefulMemcpy(&st, &image->firmware_len, FIELD_LEN(firmware_len)); | |
121 StatefulMemcpy(&st, &image->kernel_subkey_sign_algorithm, | |
122 FIELD_LEN(kernel_subkey_sign_algorithm)); | |
123 StatefulMemcpy(&st, image->kernel_subkey_sign_key, | |
124 RSAProcessedKeySize(image->kernel_subkey_sign_algorithm)); | |
125 StatefulMemcpy(&st, image->preamble, FIELD_LEN(preamble)); | |
126 | |
127 /* Read firmware preamble signature. */ | |
128 image->preamble_signature = (uint8_t*) Malloc(signature_len); | |
129 StatefulMemcpy(&st, image->preamble_signature, signature_len); | |
130 | |
131 image->firmware_signature = (uint8_t*) Malloc(signature_len); | |
132 StatefulMemcpy(&st, image->firmware_signature, signature_len); | |
133 | |
134 image->firmware_data = (uint8_t*) Malloc(image->firmware_len); | |
135 StatefulMemcpy(&st, image->firmware_data, image->firmware_len); | |
136 | |
137 if(st.overrun || st.remaining_len != 0) { /* Overrun or underrun. */ | |
138 Free(firmware_buf); | |
139 return NULL; | |
140 } | |
141 | |
142 Free(firmware_buf); | |
143 return image; | |
144 } | |
145 | |
146 int GetFirmwareHeaderLen(const FirmwareImage* image) { | |
147 return (FIELD_LEN(header_len) + FIELD_LEN(firmware_sign_algorithm) + | |
148 RSAProcessedKeySize(image->firmware_sign_algorithm) + | |
149 FIELD_LEN(firmware_key_version) + FIELD_LEN(header_checksum)); | |
150 } | |
151 | |
152 void CalculateFirmwareHeaderChecksum(const FirmwareImage* image, | |
153 uint8_t* header_checksum) { | |
154 uint8_t* checksum; | |
155 DigestContext ctx; | |
156 DigestInit(&ctx, SHA512_DIGEST_ALGORITHM); | |
157 DigestUpdate(&ctx, (uint8_t*) &image->header_len, | |
158 sizeof(image->header_len)); | |
159 DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm, | |
160 sizeof(image->firmware_sign_algorithm)); | |
161 DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version, | |
162 sizeof(image->firmware_key_version)); | |
163 DigestUpdate(&ctx, image->firmware_sign_key, | |
164 RSAProcessedKeySize(image->firmware_sign_algorithm)); | |
165 checksum = DigestFinal(&ctx); | |
166 Memcpy(header_checksum, checksum, FIELD_LEN(header_checksum)); | |
167 Free(checksum); | |
168 return; | |
169 } | |
170 | |
171 | |
172 uint8_t* GetFirmwareHeaderBlob(const FirmwareImage* image) { | |
173 uint8_t* header_blob = NULL; | |
174 MemcpyState st; | |
175 | |
176 header_blob = (uint8_t*) Malloc(GetFirmwareHeaderLen(image)); | |
177 st.remaining_len = GetFirmwareHeaderLen(image); | |
178 st.remaining_buf = header_blob; | |
179 st.overrun = 0; | |
180 | |
181 StatefulMemcpy_r(&st, &image->header_len, FIELD_LEN(header_len)); | |
182 StatefulMemcpy_r(&st, &image->firmware_sign_algorithm, FIELD_LEN(header_len)); | |
183 StatefulMemcpy_r(&st, &image->firmware_key_version, | |
184 FIELD_LEN(firmware_key_version)); | |
185 StatefulMemcpy_r(&st, image->firmware_sign_key, | |
186 RSAProcessedKeySize(image->firmware_sign_algorithm)); | |
187 StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum)); | |
188 | |
189 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */ | |
190 Free(header_blob); | |
191 return NULL; | |
192 } | |
193 return header_blob; | |
194 } | |
195 | |
196 | |
197 uint8_t* GetFirmwarePreambleBlob(const FirmwareImage* image) { | |
198 uint8_t* preamble_blob = NULL; | |
199 MemcpyState st; | |
200 uint64_t preamble_len = GetFirmwarePreambleLen( | |
201 image->kernel_subkey_sign_algorithm); | |
202 | |
203 preamble_blob = (uint8_t*) Malloc(preamble_len); | |
204 st.remaining_len = preamble_len; | |
205 st.remaining_buf = preamble_blob; | |
206 st.overrun = 0; | |
207 | |
208 StatefulMemcpy_r(&st, &image->firmware_version, FIELD_LEN(firmware_version)); | |
209 StatefulMemcpy_r(&st, &image->firmware_len, FIELD_LEN(firmware_len)); | |
210 StatefulMemcpy_r(&st, &image->kernel_subkey_sign_algorithm, | |
211 FIELD_LEN(kernel_subkey_sign_algorithm)); | |
212 StatefulMemcpy_r(&st, image->kernel_subkey_sign_key, | |
213 RSAProcessedKeySize(image->kernel_subkey_sign_algorithm)); | |
214 StatefulMemcpy_r(&st, image->preamble, FIELD_LEN(preamble)); | |
215 | |
216 if (st.overrun || st.remaining_len != 0 ) { /* Underrun or Overrun. */ | |
217 Free(preamble_blob); | |
218 return NULL; | |
219 } | |
220 return preamble_blob; | |
221 } | |
222 | |
223 | |
224 uint8_t* GetFirmwareBlob(const FirmwareImage* image, uint64_t* blob_len) { | |
225 int firmware_signature_len; | |
226 uint8_t* firmware_blob = NULL; | |
227 uint8_t* header_blob = NULL; | |
228 uint8_t* preamble_blob = NULL; | |
229 MemcpyState st; | |
230 | |
231 if (!image) | |
232 return NULL; | |
233 | |
234 firmware_signature_len = siglen_map[image->firmware_sign_algorithm]; | |
235 *blob_len = (FIELD_LEN(magic) + | |
236 GetFirmwareHeaderLen(image) + | |
237 FIELD_LEN(firmware_key_signature) + | |
238 GetFirmwarePreambleLen(image->kernel_subkey_sign_algorithm) + | |
239 2 * firmware_signature_len + | |
240 image->firmware_len); | |
241 firmware_blob = (uint8_t*) Malloc(*blob_len); | |
242 st.remaining_len = *blob_len; | |
243 st.remaining_buf = firmware_blob; | |
244 st.overrun = 0; | |
245 | |
246 header_blob = GetFirmwareHeaderBlob(image); | |
247 preamble_blob = GetFirmwarePreambleBlob(image); | |
248 | |
249 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); | |
250 StatefulMemcpy_r(&st, header_blob, GetFirmwareHeaderLen(image)); | |
251 StatefulMemcpy_r(&st, image->firmware_key_signature, | |
252 FIELD_LEN(firmware_key_signature)); | |
253 StatefulMemcpy_r(&st, preamble_blob, | |
254 GetFirmwarePreambleLen(image->kernel_subkey_sign_algorithm)); | |
255 StatefulMemcpy_r(&st, image->preamble_signature, firmware_signature_len); | |
256 StatefulMemcpy_r(&st, image->firmware_signature, firmware_signature_len); | |
257 StatefulMemcpy_r(&st, image->firmware_data, image->firmware_len); | |
258 | |
259 Free(preamble_blob); | |
260 Free(header_blob); | |
261 | |
262 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */ | |
263 Free(firmware_blob); | |
264 return NULL; | |
265 } | |
266 return firmware_blob; | |
267 } | |
268 | |
269 int WriteFirmwareImage(const char* output_file, | |
270 const FirmwareImage* image, | |
271 int is_only_vblock, | |
272 int is_subkey_out) { | |
273 int fd; | |
274 int success = 1; | |
275 uint8_t* firmware_blob; | |
276 uint8_t* subkey_out_buf = NULL; | |
277 uint8_t* subkey_header = NULL; | |
278 uint64_t blob_len; | |
279 | |
280 if (!image) | |
281 return 0; | |
282 if (-1 == (fd = creat(output_file, 0666))) { | |
283 debug("Couldn't open file for writing.\n"); | |
284 return 0; | |
285 } | |
286 if (is_subkey_out) { | |
287 blob_len = GetFirmwareHeaderLen(image) + | |
288 siglen_map[ROOT_SIGNATURE_ALGORITHM]; | |
289 subkey_out_buf = (uint8_t*) Malloc(blob_len); | |
290 subkey_header = GetFirmwareHeaderBlob(image); | |
291 Memcpy(subkey_out_buf, subkey_header, GetFirmwareHeaderLen(image)); | |
292 Memcpy(subkey_out_buf + GetFirmwareHeaderLen(image), | |
293 image->firmware_key_signature, | |
294 siglen_map[ROOT_SIGNATURE_ALGORITHM]); | |
295 if (blob_len != write(fd, subkey_out_buf, blob_len)) { | |
296 debug("Couldn't write kernel subkey header to file: %s\n", | |
297 output_file); | |
298 success = 0; | |
299 } | |
300 Free(subkey_header); | |
301 Free(subkey_out_buf); | |
302 close(fd); | |
303 return success; | |
304 } | |
305 | |
306 firmware_blob = GetFirmwareBlob(image, &blob_len); | |
307 if (!firmware_blob) { | |
308 debug("Couldn't create firmware blob from FirmwareImage.\n"); | |
309 return 0; | |
310 } | |
311 if (!is_only_vblock) { | |
312 if (blob_len != write(fd, firmware_blob, blob_len)) { | |
313 debug("Couldn't write Firmware Image to file: %s\n", output_file); | |
314 success = 0; | |
315 } | |
316 } else { | |
317 /* Exclude the firmware_data. */ | |
318 int vblock_len = blob_len - image->firmware_len; | |
319 if (vblock_len != write(fd, firmware_blob, vblock_len)) { | |
320 debug("Couldn't write Firmware Image verifcation block to file: %s\n", | |
321 output_file); | |
322 success = 0; | |
323 } | |
324 } | |
325 Free(firmware_blob); | |
326 close(fd); | |
327 return success; | |
328 } | |
329 | |
330 void PrintFirmwareImage(const FirmwareImage* image) { | |
331 if (!image) | |
332 return; | |
333 | |
334 /* Print header. */ | |
335 debug("Header Length = %d\n" | |
336 "Firmware Signature Algorithm = %s\n" | |
337 "Firmware Key Version = %d\n\n", | |
338 image->header_len, | |
339 algo_strings[image->firmware_sign_algorithm], | |
340 image->firmware_key_version); | |
341 /* TODO(gauravsh): Output hash and key signature here? */ | |
342 /* Print preamble. */ | |
343 debug("Firmware Version = %d\n" | |
344 "Firmware Length = %" PRIu64 "\n\n", | |
345 image->firmware_version, | |
346 image->firmware_len); | |
347 /* Output key signature here? */ | |
348 } | |
349 | |
350 int VerifyFirmwareImage(const RSAPublicKey* root_key, | |
351 const FirmwareImage* image) { | |
352 RSAPublicKey* firmware_sign_key = NULL; | |
353 uint8_t* header_digest = NULL; | |
354 uint8_t* preamble_digest = NULL; | |
355 uint8_t* firmware_digest = NULL; | |
356 int firmware_sign_key_size; | |
357 int signature_size; | |
358 int error_code = 0; | |
359 DigestContext ctx; | |
360 DigestContext firmware_ctx; | |
361 | |
362 if (!image) | |
363 return VERIFY_FIRMWARE_INVALID_IMAGE; | |
364 | |
365 /* Verify root key signature on the sign key header if we | |
366 * are not in dev mode. | |
367 * | |
368 * TODO(gauravsh): Add additional sanity checks here for: | |
369 * 1) verifying the header length is correct. | |
370 * 2) header_checksum is correct. | |
371 */ | |
372 | |
373 /* Check key signature. */ | |
374 DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM); | |
375 DigestUpdate(&ctx, (uint8_t*) &image->header_len, | |
376 FIELD_LEN(header_len)); | |
377 DigestUpdate(&ctx, (uint8_t*) &image->firmware_sign_algorithm, | |
378 FIELD_LEN(firmware_sign_algorithm)); | |
379 DigestUpdate(&ctx, (uint8_t*) &image->firmware_key_version, | |
380 FIELD_LEN(firmware_key_version)); | |
381 DigestUpdate(&ctx, image->firmware_sign_key, | |
382 RSAProcessedKeySize(image->firmware_sign_algorithm)); | |
383 DigestUpdate(&ctx, image->header_checksum, | |
384 FIELD_LEN(header_checksum)); | |
385 header_digest = DigestFinal(&ctx); | |
386 if (!RSAVerify(root_key, image->firmware_key_signature, | |
387 FIELD_LEN(firmware_key_signature), | |
388 ROOT_SIGNATURE_ALGORITHM, | |
389 header_digest)) { | |
390 error_code = VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED; | |
391 goto verify_failure; | |
392 } | |
393 | |
394 /* Get sign key to verify the rest of the firmware. */ | |
395 firmware_sign_key_size = RSAProcessedKeySize(image->firmware_sign_algorithm); | |
396 firmware_sign_key = RSAPublicKeyFromBuf(image->firmware_sign_key, | |
397 firmware_sign_key_size); | |
398 signature_size = siglen_map[image->firmware_sign_algorithm]; | |
399 | |
400 if (image->firmware_sign_algorithm >= kNumAlgorithms) | |
401 return VERIFY_FIRMWARE_INVALID_ALGORITHM; | |
402 | |
403 /* Verify firmware preamble signature. */ | |
404 DigestInit(&ctx, image->firmware_sign_algorithm); | |
405 DigestUpdate(&ctx, (uint8_t*) &image->firmware_version, | |
406 FIELD_LEN(firmware_version)); | |
407 DigestUpdate(&ctx, (uint8_t*) &image->firmware_len, | |
408 FIELD_LEN(firmware_len)); | |
409 DigestUpdate(&ctx, (uint8_t*) &image->kernel_subkey_sign_algorithm, | |
410 FIELD_LEN(kernel_subkey_sign_algorithm)); | |
411 DigestUpdate(&ctx, (uint8_t*) image->kernel_subkey_sign_key, | |
412 RSAProcessedKeySize(image->kernel_subkey_sign_algorithm)); | |
413 DigestUpdate(&ctx, (uint8_t*) &image->preamble, | |
414 FIELD_LEN(preamble)); | |
415 preamble_digest = DigestFinal(&ctx); | |
416 if (!RSAVerify(firmware_sign_key, image->preamble_signature, | |
417 signature_size, image->firmware_sign_algorithm, | |
418 preamble_digest)) { | |
419 error_code = VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED; | |
420 goto verify_failure; | |
421 } | |
422 | |
423 /* Verify firmware signature - firmware signature is on the contents | |
424 of firmware preamble + firmware_data. */ | |
425 DigestInit(&firmware_ctx, image->firmware_sign_algorithm); | |
426 DigestUpdate(&firmware_ctx, (uint8_t*) &image->firmware_version, | |
427 FIELD_LEN(firmware_version)); | |
428 DigestUpdate(&firmware_ctx, (uint8_t*) &image->firmware_len, | |
429 FIELD_LEN(firmware_len)); | |
430 DigestUpdate(&firmware_ctx, (uint8_t*) &image->kernel_subkey_sign_algorithm, | |
431 FIELD_LEN(kernel_subkey_sign_algorithm)); | |
432 DigestUpdate(&firmware_ctx, (uint8_t*) image->kernel_subkey_sign_key, | |
433 RSAProcessedKeySize(image->kernel_subkey_sign_algorithm)); | |
434 DigestUpdate(&firmware_ctx, (uint8_t*) &image->preamble, | |
435 FIELD_LEN(preamble)); | |
436 DigestUpdate(&firmware_ctx, image->firmware_data, image->firmware_len); | |
437 firmware_digest = DigestFinal(&firmware_ctx); | |
438 if (!RSAVerify(firmware_sign_key, image->firmware_signature, | |
439 signature_size, image->firmware_sign_algorithm, | |
440 firmware_digest)) { | |
441 error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED; | |
442 goto verify_failure; | |
443 } | |
444 | |
445 verify_failure: | |
446 RSAPublicKeyFree(firmware_sign_key); | |
447 Free(firmware_digest); | |
448 Free(preamble_digest); | |
449 Free(header_digest); | |
450 return error_code; | |
451 } | |
452 | |
453 const char* VerifyFirmwareErrorString(int error) { | |
454 return kVerifyFirmwareErrors[error]; | |
455 } | |
456 | |
457 int AddFirmwareKeySignature(FirmwareImage* image, const char* root_key_file) { | |
458 uint8_t* header_blob = NULL; | |
459 uint8_t* signature; | |
460 if (!image || !root_key_file) | |
461 return 0; | |
462 header_blob = GetFirmwareHeaderBlob(image); | |
463 if (!header_blob) | |
464 return 0; | |
465 if (!(signature = SignatureBuf(header_blob, | |
466 GetFirmwareHeaderLen(image), | |
467 root_key_file, | |
468 ROOT_SIGNATURE_ALGORITHM))) { | |
469 Free(header_blob); | |
470 return 0; | |
471 } | |
472 Memcpy(image->firmware_key_signature, signature, RSA8192NUMBYTES); | |
473 Free(header_blob); | |
474 Free(signature); | |
475 return 1; | |
476 } | |
477 | |
478 int AddFirmwareSignature(FirmwareImage* image, const char* signing_key_file) { | |
479 uint8_t* preamble_blob = NULL; | |
480 uint8_t* preamble_signature = NULL; | |
481 uint8_t* firmware_signature = NULL; | |
482 uint8_t* firmware_buf = NULL; | |
483 int signature_len = siglen_map[image->firmware_sign_algorithm]; | |
484 uint64_t preamble_len = GetFirmwarePreambleLen( | |
485 image->kernel_subkey_sign_algorithm); | |
486 | |
487 preamble_blob = GetFirmwarePreambleBlob(image); | |
488 if (!preamble_blob) | |
489 return 0; | |
490 if (!(preamble_signature = SignatureBuf(preamble_blob, | |
491 preamble_len, | |
492 signing_key_file, | |
493 image->firmware_sign_algorithm))) { | |
494 Free(preamble_blob); | |
495 return 0; | |
496 } | |
497 image->preamble_signature = (uint8_t*) Malloc(signature_len); | |
498 Memcpy(image->preamble_signature, preamble_signature, signature_len); | |
499 Free(preamble_signature); | |
500 /* Firmware signature must be calculated on preamble + firmware_data | |
501 * to avoid splicing attacks. */ | |
502 firmware_buf = (uint8_t*) Malloc(preamble_len + | |
503 image->firmware_len); | |
504 Memcpy(firmware_buf, preamble_blob, preamble_len); | |
505 Memcpy(firmware_buf + preamble_len, image->firmware_data, | |
506 image->firmware_len); | |
507 if (!(firmware_signature = SignatureBuf(firmware_buf, | |
508 preamble_len + | |
509 image->firmware_len, | |
510 signing_key_file, | |
511 image->firmware_sign_algorithm))) { | |
512 Free(preamble_blob); | |
513 Free(firmware_buf); | |
514 return 0; | |
515 } | |
516 image->firmware_signature = (uint8_t*) Malloc(signature_len); | |
517 Memcpy(image->firmware_signature, firmware_signature, signature_len); | |
518 Free(firmware_signature); | |
519 Free(firmware_buf); | |
520 Free(preamble_blob); | |
521 return 1; | |
522 } | |
OLD | NEW |