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

Side by Side Diff: vboot_firmware/lib/vboot_firmware.c

Issue 2848006: Refactor LoadFrmware() to avoid global variables, which don't work when running out of ROM (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Undo change to vboot_struct 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
« no previous file with comments | « vboot_firmware/lib/vboot_common.c ('k') | vboot_firmware/linktest/main.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 * High-level firmware API for loading and verifying rewritable firmware. 5 * High-level firmware API for loading and verifying rewritable firmware.
6 * (Firmware portion) 6 * (Firmware portion)
7 */ 7 */
8 8
9 #include "vboot_firmware.h" 9 #include "vboot_firmware.h"
10 10
11 #include "load_firmware_fw.h" 11 #include "load_firmware_fw.h"
12 #include "rollback_index.h" 12 #include "rollback_index.h"
13 #include "utility.h" 13 #include "utility.h"
14 #include "vboot_common.h" 14 #include "vboot_common.h"
15 15
16 /* Static variables for UpdateFirmwareBodyHash(). It's less than 16 /* Static variables for UpdateFirmwareBodyHash(). It's less than
17 * optimal to have static variables in a library, but in UEFI the 17 * optimal to have static variables in a library, but in UEFI the
18 * caller is deep inside a different firmware stack and doesn't have a 18 * caller is deep inside a different firmware stack and doesn't have a
19 * good way to pass the params struct back to us. */ 19 * good way to pass the params struct back to us. */
20 static DigestContext ctx; 20 typedef struct VbLoadFirmwareInternal {
21 static uint64_t body_size_accum = 0; 21 DigestContext ctx;
22 static int inside_load_firmware = 0; 22 uint64_t body_size_accum;
23 } VbLoadFirmwareInternal;
23 24
24 void UpdateFirmwareBodyHash2(uint8_t* data, uint64_t size) {
25 25
26 if (!inside_load_firmware) { 26 void UpdateFirmwareBodyHash(LoadFirmwareParams* params,
27 debug("UpdateFirmwareBodyHash() called outside LoadFirmware()\n"); 27 uint8_t* data, uint64_t size) {
28 return; 28 VbLoadFirmwareInternal* lfi =
29 } 29 (VbLoadFirmwareInternal*)params->load_firmware_internal;
30 30
31 DigestUpdate(&ctx, data, size); 31 DigestUpdate(&lfi->ctx, data, size);
32 body_size_accum += size; 32 lfi->body_size_accum += size;
33 } 33 }
34 34
35 35
36 int LoadFirmware2(LoadFirmwareParams* params) { 36 int LoadFirmware2(LoadFirmwareParams* params) {
37 37
38 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; 38 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
39 VbLoadFirmwareInternal* lfi;
39 40
40 uint16_t tpm_key_version = 0; 41 uint16_t tpm_key_version = 0;
41 uint16_t tpm_fw_version = 0; 42 uint16_t tpm_fw_version = 0;
42 uint64_t lowest_key_version = 0xFFFF; 43 uint64_t lowest_key_version = 0xFFFF;
43 uint64_t lowest_fw_version = 0xFFFF; 44 uint64_t lowest_fw_version = 0xFFFF;
44 int good_index = -1; 45 int good_index = -1;
45 int index; 46 int index;
46 47
47 /* Clear output params in case we fail */ 48 /* Clear output params in case we fail */
48 params->firmware_index = 0; 49 params->firmware_index = 0;
49 params->kernel_sign_key_blob = NULL; 50 params->kernel_sign_key_blob = NULL;
50 params->kernel_sign_key_size = 0; 51 params->kernel_sign_key_size = 0;
51 52
52 /* Must have a root key */ 53 /* Must have a root key */
53 if (!root_key) 54 if (!root_key)
54 return LOAD_FIRMWARE_RECOVERY; 55 return LOAD_FIRMWARE_RECOVERY;
55 56
56 /* Initialize the TPM and read rollback indices. */ 57 /* Initialize the TPM and read rollback indices. */
57 /* TODO: fix SetupTPM parameter */ 58 /* TODO: fix SetupTPM parameter */
58 if (0 != SetupTPM(0, 0) ) 59 if (0 != SetupTPM(0, 0) )
59 return LOAD_FIRMWARE_RECOVERY; 60 return LOAD_FIRMWARE_RECOVERY;
60 if (0 != GetStoredVersions(FIRMWARE_VERSIONS, 61 if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
61 &tpm_key_version, &tpm_fw_version)) 62 &tpm_key_version, &tpm_fw_version))
62 return LOAD_FIRMWARE_RECOVERY; 63 return LOAD_FIRMWARE_RECOVERY;
63 64
65 /* Allocate our internal data */
66 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal));
67 if (!lfi)
68 return LOAD_FIRMWARE_RECOVERY;
69 params->load_firmware_internal = lfi;
70
64 /* Loop over indices */ 71 /* Loop over indices */
65 for (index = 0; index < 2; index++) { 72 for (index = 0; index < 2; index++) {
66 VbKeyBlockHeader* key_block; 73 VbKeyBlockHeader* key_block;
67 uint64_t vblock_size; 74 uint64_t vblock_size;
68 VbFirmwarePreambleHeader* preamble; 75 VbFirmwarePreambleHeader* preamble;
69 RSAPublicKey* data_key; 76 RSAPublicKey* data_key;
70 uint64_t key_version; 77 uint64_t key_version;
71 uint8_t* body_data;
72 uint64_t body_size;
73 uint8_t* body_digest; 78 uint8_t* body_digest;
74 79
75 /* Verify the key block */ 80 /* Verify the key block */
76 if (0 == index) { 81 if (0 == index) {
77 key_block = (VbKeyBlockHeader*)params->verification_block_0; 82 key_block = (VbKeyBlockHeader*)params->verification_block_0;
78 vblock_size = params->verification_size_0; 83 vblock_size = params->verification_size_0;
79 } else { 84 } else {
80 key_block = (VbKeyBlockHeader*)params->verification_block_1; 85 key_block = (VbKeyBlockHeader*)params->verification_block_1;
81 vblock_size = params->verification_size_1; 86 vblock_size = params->verification_size_1;
82 } 87 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 lowest_fw_version = preamble->firmware_version; 125 lowest_fw_version = preamble->firmware_version;
121 } 126 }
122 127
123 /* If we already have good firmware, no need to read another one; 128 /* If we already have good firmware, no need to read another one;
124 * we only needed to look at the versions to check for 129 * we only needed to look at the versions to check for
125 * rollback. */ 130 * rollback. */
126 if (-1 != good_index) 131 if (-1 != good_index)
127 continue; 132 continue;
128 133
129 /* Read the firmware data */ 134 /* Read the firmware data */
130 DigestInit(&ctx, data_key->algorithm); 135 DigestInit(&lfi->ctx, data_key->algorithm);
131 body_size_accum = 0; 136 lfi->body_size_accum = 0;
132 inside_load_firmware = 1; 137 if ((0 != GetFirmwareBody(params, index)) ||
133 body_data = GetFirmwareBody(index, &body_size); 138 (lfi->body_size_accum != preamble->body_signature.data_size)) {
134 inside_load_firmware = 0;
135 body_digest = DigestFinal(&ctx);
136 if (!body_data || (body_size != preamble->body_signature.data_size) ||
137 (body_size_accum != body_size)) {
138 RSAPublicKeyFree(data_key); 139 RSAPublicKeyFree(data_key);
139 Free(body_digest);
140 continue; 140 continue;
141 } 141 }
142 142
143 /* Verify firmware data */ 143 /* Verify firmware data */
144 body_digest = DigestFinal(&lfi->ctx);
144 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) { 145 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) {
145 RSAPublicKeyFree(data_key); 146 RSAPublicKeyFree(data_key);
146 Free(body_digest); 147 Free(body_digest);
147 continue; 148 continue;
148 } 149 }
149 150
150 /* Done with the digest and data key, so can free them now */ 151 /* Done with the digest and data key, so can free them now */
151 RSAPublicKeyFree(data_key); 152 RSAPublicKeyFree(data_key);
152 Free(body_digest); 153 Free(body_digest);
153 154
154 /* If we're still here, the firmware is valid. */ 155 /* If we're still here, the firmware is valid. */
155 /* Save the first good firmware we find; that's the one we'll boot */ 156 /* Save the first good firmware we find; that's the one we'll boot */
156 if (-1 == good_index) { 157 if (-1 == good_index) {
158 VbPublicKey *kdest = (VbPublicKey*)params->kernel_sign_key_blob;
159
160 /* Copy the kernel sign key blob into the destination buffer */
161 PublicKeyInit(kdest, (uint8_t*)(kdest + 1),
162 (params->kernel_sign_key_size - sizeof(VbPublicKey)));
163
164 if (0 != PublicKeyCopy(kdest, &preamble->kernel_subkey))
165 continue; /* The firmware signature was good, but the public
166 * key was bigger that the caller can handle. */
167
168 /* Save the key size we actually used */
169 params->kernel_sign_key_size = kdest->key_offset + kdest->key_size;
170
171 /* Save the good index, now that we're sure we can actually use
172 * this firmware. */
157 good_index = index; 173 good_index = index;
158 params->firmware_index = index; 174 params->firmware_index = index;
159 params->kernel_sign_key_blob = &preamble->kernel_subkey;
160 params->kernel_sign_key_size = (preamble->kernel_subkey.key_offset +
161 preamble->kernel_subkey.key_size);
162 175
163 /* If the good firmware's key version is the same as the tpm, 176 /* If the good firmware's key version is the same as the tpm,
164 * then the TPM doesn't need updating; we can stop now. 177 * then the TPM doesn't need updating; we can stop now.
165 * Otherwise, we'll check all the other headers to see if they 178 * Otherwise, we'll check all the other headers to see if they
166 * contain a newer key. */ 179 * contain a newer key. */
167 if (key_version == tpm_key_version && 180 if (key_version == tpm_key_version &&
168 preamble->firmware_version == tpm_fw_version) 181 preamble->firmware_version == tpm_fw_version)
169 break; 182 break;
170 } 183 }
171 } 184 }
172 185
186 /* Free internal data */
187 Free(lfi);
188 params->load_firmware_internal = NULL;
189
173 /* Handle finding good firmware */ 190 /* Handle finding good firmware */
174 if (good_index >= 0) { 191 if (good_index >= 0) {
175 192
176 /* Update TPM if necessary */ 193 /* Update TPM if necessary */
177 if ((lowest_key_version > tpm_key_version) || 194 if ((lowest_key_version > tpm_key_version) ||
178 (lowest_key_version == tpm_key_version && 195 (lowest_key_version == tpm_key_version &&
179 lowest_fw_version > tpm_fw_version)) { 196 lowest_fw_version > tpm_fw_version)) {
180 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS, 197 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS,
181 lowest_key_version, 198 lowest_key_version,
182 lowest_fw_version)) 199 lowest_fw_version))
183 return LOAD_FIRMWARE_RECOVERY; 200 return LOAD_FIRMWARE_RECOVERY;
184 } 201 }
185 202
186 /* Lock Firmware TPM rollback indices from further writes. In 203 /* Lock Firmware TPM rollback indices from further writes. In
187 * this design, this is done by setting the globalLock bit, which 204 * this design, this is done by setting the globalLock bit, which
188 * is cleared only by TPM_Init at reboot. */ 205 * is cleared only by TPM_Init at reboot. */
189 if (0 != LockFirmwareVersions()) 206 if (0 != LockFirmwareVersions())
190 return LOAD_FIRMWARE_RECOVERY; 207 return LOAD_FIRMWARE_RECOVERY;
191 } 208 }
192 209
193 /* If we're still here, no good firmware, so go to recovery mode. */ 210 /* If we're still here, no good firmware, so go to recovery mode. */
194 return LOAD_FIRMWARE_RECOVERY; 211 return LOAD_FIRMWARE_RECOVERY;
195 } 212 }
OLDNEW
« no previous file with comments | « vboot_firmware/lib/vboot_common.c ('k') | vboot_firmware/linktest/main.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698