diff options
Diffstat (limited to 'firmware/lib')
-rw-r--r-- | firmware/lib/include/load_firmware_fw.h | 29 | ||||
-rw-r--r-- | firmware/lib/include/rollback_index.h | 66 | ||||
-rw-r--r-- | firmware/lib/include/tpm_bootmode.h | 29 | ||||
-rw-r--r-- | firmware/lib/include/vboot_kernel.h | 1 | ||||
-rw-r--r-- | firmware/lib/mocked_rollback_index.c | 48 | ||||
-rw-r--r-- | firmware/lib/mocked_tpm_bootmode.c | 69 | ||||
-rw-r--r-- | firmware/lib/rollback_index.c | 381 | ||||
-rw-r--r-- | firmware/lib/tpm_bootmode.c | 169 | ||||
-rw-r--r-- | firmware/lib/vboot_api_firmware.c | 146 | ||||
-rw-r--r-- | firmware/lib/vboot_api_init.c | 378 | ||||
-rw-r--r-- | firmware/lib/vboot_firmware.c | 368 | ||||
-rw-r--r-- | firmware/lib/vboot_nvstorage_rollback.c | 95 |
12 files changed, 1 insertions, 1778 deletions
diff --git a/firmware/lib/include/load_firmware_fw.h b/firmware/lib/include/load_firmware_fw.h deleted file mode 100644 index 555cf6fd..00000000 --- a/firmware/lib/include/load_firmware_fw.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware API for loading and verifying rewritable firmware. - * (Firmware Portion) - */ - -#ifndef VBOOT_REFERENCE_LOAD_FIRMWARE_FW_H_ -#define VBOOT_REFERENCE_LOAD_FIRMWARE_FW_H_ - -#include "vboot_api.h" -#include "vboot_nvstorage.h" -#include "vboot_struct.h" - -/** - * Load the rewritable firmware. - * - * Pass the common and firmware params from VbSelectFirmware(), and a - * VbNvContext. Caller is responsible for calling VbNvSetup() and - * VbNvTeardown() on the VbNvContext. - * - * Returns VBERROR_SUCCESS if successful. If unsuccessful, sets a recovery - * reason via VbNvStorage and returns an error code. - */ -int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, - VbNvContext *vnc); - -#endif /* VBOOT_REFERENCE_LOAD_FIRMWARE_FW_H_ */ diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h index 6cc9ee61..22a753a9 100644 --- a/firmware/lib/include/rollback_index.h +++ b/firmware/lib/include/rollback_index.h @@ -103,37 +103,6 @@ enum fwmp_flags { /* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */ /* - * These functions are called from VbInit(). They cannot use global - * variables. - */ - -uint32_t RollbackS3Resume(void); - -/* - * These functions are callable from VbSelectFirmware(). They cannot use - * global variables. - */ - -/** - * This must be called. - */ -uint32_t RollbackFirmwareSetup(int is_hw_dev, - int disable_dev_request, - int clear_tpm_owner_request, - /* two outputs on success */ - int *is_virt_dev, uint32_t *tpm_version); - -/** - * Write may be called if the versions change. - */ -uint32_t RollbackFirmwareWrite(uint32_t version); - -/** - * Lock must be called. - */ -uint32_t RollbackFirmwareLock(void); - -/* * These functions are callable from VbSelectAndLoadKernel(). They may use * global variables. */ @@ -149,16 +118,6 @@ uint32_t RollbackKernelRead(uint32_t *version); uint32_t RollbackKernelWrite(uint32_t version); /** - * Read backup data. - */ -uint32_t RollbackBackupRead(uint8_t *raw); - -/** - * Write backup data. - */ -uint32_t RollbackBackupWrite(uint8_t *raw); - -/** * Lock must be called. Internally, it's ignored in recovery mode. */ uint32_t RollbackKernelLock(int recovery_mode); @@ -193,31 +152,6 @@ uint32_t TPMClearAndReenable(void); uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length); /** - * Similarly to SafeWrite(), this ensures we don't fail a DefineSpace because - * we hit the TPM write limit. This is even less likely to happen than with - * writes because we only define spaces once at initialization, but we'd rather - * be paranoid about this. - */ -uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size); - -/** - * Perform one-time initializations. - * - * Create the NVRAM spaces, and set their initial values as needed. Sets the - * nvLocked bit and ensures the physical presence command is enabled and - * locked. - */ -uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf, - RollbackSpaceKernel *rsk); - -/** - * Start the TPM and establish the root of trust for the anti-rollback - * mechanism. - */ -uint32_t SetupTPM(int developer_mode, int disable_dev_request, - int clear_tpm_owner_request, RollbackSpaceFirmware *rsf); - -/** * Utility function to turn the virtual dev-mode flag on or off. 0=off, 1=on. */ uint32_t SetVirtualDevMode(int val); diff --git a/firmware/lib/include/tpm_bootmode.h b/firmware/lib/include/tpm_bootmode.h deleted file mode 100644 index 75509497..00000000 --- a/firmware/lib/include/tpm_bootmode.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions for updating the TPM state with the status of boot path. - */ - -#ifndef VBOOT_REFERENCE_TPM_BOOTMODE_H_ -#define VBOOT_REFERENCE_TPM_BOOTMODE_H_ - -#include "gbb_header.h" -#include "sysincludes.h" - -/** - * Update TPM PCR State with the boot path status. - * - * [developer_mode]: State of the developer switch. - * [recovery_mode]: State of the recovery mode. - * [fw_keyblock_flags]: Keyblock flags of the to-be-booted - * RW firmware keyblock. - * [gbb]: Pointer to GBB header from RO firmware. - * - * Returns: TPM_SUCCESS if the TPM extend operation succeeds. - */ -uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, - uint64_t fw_keyblock_flags, - GoogleBinaryBlockHeader *gbb); - -#endif /* VBOOT_REFERENCE_TPM_BOOTMODE_H_ */ diff --git a/firmware/lib/include/vboot_kernel.h b/firmware/lib/include/vboot_kernel.h index 2f1be5be..2c69f969 100644 --- a/firmware/lib/include/vboot_kernel.h +++ b/firmware/lib/include/vboot_kernel.h @@ -11,7 +11,6 @@ #include "cgptlib.h" #include "gpt_misc.h" -#include "load_firmware_fw.h" #include "load_kernel_fw.h" #include "vboot_api.h" diff --git a/firmware/lib/mocked_rollback_index.c b/firmware/lib/mocked_rollback_index.c index d20ca23a..bb253d15 100644 --- a/firmware/lib/mocked_rollback_index.c +++ b/firmware/lib/mocked_rollback_index.c @@ -18,71 +18,23 @@ uint32_t SetVirtualDevMode(int val) { return TPM_SUCCESS; } - uint32_t TPMClearAndReenable(void) { return TPM_SUCCESS; } - -uint32_t SetupTPM(int developer_mode, int disable_dev_request, - int clear_tpm_owner_request, RollbackSpaceFirmware* rsf) { - return TPM_SUCCESS; -} - - -uint32_t RollbackS3Resume(void) { - return TPM_SUCCESS; -} - - -uint32_t RollbackFirmwareSetup(int is_hw_dev, - int disable_dev_request, - int clear_tpm_owner_request, - int *is_virt_dev, uint32_t *version) { - *version = 0; - return TPM_SUCCESS; -} - - -uint32_t RollbackFirmwareWrite(uint32_t version) { - return TPM_SUCCESS; -} - - -uint32_t RollbackFirmwareLock(void) { - return TPM_SUCCESS; -} - - uint32_t RollbackKernelRead(uint32_t* version) { *version = 0; return TPM_SUCCESS; } - uint32_t RollbackKernelWrite(uint32_t version) { return TPM_SUCCESS; } - uint32_t RollbackKernelLock(int recovery_mode) { return TPM_SUCCESS; } -static uint8_t rollback_backup[BACKUP_NV_SIZE]; - -uint32_t RollbackBackupRead(uint8_t *raw) -{ - Memcpy(raw, rollback_backup, BACKUP_NV_SIZE); - return TPM_SUCCESS; -} - -uint32_t RollbackBackupWrite(uint8_t *raw) -{ - Memcpy(rollback_backup, raw, BACKUP_NV_SIZE); - return TPM_SUCCESS; -} - uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp) { Memset(fwmp, 0, sizeof(*fwmp)); diff --git a/firmware/lib/mocked_tpm_bootmode.c b/firmware/lib/mocked_tpm_bootmode.c deleted file mode 100644 index c1a02717..00000000 --- a/firmware/lib/mocked_tpm_bootmode.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions for updating the TPM state with the status of boot path. - */ - -#include "sysincludes.h" - -#include "tpm_bootmode.h" -#include "tss_constants.h" - -const char* kBootStateSHA1Digests[] = { - /* SHA1("\x00\x00\x00") */ - "\x29\xe2\xdc\xfb\xb1\x6f\x63\xbb\x02\x54\xdf\x75\x85\xa1\x5b\xb6" - "\xfb\x5e\x92\x7d", - - /* SHA1("\x00\x00\x01") */ - "\x25\x47\xcc\x73\x6e\x95\x1f\xa4\x91\x98\x53\xc4\x3a\xe8\x90\x86" - "\x1a\x3b\x32\x64", - - /* SHA1("\x00\x00\x02") */ - "\x1e\xf6\x24\x48\x2d\x62\x0e\x43\xe6\xd3\x4d\xa1\xaf\xe4\x62\x67" - "\xfc\x69\x5d\x9b", - - /* SHA1("\x00\x01\x00") */ - "\x62\x57\x18\x91\x21\x5b\x4e\xfc\x1c\xea\xb7\x44\xce\x59\xdd\x0b" - "\x66\xea\x6f\x73", - - /* SHA1("\x00\x01\x01") */ - "\xee\xe4\x47\xed\xc7\x9f\xea\x1c\xa7\xc7\xd3\x4e\x46\x32\x61\xcd" - "\xa4\xba\x33\x9e", - - /* SHA1("\x00\x01\x02") */ - "\x0c\x7a\x62\x3f\xd2\xbb\xc0\x5b\x06\x42\x3b\xe3\x59\xe4\x02\x1d" - "\x36\xe7\x21\xad", - - /* SHA1("\x01\x00\x00") */ - "\x95\x08\xe9\x05\x48\xb0\x44\x0a\x4a\x61\xe5\x74\x3b\x76\xc1\xe3" - "\x09\xb2\x3b\x7f", - - /* SHA1("\x01\x00\x01") */ - "\xc4\x2a\xc1\xc4\x6f\x1d\x4e\x21\x1c\x73\x5c\xc7\xdf\xad\x4f\xf8" - "\x39\x11\x10\xe9", - - /* SHA1("\x01\x00\x02") */ - "\xfa\x01\x0d\x26\x64\xcc\x5b\x3b\x82\xee\x48\x8f\xe2\xb9\xf5\x0f" - "\x49\x32\xeb\x8f", - - /* SHA1("\x01\x01\x00") */ - "\x47\xec\x8d\x98\x36\x64\x33\xdc\x00\x2e\x77\x21\xc9\xe3\x7d\x50" - "\x67\x54\x79\x37", - - /* SHA1("\x01\x01\x01") */ - "\x28\xd8\x6c\x56\xb3\xbf\x26\xd2\x36\x56\x9b\x8d\xc8\xc3\xf9\x1f" - "\x32\xf4\x7b\xc7", - - /* SHA1("\x01\x01\x02") */ - "\x12\xa3\x40\xd7\x89\x7f\xe7\x13\xfc\x8f\x02\xac\x53\x65\xb8\x6e" - "\xbf\x35\x31\x78", -}; - - -uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, - uint64_t fw_keyblock_flags, - GoogleBinaryBlockHeader *gbb) -{ - return TPM_SUCCESS; -} diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c index 2431e98f..cf446d98 100644 --- a/firmware/lib/rollback_index.c +++ b/firmware/lib/rollback_index.c @@ -69,17 +69,6 @@ uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length) } } -uint32_t SafeDefineSpace(uint32_t index, uint32_t perm, uint32_t size) -{ - uint32_t result = TlclDefineSpace(index, perm, size); - if (result == TPM_E_MAXNVWRITES) { - RETURN_ON_FAILURE(TPMClearAndReenable()); - return TlclDefineSpace(index, perm, size); - } else { - return result; - } -} - /* Functions to read and write firmware and kernel spaces. */ uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf) { @@ -167,7 +156,7 @@ uint32_t SetVirtualDevMode(int val) rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON; /* * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit. That - * will be done by SetupTPM() on the next boot. + * will be done on the next boot. */ VBDEBUG(("TPM: flags are now 0x%02x\n", rsf.flags)); @@ -247,293 +236,9 @@ uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk) return TPM_E_CORRUPTED_STATE; } -#ifndef TPM2_MODE -uint32_t OneTimeInitializeTPM(RollbackSpaceFirmware *rsf, - RollbackSpaceKernel *rsk) -{ - static const RollbackSpaceFirmware rsf_init = { - .struct_version = ROLLBACK_SPACE_FIRMWARE_VERSION, - }; - static const RollbackSpaceKernel rsk_init = { - .struct_version = ROLLBACK_SPACE_KERNEL_VERSION, - .uid = ROLLBACK_SPACE_KERNEL_UID, - }; - TPM_PERMANENT_FLAGS pflags; - uint32_t result; - - VBDEBUG(("TPM: One-time initialization\n")); - - /* - * Do a full test. This only happens the first time the device is - * turned on in the factory, so performance is not an issue. This is - * almost certainly not necessary, but it gives us more confidence - * about some code paths below that are difficult to - * test---specifically the ones that set lifetime flags, and are only - * executed once per physical TPM. - */ - result = TlclSelfTestFull(); - if (result != TPM_SUCCESS) - return result; - - result = TlclGetPermanentFlags(&pflags); - if (result != TPM_SUCCESS) - return result; - - /* - * TPM may come from the factory without physical presence finalized. - * Fix if necessary. - */ - VBDEBUG(("TPM: physicalPresenceLifetimeLock=%d\n", - pflags.physicalPresenceLifetimeLock)); - if (!pflags.physicalPresenceLifetimeLock) { - VBDEBUG(("TPM: Finalizing physical presence\n")); - RETURN_ON_FAILURE(TlclFinalizePhysicalPresence()); - } - - /* - * The TPM will not enforce the NV authorization restrictions until the - * execution of a TPM_NV_DefineSpace with the handle of - * TPM_NV_INDEX_LOCK. Here we create that space if it doesn't already - * exist. */ - VBDEBUG(("TPM: nvLocked=%d\n", pflags.nvLocked)); - if (!pflags.nvLocked) { - VBDEBUG(("TPM: Enabling NV locking\n")); - RETURN_ON_FAILURE(TlclSetNvLocked()); - } - - /* Clear TPM owner, in case the TPM is already owned for some reason. */ - VBDEBUG(("TPM: Clearing owner\n")); - RETURN_ON_FAILURE(TPMClearAndReenable()); - - /* Initializes the firmware and kernel spaces */ - Memcpy(rsf, &rsf_init, sizeof(RollbackSpaceFirmware)); - Memcpy(rsk, &rsk_init, sizeof(RollbackSpaceKernel)); - - /* Define the backup space. No need to initialize it, though. */ - RETURN_ON_FAILURE(SafeDefineSpace( - BACKUP_NV_INDEX, TPM_NV_PER_PPWRITE, BACKUP_NV_SIZE)); - - /* Define and initialize the kernel space */ - RETURN_ON_FAILURE(SafeDefineSpace(KERNEL_NV_INDEX, TPM_NV_PER_PPWRITE, - sizeof(RollbackSpaceKernel))); - RETURN_ON_FAILURE(WriteSpaceKernel(rsk)); - - /* Do the firmware space last, so we retry if we don't get this far. */ - RETURN_ON_FAILURE(SafeDefineSpace( - FIRMWARE_NV_INDEX, - TPM_NV_PER_GLOBALLOCK | TPM_NV_PER_PPWRITE, - sizeof(RollbackSpaceFirmware))); - RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); - - return TPM_SUCCESS; -} -#endif - -/* - * SetupTPM starts the TPM and establishes the root of trust for the - * anti-rollback mechanism. SetupTPM can fail for three reasons. 1 A bug. 2 a - * TPM hardware failure. 3 An unexpected TPM state due to some attack. In - * general we cannot easily distinguish the kind of failure, so our strategy is - * to reboot in recovery mode in all cases. The recovery mode calls SetupTPM - * again, which executes (almost) the same sequence of operations. There is a - * good chance that, if recovery mode was entered because of a TPM failure, the - * failure will repeat itself. (In general this is impossible to guarantee - * because we have no way of creating the exact TPM initial state at the - * previous boot.) In recovery mode, we ignore the failure and continue, thus - * giving the recovery kernel a chance to fix things (that's why we don't set - * bGlobalLock). The choice is between a knowingly insecure device and a - * bricked device. - * - * As a side note, observe that we go through considerable hoops to avoid using - * the STCLEAR permissions for the index spaces. We do this to avoid writing - * to the TPM flashram at every reboot or wake-up, because of concerns about - * the durability of the NVRAM. - */ -uint32_t SetupTPM(int developer_mode, int disable_dev_request, - int clear_tpm_owner_request, RollbackSpaceFirmware* rsf) -{ - uint8_t in_flags; -#ifndef TPM2_MODE - uint8_t disable; - uint8_t deactivated; -#endif - uint32_t result; - uint32_t versions; - - RETURN_ON_FAILURE(TlclLibInit()); - -#ifdef TEGRA_SOFT_REBOOT_WORKAROUND - result = TlclStartup(); - if (result == TPM_E_INVALID_POSTINIT) { - /* - * Some prototype hardware doesn't reset the TPM on a CPU - * reset. We do a hard reset to get around this. - */ - VBDEBUG(("TPM: soft reset detected\n", result)); - return TPM_E_MUST_REBOOT; - } else if (result != TPM_SUCCESS) { - VBDEBUG(("TPM: TlclStartup returned %08x\n", result)); - return result; - } -#else - RETURN_ON_FAILURE(TlclStartup()); -#endif - - /* - * Some TPMs start the self test automatically at power on. In that case we - * don't need to call ContinueSelfTest. On some (other) TPMs, - * ContinueSelfTest may block. In that case, we definitely don't want to - * call it here. For TPMs in the intersection of these two sets, we're - * screwed. (In other words: TPMs that require manually starting the - * self-test AND block will have poor performance until we split - * TlclSendReceive() into Send() and Receive(), and have a state machine to - * control setup.) - * - * This comment is likely to become obsolete in the near future, so don't - * trust it. It may have not been updated. - */ -#ifdef TPM_MANUAL_SELFTEST -#ifdef TPM_BLOCKING_CONTINUESELFTEST -#warning "lousy TPM!" -#endif - RETURN_ON_FAILURE(TlclContinueSelfTest()); -#endif -#ifndef TPM2_MODE - result = TlclAssertPhysicalPresence(); - if (result != TPM_SUCCESS) { - /* - * It is possible that the TPM was delivered with the physical - * presence command disabled. This tries enabling it, then - * tries asserting PP again. - */ - RETURN_ON_FAILURE(TlclPhysicalPresenceCMDEnable()); - RETURN_ON_FAILURE(TlclAssertPhysicalPresence()); - } - - /* Check that the TPM is enabled and activated. */ - RETURN_ON_FAILURE(TlclGetFlags(&disable, &deactivated, NULL)); - if (disable || deactivated) { - VBDEBUG(("TPM: disabled (%d) or deactivated (%d). Fixing...\n", - disable, deactivated)); - RETURN_ON_FAILURE(TlclSetEnable()); - RETURN_ON_FAILURE(TlclSetDeactivated(0)); - VBDEBUG(("TPM: Must reboot to re-enable\n")); - return TPM_E_MUST_REBOOT; - } -#endif - - /* Read the firmware space. */ - result = ReadSpaceFirmware(rsf); -#ifndef TPM2_MODE - if (TPM_E_BADINDEX == result) { - RollbackSpaceKernel rsk; - - /* - * This is the first time we've run, and the TPM has not been - * initialized. Initialize it. - */ - VBDEBUG(("TPM: Not initialized yet.\n")); - RETURN_ON_FAILURE(OneTimeInitializeTPM(rsf, &rsk)); - } else -#endif - if (TPM_SUCCESS != result) { - VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n")); - return TPM_E_CORRUPTED_STATE; - } - Memcpy(&versions, &rsf->fw_versions, sizeof(versions)); - VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n", - rsf->struct_version, rsf->flags, versions)); - in_flags = rsf->flags; - - /* If we've been asked to clear the virtual dev-mode flag, do so now */ - if (disable_dev_request) { - rsf->flags &= ~FLAG_VIRTUAL_DEV_MODE_ON; - VBDEBUG(("TPM: Clearing virt dev-switch: f%x\n", rsf->flags)); - } - - /* - * The developer_mode value that's passed in is only set by a hardware - * dev-switch. We should OR it with the virtual switch, whether or not - * the virtual switch is used. If it's not used, it shouldn't change, - * so it doesn't matter. - */ - if (rsf->flags & FLAG_VIRTUAL_DEV_MODE_ON) - developer_mode = 1; - - /* - * Clear ownership if developer flag has toggled, or if an owner-clear - * has been requested. - */ - if ((developer_mode ? FLAG_LAST_BOOT_DEVELOPER : 0) != - (in_flags & FLAG_LAST_BOOT_DEVELOPER)) { - VBDEBUG(("TPM: Developer flag changed; clearing owner.\n")); - RETURN_ON_FAILURE(TPMClearAndReenable()); - } else if (clear_tpm_owner_request) { - VBDEBUG(("TPM: Clearing owner as specifically requested.\n")); - RETURN_ON_FAILURE(TPMClearAndReenable()); - } - - if (developer_mode) - rsf->flags |= FLAG_LAST_BOOT_DEVELOPER; - else - rsf->flags &= ~FLAG_LAST_BOOT_DEVELOPER; - - - /* If firmware space is dirty, flush it back to the TPM */ - if (rsf->flags != in_flags) { - VBDEBUG(("TPM: Updating firmware space.\n")); - RETURN_ON_FAILURE(WriteSpaceFirmware(rsf)); - } - - VBDEBUG(("TPM: SetupTPM() succeeded\n")); - return TPM_SUCCESS; -} - #ifdef DISABLE_ROLLBACK_TPM /* Dummy implementations which don't support TPM rollback protection */ -uint32_t RollbackS3Resume(void) -{ -#ifndef CHROMEOS_ENVIRONMENT - /* - * Initialize the TPM, but ignore return codes. In ChromeOS - * environment, don't even talk to the TPM. - */ - TlclLibInit(); - TlclResume(); -#endif - return TPM_SUCCESS; -} - -uint32_t RollbackFirmwareSetup(int is_hw_dev, - int disable_dev_request, - int clear_tpm_owner_request, - int *is_virt_dev, uint32_t *version) -{ -#ifndef CHROMEOS_ENVIRONMENT - /* - * Initialize the TPM, but ignores return codes. In ChromeOS - * environment, don't even talk to the TPM. - */ - TlclLibInit(); - TlclStartup(); - TlclContinueSelfTest(); -#endif - *is_virt_dev = 0; - *version = 0; - return TPM_SUCCESS; -} - -uint32_t RollbackFirmwareWrite(uint32_t version) -{ - return TPM_SUCCESS; -} - -uint32_t RollbackFirmwareLock(void) -{ - return TPM_SUCCESS; -} - uint32_t RollbackKernelRead(uint32_t* version) { *version = 0; @@ -545,16 +250,6 @@ uint32_t RollbackKernelWrite(uint32_t version) return TPM_SUCCESS; } -uint32_t RollbackBackupRead(uint8_t *raw) -{ - return TPM_SUCCESS; -} - -uint32_t RollbackBackupWrite(uint8_t *raw) -{ - return TPM_SUCCESS; -} - uint32_t RollbackKernelLock(int recovery_mode) { return TPM_SUCCESS; @@ -568,57 +263,6 @@ uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp) #else -uint32_t RollbackS3Resume(void) -{ - uint32_t result; - RETURN_ON_FAILURE(TlclLibInit()); - result = TlclResume(); - if (result == TPM_E_INVALID_POSTINIT) { - /* - * We're on a platform where the TPM maintains power in S3, so - * it's already initialized. - */ - return TPM_SUCCESS; - } - return result; -} - -uint32_t RollbackFirmwareSetup(int is_hw_dev, - int disable_dev_request, - int clear_tpm_owner_request, - int *is_virt_dev, uint32_t *version) -{ - RollbackSpaceFirmware rsf; - - /* Set version to 0 in case we fail */ - *version = 0; - - RETURN_ON_FAILURE(SetupTPM(is_hw_dev, disable_dev_request, - clear_tpm_owner_request, &rsf)); - Memcpy(version, &rsf.fw_versions, sizeof(*version)); - *is_virt_dev = (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON) ? 1 : 0; - VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)*version)); - return TPM_SUCCESS; -} - -uint32_t RollbackFirmwareWrite(uint32_t version) -{ - RollbackSpaceFirmware rsf; - uint32_t old_version; - - RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf)); - Memcpy(&old_version, &rsf.fw_versions, sizeof(old_version)); - VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)old_version, - (int)version)); - Memcpy(&rsf.fw_versions, &version, sizeof(version)); - return WriteSpaceFirmware(&rsf); -} - -uint32_t RollbackFirmwareLock(void) -{ - return TlclSetGlobalLock(); -} - uint32_t RollbackKernelRead(uint32_t* version) { RollbackSpaceKernel rsk; @@ -664,29 +308,6 @@ uint32_t RollbackKernelWrite(uint32_t version) return WriteSpaceKernel(&rsk); } -/* - * We don't really care whether the TPM owner has been messing with this or - * not. We lock it along with the Kernel space just to avoid problems, but it's - * only useful in dev-mode and only when the battery has been drained - * completely. There aren't any security issues. It's just in the TPM because - * we don't have any other place to keep it. - */ -uint32_t RollbackBackupRead(uint8_t *raw) -{ - uint32_t r; - r = TlclRead(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE); - VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r)); - return r; -} - -uint32_t RollbackBackupWrite(uint8_t *raw) -{ - uint32_t r; - r = TlclWrite(BACKUP_NV_INDEX, raw, BACKUP_NV_SIZE); - VBDEBUG(("TPM: %s returning 0x%x\n", __func__, r)); - return r; -} - uint32_t RollbackKernelLock(int recovery_mode) { static int kernel_locked = 0; diff --git a/firmware/lib/tpm_bootmode.c b/firmware/lib/tpm_bootmode.c deleted file mode 100644 index cae4b0b1..00000000 --- a/firmware/lib/tpm_bootmode.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions for updating the TPM state with the status of boot path. - */ - -#include "sysincludes.h" - -#include "tlcl.h" -#include "tpm_bootmode.h" -#include "utility.h" -#include "vboot_api.h" - -/* TPM PCRs to use for storing boot mode measurements. */ -#define BOOT_MODE_PCR 0 -#define HWID_DIGEST_PCR 1 - -/* - * Input digests for PCR extend. - * These are calculated as: - * SHA1("|Developer_Mode||Recovery_Mode||Keyblock_Mode|"). - * Developer_Mode can be 0 or 1. - * Recovery_Mode can be 0 or 1. - * Keyblock flags are defined in vboot_struct.h - * - * We map them to Keyblock_Mode as follows: - * ----------------------------------------- - * Keyblock Flags | Keyblock Mode - * ----------------------------------------- - * 6 (Dev-signed firmware) | 2 - * 7 Normal-signed firmware | 1 - * (anything else) | 0 - */ - -const char* kBootStateSHA1Digests[] = { - /* SHA1("\x00\x00\x00") */ - "\x29\xe2\xdc\xfb\xb1\x6f\x63\xbb\x02\x54\xdf\x75\x85\xa1\x5b\xb6" - "\xfb\x5e\x92\x7d", - - /* SHA1("\x00\x00\x01") */ - "\x25\x47\xcc\x73\x6e\x95\x1f\xa4\x91\x98\x53\xc4\x3a\xe8\x90\x86" - "\x1a\x3b\x32\x64", - - /* SHA1("\x00\x00\x02") */ - "\x1e\xf6\x24\x48\x2d\x62\x0e\x43\xe6\xd3\x4d\xa1\xaf\xe4\x62\x67" - "\xfc\x69\x5d\x9b", - - /* SHA1("\x00\x01\x00") */ - "\x62\x57\x18\x91\x21\x5b\x4e\xfc\x1c\xea\xb7\x44\xce\x59\xdd\x0b" - "\x66\xea\x6f\x73", - - /* SHA1("\x00\x01\x01") */ - "\xee\xe4\x47\xed\xc7\x9f\xea\x1c\xa7\xc7\xd3\x4e\x46\x32\x61\xcd" - "\xa4\xba\x33\x9e", - - /* SHA1("\x00\x01\x02") */ - "\x0c\x7a\x62\x3f\xd2\xbb\xc0\x5b\x06\x42\x3b\xe3\x59\xe4\x02\x1d" - "\x36\xe7\x21\xad", - - /* SHA1("\x01\x00\x00") */ - "\x95\x08\xe9\x05\x48\xb0\x44\x0a\x4a\x61\xe5\x74\x3b\x76\xc1\xe3" - "\x09\xb2\x3b\x7f", - - /* SHA1("\x01\x00\x01") */ - "\xc4\x2a\xc1\xc4\x6f\x1d\x4e\x21\x1c\x73\x5c\xc7\xdf\xad\x4f\xf8" - "\x39\x11\x10\xe9", - - /* SHA1("\x01\x00\x02") */ - "\xfa\x01\x0d\x26\x64\xcc\x5b\x3b\x82\xee\x48\x8f\xe2\xb9\xf5\x0f" - "\x49\x32\xeb\x8f", - - /* SHA1("\x01\x01\x00") */ - "\x47\xec\x8d\x98\x36\x64\x33\xdc\x00\x2e\x77\x21\xc9\xe3\x7d\x50" - "\x67\x54\x79\x37", - - /* SHA1("\x01\x01\x01") */ - "\x28\xd8\x6c\x56\xb3\xbf\x26\xd2\x36\x56\x9b\x8d\xc8\xc3\xf9\x1f" - "\x32\xf4\x7b\xc7", - - /* SHA1("\x01\x01\x02") */ - "\x12\xa3\x40\xd7\x89\x7f\xe7\x13\xfc\x8f\x02\xac\x53\x65\xb8\x6e" - "\xbf\x35\x31\x78", -}; - -#define MAX_BOOT_STATE_INDEX (sizeof(kBootStateSHA1Digests)/sizeof(char *)) - -/* - * Used for PCR extend when the passed-in boot state is invalid or if there is - * an internal error. - */ -const uint8_t kBootInvalidSHA1Digest[] = { - "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff" -}; - -/** - * Given the boot state, return the correct SHA1 digest index for TPMExtend - * in kBootStateSHA1Digests[]. - */ -static int GetBootStateIndex(int dev_mode, int rec_mode, - uint64_t keyblock_flags) -{ - int index = 0; - - /* - * Convert keyblock flags into keyblock mode which we use to index into - * kBootStateSHA1Digest[]. - */ - switch(keyblock_flags) { - case 6: - /* - * KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1 - * - * Developer firmware. */ - index = 2; - break; - case 7: - /* - * KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_0 - * | KEY_BLOCK_FLAGS_DEVELOPER_1 - */ - index = 1; - break; - default: - /* Any other keyblock flags. */ - index = 0; - }; - - if (rec_mode) - index += 3; - if (dev_mode) - index += 6; - return index; -} - -uint32_t SetTPMBootModeState(int developer_mode, int recovery_mode, - uint64_t fw_keyblock_flags, - GoogleBinaryBlockHeader *gbb) -{ - uint32_t result0, result1 = 0; - const uint8_t *in_digest = NULL; - uint8_t out_digest[20]; /* For PCR extend output. */ - int digest_index = GetBootStateIndex(developer_mode, recovery_mode, - fw_keyblock_flags); - - if (digest_index >= 0 && digest_index < MAX_BOOT_STATE_INDEX) { - in_digest = (const uint8_t*) - kBootStateSHA1Digests[digest_index]; - } else { - /* Internal out of bounds error. */ - in_digest = kBootInvalidSHA1Digest; - } - - result0 = TlclExtend(BOOT_MODE_PCR, in_digest, out_digest); - VBDEBUG(("TPM: SetTPMBootModeState boot mode PCR%d result %d\n", - BOOT_MODE_PCR, result0)); - - /* Extend the HWID Digest into PCR1 (GBB v1.2 and later only) */ - if (gbb && gbb->minor_version >= 2) { - result1 = TlclExtend(HWID_DIGEST_PCR, gbb->hwid_digest, - out_digest); - VBDEBUG(("TPM: SetTPMBootModeState HWID PCR%d result %d\n", - HWID_DIGEST_PCR, result1)); - } - - /* The caller only looks for nonzero results, not error codes. */ - return result0 || result1; -} diff --git a/firmware/lib/vboot_api_firmware.c b/firmware/lib/vboot_api_firmware.c deleted file mode 100644 index c893d704..00000000 --- a/firmware/lib/vboot_api_firmware.c +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware wrapper API - entry points for init, firmware selection - */ - -#include "sysincludes.h" - -#include "gbb_access.h" -#include "gbb_header.h" -#include "load_firmware_fw.h" -#include "rollback_index.h" -#include "tpm_bootmode.h" -#include "utility.h" -#include "vboot_api.h" -#include "vboot_common.h" -#include "vboot_nvstorage.h" - -VbError_t VbSelectFirmware(VbCommonParams *cparams, - VbSelectFirmwareParams *fparams) -{ - VbSharedDataHeader *shared = - (VbSharedDataHeader *)cparams->shared_data_blob; - VbNvContext vnc; - VbError_t retval = VBERROR_UNKNOWN; /* Default to error */ - int is_rec = (shared->recovery_reason ? 1 : 0); - int is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); - uint32_t tpm_status = 0; - - cparams->gbb = NULL; - cparams->bmp = NULL; - - /* Start timer */ - shared->timer_vb_select_firmware_enter = VbExGetTimer(); - - /* Load NV storage */ - VbExNvStorageRead(vnc.raw); - VbNvSetup(&vnc); - - if (is_rec) { - /* - * Recovery is requested; go straight to recovery without - * checking the RW firmware. - */ - VBDEBUG(("VbSelectFirmware() detected recovery request\n")); - - /* Best effort to read the GBB */ - cparams->gbb = VbExMalloc(sizeof(*cparams->gbb)); - retval = VbGbbReadHeader_static(cparams, cparams->gbb); - if (VBERROR_SUCCESS != retval) { - VBDEBUG(("Can't read GBB. Continuing anyway...\n")); - VbExFree(cparams->gbb); - cparams->gbb = NULL; - } - - /* Go directly to recovery mode */ - fparams->selected_firmware = VB_SELECT_FIRMWARE_RECOVERY; - } else { - cparams->gbb = VbExMalloc(sizeof(*cparams->gbb)); - retval = VbGbbReadHeader_static(cparams, cparams->gbb); - if (VBERROR_SUCCESS != retval) - goto VbSelectFirmware_exit; - - /* Chain to LoadFirmware() */ - retval = LoadFirmware(cparams, fparams, &vnc); - - /* Exit if we failed to find an acceptable firmware */ - if (VBERROR_SUCCESS != retval) - goto VbSelectFirmware_exit; - - /* Translate the selected firmware path */ - if (shared->flags & VBSD_LF_USE_RO_NORMAL) { - /* Request the read-only normal/dev code path */ - fparams->selected_firmware = - VB_SELECT_FIRMWARE_READONLY; - } else if (0 == shared->firmware_index) - fparams->selected_firmware = VB_SELECT_FIRMWARE_A; - else { - fparams->selected_firmware = VB_SELECT_FIRMWARE_B; - } - - /* Update TPM if necessary */ - if (shared->fw_version_tpm_start < shared->fw_version_tpm) { - tpm_status = - RollbackFirmwareWrite(shared->fw_version_tpm); - if (0 != tpm_status) { - VBDEBUG(("Can't write FW version to TPM.\n")); - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_RO_TPM_W_ERROR); - retval = VBERROR_TPM_WRITE_FIRMWARE; - goto VbSelectFirmware_exit; - } - } - - /* Lock firmware versions in TPM */ - tpm_status = RollbackFirmwareLock(); - if (0 != tpm_status) { - VBDEBUG(("Unable to lock firmware version in TPM.\n")); - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_RO_TPM_L_ERROR); - retval = VBERROR_TPM_LOCK_FIRMWARE; - goto VbSelectFirmware_exit; - } - } - - /* - * At this point, we have a good idea of how we are going to - * boot. Update the TPM with this state information. - */ - tpm_status = SetTPMBootModeState(is_dev, is_rec, - shared->fw_keyblock_flags, - cparams->gbb); - if (0 != tpm_status) { - VBDEBUG(("Can't update the TPM with boot mode information.\n")); - if (!is_rec) { - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_RO_TPM_U_ERROR); - retval = VBERROR_TPM_SET_BOOT_MODE_STATE; - goto VbSelectFirmware_exit; - } - } - - /* Success! */ - retval = VBERROR_SUCCESS; - - VbSelectFirmware_exit: - - if (cparams->gbb) { - VbExFree(cparams->gbb); - cparams->gbb = NULL; - } - - /* Save NV storage */ - VbNvTeardown(&vnc); - if (vnc.raw_changed) - VbExNvStorageWrite(vnc.raw); - - /* Stop timer */ - shared->timer_vb_select_firmware_exit = VbExGetTimer(); - - /* Should always have a known error code */ - VbAssert(VBERROR_UNKNOWN != retval); - - return retval; -} diff --git a/firmware/lib/vboot_api_init.c b/firmware/lib/vboot_api_init.c deleted file mode 100644 index 2657fb5d..00000000 --- a/firmware/lib/vboot_api_init.c +++ /dev/null @@ -1,378 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware wrapper API - entry points for init, firmware selection - */ - -#include "sysincludes.h" - -#include "region.h" -#include "gbb_access.h" -#include "gbb_header.h" -#include "load_firmware_fw.h" -#include "rollback_index.h" -#include "utility.h" -#include "vboot_api.h" -#include "vboot_common.h" -#include "vboot_nvstorage.h" - -VbError_t VbInit(VbCommonParams *cparams, VbInitParams *iparams) -{ - VbSharedDataHeader *shared = - (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader gbb; - VbNvContext vnc; - VbError_t retval = VBERROR_SUCCESS; - uint32_t recovery = VBNV_RECOVERY_NOT_REQUESTED; - int is_s3_resume = 0; - uint32_t s3_debug_boot = 0; - uint32_t require_official_os = 0; - uint32_t tpm_version = 0; - uint32_t tpm_status = 0; - int has_virt_dev_switch = 0; - int is_hw_dev = 0; - int is_virt_dev = 0; - uint32_t disable_dev_request = 0; - uint32_t clear_tpm_owner_request = 0; - int is_dev = 0; - uint32_t backup_requested = 0; - uint32_t backup_for_safety = 0; - int lost_nvram; - - /* Initialize output flags */ - iparams->out_flags = 0; - - retval = VbGbbReadHeader_static(cparams, &gbb); - if (retval) - return retval; - - VBDEBUG(("VbInit() input flags 0x%x gbb flags 0x%x\n", iparams->flags, - gbb.flags)); - - /* Set up NV storage */ - VbExNvStorageRead(vnc.raw); - VbNvSetup(&vnc); - lost_nvram = vnc.regenerate_crc; - - /* Initialize shared data structure */ - if (0 != VbSharedDataInit(shared, cparams->shared_data_size)) { - VBDEBUG(("Shared data init error\n")); - return VBERROR_INIT_SHARED_DATA; - } - - shared->timer_vb_init_enter = VbExGetTimer(); - - /* Copy some boot switch flags */ - /* TODO: in next refactor, just save in/out flags in VbSharedData */ - shared->flags = 0; - if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) - shared->flags |= VBSD_BOOT_REC_SWITCH_ON; - if (iparams->flags & VB_INIT_FLAG_WP_ENABLED) - shared->flags |= VBSD_BOOT_FIRMWARE_WP_ENABLED; - if (iparams->flags & VB_INIT_FLAG_SW_WP_ENABLED) - shared->flags |= VBSD_BOOT_FIRMWARE_SW_WP_ENABLED; - if (iparams->flags & VB_INIT_FLAG_S3_RESUME) - shared->flags |= VBSD_BOOT_S3_RESUME; - if (iparams->flags & VB_INIT_FLAG_RO_NORMAL_SUPPORT) - shared->flags |= VBSD_BOOT_RO_NORMAL_SUPPORT; - if (iparams->flags & VB_INIT_FLAG_NOFAIL_BOOT) - shared->flags |= VBSD_NOFAIL_BOOT; - if (iparams->flags & VB_INIT_FLAG_EC_SOFTWARE_SYNC) - shared->flags |= VBSD_EC_SOFTWARE_SYNC; - if (iparams->flags & VB_INIT_FLAG_EC_SLOW_UPDATE) - shared->flags |= VBSD_EC_SLOW_UPDATE; - if (iparams->flags & VB_INIT_FLAG_VIRTUAL_REC_SWITCH) - shared->flags |= VBSD_BOOT_REC_SWITCH_VIRTUAL; - if (iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) - shared->flags |= VBSD_OPROM_MATTERS; - if (iparams->flags & VB_INIT_FLAG_OPROM_LOADED) - shared->flags |= VBSD_OPROM_LOADED; - - is_s3_resume = (iparams->flags & VB_INIT_FLAG_S3_RESUME ? 1 : 0); - - /* Check if the OS is requesting a debug S3 reset */ - VbNvGet(&vnc, VBNV_DEBUG_RESET_MODE, &s3_debug_boot); - if (s3_debug_boot) { - if (is_s3_resume) { - VBDEBUG(("VbInit() requesting S3 debug boot\n")); - iparams->out_flags |= VB_INIT_OUT_S3_DEBUG_BOOT; - is_s3_resume = 0; /* Proceed as if normal boot */ - } - - /* - * Clear the request even if this is a normal boot, since we - * don't want the NEXT S3 resume to be a debug reset unless the - * OS asserts the request again. - */ - VbNvSet(&vnc, VBNV_DEBUG_RESET_MODE, 0); - } - - /* - * If this isn't a S3 resume, read the current recovery request, then - * clear it so we don't get stuck in recovery mode. - */ - if (!is_s3_resume) { - VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &recovery); - VBDEBUG(("VbInit sees recovery request = %d\n", recovery)); - if (VBNV_RECOVERY_NOT_REQUESTED != recovery) - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_NOT_REQUESTED); - } - - /* - * If the previous boot failed in the firmware somewhere outside of - * verified boot, and recovery is not requested for our own reasons, - * request recovery mode. This gives the calling firmware a way to - * request recovery if it finds something terribly wrong. - */ - if (VBNV_RECOVERY_NOT_REQUESTED == recovery && - iparams->flags & VB_INIT_FLAG_PREVIOUS_BOOT_FAIL) { - recovery = VBNV_RECOVERY_RO_FIRMWARE; - } - - /* - * If recovery button is pressed, override recovery reason. Note that - * we do this in the S3 resume path also. - */ - if (iparams->flags & VB_INIT_FLAG_REC_BUTTON_PRESSED) - recovery = VBNV_RECOVERY_RO_MANUAL; - - /* - * Copy current recovery reason to shared data. If we fail later on, it - * won't matter, since we'll just reboot. - */ - shared->recovery_reason = (uint8_t)recovery; - VBDEBUG(("VbInit now sets shared->recovery_reason = %d\n", recovery)); - - /* - * If this is a S3 resume, resume the TPM. - * - * FIXME: I think U-Boot won't ever ask us to do this. Can we remove - * it? - */ - if (is_s3_resume) { - if (TPM_SUCCESS != RollbackS3Resume()) { - /* - * If we can't resume, just do a full reboot. No need - * to go to recovery mode here, since if the TPM is - * really broken we'll catch it on the next boot. - */ - retval = VBERROR_TPM_S3_RESUME; - } - } else { - /* Should we pay attention to the TPM's virtual dev-switch? */ - if (iparams->flags & VB_INIT_FLAG_VIRTUAL_DEV_SWITCH) { - shared->flags |= VBSD_HONOR_VIRT_DEV_SWITCH; - has_virt_dev_switch = 1; - } - - /* - * We always believe the HW dev-switch, since there's one - * attached to servo which may be active even on systems - * without a physical switch. The EC may also implement a fake - * dev-switch for testing. - */ - if (iparams->flags & VB_INIT_FLAG_DEV_SWITCH_ON) - is_hw_dev = 1; - - /* We may be asked to clear the virtual dev-switch at boot. */ - VbNvGet(&vnc, VBNV_DISABLE_DEV_REQUEST, &disable_dev_request); - - /* Allow GBB flag to override dev switch */ - if (gbb.flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) - is_hw_dev = 1; - - /* Have we been explicitly asked to clear the TPM owner? */ - VbNvGet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, - &clear_tpm_owner_request); - - /* - * Initialize the TPM. If the developer mode state has changed - * since the last boot, we need to clear TPM ownership. If the - * TPM space is initialized by this call, the virtual - * dev-switch will be disabled by default) - */ - VBDEBUG(("TPM: Call RollbackFirmwareSetup(r%d, d%d)\n", - recovery, is_hw_dev)); - tpm_status = RollbackFirmwareSetup(is_hw_dev, - disable_dev_request, - clear_tpm_owner_request, - /* two outputs on success */ - &is_virt_dev, &tpm_version); - - if (0 != tpm_status) { - VBDEBUG(("Unable to setup TPM and read " - "firmware version (0x%x)\n", tpm_status)); - - if (TPM_E_MUST_REBOOT == tpm_status) { - /* - * TPM wants to reboot into the same mode we're - * in now - */ - VBDEBUG(("TPM requires a reboot.\n")); - if (!recovery) { - /* - * Not recovery mode. Just reboot (not - * into recovery). - */ - retval = VBERROR_TPM_REBOOT_REQUIRED; - goto VbInit_exit; - } else if (VBNV_RECOVERY_RO_TPM_REBOOT != - shared->recovery_reason) { - /* - * In recovery mode now, and we haven't - * requested a TPM reboot yet, so - * request one. - */ - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_RO_TPM_REBOOT); - retval = VBERROR_TPM_REBOOT_REQUIRED; - goto VbInit_exit; - } - } - - if (!recovery) { - VbNvSet(&vnc, VBNV_RECOVERY_REQUEST, - VBNV_RECOVERY_RO_TPM_S_ERROR); - VbNvSet(&vnc, VBNV_RECOVERY_SUBCODE, - tpm_status); - retval = VBERROR_TPM_FIRMWARE_SETUP; - goto VbInit_exit; - } - } - - /* TPM setup succeeded, or we're in recovery mode and ignoring - * errors. What did we learn? */ - shared->fw_version_tpm_start = tpm_version; - shared->fw_version_tpm = tpm_version; - if (is_hw_dev || (has_virt_dev_switch && is_virt_dev)) { - is_dev = 1; - shared->flags |= VBSD_BOOT_DEV_SWITCH_ON; - } - if (disable_dev_request && !is_virt_dev) - VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 0); - if (clear_tpm_owner_request) { - VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_REQUEST, 0); - VbNvSet(&vnc, VBNV_CLEAR_TPM_OWNER_DONE, 1); - } - } - - /* - * If the nvram state was lost, try to restore the bits we care about - * from the backup in the TPM. It's okay if we can't, though. - * Note: None of the bits that we back up should have been referenced - * before this point. Otherwise, they'll just be overwritten here. - * All the other bits will be unchanged from whatever has happened to - * them since VbNvSetup() reinitialized the VbNvContext. - */ - if (lost_nvram) - RestoreNvFromBackup(&vnc); - - /* Allow BIOS to load arbitrary option ROMs? */ - if (gbb.flags & GBB_FLAG_LOAD_OPTION_ROMS) - iparams->out_flags |= VB_INIT_OUT_ENABLE_OPROM; - - /* Factory may need to boot custom OSes when the dev-switch is on */ - if (is_dev && (gbb.flags & GBB_FLAG_ENABLE_ALTERNATE_OS)) - iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; - - /* Set output flags */ - if (VBNV_RECOVERY_NOT_REQUESTED != recovery) { - /* Requesting recovery mode */ - iparams->out_flags |= (VB_INIT_OUT_ENABLE_RECOVERY | - VB_INIT_OUT_CLEAR_RAM | - VB_INIT_OUT_ENABLE_DISPLAY | - VB_INIT_OUT_ENABLE_USB_STORAGE); - } else if (is_dev) { - /* Developer switch is on, so need to support dev mode */ - iparams->out_flags |= (VB_INIT_OUT_ENABLE_DEVELOPER | - VB_INIT_OUT_CLEAR_RAM | - VB_INIT_OUT_ENABLE_DISPLAY | - VB_INIT_OUT_ENABLE_USB_STORAGE); - /* ... which may or may not include custom OSes */ - VbNvGet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os); - if (!require_official_os) - iparams->out_flags |= VB_INIT_OUT_ENABLE_ALTERNATE_OS; - - /* - * Dev-mode needs the VGA option ROM to be loaded so it can - * display the scary boot screen. If we don't have it, we need - * to request it and reboot so it can be loaded. - */ - if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && - !(iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { - VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1); - /* - * If VbInit() is run before Option ROMs are run it - * can still respond to the VbNv flag and does not - * need to reboot here. - */ - if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD)) - retval = VBERROR_VGA_OPROM_MISMATCH; - VBDEBUG(("VbInit() needs oprom, doesn't have it\n")); - } - - } else { - /* - * Normal mode, so disable dev_boot_* flags. This ensures they - * will be initially disabled if the user later transitions - * back into developer mode. - */ - VbNvSet(&vnc, VBNV_DEV_BOOT_USB, 0); - VbNvSet(&vnc, VBNV_DEV_BOOT_LEGACY, 0); - VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 0); - VbNvSet(&vnc, VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, 0); - VbNvSet(&vnc, VBNV_DEV_DEFAULT_BOOT, 0); - VbNvSet(&vnc, VBNV_FASTBOOT_UNLOCK_IN_FW, 0); - /* - * Back up any changes now, so these values can't be forgotten - * by draining the battery. We really only care about these - * three fields, but it's uncommon for any others to change so - * this is an easier test than checking each one. - */ - if (vnc.regenerate_crc) - backup_for_safety = 1; - - /* - * If we don't need the VGA option ROM but got it anyway, stop - * asking for it and reboot in case there's some vulnerability - * in using it. - */ - if ((iparams->flags & VB_INIT_FLAG_OPROM_MATTERS) && - (iparams->flags & VB_INIT_FLAG_OPROM_LOADED)) { - VbNvSet(&vnc, VBNV_OPROM_NEEDED, 0); - /* - * If VbInit() is run before Option ROMs are run it - * can still respond to the VbNv flag and does not - * need to reboot here. - */ - if (!(iparams->flags & VB_INIT_FLAG_BEFORE_OPROM_LOAD)) - retval = VBERROR_VGA_OPROM_MISMATCH; - VBDEBUG(("VbInit() has oprom, doesn't need it\n")); - } - } - -VbInit_exit: - /* - * If we successfully backup the NV storage, it will clear the - * VBNV_BACKUP_NVRAM_REQUEST field, so we want to do it before - * calling VbNvTeardown(). It's okay if we can't backup, though. - */ - VbNvGet(&vnc, VBNV_BACKUP_NVRAM_REQUEST, &backup_requested); - if (backup_requested || backup_for_safety) - SaveNvToBackup(&vnc); - - /* Tear down NV storage */ - VbNvTeardown(&vnc); - if (vnc.raw_changed) - VbExNvStorageWrite(vnc.raw); - - VBDEBUG(("VbInit() output flags 0x%x\n", iparams->out_flags)); - - shared->timer_vb_init_exit = VbExGetTimer(); - - VBDEBUG(("VbInit() returning 0x%x\n", retval)); - - return retval; -} diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c deleted file mode 100644 index bfabfd48..00000000 --- a/firmware/lib/vboot_firmware.c +++ /dev/null @@ -1,368 +0,0 @@ -/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * High-level firmware API for loading and verifying rewritable firmware. - * (Firmware portion) - */ - -#include "sysincludes.h" -#include "2sysincludes.h" - -#include "2common.h" -#include "2sha.h" -#include "region.h" -#include "gbb_access.h" -#include "gbb_header.h" -#include "load_firmware_fw.h" -#include "utility.h" -#include "vboot_api.h" -#include "vboot_common.h" -#include "vboot_nvstorage.h" - -/* - * Static variables for UpdateFirmwareBodyHash(). It's less than optimal to - * have static variables in a library, but in UEFI the caller is deep inside a - * different firmware stack and doesn't have a good way to pass the params - * struct back to us. - */ -typedef struct VbLoadFirmwareInternal { - struct vb2_digest_context body_digest_context; - uint32_t body_size_accum; -} VbLoadFirmwareInternal; - -void VbUpdateFirmwareBodyHash(VbCommonParams *cparams, uint8_t *data, - uint32_t size) -{ - VbLoadFirmwareInternal *lfi = - (VbLoadFirmwareInternal*)cparams->vboot_context; - - vb2_digest_extend(&lfi->body_digest_context, data, size); - lfi->body_size_accum += size; -} - -int LoadFirmware(VbCommonParams *cparams, VbSelectFirmwareParams *fparams, - VbNvContext *vnc) -{ - VbSharedDataHeader *shared = - (VbSharedDataHeader *)cparams->shared_data_blob; - GoogleBinaryBlockHeader *gbb = cparams->gbb; - VbPublicKey *root_key = NULL; - VbLoadFirmwareInternal *lfi; - - uint32_t try_b_count; - uint32_t lowest_version = 0xFFFFFFFF; - int good_index = -1; - int is_dev; - int index; - int i; - - int retval = VBERROR_UNKNOWN; - int recovery = VBNV_RECOVERY_RO_UNSPECIFIED; - - /* Clear output params in case we fail */ - shared->firmware_index = 0xFF; - - VBDEBUG(("LoadFirmware started...\n")); - - /* Must have a root key from the GBB */ - retval = VbGbbReadRootKey(cparams, &root_key); - if (retval) { - VBDEBUG(("No GBB\n")); - retval = VBERROR_INVALID_GBB; - goto LoadFirmwareExit; - } - - /* Parse flags */ - is_dev = (shared->flags & VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0); - if (is_dev) - shared->flags |= VBSD_LF_DEV_SWITCH_ON; - - /* Read try-b count and decrement if necessary */ - VbNvGet(vnc, VBNV_TRY_B_COUNT, &try_b_count); - if (0 != try_b_count) { - if (!(shared->flags & VBSD_NOFAIL_BOOT)) - VbNvSet(vnc, VBNV_TRY_B_COUNT, try_b_count - 1); - shared->flags |= VBSD_FWB_TRIED; - } - - /* Allocate our internal data */ - lfi = (VbLoadFirmwareInternal *) - VbExMalloc(sizeof(VbLoadFirmwareInternal)); - cparams->vboot_context = lfi; - - /* Loop over indices */ - for (i = 0; i < 2; i++) { - VbKeyBlockHeader *key_block; - uint32_t vblock_size; - VbFirmwarePreambleHeader *preamble; - RSAPublicKey *data_key; - uint64_t key_version; - uint32_t combined_version; - uint8_t *check_result; - - /* If try B count is non-zero try firmware B first */ - index = (try_b_count ? 1 - i : i); - if (0 == index) { - key_block = (VbKeyBlockHeader *) - fparams->verification_block_A; - vblock_size = fparams->verification_size_A; - check_result = &shared->check_fw_a_result; - } else { - key_block = (VbKeyBlockHeader *) - fparams->verification_block_B; - vblock_size = fparams->verification_size_B; - check_result = &shared->check_fw_b_result; - } - - /* - * Check the key block flags against the current boot mode. Do - * this before verifying the key block, since flags are faster - * to check than the RSA signature. - */ - if (!(key_block->key_block_flags & - (is_dev ? KEY_BLOCK_FLAG_DEVELOPER_1 : - KEY_BLOCK_FLAG_DEVELOPER_0))) { - VBDEBUG(("Developer flag mismatch.\n")); - *check_result = VBSD_LF_CHECK_DEV_MISMATCH; - continue; - } - - /* RW firmware never runs in recovery mode. */ - if (!(key_block->key_block_flags & KEY_BLOCK_FLAG_RECOVERY_0)) { - VBDEBUG(("Recovery flag mismatch.\n")); - *check_result = VBSD_LF_CHECK_REC_MISMATCH; - continue; - } - - /* Verify the key block */ - if ((0 != KeyBlockVerify(key_block, vblock_size, - root_key, 0))) { - VBDEBUG(("Key block verification failed.\n")); - *check_result = VBSD_LF_CHECK_VERIFY_KEYBLOCK; - continue; - } - - /* Check for rollback of key version. */ - key_version = key_block->data_key.key_version; - if (!(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) { - if (key_version < (shared->fw_version_tpm >> 16)) { - VBDEBUG(("Key rollback detected.\n")); - *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; - continue; - } - if (key_version > 0xFFFF) { - /* - * Key version is stored in 16 bits in the TPM, - * so key versions greater than 0xFFFF can't be - * stored properly. - */ - VBDEBUG(("Key version > 0xFFFF.\n")); - *check_result = VBSD_LF_CHECK_KEY_ROLLBACK; - continue; - } - } - - /* Get key for preamble/data verification from the key block. */ - data_key = PublicKeyToRSA(&key_block->data_key); - if (!data_key) { - VBDEBUG(("Unable to parse data key.\n")); - *check_result = VBSD_LF_CHECK_DATA_KEY_PARSE; - continue; - } - - /* Verify the preamble, which follows the key block. */ - preamble = (VbFirmwarePreambleHeader *) - ((uint8_t *)key_block + key_block->key_block_size); - if ((0 != VerifyFirmwarePreamble( - preamble, - vblock_size - key_block->key_block_size, - data_key))) { - VBDEBUG(("Preamble verfication failed.\n")); - *check_result = VBSD_LF_CHECK_VERIFY_PREAMBLE; - RSAPublicKeyFree(data_key); - continue; - } - - /* Check for rollback of firmware version. */ - combined_version = (uint32_t)((key_version << 16) | - (preamble->firmware_version & 0xFFFF)); - if (combined_version < shared->fw_version_tpm && - !(gbb->flags & GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK)) { - VBDEBUG(("Firmware version rollback detected.\n")); - *check_result = VBSD_LF_CHECK_FW_ROLLBACK; - RSAPublicKeyFree(data_key); - continue; - } - - /* Header for this firmware is valid */ - *check_result = VBSD_LF_CHECK_HEADER_VALID; - - /* Check for lowest key version from a valid header. */ - if (lowest_version > combined_version) - lowest_version = combined_version; - - /* - * If we already have good firmware, no need to read another - * one; we only needed to look at the versions to check for - * rollback. - */ - if (-1 != good_index) { - RSAPublicKeyFree(data_key); - continue; - } - - /* Handle preamble flag for using the RO normal/dev code path */ - VBDEBUG(("Preamble flags %#x\n", VbGetFirmwarePreambleFlags(preamble))); - if (VbGetFirmwarePreambleFlags(preamble) & - VB_FIRMWARE_PREAMBLE_USE_RO_NORMAL) { - - /* Fail if calling firmware doesn't support RO normal */ - if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT)) { - VBDEBUG(("No RO normal support.\n")); - *check_result = VBSD_LF_CHECK_NO_RO_NORMAL; - RSAPublicKeyFree(data_key); - continue; - } - - /* Use the RO normal code path */ - shared->flags |= VBSD_LF_USE_RO_NORMAL; - - } else { - VbError_t rv; - - /* Read the firmware data */ - vb2_digest_init(&lfi->body_digest_context, - vb2_crypto_to_hash(data_key->algorithm)); - lfi->body_size_accum = 0; - rv = VbExHashFirmwareBody( - cparams, - (index ? VB_SELECT_FIRMWARE_B : - VB_SELECT_FIRMWARE_A)); - if (VBERROR_SUCCESS != rv) { - VBDEBUG(("VbExHashFirmwareBody() failed for " - "index %d\n", index)); - *check_result = VBSD_LF_CHECK_GET_FW_BODY; - RSAPublicKeyFree(data_key); - continue; - } - if (lfi->body_size_accum != - preamble->body_signature.data_size) { - VBDEBUG(("Hashed %d bytes but expected %d\n", - (int)lfi->body_size_accum, - (int)preamble->body_signature.data_size)); - *check_result = VBSD_LF_CHECK_HASH_WRONG_SIZE; - RSAPublicKeyFree(data_key); - continue; - } - - /* Verify firmware data */ - uint8_t body_digest[VB2_MAX_DIGEST_SIZE]; - vb2_digest_finalize(&lfi->body_digest_context, - body_digest, sizeof(body_digest)); - if (0 != VerifyDigest(body_digest, - &preamble->body_signature, - data_key)) { - VBDEBUG(("FW body verification failed.\n")); - *check_result = VBSD_LF_CHECK_VERIFY_BODY; - RSAPublicKeyFree(data_key); - continue; - } - } - - /* Done with the data key, so can free it now */ - RSAPublicKeyFree(data_key); - - /* If we're still here, the firmware is valid. */ - VBDEBUG(("Firmware %d is valid.\n", index)); - *check_result = VBSD_LF_CHECK_VALID; - if (-1 == good_index) { - /* Save the key we actually used */ - if (0 != VbSharedDataSetKernelKey( - shared, &preamble->kernel_subkey)) { - /* - * The firmware signature was good, but the - * public key was bigger that the caller can - * handle. - */ - VBDEBUG(("Unable to save kernel subkey.\n")); - continue; - } - - /* - * Save the good index, now that we're sure we can - * actually use this firmware. That's the one we'll - * boot. - */ - good_index = index; - shared->firmware_index = (uint8_t)index; - shared->fw_keyblock_flags = key_block->key_block_flags; - - /* - * If the good firmware's key version is the same as - * the tpm, then the TPM doesn't need updating; we can - * stop now. Otherwise, we'll check all the other - * headers to see if they contain a newer key. - */ - if (combined_version == shared->fw_version_tpm) - break; - } - } - - /* Free internal data */ - VbExFree(lfi); - cparams->vboot_context = NULL; - - /* Handle finding good firmware */ - if (good_index >= 0) { - - /* Save versions we found */ - shared->fw_version_lowest = lowest_version; - if (lowest_version > shared->fw_version_tpm) - shared->fw_version_tpm = lowest_version; - - /* Success */ - VBDEBUG(("Will boot firmware index %d\n", - (int)shared->firmware_index)); - retval = VBERROR_SUCCESS; - - } else { - uint8_t a = shared->check_fw_a_result; - uint8_t b = shared->check_fw_b_result; - uint8_t best_check; - - /* No good firmware, so go to recovery mode. */ - VBDEBUG(("Alas, no good firmware.\n")); - recovery = VBNV_RECOVERY_RO_INVALID_RW; - retval = VBERROR_LOAD_FIRMWARE; - - /* - * If the best check result fits in the range of recovery - * reasons, provide more detail on how far we got in - * validation. - */ - best_check = (a > b ? a : b) + - VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN; - if (best_check >= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN && - best_check <= VBNV_RECOVERY_RO_INVALID_RW_CHECK_MAX) - recovery = best_check; - } - - LoadFirmwareExit: - VbExFree(root_key); - - /* Store recovery request, if any */ - VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ? - recovery : VBNV_RECOVERY_NOT_REQUESTED); - /* If the system does not support RO_NORMAL and LoadFirmware() - * encountered an error, update the shared recovery reason if - * recovery was not previously requested. */ - if (!(shared->flags & VBSD_BOOT_RO_NORMAL_SUPPORT) && - VBNV_RECOVERY_NOT_REQUESTED == shared->recovery_reason && - VBERROR_SUCCESS != retval) { - VBDEBUG(("RO normal but we got an error.\n")); - shared->recovery_reason = recovery; - } - - return retval; -} diff --git a/firmware/lib/vboot_nvstorage_rollback.c b/firmware/lib/vboot_nvstorage_rollback.c deleted file mode 100644 index a9132436..00000000 --- a/firmware/lib/vboot_nvstorage_rollback.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -/* Non-volatile storage routines. - */ -#include "sysincludes.h" - -#include "crc8.h" -#include "utility.h" -#include "vboot_common.h" -#include "vboot_nvstorage.h" -#include "rollback_index.h" - -/* These are the fields of the nvram that we want to back up. */ -static const VbNvParam backup_params[] = { - VBNV_KERNEL_FIELD, - VBNV_LOCALIZATION_INDEX, - VBNV_DEV_BOOT_USB, - VBNV_DEV_BOOT_LEGACY, - VBNV_DEV_BOOT_SIGNED_ONLY, - VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, - VBNV_DEV_DEFAULT_BOOT, - VBNV_FASTBOOT_UNLOCK_IN_FW, -}; - -/* We can't back things up if there isn't enough storage. */ -BUILD_ASSERT(VBNV_BLOCK_SIZE <= BACKUP_NV_SIZE); - -int RestoreNvFromBackup(VbNvContext *vnc) -{ - VbNvContext bvnc; - uint32_t value; - int i; - - VBDEBUG(("TPM: %s()\n", __func__)); - - if (TPM_SUCCESS != RollbackBackupRead(bvnc.raw)) - return 1; - - VbNvSetup(&bvnc); - if (bvnc.regenerate_crc) { - VBDEBUG(("TPM: Oops, backup is no good.\n")); - return 1; - } - - for (i = 0; i < ARRAY_SIZE(backup_params); i++) { - VbNvGet(&bvnc, backup_params[i], &value); - VbNvSet(vnc, backup_params[i], value); - } - - /* VbNvTeardown(&bvnc); is not needed. We're done with it. */ - return 0; -} - -int SaveNvToBackup(VbNvContext *vnc) -{ - VbNvContext bvnc; - uint32_t value; - int i; - - VBDEBUG(("TPM: %s()\n", __func__)); - - /* Read it first. No point in writing the same data. */ - if (TPM_SUCCESS != RollbackBackupRead(bvnc.raw)) - return 1; - - VbNvSetup(&bvnc); - VBDEBUG(("TPM: existing backup is %s\n", - bvnc.regenerate_crc ? "bad" : "good")); - - for (i = 0; i < ARRAY_SIZE(backup_params); i++) { - VbNvGet(vnc, backup_params[i], &value); - VbNvSet(&bvnc, backup_params[i], value); - } - - VbNvTeardown(&bvnc); - - if (!bvnc.raw_changed) { - VBDEBUG(("TPM: Nothing's changed, not writing backup\n")); - /* Clear the request flag, since we're happy. */ - VbNvSet(vnc, VBNV_BACKUP_NVRAM_REQUEST, 0); - return 0; - } - - if (TPM_SUCCESS == RollbackBackupWrite(bvnc.raw)) { - /* Clear the request flag if we wrote successfully too */ - VbNvSet(vnc, VBNV_BACKUP_NVRAM_REQUEST, 0); - return 0; - } - - VBDEBUG(("TPM: Sorry, couldn't write backup.\n")); - return 1; -} |