blob: 07aa8bd46b09153824ad2337f8415b87e74874ca [file] [log] [blame]
Gaurav Shah431b9882010-02-12 15:54:37 -08001/* 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 <fcntl.h>
11#include <limits.h>
12#include <stdio.h>
13#include <sys/types.h>
14#include <sys/stat.h>
15#include <unistd.h>
16
Gaurav Shah08df9b82010-02-23 16:16:23 -080017#include "file_keys.h"
Gaurav Shah431b9882010-02-12 15:54:37 -080018#include "padding.h"
19#include "rsa_utility.h"
20#include "sha_utility.h"
21#include "utility.h"
22
Gaurav Shah08df9b82010-02-23 16:16:23 -080023/* Macro to determine the size of a field structure in the FirmwareImage
24 * structure. */
25#define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field))
Gaurav Shah431b9882010-02-12 15:54:37 -080026
27FirmwareImage* FirmwareImageNew(void) {
28 FirmwareImage* fw = (FirmwareImage*) Malloc(sizeof(FirmwareImage));
29 return fw;
30}
31
32void FirmwareImageFree(FirmwareImage* image) {
33 Free(image->sign_key);
34 Free(image->key_signature);
35 Free(image->preamble_signature);
36 Free(image->firmware_signature);
37 Free(image->firmware_data);
38}
39
Gaurav Shah08df9b82010-02-23 16:16:23 -080040FirmwareImage* ReadFirmwareImage(const char* input_file,
41 FirmwareImage* image) {
Gaurav Shah431b9882010-02-12 15:54:37 -080042 int fd;
43 struct stat fd_stat;
44
45 int image_len = 0; /* Total size of the firmware image. */
46 int header_len = 0;
47 int sign_key_len;
48 int signature_len;
49 uint8_t* firmware_buf;
50 MemcpyState st;
51
52 if (!image)
53 return NULL;
54
55 if (-1 == (fd = open(input_file, O_RDONLY))) {
56 fprintf(stderr, "Couldn't open file for reading.\n");
57 return NULL;
58 }
59
60 if (-1 == fstat(fd, &fd_stat)) {
61 fprintf(stderr, "Couldn't stat file.\n");
62 close(fd);
63 return NULL;
64 }
65
66 firmware_buf = (uint8_t*) Malloc(fd_stat.st_size);
67 image_len = fd_stat.st_size;
68
69 /* Read entire file into a buffer. */
70 if (image_len != read(fd, firmware_buf, image_len)) {
71 fprintf(stderr, "Couldn't read file data.\n");
72 close(fd);
73 return NULL;
74 }
75 close(fd);
76
77 st.remaining_len = image_len;
78 st.remaining_buf = firmware_buf;
79
80 /* Read and compare magic bytes. */
81 if (!StatefulMemcpy(&st, &image->magic, FIRMWARE_MAGIC_SIZE))
82 goto parse_failure;
83
Gaurav Shah08df9b82010-02-23 16:16:23 -080084 if (SafeMemcmp(image->magic, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE)) {
Gaurav Shah431b9882010-02-12 15:54:37 -080085 fprintf(stderr, "Wrong Firmware Magic.\n");
86 goto parse_failure;
87 }
88
89 StatefulMemcpy(&st, &image->header_len, sizeof(image->header_len));
90 StatefulMemcpy(&st, &image->sign_algorithm, sizeof(image->sign_algorithm));
91
92 /* Valid Algorithm? */
93 if (image->sign_algorithm > kNumAlgorithms)
94 goto parse_failure;
95
96 /* Compute size of pre-processed RSA public key and signature. */
97 sign_key_len = (2*siglen_map[image->sign_algorithm]*sizeof(uint32_t)
98 + sizeof(uint32_t) + sizeof(int));
99 signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
100
101
102 /* Check whether the header length is correct. */
103 header_len = (sizeof(image->header_len) + sizeof(image->sign_algorithm) +
104 sizeof(image->key_version) +
Gaurav Shah08df9b82010-02-23 16:16:23 -0800105 sizeof(image->header_checksum));
Gaurav Shah431b9882010-02-12 15:54:37 -0800106 if (header_len != image->header_len) {
107 fprintf(stderr, "Header length mismatch.");
108 goto parse_failure;
109 }
110
111 /* Read pre-processed public half of the sign key. */
112 image->sign_key = (uint8_t*) Malloc(sign_key_len);
113 StatefulMemcpy(&st, image->sign_key, sign_key_len);
114 StatefulMemcpy(&st, &image->key_version, sizeof(image->key_version));
Gaurav Shah08df9b82010-02-23 16:16:23 -0800115 StatefulMemcpy(&st, image->header_checksum, sizeof(image->header_checksum));
Gaurav Shah431b9882010-02-12 15:54:37 -0800116
117 /* Read key signature. */
118 StatefulMemcpy(&st, image->key_signature, sizeof(image->key_signature));
119
120 /* Read the firmware preamble. */
121 StatefulMemcpy(&st,&image->firmware_version, sizeof(image->firmware_version));
122 StatefulMemcpy(&st, &image->firmware_len, sizeof(image->firmware_len));
123 StatefulMemcpy(&st, image->preamble, sizeof(image->preamble));
124
125 /* Read firmware preamble signature. */
126 image->preamble_signature = (uint8_t*) Malloc(signature_len);
127 StatefulMemcpy(&st, image->preamble_signature, signature_len);
128
129 image->firmware_signature = (uint8_t*) Malloc(signature_len);
130 StatefulMemcpy(&st, image->firmware_signature, signature_len);
131
132 image->firmware_data = (uint8_t*) Malloc(image->firmware_len);
133 StatefulMemcpy(&st, image->firmware_data, image->firmware_len);
134
135 if(st.remaining_len != 0) /* Overrun or underrun. */
136 goto parse_failure;
137
138 Free(firmware_buf);
139 return image;
140
141parse_failure:
142 Free(firmware_buf);
143 return NULL;
144}
145
146void WriteFirmwareHeader(int fd, FirmwareImage* image) {
147 int sign_key_len;
148 write(fd, &image->header_len, sizeof(image->header_len));
149 write(fd, &image->sign_algorithm, sizeof(image->header_len));
150 sign_key_len = (image->header_len - sizeof(image->header_len) -
151 sizeof(image->sign_algorithm) -
152 sizeof(image->key_version) -
Gaurav Shah08df9b82010-02-23 16:16:23 -0800153 sizeof(image->header_checksum));
Gaurav Shah431b9882010-02-12 15:54:37 -0800154 write(fd, image->sign_key, sign_key_len);
155 write(fd, &image->key_version, sizeof(image->key_version));
Gaurav Shah08df9b82010-02-23 16:16:23 -0800156 write(fd, &image->header_checksum, sizeof(image->header_checksum));
Gaurav Shah431b9882010-02-12 15:54:37 -0800157}
158
159void WriteFirmwarePreamble(int fd, FirmwareImage* image) {
160 write(fd, &image->firmware_version,
161 sizeof(image->firmware_version));
162 write(fd, &image->firmware_len, sizeof(image->firmware_len));
163 write(fd, image->preamble, sizeof(image->preamble));
164}
165
Gaurav Shah08df9b82010-02-23 16:16:23 -0800166FirmwareImage* WriteFirmwareImage(const char* input_file,
167 FirmwareImage* image) {
168 int fd;
169 int signature_len;
Gaurav Shah431b9882010-02-12 15:54:37 -0800170
Gaurav Shah08df9b82010-02-23 16:16:23 -0800171 if (!image)
172 return NULL;
173 if (-1 == (fd = creat(input_file, S_IRWXU))) {
174 fprintf(stderr, "Couldn't open file for writing.\n");
175 return NULL;
176 }
Gaurav Shah431b9882010-02-12 15:54:37 -0800177
Gaurav Shah08df9b82010-02-23 16:16:23 -0800178 write(fd, image->magic, sizeof(image->magic));
179 WriteFirmwareHeader(fd, image);
180 write(fd, image->key_signature, sizeof(image->key_signature));
181 signature_len = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
182 WriteFirmwarePreamble(fd, image);
183 write(fd, image->preamble_signature, signature_len);
184 write(fd, image->firmware_signature, signature_len);
185 write(fd, image->firmware_data, image->firmware_len);
Gaurav Shah431b9882010-02-12 15:54:37 -0800186
Gaurav Shah08df9b82010-02-23 16:16:23 -0800187 close(fd);
188 return image;
Gaurav Shah431b9882010-02-12 15:54:37 -0800189}
190
191void PrintFirmware(const FirmwareImage* image) {
192 if (!image)
193 return;
194
195 /* Print header. */
196 printf("Header Length = %d\n"
197 "Algorithm Id = %d\n"
198 "Signature Algorithm = %s\n"
199 "Key Version = %d\n\n",
200 image->header_len,
201 image->sign_algorithm,
202 algo_strings[image->sign_algorithm],
203 image->key_version);
204 /* TODO(gauravsh): Output hash and key signature here? */
205 /* Print preamble. */
206 printf("Firmware Version = %d\n"
207 "Firmware Length = %d\n\n",
208 image->firmware_version,
209 image->firmware_len);
210 /* Output key signature here? */
211}
212
Gaurav Shah08df9b82010-02-23 16:16:23 -0800213char* kVerifyFirmwareErrors[VERIFY_FIRMWARE_MAX] = {
214 "Success.",
215 "Invalid Image.",
216 "Root Key Signature Failed.",
217 "Invalid Verification Algorithm.",
218 "Preamble Signature Failed.",
219 "Firmware Signature Failed.",
220 "Wrong Firmware Magic.",
221};
222
223int VerifyFirmwareHeader(const uint8_t* root_key_blob,
224 const uint8_t* header_blob,
225 const int dev_mode,
226 int* algorithm,
227 int* header_len) {
228 int sign_key_len;
229 int root_key_len;
230 uint16_t hlen, algo;
231 uint8_t* header_checksum = NULL;
232
233 /* Base Offset for the header_checksum field. Actual offset is
234 * this + sign_key_len. */
235 int base_header_checksum_offset = (FIELD_LEN(header_len) +
236 FIELD_LEN(sign_algorithm) +
237 FIELD_LEN(key_version));
238
239
240 root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM);
241 Memcpy(&hlen, header_blob, sizeof(hlen));
242 Memcpy(&algo,
243 header_blob + FIELD_LEN(sign_algorithm),
244 sizeof(algo));
245 if (algo >= kNumAlgorithms)
246 return VERIFY_FIRMWARE_INVALID_ALGORITHM;
247 *algorithm = (int) algo;
248 sign_key_len = RSAProcessedKeySize(*algorithm);
249
250 /* Verify if header len is correct? */
251 if (hlen != (base_header_checksum_offset +
252 sign_key_len +
253 FIELD_LEN(header_checksum)))
254 return VERIFY_FIRMWARE_INVALID_IMAGE;
255
256 *header_len = (int) hlen;
257
258 /* Verify if the hash of the header is correct. */
259 header_checksum = DigestBuf(header_blob,
260 *header_len - FIELD_LEN(header_checksum),
261 SHA512_DIGEST_ALGORITHM);
262 if (SafeMemcmp(header_checksum,
263 header_blob + (base_header_checksum_offset + sign_key_len),
264 FIELD_LEN(header_checksum))) {
265 Free(header_checksum);
266 return VERIFY_FIRMWARE_INVALID_IMAGE;
267 }
268 Free(header_checksum);
269
270 /* Verify root key signature unless we are in dev mode. */
271 if (!dev_mode) {
272 if (!RSAVerifyBinary_f(root_key_blob, NULL, /* Key to use */
273 header_blob, /* Data to verify */
274 *header_len, /* Length of data */
275 header_blob + *header_len, /* Expected Signature */
276 ROOT_SIGNATURE_ALGORITHM))
277 return VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED;
278 }
279 return 0;
280}
281
282int VerifyFirmwarePreamble(RSAPublicKey* sign_key,
283 const uint8_t* preamble_blob,
284 int algorithm,
285 int* firmware_len) {
286 uint32_t len;
287 int preamble_len;
288 preamble_len = (FIELD_LEN(firmware_version) +
289 FIELD_LEN(firmware_len) +
290 FIELD_LEN(preamble));
291 if (!RSAVerifyBinary_f(NULL, sign_key, /* Key to use */
292 preamble_blob, /* Data to verify */
293 preamble_len, /* Length of data */
294 preamble_blob + preamble_len, /* Expected Signature */
295 algorithm))
296 return VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
297
298 Memcpy(&len, preamble_blob + FIELD_LEN(firmware_version),
299 sizeof(len));
300 *firmware_len = (int) len;
301 return 0;
302}
303
304int VerifyFirmwareData(RSAPublicKey* sign_key,
305 const uint8_t* firmware_data_start,
306 int firmware_len,
307 int algorithm) {
308 int signature_len = siglen_map[algorithm] * sizeof(uint32_t);
309 if (!RSAVerifyBinary_f(NULL, sign_key, /* Key to use. */
310 firmware_data_start + signature_len, /* Data to
311 * verify */
312 firmware_len, /* Length of data. */
313 firmware_data_start, /* Expected Signature */
314 algorithm))
315 return VERIFY_FIRMWARE_SIGNATURE_FAILED;
316 return 0;
317}
318
319int VerifyFirmware(const uint8_t* root_key_blob,
320 const uint8_t* firmware_blob,
Gaurav Shah431b9882010-02-12 15:54:37 -0800321 const int dev_mode) {
Gaurav Shah08df9b82010-02-23 16:16:23 -0800322 int error_code;
323 int algorithm; /* Signing key algorithm. */
324 RSAPublicKey* sign_key;
325 int sign_key_len, signature_len, header_len, firmware_len;
326 const uint8_t* header_ptr; /* Pointer to header. */
327 const uint8_t* sign_key_ptr; /* Pointer to signing key. */
328 const uint8_t* preamble_ptr; /* Pointer to preamble block. */
329 const uint8_t* firmware_ptr; /* Pointer to firmware signature/data. */
330
331 /* Note: All the offset calculations are based on struct FirmwareImage which
332 * is defined in include/firmware_image.h. */
333
334 /* Compare magic bytes. */
335 if (SafeMemcmp(firmware_blob, FIRMWARE_MAGIC, FIRMWARE_MAGIC_SIZE))
336 return VERIFY_FIRMWARE_WRONG_MAGIC;
337 header_ptr = firmware_blob + FIRMWARE_MAGIC_SIZE;
338
339 /* Only continue if header verification succeeds. */
340 if ((error_code = VerifyFirmwareHeader(root_key_blob, header_ptr, dev_mode,
341 &algorithm, &header_len)))
342 return error_code; /* AKA jump to revovery. */
343
344 /* Parse signing key into RSAPublicKey structure since it is required multiple
345 * times. */
346 sign_key_len = RSAProcessedKeySize(algorithm);
347 sign_key_ptr = header_ptr + (FIELD_LEN(header_len) +
348 FIELD_LEN(sign_algorithm));
349 sign_key = RSAPublicKeyFromBuf(sign_key_ptr, sign_key_len);
350 signature_len = siglen_map[algorithm] * sizeof(uint32_t);
351
352 /* Only continue if preamble verification succeeds. */
353 preamble_ptr = (header_ptr + header_len +
354 FIELD_LEN(key_signature));
355 if ((error_code = VerifyFirmwarePreamble(sign_key, preamble_ptr, algorithm,
356 &firmware_len)))
357 return error_code; /* AKA jump to recovery. */
358
359 /* Only continue if firmware data verification succeeds. */
360 firmware_ptr = (preamble_ptr +
361 FIELD_LEN(firmware_version) +
362 FIELD_LEN(firmware_len) +
363 FIELD_LEN(preamble) +
364 signature_len);
365
366 if ((error_code = VerifyFirmwareData(sign_key, firmware_ptr, firmware_len,
367 algorithm)))
368 return error_code; /* AKA jump to recovery. */
369
370 return 0; /* Success! */
371}
372
373int VerifyFirmwareImage(const RSAPublicKey* root_key,
374 const FirmwareImage* image,
375 const int dev_mode) {
Gaurav Shah431b9882010-02-12 15:54:37 -0800376 RSAPublicKey* sign_key;
377 uint8_t* header_digest = NULL;
378 uint8_t* preamble_digest = NULL;
379 uint8_t* firmware_digest = NULL;
380 int sign_key_size;
381 int signature_size;
382 int error_code = 0;
383 DigestContext ctx;
384
385 if (!image)
Gaurav Shah08df9b82010-02-23 16:16:23 -0800386 return VERIFY_FIRMWARE_INVALID_IMAGE;
Gaurav Shah431b9882010-02-12 15:54:37 -0800387
388 /* Verify root key signature on the sign key header if we
Gaurav Shah08df9b82010-02-23 16:16:23 -0800389 * are not in dev mode.
390 *
391 * TODO(gauravsh): Add additional sanity checks here for:
392 * 1) verifying the header length is correct.
393 * 2) header_checksum is correct.
394 */
Gaurav Shah431b9882010-02-12 15:54:37 -0800395 if (!dev_mode) {
396 DigestInit(&ctx, ROOT_SIGNATURE_ALGORITHM);
397 DigestUpdate(&ctx, (uint8_t*) &image->header_len,
398 sizeof(image->header_len));
399 DigestUpdate(&ctx, (uint8_t*) &image->sign_algorithm,
400 sizeof(image->sign_algorithm));
401 DigestUpdate(&ctx, image->sign_key,
402 RSAProcessedKeySize(image->sign_algorithm));
403 DigestUpdate(&ctx, (uint8_t*) &image->key_version,
404 sizeof(image->key_version));
Gaurav Shah08df9b82010-02-23 16:16:23 -0800405 DigestUpdate(&ctx, image->header_checksum,
406 sizeof(image->header_checksum));
Gaurav Shah431b9882010-02-12 15:54:37 -0800407 header_digest = DigestFinal(&ctx);
408 if (!RSA_verify(root_key, image->key_signature,
409 sizeof(image->key_signature),
410 ROOT_SIGNATURE_ALGORITHM,
411 header_digest)) {
Gaurav Shah08df9b82010-02-23 16:16:23 -0800412 error_code = VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED;
Gaurav Shah431b9882010-02-12 15:54:37 -0800413 goto verify_failure;
414 }
415 }
416
417 /* Get sign key to verify the rest of the firmware. */
418 sign_key_size = RSAProcessedKeySize(image->sign_algorithm);
419 sign_key = RSAPublicKeyFromBuf(image->sign_key,
420 sign_key_size);
421 signature_size = siglen_map[image->sign_algorithm] * sizeof(uint32_t);
422
423 if (image->sign_algorithm >= kNumAlgorithms)
Gaurav Shah08df9b82010-02-23 16:16:23 -0800424 return VERIFY_FIRMWARE_INVALID_ALGORITHM;
Gaurav Shah431b9882010-02-12 15:54:37 -0800425
426 /* Verify firmware preamble signature. */
427 DigestInit(&ctx, image->sign_algorithm);
428 DigestUpdate(&ctx, (uint8_t*) &image->firmware_version,
429 sizeof(image->firmware_version));
430 DigestUpdate(&ctx, (uint8_t*) &image->firmware_len,
431 sizeof(image->firmware_len));
432 DigestUpdate(&ctx, (uint8_t*) &image->preamble,
433 sizeof(image->preamble));
434 preamble_digest = DigestFinal(&ctx);
435 if (!RSA_verify(sign_key, image->preamble_signature,
436 signature_size, image->sign_algorithm,
437 preamble_digest)) {
Gaurav Shah08df9b82010-02-23 16:16:23 -0800438 error_code = VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
Gaurav Shah431b9882010-02-12 15:54:37 -0800439 goto verify_failure;
440 }
441
442 /* Verify firmware signature. */
443 firmware_digest = DigestBuf(image->firmware_data,
444 image->firmware_len,
445 image->sign_algorithm);
446 if(!RSA_verify(sign_key, image->firmware_signature,
447 signature_size, image->sign_algorithm,
448 firmware_digest)) {
449 error_code = VERIFY_FIRMWARE_SIGNATURE_FAILED;
450 goto verify_failure;
451 }
452
453verify_failure:
454 Free(firmware_digest);
455 Free(preamble_digest);
456 Free(header_digest);
457 return error_code;
458}
459
Gaurav Shah431b9882010-02-12 15:54:37 -0800460
461int AddKeySignature(FirmwareImage* image, char* root_key_file) {
462 int tmp_hdr_fd;
463 char* tmp_hdr_file = ".tmpHdrFile";
464 uint8_t* signature;
465
466 if(-1 == (tmp_hdr_fd = creat(tmp_hdr_file, S_IRWXU))) {
467 fprintf(stderr, "Could not open temporary file for writing "
468 "firmware header.\n");
469 return 0;
470 }
471 WriteFirmwareHeader(tmp_hdr_fd, image);
472 close(tmp_hdr_fd);
473
474 if (!(signature = SignatureFile(tmp_hdr_file, root_key_file,
475 ROOT_SIGNATURE_ALGORITHM)))
476 return 0;
477 Memcpy(image->key_signature, signature, RSA8192NUMBYTES);
478 return 1;
479}
480
481int AddFirmwareSignature(FirmwareImage* image, char* signing_key_file,
482 int algorithm) {
483 int tmp_preamble_fd;
484 char* tmp_preamble_file = ".tmpPreambleFile";
485 int tmp_firmware_fd;
486 char* tmp_firmware_file = ".tmpFirmwareFile";
487 uint8_t* preamble_signature;
488 uint8_t* firmware_signature;
489 int signature_len = siglen_map[algorithm] * sizeof(uint32_t);
490
491 /* Write preamble to a file. */
492 if(-1 == (tmp_preamble_fd = creat(tmp_preamble_file, S_IRWXU))) {
493 fprintf(stderr, "Could not open temporary file for writing "
Gaurav Shah08df9b82010-02-23 16:16:23 -0800494 "firmware preamble.\n");
Gaurav Shah431b9882010-02-12 15:54:37 -0800495 return 0;
496 }
497 WriteFirmwarePreamble(tmp_preamble_fd, image);
498 close(tmp_preamble_fd);
499 if (!(preamble_signature = SignatureFile(tmp_preamble_file, signing_key_file,
500 algorithm)))
501 return 0;
502 image->preamble_signature = (uint8_t*) Malloc(signature_len);
503 Memcpy(image->preamble_signature, preamble_signature, signature_len);
504 Free(preamble_signature);
505
506 if (-1 == (tmp_firmware_fd = creat(tmp_firmware_file, S_IRWXU))) {
507 fprintf(stderr, "Could not open temporary file for writing "
508 "firmware.\n");
509 return 0;
510 }
511 write(tmp_firmware_fd, image->firmware_data, image->firmware_len);
512 close(tmp_firmware_fd);
513
514 if (!(firmware_signature = SignatureFile(tmp_firmware_file, signing_key_file,
515 algorithm))) {
516 fprintf(stderr, "Could not open temporary file for writing "
517 "firmware.\n");
518 return 0;
519 }
520 image->firmware_signature = (uint8_t*) Malloc(signature_len);
521 Memcpy(image->firmware_signature, firmware_signature, signature_len);
522 Free(firmware_signature);
523 return 1;
524}