summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorLuigi Semenzato <semenzato@google.com>2010-06-28 13:34:31 -0700
committerLuigi Semenzato <semenzato@google.com>2010-06-28 13:34:31 -0700
commit2b9ddae52ba564dddcfc8bdcbed04dc07a52a7c6 (patch)
tree13832a568a9bfca1f6851991ed681cba0db5928d /firmware
parent46186faf4620c9775836bf8ad703fb6c481e68cd (diff)
downloadvboot-2b9ddae52ba564dddcfc8bdcbed04dc07a52a7c6.tar.gz
New rollback_index API.
Review URL: http://codereview.chromium.org/2869022
Diffstat (limited to 'firmware')
-rw-r--r--firmware/lib/include/rollback_index.h44
-rw-r--r--firmware/lib/rollback_index.c205
-rw-r--r--firmware/lib/vboot_firmware.c10
-rw-r--r--firmware/linktest/main.c3
-rw-r--r--firmware/version.c2
5 files changed, 91 insertions, 173 deletions
diff --git a/firmware/lib/include/rollback_index.h b/firmware/lib/include/rollback_index.h
index d60a1701..e3399123 100644
--- a/firmware/lib/include/rollback_index.h
+++ b/firmware/lib/include/rollback_index.h
@@ -11,13 +11,6 @@
#include "sysincludes.h"
-/* TODO: global variables won't work in the boot stub, since it runs
- directly out of ROM. */
-extern uint16_t g_firmware_key_version;
-extern uint16_t g_firmware_version;
-extern uint16_t g_kernel_key_version;
-extern uint16_t g_kernel_version;
-
/* Rollback version types. */
#define FIRMWARE_VERSIONS 0
#define KERNEL_VERSIONS 1
@@ -43,7 +36,6 @@ extern uint16_t g_kernel_version;
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */
-
/*
Call from LoadFirmware()
@@ -51,7 +43,8 @@ Call from LoadFirmware()
Wants firmware versions
Must send in developer flag
- RollbackFirmwareSetup(IN devmode, OUT firmware versions)
+ RollbackFirmwareSetup(IN devmode)
+ (maybe) RollbackFirmwareRead()
(maybe) RollbackFirmwareWrite()
RollbackFirmwareLock()
@@ -73,48 +66,33 @@ Call from LoadKernel()
/* These functions are callable from LoadFirmware(). They cannot use
* global variables. */
+
/* Setup must be called. Pass developer_mode=nonzero if in developer
* mode. */
-uint32_t RollbackFirmwareSetup(int developer_mode,
- uint16_t* key_version, uint16_t* version);
+uint32_t RollbackFirmwareSetup(int developer_mode);
+/* Read and Write may be called after Setup. */
+uint32_t RollbackFirmwareRead(uint16_t* key_version, uint16_t* version);
/* Write may be called if the versions change */
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version);
+
/* Lock must be called */
uint32_t RollbackFirmwareLock(void);
/* These functions are callable from LoadKernel(). They may use global
* variables. */
+
/* Recovery may be called. If it is, this is the first time a
* rollback function has been called this boot, so it needs to know if
* we're in developer mode. Pass developer_mode=nonzero if in developer
* mode. */
uint32_t RollbackKernelRecovery(int developer_mode);
+
/* Read and write may be called if not in developer mode. If called in
- * recovery mode, these are ignored and/or return 0 versions. */
+ * recovery mode, the effect is undefined. */
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version);
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version);
+
/* Lock must be called. Internally, it's ignored in recovery mode. */
uint32_t RollbackKernelLock(void);
-
-/* SetupTPM is called on boot and on starting the RW firmware, passing the
- * appripriate MODE and DEVELOPER_FLAG parameters. MODE can be one of
- * RO_RECOVERY_MODE, RO_NORMAL_MODE, RW_NORMAL_MODE. DEVELOPER_FLAG is 1 when
- * the developer switch is ON, 0 otherwise.
- *
- * If SetupTPM returns TPM_SUCCESS, the caller may proceed. If it returns
- * TPM_E_MUST_REBOOT, the caller must reboot in the current mode. For all
- * other return values, the caller must reboot in recovery mode.
- *
- * This function has many side effects on the TPM state. In particular, when
- * called with mode = RECOVERY_MODE, it locks the firmware versions before
- * returning. In all other cases, the caller is responsible for locking the
- * firmware versions once it decides it doesn't need to update them.
- */
-uint32_t SetupTPM(int mode, int developer_flag);
-uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version);
-uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version);
-uint32_t LockFirmwareVersions(void);
-uint32_t LockKernelVersionsByLockingPP(void);
-
#endif /* VBOOT_REFERENCE_ROLLBACK_INDEX_H_ */
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 4fb7ec97..4629e6e4 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -12,10 +12,7 @@
#include "tss_constants.h"
#include "utility.h"
-uint16_t g_firmware_key_version = 0;
-uint16_t g_firmware_version = 0;
-uint16_t g_kernel_key_version = 0;
-uint16_t g_kernel_version = 0;
+static int g_rollback_recovery_mode = 0;
/* disable MSVC warning on const logical expression (as in } while(0);) */
__pragma(warning (disable: 4127))
@@ -133,34 +130,6 @@ static uint32_t SetDistrustKernelSpaceAtNextBoot(uint32_t distrust) {
return TPM_SUCCESS;
}
-static uint32_t GetTPMRollbackIndices(int type) {
- uint32_t firmware_versions;
- uint32_t kernel_versions;
-
- /* We perform the reads, making sure they succeed. A failure means that the
- * rollback index locations are missing or somehow messed up. We let the
- * caller deal with that.
- */
- switch (type) {
- case FIRMWARE_VERSIONS:
- RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX,
- (uint8_t*) &firmware_versions,
- sizeof(firmware_versions)));
- g_firmware_key_version = (uint16_t) (firmware_versions >> 16);
- g_firmware_version = (uint16_t) (firmware_versions & 0xffff);
- break;
- case KERNEL_VERSIONS:
- RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
- (uint8_t*) &kernel_versions,
- sizeof(kernel_versions)));
- g_kernel_key_version = (uint16_t) (kernel_versions >> 16);
- g_kernel_version = (uint16_t) (kernel_versions & 0xffff);
- break;
- }
-
- return TPM_SUCCESS;
-}
-
/* Checks if the kernel version space has been mucked with. If it has,
* reconstructs it using the backup value.
*/
@@ -244,9 +213,30 @@ static uint32_t CheckDeveloperModeTransition(uint32_t current_developer) {
return TPM_SUCCESS;
}
-static uint32_t SetupTPM_(int mode, int developer_flag) {
+/* 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.
+ */
+static uint32_t SetupTPM(int recovery_mode,
+ int developer_mode) {
uint8_t disable;
uint8_t deactivated;
+
TlclLibInit();
RETURN_ON_FAILURE(TlclStartup());
RETURN_ON_FAILURE(TlclContinueSelfTest());
@@ -272,136 +262,83 @@ static uint32_t SetupTPM_(int mode, int developer_flag) {
}
}
RETURN_ON_FAILURE(BackupKernelSpace());
- RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(mode == RO_RECOVERY_MODE));
- RETURN_ON_FAILURE(GetTPMRollbackIndices(FIRMWARE_VERSIONS));
- RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS));
-
- RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_flag));
-
- /* As a courtesy (I hope) to the caller, lock the firmware versions if we are
- * in recovery mode. The normal mode may need to update the firmware
- * versions, so they cannot be locked here.
- */
- if (mode == RO_RECOVERY_MODE) {
- RETURN_ON_FAILURE(LockFirmwareVersions());
- }
- return TPM_SUCCESS;
-}
-
-/* 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 mode, int developer_flag) {
- switch (mode) {
- case RO_RECOVERY_MODE:
- case RO_NORMAL_MODE: {
- uint32_t result = SetupTPM_(mode, developer_flag);
- if (mode == RO_NORMAL_MODE) {
- return result;
- } else {
- /* In recovery mode we want to keep going even if there are errors. */
- return TPM_SUCCESS;
- }
- }
- case RW_NORMAL_MODE:
- RETURN_ON_FAILURE(GetTPMRollbackIndices(KERNEL_VERSIONS));
- default:
- return TPM_E_INTERNAL_INCONSISTENCY;
- }
-}
-
-uint32_t GetStoredVersions(int type, uint16_t* key_version, uint16_t* version) {
- /* TODO: should verify that SetupTPM() has been called.
- *
- * Note that SetupTPM() does hardware setup AND sets global variables. When
- * we get down into kernel verification, the hardware setup persists, but we
- * lose the global variables.
- */
- switch (type) {
- case FIRMWARE_VERSIONS:
- *key_version = g_firmware_key_version;
- *version = g_firmware_version;
- break;
- case KERNEL_VERSIONS:
- *key_version = g_kernel_key_version;
- *version = g_kernel_version;
- break;
- }
-
- return TPM_SUCCESS;
-}
+ RETURN_ON_FAILURE(SetDistrustKernelSpaceAtNextBoot(recovery_mode));
+ RETURN_ON_FAILURE(CheckDeveloperModeTransition(developer_mode));
-uint32_t WriteStoredVersions(int type, uint16_t key_version, uint16_t version) {
- uint32_t combined_version = (key_version << 16) & version;
- switch (type) {
- case FIRMWARE_VERSIONS:
- RETURN_ON_FAILURE(SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
- (uint8_t*) &combined_version,
- sizeof(uint32_t)));
- break;
-
- case KERNEL_VERSIONS:
- RETURN_ON_FAILURE(SafeWrite(KERNEL_VERSIONS_NV_INDEX,
- (uint8_t*) &combined_version,
- sizeof(uint32_t)));
+ if (recovery_mode) {
+ /* In recovery mode global variables are usable. */
+ g_rollback_recovery_mode = 1;
}
return TPM_SUCCESS;
}
-uint32_t LockFirmwareVersions() {
- return TlclSetGlobalLock();
-}
-
-uint32_t LockKernelVersionsByLockingPP() {
- return TlclLockPhysicalPresence();
-}
-
/* disable MSVC warnings on unused arguments */
__pragma(warning (disable: 4100))
-/* NEW APIS! HELP ME LUIGI, YOU'RE MY ONLY HOPE! */
+uint32_t RollbackFirmwareSetup(int developer_mode) {
+ return SetupTPM(0, developer_mode);
+}
-uint32_t RollbackFirmwareSetup(int developer_mode,
- uint16_t* key_version, uint16_t* version) {
+uint32_t RollbackFirmwareRead(uint16_t* key_version, uint16_t* version) {
+ uint32_t firmware_versions;
+ /* Gets firmware versions. */
+ RETURN_ON_FAILURE(TlclRead(FIRMWARE_VERSIONS_NV_INDEX,
+ (uint8_t*) &firmware_versions,
+ sizeof(firmware_versions)));
+ *key_version = (uint16_t) (firmware_versions >> 16);
+ *version = (uint16_t) (firmware_versions & 0xffff);
return TPM_SUCCESS;
}
uint32_t RollbackFirmwareWrite(uint16_t key_version, uint16_t version) {
- return TPM_SUCCESS;
+ uint32_t combined_version = (key_version << 16) & version;
+ return SafeWrite(FIRMWARE_VERSIONS_NV_INDEX,
+ (uint8_t*) &combined_version,
+ sizeof(uint32_t));
}
uint32_t RollbackFirmwareLock(void) {
- return TPM_SUCCESS;
+ return TlclSetGlobalLock();
}
uint32_t RollbackKernelRecovery(int developer_mode) {
+ uint32_t result = SetupTPM(1, developer_mode);
+ if (result == TPM_SUCCESS) {
+ RETURN_ON_FAILURE(TlclSetGlobalLock());
+ }
return TPM_SUCCESS;
}
uint32_t RollbackKernelRead(uint16_t* key_version, uint16_t* version) {
+ uint32_t kernel_versions;
+ if (g_rollback_recovery_mode) {
+ *key_version = 0;
+ *version = 0;
+ } else {
+ /* Reads kernel versions from TPM. */
+ RETURN_ON_FAILURE(TlclRead(KERNEL_VERSIONS_NV_INDEX,
+ (uint8_t*) &kernel_versions,
+ sizeof(kernel_versions)));
+ *key_version = (uint16_t) (kernel_versions >> 16);
+ *version = (uint16_t) (kernel_versions & 0xffff);
+ }
return TPM_SUCCESS;
}
uint32_t RollbackKernelWrite(uint16_t key_version, uint16_t version) {
+ if (!g_rollback_recovery_mode) {
+ uint32_t combined_version = (key_version << 16) & version;
+ return SafeWrite(KERNEL_VERSIONS_NV_INDEX,
+ (uint8_t*) &combined_version,
+ sizeof(uint32_t));
+ }
return TPM_SUCCESS;
}
uint32_t RollbackKernelLock(void) {
- return TPM_SUCCESS;
+ if (!g_rollback_recovery_mode) {
+ return TlclLockPhysicalPresence();
+ } else {
+ return TPM_SUCCESS;
+ }
}
diff --git a/firmware/lib/vboot_firmware.c b/firmware/lib/vboot_firmware.c
index 11ea6f77..c445a819 100644
--- a/firmware/lib/vboot_firmware.c
+++ b/firmware/lib/vboot_firmware.c
@@ -60,10 +60,12 @@ int LoadFirmware(LoadFirmwareParams* params) {
}
/* Initialize the TPM and read rollback indices. */
- if (0 != RollbackFirmwareSetup(
- (params->boot_flags & BOOT_FLAG_DEVELOPER ? 1 : 0),
- &tpm_key_version, &tpm_fw_version)) {
- VBDEBUG(("Unable to get stored versions.\n"));
+ if (0 != RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER)) {
+ VBDEBUG(("Unable to setup TPM.\n"));
+ return LOAD_FIRMWARE_RECOVERY;
+ }
+ if (0 != RollbackFirmwareRead(&tpm_key_version, &tpm_fw_version)) {
+ VBDEBUG(("Unable to read stored versions.\n"));
return LOAD_FIRMWARE_RECOVERY;
}
diff --git a/firmware/linktest/main.c b/firmware/linktest/main.c
index f91da995..4696c2e6 100644
--- a/firmware/linktest/main.c
+++ b/firmware/linktest/main.c
@@ -24,7 +24,8 @@ int main(void)
LoadKernel(0);
/* rollback_index.h */
- RollbackFirmwareSetup(0, &x, &y);
+ RollbackFirmwareSetup(0);
+ RollbackFirmwareRead(&x, &y);
RollbackFirmwareWrite(0, 0);
RollbackFirmwareLock();
RollbackKernelRecovery(0);
diff --git a/firmware/version.c b/firmware/version.c
index 85a0ae77..3fa3bed5 100644
--- a/firmware/version.c
+++ b/firmware/version.c
@@ -1 +1 @@
-char* VbootVersion = "VBOOv=c9cb6a2f";
+char* VbootVersion = "VBOOv=7bb80e3a";