Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1305)

Unified Diff: vboot_firmware/lib/vboot_firmware.c

Issue 2745007: Major refactoring of structures, with unit tests. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Implemented LoadFirmware2() Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: vboot_firmware/lib/vboot_firmware.c
diff --git a/vboot_firmware/lib/vboot_firmware.c b/vboot_firmware/lib/vboot_firmware.c
new file mode 100644
index 0000000000000000000000000000000000000000..ce3f5290bdb6f8c48b9d4a63fce72e03f6d729bc
--- /dev/null
+++ b/vboot_firmware/lib/vboot_firmware.c
@@ -0,0 +1,173 @@
+/* Copyright (c) 2010 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 "vboot_firmware.h"
+
+#include "load_firmware_fw.h"
+#include "rollback_index.h"
+#include "utility.h"
+#include "vboot_common.h"
+
+
+void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) {
+ /* TODO: actually update the hash. */
+}
+
+
+int LoadFirmware2(LoadFirmwareParams* params) {
+
+ VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
+
+ uint16_t tpm_key_version = 0;
+ uint16_t tpm_fw_version = 0;
+ uint64_t lowest_key_version = 0xFFFF;
+ uint64_t lowest_fw_version = 0xFFFF;
+ int good_index = -1;
+ int index;
+
+ /* Clear output params in case we fail */
+ params->firmware_index = 0;
+ params->kernel_sign_key_blob = NULL;
+ params->kernel_sign_key_size = 0;
+
+ /* Must have a root key */
+ if (!root_key)
+ return LOAD_FIRMWARE_RECOVERY;
+
+ /* Initialize the TPM and read rollback indices. */
+ if (0 != SetupTPM() )
+ return LOAD_FIRMWARE_RECOVERY;
+ if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
+ &tpm_key_version, &tpm_fw_version))
+ return LOAD_FIRMWARE_RECOVERY;
+
+ /* Loop over indices */
+ for (index = 0; index < 2; index++) {
+ VbKeyBlockHeader* key_block;
+ uint64_t vblock_size;
+ VbFirmwarePreambleHeader* preamble;
+ RSAPublicKey* data_key;
+ uint64_t key_version;
+ uint8_t* body_data;
+ uint64_t body_size;
+
+ /* Verify the key block */
+ if (index) {
gauravsh 2010/06/10 14:44:13 nit/suggestion: since this is not a boolean check,
+ key_block = (VbKeyBlockHeader*)params->verification_block_1;
+ vblock_size = params->verification_size_1;
+ } else {
+ key_block = (VbKeyBlockHeader*)params->verification_block_0;
+ vblock_size = params->verification_size_0;
+ }
+ if ((0 != VerifyKeyBlock(key_block, vblock_size, root_key)))
+ continue;
+
+ /* Check for rollback of key version. */
+ key_version = key_block->data_key.key_version;
+ if (key_version < tpm_key_version)
+ continue;
+
+ /* Get the key for preamble/data verification from the key block. */
+ data_key = PublicKeyToRSA(&key_block->data_key);
+ if (!data_key)
+ continue;
+
+ /* Verify the preamble, which follows the key block. */
+ preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block +
+ key_block->key_block_size);
+ if ((0 != VerifyFirmwarePreamble2(preamble,
+ vblock_size - key_block->key_block_size,
+ data_key))) {
+ RSAPublicKeyFree(data_key);
+ continue;
+ }
+
+ /* Check for rollback of firmware version. */
+ if (key_version == tpm_key_version &&
+ preamble->firmware_version < tpm_fw_version) {
+ RSAPublicKeyFree(data_key);
+ continue;
+ }
+
+ /* Check for lowest key version from a valid header. */
+ if (lowest_key_version > key_version) {
+ lowest_key_version = key_version;
+ lowest_fw_version = preamble->firmware_version;
+ }
+ else if (lowest_key_version == key_version &&
+ lowest_fw_version > preamble->firmware_version) {
+ lowest_fw_version = preamble->firmware_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)
+ continue;
+
+ /* Read the firmware data */
+ /* TODO: should set up hash for UpdateFirmwareBodyHash(). */
+ body_data = GetFirmwareBody(index, &body_size);
+ if (!body_data || (body_size != preamble->body_signature.data_size)) {
+ RSAPublicKeyFree(data_key);
+ continue;
+ }
+
+ /* Verify firmware data */
+ /* TODO: should use hash from UpdateFirmwareBodyHash() rather than
+ * recalculating it in VerifyData(). */
+ if (0 != VerifyData(body_data, &preamble->body_signature, data_key)) {
+ 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. */
+ /* Save the first good firmware we find; that's the one we'll boot */
+ if (-1 == good_index) {
+ good_index = index;
+ params->firmware_index = index;
+ params->kernel_sign_key_blob = &preamble->kernel_subkey;
+ params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset +
+ preamble->kernel_subkey.key_size);
+
+ /* 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 (key_version == tpm_key_version &&
+ preamble->firmware_version == tpm_fw_version)
+ break;
+ }
+ }
+
+ /* Handle finding good firmware */
+ if (good_index >= 0) {
+
+ /* Update TPM if necessary */
+ if ((lowest_key_version > tpm_key_version) ||
+ (lowest_key_version == tpm_key_version &&
+ lowest_fw_version > tpm_fw_version)) {
+ if (0 != WriteStoredVersions(FIRMWARE_VERSIONS,
+ lowest_key_version,
+ lowest_fw_version))
+ return LOAD_FIRMWARE_RECOVERY;
+ }
+
+ /* Lock Firmware TPM rollback indices from further writes. In
+ * this design, this is done by setting the globalLock bit, which
+ * is cleared only by TPM_Init at reboot. */
+ if (0 != LockFirmwareVersions())
+ return LOAD_FIRMWARE_RECOVERY;
+ }
+
+ /* If we're still here, no good firmware, so go to recovery mode. */
+ return LOAD_FIRMWARE_RECOVERY;
+}

Powered by Google App Engine
This is Rietveld 408576698