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 verifying a verified boot kernel image. | 5 * Functions for verifying a verified boot kernel image. |
6 * (Firmware portion) | 6 * (Firmware portion) |
7 */ | 7 */ |
8 | 8 |
9 #include "kernel_image_fw.h" | 9 #include "kernel_image_fw.h" |
10 | 10 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 /* Contains the logical kernel version (32-bit) which is calculated as | 359 /* Contains the logical kernel version (32-bit) which is calculated as |
360 * (kernel_key_version << 16 | kernel_version) where | 360 * (kernel_key_version << 16 | kernel_version) where |
361 * [kernel_key_version], [firmware_version] are both 16-bit. | 361 * [kernel_key_version], [firmware_version] are both 16-bit. |
362 */ | 362 */ |
363 uint32_t kernelA_lversion, kernelB_lversion; | 363 uint32_t kernelA_lversion, kernelB_lversion; |
364 uint32_t min_lversion; /* Minimum of kernel A and kernel B lversion. */ | 364 uint32_t min_lversion; /* Minimum of kernel A and kernel B lversion. */ |
365 uint32_t stored_lversion; /* Stored logical version in the TPM. */ | 365 uint32_t stored_lversion; /* Stored logical version in the TPM. */ |
366 kernel_entry* try_kernel[2]; /* Kernel in try order. */ | 366 kernel_entry* try_kernel[2]; /* Kernel in try order. */ |
367 int try_kernel_which[2]; /* Which corresponding kernel in the try order */ | 367 int try_kernel_which[2]; /* Which corresponding kernel in the try order */ |
368 uint32_t try_kernel_lversion[2]; /* Their logical versions. */ | 368 uint32_t try_kernel_lversion[2]; /* Their logical versions. */ |
| 369 uint16_t kernel_version, kernel_key_version; /* Temporary variables */ |
369 | 370 |
370 /* [kernel_to_boot] will eventually contain the boot path to follow | 371 /* [kernel_to_boot] will eventually contain the boot path to follow |
371 * and is returned to the caller. Initially, we set it to recovery. If | 372 * and is returned to the caller. Initially, we set it to recovery. If |
372 * a valid bootable kernel is found, it will be set to that. */ | 373 * a valid bootable kernel is found, it will be set to that. */ |
373 int kernel_to_boot = BOOT_KERNEL_RECOVERY_CONTINUE; | 374 int kernel_to_boot = BOOT_KERNEL_RECOVERY_CONTINUE; |
374 | 375 |
375 | 376 |
376 /* The TPM must already have be initialized, so no need to call SetupTPM(). */ | 377 /* The TPM must already have be initialized, so no need to call SetupTPM(). */ |
377 | 378 |
378 /* We get the key versions by reading directly from the image blobs without | 379 /* We get the key versions by reading directly from the image blobs without |
379 * any additional (expensive) sanity checking on the blob since it's faster to | 380 * any additional (expensive) sanity checking on the blob since it's faster to |
380 * outright reject a kernel with an older kernel key version. A malformed | 381 * outright reject a kernel with an older kernel key version. A malformed |
381 * or corrupted kernel blob will still fail when VerifyKernel() is called | 382 * or corrupted kernel blob will still fail when VerifyKernel() is called |
382 * on it. | 383 * on it. |
383 */ | 384 */ |
384 kernelA_lversion = GetLogicalKernelVersion(kernelA->kernel_blob); | 385 kernelA_lversion = GetLogicalKernelVersion(kernelA->kernel_blob); |
385 kernelB_lversion = GetLogicalKernelVersion(kernelB->kernel_blob); | 386 kernelB_lversion = GetLogicalKernelVersion(kernelB->kernel_blob); |
386 min_lversion = Min(kernelA_lversion, kernelB_lversion); | 387 min_lversion = Min(kernelA_lversion, kernelB_lversion); |
387 stored_lversion = CombineUint16Pair(GetStoredVersion(KERNEL_KEY_VERSION), | 388 GetStoredVersions(KERNEL_VERSIONS, &kernel_key_version, &kernel_version); |
388 GetStoredVersion(KERNEL_VERSION)); | 389 stored_lversion = CombineUint16Pair(kernel_key_version, kernel_version); |
389 | 390 |
390 /* TODO(gauravsh): The kernel entries kernelA and kernelB come from the | 391 /* TODO(gauravsh): The kernel entries kernelA and kernelB come from the |
391 * partition table - verify its signature/checksum before proceeding | 392 * partition table - verify its signature/checksum before proceeding |
392 * further. */ | 393 * further. */ |
393 | 394 |
394 /* The logic for deciding which kernel to boot from is taken from the | 395 /* The logic for deciding which kernel to boot from is taken from the |
395 * the Chromium OS Drive Map design document. | 396 * the Chromium OS Drive Map design document. |
396 * | 397 * |
397 * We went to consider the kernels in their according to their boot | 398 * We went to consider the kernels in their according to their boot |
398 * priority attribute value. | 399 * priority attribute value. |
(...skipping 27 matching lines...) Expand all Loading... |
426 if (try_kernel[i]->boot_tries_remaining > 0) | 427 if (try_kernel[i]->boot_tries_remaining > 0) |
427 try_kernel[i]->boot_tries_remaining--; | 428 try_kernel[i]->boot_tries_remaining--; |
428 if (stored_lversion > try_kernel_lversion[i]) | 429 if (stored_lversion > try_kernel_lversion[i]) |
429 continue; /* Rollback: I am afraid I can't let you do that Dave. */ | 430 continue; /* Rollback: I am afraid I can't let you do that Dave. */ |
430 if (i == 0 && (stored_lversion < try_kernel_lversion[1])) { | 431 if (i == 0 && (stored_lversion < try_kernel_lversion[1])) { |
431 /* The higher priority kernel is valid and bootable, See if we | 432 /* The higher priority kernel is valid and bootable, See if we |
432 * need to update the stored version for rollback prevention. */ | 433 * need to update the stored version for rollback prevention. */ |
433 if (VERIFY_KERNEL_SUCCESS == VerifyKernel(firmware_key_blob, | 434 if (VERIFY_KERNEL_SUCCESS == VerifyKernel(firmware_key_blob, |
434 try_kernel[1]->kernel_blob, | 435 try_kernel[1]->kernel_blob, |
435 dev_mode)) { | 436 dev_mode)) { |
436 WriteStoredVersion(KERNEL_KEY_VERSION, | 437 WriteStoredVersions(KERNEL_VERSIONS, |
437 (uint16_t) (min_lversion >> 16)); | 438 (uint16_t) (min_lversion >> 16), |
438 WriteStoredVersion(KERNEL_VERSION, | 439 (uint16_t) (min_lversion & 0xFFFF)); |
439 (uint16_t) (min_lversion & 0xFFFF)); | |
440 stored_lversion = min_lversion; /* Update stored version as it's | 440 stored_lversion = min_lversion; /* Update stored version as it's |
441 * used later. */ | 441 * used later. */ |
442 } | 442 } |
443 } | 443 } |
444 kernel_to_boot = try_kernel_which[i]; | 444 kernel_to_boot = try_kernel_which[i]; |
445 break; /* We found a valid kernel. */ | 445 break; /* We found a valid kernel. */ |
446 } | 446 } |
447 try_kernel[i]->boot_priority = 0; | 447 try_kernel[i]->boot_priority = 0; |
448 } /* for loop. */ | 448 } /* for loop. */ |
449 | 449 |
450 /* Lock Kernel TPM rollback indices from further writes. In this design, | 450 /* Lock Kernel TPM rollback indices from further writes. In this design, |
451 * this is tied to locking physical presence---so (software) physical | 451 * this is tied to locking physical presence---so (software) physical |
452 * presence cannot be asserted after this point. This is a big side effect, | 452 * presence cannot be asserted after this point. This is a big side effect, |
453 * so we want to make it clear in the function name. | 453 * so we want to make it clear in the function name. |
454 * TODO(gauravsh): figure out better abstractions. | 454 * TODO(gauravsh): figure out better abstractions. |
455 */ | 455 */ |
456 LockKernelVersionsByLockingPP(); | 456 LockKernelVersionsByLockingPP(); |
457 return kernel_to_boot; | 457 return kernel_to_boot; |
458 } | 458 } |
OLD | NEW |