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