| 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 |