OLD | NEW |
1 /* Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 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 | 2 * Use of this source code is governed by a BSD-style license that can be |
3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
4 * | 4 * |
5 * Functions for generating and manipulating a verified boot kernel image. | 5 * Functions for generating and manipulating a verified boot kernel image. |
6 * (Userland portion) | 6 * (Userland portion) |
7 */ | 7 */ |
8 | 8 |
9 #include "kernel_image.h" | 9 #include "kernel_image.h" |
10 | 10 |
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 Free(header_blob); | 215 Free(header_blob); |
216 return NULL; | 216 return NULL; |
217 } | 217 } |
218 return header_blob; | 218 return header_blob; |
219 } | 219 } |
220 | 220 |
221 uint8_t* GetKernelPreambleBlob(const KernelImage* image) { | 221 uint8_t* GetKernelPreambleBlob(const KernelImage* image) { |
222 uint8_t* preamble_blob = NULL; | 222 uint8_t* preamble_blob = NULL; |
223 MemcpyState st; | 223 MemcpyState st; |
224 | 224 |
225 preamble_blob = (uint8_t*) Malloc(GetKernelPreambleLen()); | 225 preamble_blob = (uint8_t*) Malloc( |
226 st.remaining_len = GetKernelPreambleLen(); | 226 GetKernelPreambleLen(image->kernel_sign_algorithm)); |
| 227 st.remaining_len = GetKernelPreambleLen(image->kernel_sign_algorithm); |
227 st.remaining_buf = preamble_blob; | 228 st.remaining_buf = preamble_blob; |
228 st.overrun = 0; | 229 st.overrun = 0; |
229 | 230 |
230 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | 231 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
231 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); | 232 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); |
232 StatefulMemcpy_r(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset))
; | 233 StatefulMemcpy_r(&st, &image->bootloader_offset, FIELD_LEN(bootloader_offset))
; |
233 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); | 234 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); |
234 StatefulMemcpy_r(&st, &image->padded_header_size, | 235 StatefulMemcpy_r(&st, &image->padded_header_size, |
235 FIELD_LEN(padded_header_size)); | 236 FIELD_LEN(padded_header_size)); |
| 237 StatefulMemcpy_r(&st, image->kernel_signature, |
| 238 siglen_map[image->kernel_sign_algorithm]); |
236 | 239 |
237 if (st.overrun || st.remaining_len != 0) { /* Overrun or Underrun. */ | 240 if (st.overrun || st.remaining_len != 0) { /* Overrun or Underrun. */ |
238 Free(preamble_blob); | 241 Free(preamble_blob); |
239 return NULL; | 242 return NULL; |
240 } | 243 } |
241 return preamble_blob; | 244 return preamble_blob; |
242 } | 245 } |
243 | 246 |
244 uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { | 247 uint8_t* GetKernelBlob(const KernelImage* image, uint64_t* blob_len) { |
245 int kernel_key_signature_len; | 248 int kernel_key_signature_len; |
246 int kernel_signature_len; | 249 int kernel_signature_len; |
247 uint8_t* kernel_blob = NULL; | 250 uint8_t* kernel_blob = NULL; |
248 uint8_t* header_blob = NULL; | 251 uint8_t* header_blob = NULL; |
249 MemcpyState st; | 252 MemcpyState st; |
250 | 253 |
251 if (!image) | 254 if (!image) |
252 return NULL; | 255 return NULL; |
253 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; | 256 kernel_key_signature_len = siglen_map[image->firmware_sign_algorithm]; |
254 kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; | 257 kernel_signature_len = siglen_map[image->kernel_sign_algorithm]; |
255 *blob_len = (FIELD_LEN(magic) + | 258 *blob_len = (FIELD_LEN(magic) + |
256 GetKernelHeaderLen(image) + | 259 GetKernelHeaderLen(image) + |
257 kernel_key_signature_len + | 260 kernel_key_signature_len + |
258 GetKernelPreambleLen() + | 261 GetKernelPreambleLen(image->kernel_sign_algorithm) + |
259 2 * kernel_signature_len + | 262 kernel_signature_len + |
260 image->kernel_len); | 263 image->kernel_len); |
261 kernel_blob = (uint8_t*) Malloc(*blob_len); | 264 kernel_blob = (uint8_t*) Malloc(*blob_len); |
262 st.remaining_len = *blob_len; | 265 st.remaining_len = *blob_len; |
263 st.remaining_buf = kernel_blob; | 266 st.remaining_buf = kernel_blob; |
264 st.overrun = 0; | 267 st.overrun = 0; |
265 | 268 |
266 header_blob = GetKernelHeaderBlob(image); | 269 header_blob = GetKernelHeaderBlob(image); |
267 | 270 |
268 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); | 271 StatefulMemcpy_r(&st, image->magic, FIELD_LEN(magic)); |
269 StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); | 272 StatefulMemcpy_r(&st, header_blob, GetKernelHeaderLen(image)); |
270 StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); | 273 StatefulMemcpy_r(&st, image->kernel_key_signature, kernel_key_signature_len); |
271 /* Copy over kernel preamble blob (including signatures.) */ | 274 /* Copy over kernel preamble blob (including signatures.) */ |
272 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | 275 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
273 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); | 276 StatefulMemcpy_r(&st, &image->kernel_len, FIELD_LEN(kernel_len)); |
274 StatefulMemcpy_r(&st, &image->bootloader_offset, | 277 StatefulMemcpy_r(&st, &image->bootloader_offset, |
275 FIELD_LEN(bootloader_offset)); | 278 FIELD_LEN(bootloader_offset)); |
276 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); | 279 StatefulMemcpy_r(&st, &image->bootloader_size, FIELD_LEN(bootloader_size)); |
277 StatefulMemcpy_r(&st, &image->padded_header_size, | 280 StatefulMemcpy_r(&st, &image->padded_header_size, |
278 FIELD_LEN(padded_header_size)); | 281 FIELD_LEN(padded_header_size)); |
| 282 StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len); |
279 StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len); | 283 StatefulMemcpy_r(&st, image->preamble_signature, kernel_signature_len); |
280 StatefulMemcpy_r(&st, image->kernel_signature, kernel_signature_len); | |
281 StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len); | 284 StatefulMemcpy_r(&st, image->kernel_data, image->kernel_len); |
282 | 285 |
283 Free(header_blob); | 286 Free(header_blob); |
284 | 287 |
285 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */ | 288 if (st.overrun || st.remaining_len != 0) { /* Underrun or Overrun. */ |
| 289 debug("GetKernelBlob() failed.\n"); |
286 Free(kernel_blob); | 290 Free(kernel_blob); |
287 return NULL; | 291 return NULL; |
288 } | 292 } |
289 return kernel_blob; | 293 return kernel_blob; |
290 } | 294 } |
291 | 295 |
292 int WriteKernelImage(const char* input_file, | 296 int WriteKernelImage(const char* input_file, |
293 const KernelImage* image, | 297 const KernelImage* image, |
294 int is_only_vblock) { | 298 int is_only_vblock) { |
295 int fd; | 299 int fd; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 const KernelImage* image, | 368 const KernelImage* image, |
365 const int dev_mode) { | 369 const int dev_mode) { |
366 RSAPublicKey* kernel_sign_key = NULL; | 370 RSAPublicKey* kernel_sign_key = NULL; |
367 uint8_t* header_digest = NULL; | 371 uint8_t* header_digest = NULL; |
368 uint8_t* preamble_digest = NULL; | 372 uint8_t* preamble_digest = NULL; |
369 uint8_t* kernel_digest = NULL; | 373 uint8_t* kernel_digest = NULL; |
370 int kernel_sign_key_size; | 374 int kernel_sign_key_size; |
371 int kernel_signature_size; | 375 int kernel_signature_size; |
372 int error_code = 0; | 376 int error_code = 0; |
373 DigestContext ctx; | 377 DigestContext ctx; |
374 DigestContext kernel_ctx; | |
375 if (!image) | 378 if (!image) |
376 return VERIFY_KERNEL_INVALID_IMAGE; | 379 return VERIFY_KERNEL_INVALID_IMAGE; |
377 | 380 |
378 /* Verify kernel key signature on the key header if we | 381 /* Verify kernel key signature on the key header if we |
379 * are not in dev mode. | 382 * are not in dev mode. |
380 * | 383 * |
381 * TODO(gauravsh): Add additional sanity checks here for: | 384 * TODO(gauravsh): Add additional sanity checks here for: |
382 * 1) verifying the header length is correct. | 385 * 1) verifying the header length is correct. |
383 * 2) header_checksum is correct. | 386 * 2) header_checksum is correct. |
384 */ | 387 */ |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version, | 429 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version, |
427 FIELD_LEN(kernel_version)); | 430 FIELD_LEN(kernel_version)); |
428 DigestUpdate(&ctx, (uint8_t*) &image->kernel_len, | 431 DigestUpdate(&ctx, (uint8_t*) &image->kernel_len, |
429 FIELD_LEN(kernel_len)); | 432 FIELD_LEN(kernel_len)); |
430 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_offset, | 433 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_offset, |
431 FIELD_LEN(bootloader_offset)); | 434 FIELD_LEN(bootloader_offset)); |
432 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_size, | 435 DigestUpdate(&ctx, (uint8_t*) &image->bootloader_size, |
433 FIELD_LEN(bootloader_size)); | 436 FIELD_LEN(bootloader_size)); |
434 DigestUpdate(&ctx, (uint8_t*) &image->padded_header_size, | 437 DigestUpdate(&ctx, (uint8_t*) &image->padded_header_size, |
435 FIELD_LEN(padded_header_size)); | 438 FIELD_LEN(padded_header_size)); |
| 439 DigestUpdate(&ctx, (uint8_t*) image->kernel_signature, |
| 440 kernel_signature_size); |
436 preamble_digest = DigestFinal(&ctx); | 441 preamble_digest = DigestFinal(&ctx); |
437 if (!RSAVerify(kernel_sign_key, image->preamble_signature, | 442 if (!RSAVerify(kernel_sign_key, image->preamble_signature, |
438 kernel_signature_size, image->kernel_sign_algorithm, | 443 kernel_signature_size, image->kernel_sign_algorithm, |
439 preamble_digest)) { | 444 preamble_digest)) { |
440 error_code = VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; | 445 error_code = VERIFY_KERNEL_PREAMBLE_SIGNATURE_FAILED; |
441 goto verify_failure; | 446 goto verify_failure; |
442 } | 447 } |
443 | 448 |
444 /* Verify kernel signature - kernel signature is computed on the contents | 449 /* Verify kernel signature - kernel signature is computed on the contents |
445 of kernel version + kernel options + kernel_data. */ | 450 * of kernel_data. |
446 DigestInit(&kernel_ctx, image->kernel_sign_algorithm); | 451 * Association between the kernel_data and preamble is maintained by making |
447 DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_version, | 452 * the kernel signature a part of the preamble and verifying it as part |
448 FIELD_LEN(kernel_version)); | 453 * of preamble signature checking. */ |
449 DigestUpdate(&kernel_ctx, (uint8_t*) &image->kernel_len, | 454 |
450 FIELD_LEN(kernel_len)); | 455 kernel_digest = DigestBuf(image->kernel_data, |
451 DigestUpdate(&kernel_ctx, (uint8_t*) &image->bootloader_offset, | 456 image->kernel_len, |
452 FIELD_LEN(bootloader_offset)); | 457 image->kernel_sign_algorithm); |
453 DigestUpdate(&kernel_ctx, (uint8_t*) &image->bootloader_size, | |
454 FIELD_LEN(bootloader_size)); | |
455 DigestUpdate(&kernel_ctx, (uint8_t*) &image->padded_header_size, | |
456 FIELD_LEN(padded_header_size)); | |
457 DigestUpdate(&kernel_ctx, (uint8_t*) image->kernel_data, | |
458 image->kernel_len); | |
459 kernel_digest = DigestFinal(&kernel_ctx); | |
460 if (!RSAVerify(kernel_sign_key, image->kernel_signature, | 458 if (!RSAVerify(kernel_sign_key, image->kernel_signature, |
461 kernel_signature_size, image->kernel_sign_algorithm, | 459 kernel_signature_size, image->kernel_sign_algorithm, |
462 kernel_digest)) { | 460 kernel_digest)) { |
463 error_code = VERIFY_KERNEL_SIGNATURE_FAILED; | 461 error_code = VERIFY_KERNEL_SIGNATURE_FAILED; |
464 goto verify_failure; | 462 goto verify_failure; |
465 } | 463 } |
466 | 464 |
467 verify_failure: | 465 verify_failure: |
468 RSAPublicKeyFree(kernel_sign_key); | 466 RSAPublicKeyFree(kernel_sign_key); |
469 Free(kernel_digest); | 467 Free(kernel_digest); |
(...skipping 28 matching lines...) Expand all Loading... |
498 Free(header_blob); | 496 Free(header_blob); |
499 return 1; | 497 return 1; |
500 } | 498 } |
501 | 499 |
502 int AddKernelSignature(KernelImage* image, | 500 int AddKernelSignature(KernelImage* image, |
503 const char* kernel_signing_key_file) { | 501 const char* kernel_signing_key_file) { |
504 uint8_t* preamble_blob = NULL; | 502 uint8_t* preamble_blob = NULL; |
505 uint8_t* preamble_signature = NULL; | 503 uint8_t* preamble_signature = NULL; |
506 uint8_t* kernel_signature = NULL; | 504 uint8_t* kernel_signature = NULL; |
507 uint8_t* kernel_buf; | 505 uint8_t* kernel_buf; |
508 int signature_len = siglen_map[image->kernel_sign_algorithm]; | 506 int algorithm = image->kernel_sign_algorithm; |
| 507 int signature_len = siglen_map[algorithm]; |
509 | 508 |
510 preamble_blob = GetKernelPreambleBlob(image); | 509 /* Kernel signature must be calculated first as its used for computing the |
511 if (!(preamble_signature = SignatureBuf(preamble_blob, | 510 * preamble signature. */ |
512 GetKernelPreambleLen(), | 511 kernel_buf = (uint8_t*) Malloc(image->kernel_len); |
513 kernel_signing_key_file, | 512 Memcpy(kernel_buf, image->kernel_data, image->kernel_len); |
514 image->kernel_sign_algorithm))) { | |
515 debug("Could not compute signature on the kernel preamble.\n"); | |
516 Free(preamble_blob); | |
517 return 0; | |
518 } | |
519 | |
520 image->preamble_signature = (uint8_t*) Malloc(signature_len); | |
521 Memcpy(image->preamble_signature, preamble_signature, signature_len); | |
522 Free(preamble_signature); | |
523 /* Kernel signature muse be calculated on the kernel version, options and | |
524 * kernel data to avoid splicing attacks. */ | |
525 kernel_buf = (uint8_t*) Malloc(GetKernelPreambleLen() + | |
526 image->kernel_len); | |
527 Memcpy(kernel_buf, preamble_blob, GetKernelPreambleLen()); | |
528 Memcpy(kernel_buf + GetKernelPreambleLen(), image->kernel_data, | |
529 image->kernel_len); | |
530 if (!(kernel_signature = SignatureBuf(kernel_buf, | 513 if (!(kernel_signature = SignatureBuf(kernel_buf, |
531 GetKernelPreambleLen() + | |
532 image->kernel_len, | 514 image->kernel_len, |
533 kernel_signing_key_file, | 515 kernel_signing_key_file, |
534 image->kernel_sign_algorithm))) { | 516 algorithm))) { |
535 Free(preamble_blob); | 517 Free(preamble_blob); |
536 Free(kernel_buf); | 518 Free(kernel_buf); |
537 debug("Could not compute signature on the kernel.\n"); | 519 debug("Could not compute signature on the kernel.\n"); |
538 return 0; | 520 return 0; |
539 } | 521 } |
540 image->kernel_signature = (uint8_t*) Malloc(signature_len); | 522 image->kernel_signature = (uint8_t*) Malloc(signature_len); |
541 Memcpy(image->kernel_signature, kernel_signature, signature_len); | 523 Memcpy(image->kernel_signature, kernel_signature, signature_len); |
| 524 |
| 525 |
| 526 preamble_blob = GetKernelPreambleBlob(image); |
| 527 if (!(preamble_signature = SignatureBuf(preamble_blob, |
| 528 GetKernelPreambleLen(algorithm), |
| 529 kernel_signing_key_file, |
| 530 algorithm))) { |
| 531 debug("Could not compute signature on the kernel preamble.\n"); |
| 532 Free(preamble_blob); |
| 533 return 0; |
| 534 } |
| 535 image->preamble_signature = (uint8_t*) Malloc(signature_len); |
| 536 Memcpy(image->preamble_signature, preamble_signature, signature_len); |
| 537 |
| 538 Free(preamble_signature); |
| 539 Free(preamble_blob); |
542 Free(kernel_signature); | 540 Free(kernel_signature); |
543 Free(kernel_buf); | 541 Free(kernel_buf); |
544 Free(preamble_blob); | |
545 return 1; | 542 return 1; |
546 } | 543 } |
547 | 544 |
548 void PrintKernelEntry(kernel_entry* entry) { | 545 void PrintKernelEntry(kernel_entry* entry) { |
549 debug("Boot Priority = %d\n", entry->boot_priority); | 546 debug("Boot Priority = %d\n", entry->boot_priority); |
550 debug("Boot Tries Remaining = %d\n", entry->boot_tries_remaining); | 547 debug("Boot Tries Remaining = %d\n", entry->boot_tries_remaining); |
551 debug("Boot Success Flag = %d\n", entry->boot_success_flag); | 548 debug("Boot Success Flag = %d\n", entry->boot_success_flag); |
552 } | 549 } |
OLD | NEW |