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

Side by Side 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 unified diff | Download patch
OLDNEW
(Empty)
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
3 * found in the LICENSE file.
4 *
5 * High-level firmware API for loading and verifying rewritable firmware.
6 * (Firmware portion)
7 */
8
9 #include "vboot_firmware.h"
10
11 #include "load_firmware_fw.h"
12 #include "rollback_index.h"
13 #include "utility.h"
14 #include "vboot_common.h"
15
16
17 void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) {
18 /* TODO: actually update the hash. */
19 }
20
21
22 int LoadFirmware2(LoadFirmwareParams* params) {
23
24 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
25
26 uint16_t tpm_key_version = 0;
27 uint16_t tpm_fw_version = 0;
28 uint64_t lowest_key_version = 0xFFFF;
29 uint64_t lowest_fw_version = 0xFFFF;
30 int good_index = -1;
31 int index;
32
33 /* Clear output params in case we fail */
34 params->firmware_index = 0;
35 params->kernel_sign_key_blob = NULL;
36 params->kernel_sign_key_size = 0;
37
38 /* Must have a root key */
39 if (!root_key)
40 return LOAD_FIRMWARE_RECOVERY;
41
42 /* Initialize the TPM and read rollback indices. */
43 if (0 != SetupTPM() )
44 return LOAD_FIRMWARE_RECOVERY;
45 if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
46 &tpm_key_version, &tpm_fw_version))
47 return LOAD_FIRMWARE_RECOVERY;
48
49 /* Loop over indices */
50 for (index = 0; index < 2; index++) {
51 VbKeyBlockHeader* key_block;
52 uint64_t vblock_size;
53 VbFirmwarePreambleHeader* preamble;
54 RSAPublicKey* data_key;
55 uint64_t key_version;
56 uint8_t* body_data;
57 uint64_t body_size;
58
59 /* Verify the key block */
60 if (index) {
gauravsh 2010/06/10 14:44:13 nit/suggestion: since this is not a boolean check,
61 key_block = (VbKeyBlockHeader*)params->verification_block_1;
62 vblock_size = params->verification_size_1;
63 } else {
64 key_block = (VbKeyBlockHeader*)params->verification_block_0;
65 vblock_size = params->verification_size_0;
66 }
67 if ((0 != VerifyKeyBlock(key_block, vblock_size, root_key)))
68 continue;
69
70 /* Check for rollback of key version. */
71 key_version = key_block->data_key.key_version;
72 if (key_version < tpm_key_version)
73 continue;
74
75 /* Get the key for preamble/data verification from the key block. */
76 data_key = PublicKeyToRSA(&key_block->data_key);
77 if (!data_key)
78 continue;
79
80 /* Verify the preamble, which follows the key block. */
81 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block +
82 key_block->key_block_size);
83 if ((0 != VerifyFirmwarePreamble2(preamble,
84 vblock_size - key_block->key_block_size,
85 data_key))) {
86 RSAPublicKeyFree(data_key);
87 continue;
88 }
89
90 /* Check for rollback of firmware version. */
91 if (key_version == tpm_key_version &&
92 preamble->firmware_version < tpm_fw_version) {
93 RSAPublicKeyFree(data_key);
94 continue;
95 }
96
97 /* Check for lowest key version from a valid header. */
98 if (lowest_key_version > key_version) {
99 lowest_key_version = key_version;
100 lowest_fw_version = preamble->firmware_version;
101 }
102 else if (lowest_key_version == key_version &&
103 lowest_fw_version > preamble->firmware_version) {
104 lowest_fw_version = preamble->firmware_version;
105 }
106
107 /* If we already have good firmware, no need to read another one;
108 * we only needed to look at the versions to check for
109 * rollback. */
110 if (-1 != good_index)
111 continue;
112
113 /* Read the firmware data */
114 /* TODO: should set up hash for UpdateFirmwareBodyHash(). */
115 body_data = GetFirmwareBody(index, &body_size);
116 if (!body_data || (body_size != preamble->body_signature.data_size)) {
117 RSAPublicKeyFree(data_key);
118 continue;
119 }
120
121 /* Verify firmware data */
122 /* TODO: should use hash from UpdateFirmwareBodyHash() rather than
123 * recalculating it in VerifyData(). */
124 if (0 != VerifyData(body_data, &preamble->body_signature, data_key)) {
125 RSAPublicKeyFree(data_key);
126 continue;
127 }
128
129 /* Done with the data key, so can free it now */
130 RSAPublicKeyFree(data_key);
131
132 /* If we're still here, the firmware is valid. */
133 /* Save the first good firmware we find; that's the one we'll boot */
134 if (-1 == good_index) {
135 good_index = index;
136 params->firmware_index = index;
137 params->kernel_sign_key_blob = &preamble->kernel_subkey;
138 params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset +
139 preamble->kernel_subkey.key_size);
140
141 /* If the good firmware's key version is the same as the tpm,
142 * then the TPM doesn't need updating; we can stop now.
143 * Otherwise, we'll check all the other headers to see if they
144 * contain a newer key. */
145 if (key_version == tpm_key_version &&
146 preamble->firmware_version == tpm_fw_version)
147 break;
148 }
149 }
150
151 /* Handle finding good firmware */
152 if (good_index >= 0) {
153
154 /* Update TPM if necessary */
155 if ((lowest_key_version > tpm_key_version) ||
156 (lowest_key_version == tpm_key_version &&
157 lowest_fw_version > tpm_fw_version)) {
158 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS,
159 lowest_key_version,
160 lowest_fw_version))
161 return LOAD_FIRMWARE_RECOVERY;
162 }
163
164 /* Lock Firmware TPM rollback indices from further writes. In
165 * this design, this is done by setting the globalLock bit, which
166 * is cleared only by TPM_Init at reboot. */
167 if (0 != LockFirmwareVersions())
168 return LOAD_FIRMWARE_RECOVERY;
169 }
170
171 /* If we're still here, no good firmware, so go to recovery mode. */
172 return LOAD_FIRMWARE_RECOVERY;
173 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698