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 */ | 6 */ |
7 | 7 |
8 #include "kernel_image.h" | 8 #include "kernel_image.h" |
9 | 9 |
10 #include <fcntl.h> | 10 #include <fcntl.h> |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); | 125 StatefulMemcpy(&st, image->header_checksum, FIELD_LEN(header_checksum)); |
126 | 126 |
127 /* Read key signature. */ | 127 /* Read key signature. */ |
128 image->kernel_key_signature = (uint8_t*) Malloc(kernel_key_signature_len); | 128 image->kernel_key_signature = (uint8_t*) Malloc(kernel_key_signature_len); |
129 StatefulMemcpy(&st, image->kernel_key_signature, | 129 StatefulMemcpy(&st, image->kernel_key_signature, |
130 kernel_key_signature_len); | 130 kernel_key_signature_len); |
131 | 131 |
132 /* Read the kernel config. */ | 132 /* Read the kernel config. */ |
133 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | 133 StatefulMemcpy(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
134 StatefulMemcpy(&st, &image->options.version, FIELD_LEN(options.version)); | 134 StatefulMemcpy(&st, &image->options.version, FIELD_LEN(options.version)); |
| 135 StatefulMemcpy(&st, &image->options.cmd_line, FIELD_LEN(options.cmd_line)); |
135 StatefulMemcpy(&st, &image->options.kernel_len, | 136 StatefulMemcpy(&st, &image->options.kernel_len, |
136 FIELD_LEN(options.kernel_len)); | 137 FIELD_LEN(options.kernel_len)); |
137 StatefulMemcpy(&st, &image->options.kernel_load_addr, | 138 StatefulMemcpy(&st, &image->options.kernel_load_addr, |
138 FIELD_LEN(options.kernel_load_addr)); | 139 FIELD_LEN(options.kernel_load_addr)); |
139 StatefulMemcpy(&st, &image->options.kernel_entry_addr, | 140 StatefulMemcpy(&st, &image->options.kernel_entry_addr, |
140 FIELD_LEN(options.kernel_entry_addr)); | 141 FIELD_LEN(options.kernel_entry_addr)); |
141 | 142 |
142 /* Read kernel config signature. */ | 143 /* Read kernel config signature. */ |
143 image->config_signature = (uint8_t*) Malloc(kernel_signature_len); | 144 image->config_signature = (uint8_t*) Malloc(kernel_signature_len); |
144 StatefulMemcpy(&st, image->config_signature, kernel_signature_len); | 145 StatefulMemcpy(&st, image->config_signature, kernel_signature_len); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum)); | 187 StatefulMemcpy_r(&st, &image->header_checksum, FIELD_LEN(header_checksum)); |
187 | 188 |
188 if (st.remaining_len != 0) { /* Underrun or Overrun. */ | 189 if (st.remaining_len != 0) { /* Underrun or Overrun. */ |
189 Free(header_blob); | 190 Free(header_blob); |
190 return NULL; | 191 return NULL; |
191 } | 192 } |
192 return header_blob; | 193 return header_blob; |
193 } | 194 } |
194 | 195 |
195 int GetKernelConfigLen(const KernelImage* image) { | 196 int GetKernelConfigLen(const KernelImage* image) { |
196 return (FIELD_LEN(kernel_version) + FIELD_LEN(options.version) + | 197 return (FIELD_LEN(kernel_version) + |
| 198 FIELD_LEN(options.version) + FIELD_LEN(options.cmd_line) + |
197 FIELD_LEN(options.kernel_len) + FIELD_LEN(options.kernel_load_addr) + | 199 FIELD_LEN(options.kernel_len) + FIELD_LEN(options.kernel_load_addr) + |
198 FIELD_LEN(options.kernel_entry_addr)); | 200 FIELD_LEN(options.kernel_entry_addr)); |
199 } | 201 } |
200 | 202 |
201 uint8_t* GetKernelConfigBlob(const KernelImage* image) { | 203 uint8_t* GetKernelConfigBlob(const KernelImage* image) { |
202 uint8_t* config_blob = NULL; | 204 uint8_t* config_blob = NULL; |
203 MemcpyState st; | 205 MemcpyState st; |
204 | 206 |
205 config_blob = (uint8_t*) Malloc(GetKernelConfigLen(image)); | 207 config_blob = (uint8_t*) Malloc(GetKernelConfigLen(image)); |
206 st.remaining_len = GetKernelConfigLen(image); | 208 st.remaining_len = GetKernelConfigLen(image); |
207 st.remaining_buf = config_blob; | 209 st.remaining_buf = config_blob; |
208 | 210 |
209 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); | 211 StatefulMemcpy_r(&st, &image->kernel_version, FIELD_LEN(kernel_version)); |
210 StatefulMemcpy_r(&st, image->options.version, FIELD_LEN(options.version)); | 212 StatefulMemcpy_r(&st, image->options.version, FIELD_LEN(options.version)); |
| 213 StatefulMemcpy_r(&st, image->options.cmd_line, FIELD_LEN(options.cmd_line)); |
211 StatefulMemcpy_r(&st, &image->options.kernel_len, | 214 StatefulMemcpy_r(&st, &image->options.kernel_len, |
212 FIELD_LEN(options.kernel_len)); | 215 FIELD_LEN(options.kernel_len)); |
213 StatefulMemcpy_r(&st, &image->options.kernel_load_addr, | 216 StatefulMemcpy_r(&st, &image->options.kernel_load_addr, |
214 FIELD_LEN(options.kernel_load_addr)); | 217 FIELD_LEN(options.kernel_load_addr)); |
215 StatefulMemcpy_r(&st, &image->options.kernel_entry_addr, | 218 StatefulMemcpy_r(&st, &image->options.kernel_entry_addr, |
216 FIELD_LEN(options.kernel_entry_addr)); | 219 FIELD_LEN(options.kernel_entry_addr)); |
217 if (st.remaining_len != 0) { /* Overrun or Underrun. */ | 220 if (st.remaining_len != 0) { /* Overrun or Underrun. */ |
218 Free(config_blob); | 221 Free(config_blob); |
219 return NULL; | 222 return NULL; |
220 } | 223 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 "Kernel Key Version = %d\n\n", | 310 "Kernel Key Version = %d\n\n", |
308 image->header_len, | 311 image->header_len, |
309 image->firmware_sign_algorithm, | 312 image->firmware_sign_algorithm, |
310 image->kernel_sign_algorithm, | 313 image->kernel_sign_algorithm, |
311 algo_strings[image->kernel_sign_algorithm], | 314 algo_strings[image->kernel_sign_algorithm], |
312 image->kernel_key_version); | 315 image->kernel_key_version); |
313 /* TODO(gauravsh): Output hash and key signature here? */ | 316 /* TODO(gauravsh): Output hash and key signature here? */ |
314 /* Print preamble. */ | 317 /* Print preamble. */ |
315 printf("Kernel Version = %d\n" | 318 printf("Kernel Version = %d\n" |
316 "Kernel Config Version = %d.%d\n" | 319 "Kernel Config Version = %d.%d\n" |
| 320 "Kernel Config command line = %s\n" |
317 "kernel Length = %" PRId64 "\n" | 321 "kernel Length = %" PRId64 "\n" |
318 "Kernel Load Address = %" PRId64 "\n" | 322 "Kernel Load Address = %" PRId64 "\n" |
319 "Kernel Entry Address = %" PRId64 "\n\n", | 323 "Kernel Entry Address = %" PRId64 "\n\n", |
320 image->kernel_version, | 324 image->kernel_version, |
321 image->options.version[0], image->options.version[1], | 325 image->options.version[0], image->options.version[1], |
| 326 image->options.cmd_line, |
322 image->options.kernel_len, | 327 image->options.kernel_len, |
323 image->options.kernel_load_addr, | 328 image->options.kernel_load_addr, |
324 image->options.kernel_entry_addr); | 329 image->options.kernel_entry_addr); |
325 /* TODO(gauravsh): Output kernel signature here? */ | 330 /* TODO(gauravsh): Output kernel signature here? */ |
326 } | 331 } |
327 | 332 |
328 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { | 333 char* kVerifyKernelErrors[VERIFY_KERNEL_MAX] = { |
329 "Success.", | 334 "Success.", |
330 "Invalid Image.", | 335 "Invalid Image.", |
331 "Kernel Key Signature Failed.", | 336 "Kernel Key Signature Failed.", |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
413 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; | 418 return VERIFY_KERNEL_KEY_SIGNATURE_FAILED; |
414 } | 419 } |
415 return 0; | 420 return 0; |
416 } | 421 } |
417 | 422 |
418 int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, | 423 int VerifyKernelConfig(RSAPublicKey* kernel_sign_key, |
419 const uint8_t* config_blob, | 424 const uint8_t* config_blob, |
420 int algorithm, | 425 int algorithm, |
421 int* kernel_len) { | 426 int* kernel_len) { |
422 uint32_t len, config_len; | 427 uint32_t len, config_len; |
423 config_len = (FIELD_LEN(kernel_version) + | 428 config_len = GetKernelConfigLen(NULL); |
424 FIELD_LEN(options.version)+ | |
425 FIELD_LEN(options.kernel_len) + | |
426 FIELD_LEN(options.kernel_load_addr) + | |
427 FIELD_LEN(options.kernel_entry_addr)); | |
428 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ | 429 if (!RSAVerifyBinary_f(NULL, kernel_sign_key, /* Key to use */ |
429 config_blob, /* Data to verify */ | 430 config_blob, /* Data to verify */ |
430 config_len, /* Length of data */ | 431 config_len, /* Length of data */ |
431 config_blob + config_len, /* Expected Signature */ | 432 config_blob + config_len, /* Expected Signature */ |
432 algorithm)) | 433 algorithm)) |
433 return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; | 434 return VERIFY_KERNEL_CONFIG_SIGNATURE_FAILED; |
434 | 435 |
435 Memcpy(&len, config_blob + (FIELD_LEN(kernel_version)+ | 436 Memcpy(&len, |
436 FIELD_LEN(options.version)), | 437 config_blob + (FIELD_LEN(kernel_version) + FIELD_LEN(options.version) + |
| 438 FIELD_LEN(options.cmd_line)), |
437 sizeof(len)); | 439 sizeof(len)); |
438 *kernel_len = (int) len; | 440 *kernel_len = (int) len; |
439 return 0; | 441 return 0; |
440 } | 442 } |
441 | 443 |
442 int VerifyKernelData(RSAPublicKey* kernel_sign_key, | 444 int VerifyKernelData(RSAPublicKey* kernel_sign_key, |
443 const uint8_t* kernel_data_start, | 445 const uint8_t* kernel_data_start, |
444 int kernel_len, | 446 int kernel_len, |
445 int algorithm) { | 447 int algorithm) { |
446 int signature_len = siglen_map[algorithm]; | 448 int signature_len = siglen_map[algorithm]; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 /* Only continue if config verification succeeds. */ | 501 /* Only continue if config verification succeeds. */ |
500 config_ptr = (header_ptr + header_len + kernel_key_signature_len); | 502 config_ptr = (header_ptr + header_len + kernel_key_signature_len); |
501 if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr, | 503 if ((error_code = VerifyKernelConfig(kernel_sign_key, config_ptr, |
502 kernel_sign_algorithm, | 504 kernel_sign_algorithm, |
503 &kernel_len))) { | 505 &kernel_len))) { |
504 RSAPublicKeyFree(kernel_sign_key); | 506 RSAPublicKeyFree(kernel_sign_key); |
505 return error_code; /* AKA jump to recovery. */ | 507 return error_code; /* AKA jump to recovery. */ |
506 } | 508 } |
507 /* Only continue if kernel data verification succeeds. */ | 509 /* Only continue if kernel data verification succeeds. */ |
508 kernel_ptr = (config_ptr + | 510 kernel_ptr = (config_ptr + |
509 FIELD_LEN(kernel_version) + | 511 GetKernelConfigLen(NULL) + /* Skip config block/signature. */ |
510 FIELD_LEN(options.version) + | |
511 FIELD_LEN(options.kernel_len) + | |
512 FIELD_LEN(options.kernel_entry_addr) + | |
513 FIELD_LEN(options.kernel_load_addr) + | |
514 kernel_signature_len); | 512 kernel_signature_len); |
515 | 513 |
516 if ((error_code = VerifyKernelData(kernel_sign_key, kernel_ptr, kernel_len, | 514 if ((error_code = VerifyKernelData(kernel_sign_key, kernel_ptr, kernel_len, |
517 kernel_sign_algorithm))) { | 515 kernel_sign_algorithm))) { |
518 RSAPublicKeyFree(kernel_sign_key); | 516 RSAPublicKeyFree(kernel_sign_key); |
519 return error_code; /* AKA jump to recovery. */ | 517 return error_code; /* AKA jump to recovery. */ |
520 } | 518 } |
521 RSAPublicKeyFree(kernel_sign_key); | 519 RSAPublicKeyFree(kernel_sign_key); |
522 return 0; /* Success! */ | 520 return 0; /* Success! */ |
523 } | 521 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 /* Get kernel signing key to verify the rest of the kernel. */ | 578 /* Get kernel signing key to verify the rest of the kernel. */ |
581 kernel_sign_key_size = RSAProcessedKeySize(image->kernel_sign_algorithm); | 579 kernel_sign_key_size = RSAProcessedKeySize(image->kernel_sign_algorithm); |
582 kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, | 580 kernel_sign_key = RSAPublicKeyFromBuf(image->kernel_sign_key, |
583 kernel_sign_key_size); | 581 kernel_sign_key_size); |
584 kernel_signature_size = siglen_map[image->kernel_sign_algorithm]; | 582 kernel_signature_size = siglen_map[image->kernel_sign_algorithm]; |
585 | 583 |
586 /* Verify kernel config signature. */ | 584 /* Verify kernel config signature. */ |
587 DigestInit(&ctx, image->kernel_sign_algorithm); | 585 DigestInit(&ctx, image->kernel_sign_algorithm); |
588 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version, | 586 DigestUpdate(&ctx, (uint8_t*) &image->kernel_version, |
589 FIELD_LEN(kernel_version)); | 587 FIELD_LEN(kernel_version)); |
590 DigestUpdate(&ctx, (uint8_t*) &image->options.version, | 588 DigestUpdate(&ctx, (uint8_t*) image->options.version, |
591 FIELD_LEN(options.version)); | 589 FIELD_LEN(options.version)); |
| 590 DigestUpdate(&ctx, (uint8_t*) image->options.cmd_line, |
| 591 FIELD_LEN(options.cmd_line)); |
592 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_len, | 592 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_len, |
593 FIELD_LEN(options.kernel_len)); | 593 FIELD_LEN(options.kernel_len)); |
594 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_load_addr, | 594 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_load_addr, |
595 FIELD_LEN(options.kernel_load_addr)); | 595 FIELD_LEN(options.kernel_load_addr)); |
596 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr, | 596 DigestUpdate(&ctx, (uint8_t*) &image->options.kernel_entry_addr, |
597 FIELD_LEN(options.kernel_entry_addr)); | 597 FIELD_LEN(options.kernel_entry_addr)); |
598 config_digest = DigestFinal(&ctx); | 598 config_digest = DigestFinal(&ctx); |
599 if (!RSAVerify(kernel_sign_key, image->config_signature, | 599 if (!RSAVerify(kernel_sign_key, image->config_signature, |
600 kernel_signature_size, image->kernel_sign_algorithm, | 600 kernel_signature_size, image->kernel_sign_algorithm, |
601 config_digest)) { | 601 config_digest)) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 kernel_signing_key_file, | 676 kernel_signing_key_file, |
677 image->kernel_sign_algorithm))) { | 677 image->kernel_sign_algorithm))) { |
678 fprintf(stderr, "Could not compute signature on the kernel.\n"); | 678 fprintf(stderr, "Could not compute signature on the kernel.\n"); |
679 return 0; | 679 return 0; |
680 } | 680 } |
681 image->kernel_signature = (uint8_t*) Malloc(signature_len); | 681 image->kernel_signature = (uint8_t*) Malloc(signature_len); |
682 Memcpy(image->kernel_signature, kernel_signature, signature_len); | 682 Memcpy(image->kernel_signature, kernel_signature, signature_len); |
683 Free(kernel_signature); | 683 Free(kernel_signature); |
684 return 1; | 684 return 1; |
685 } | 685 } |
OLD | NEW |