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

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

Issue 3114013: Change rollback interface so kernel/firmware version numbers are (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: Created 10 years, 4 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 | « firmware/lib/rollback_index.c ('k') | firmware/lib/vboot_kernel.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 "load_firmware_fw.h" 9 #include "load_firmware_fw.h"
10 #include "rollback_index.h" 10 #include "rollback_index.h"
(...skipping 18 matching lines...) Expand all
29 DigestUpdate(&lfi->body_digest_context, data, size); 29 DigestUpdate(&lfi->body_digest_context, data, size);
30 lfi->body_size_accum += size; 30 lfi->body_size_accum += size;
31 } 31 }
32 32
33 33
34 int LoadFirmware(LoadFirmwareParams* params) { 34 int LoadFirmware(LoadFirmwareParams* params) {
35 35
36 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob; 36 VbPublicKey* root_key = (VbPublicKey*)params->firmware_root_key_blob;
37 VbLoadFirmwareInternal* lfi; 37 VbLoadFirmwareInternal* lfi;
38 38
39 uint16_t tpm_key_version = 0; 39 uint32_t tpm_version = 0;
40 uint16_t tpm_fw_version = 0; 40 uint64_t lowest_version = 0xFFFFFFFF;
41 uint64_t lowest_key_version = 0xFFFF;
42 uint64_t lowest_fw_version = 0xFFFF;
43 uint32_t status; 41 uint32_t status;
44 int good_index = -1; 42 int good_index = -1;
45 int index; 43 int index;
46 44
47 /* Clear output params in case we fail */ 45 /* Clear output params in case we fail */
48 params->firmware_index = 0; 46 params->firmware_index = 0;
49 47
50 VBDEBUG(("LoadFirmware started...\n")); 48 VBDEBUG(("LoadFirmware started...\n"));
51 49
52 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) { 50 if (params->kernel_sign_key_size < sizeof(VbPublicKey)) {
53 VBDEBUG(("Kernel sign key buffer too small\n")); 51 VBDEBUG(("Kernel sign key buffer too small\n"));
54 return LOAD_FIRMWARE_RECOVERY; 52 return LOAD_FIRMWARE_RECOVERY;
55 } 53 }
56 54
57 /* Must have a root key */ 55 /* Must have a root key */
58 if (!root_key) { 56 if (!root_key) {
59 VBDEBUG(("No root key\n")); 57 VBDEBUG(("No root key\n"));
60 return LOAD_FIRMWARE_RECOVERY; 58 return LOAD_FIRMWARE_RECOVERY;
61 } 59 }
62 60
63 /* Initialize the TPM and read rollback indices. */ 61 /* Initialize the TPM and read rollback indices. */
64 status = RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER, 62 status = RollbackFirmwareSetup(params->boot_flags & BOOT_FLAG_DEVELOPER,
65 &tpm_key_version, &tpm_fw_version); 63 &tpm_version);
66 if (0 != status) { 64 if (0 != status) {
67 VBDEBUG(("Unable to setup TPM and read stored versions.\n")); 65 VBDEBUG(("Unable to setup TPM and read stored versions.\n"));
68 return (status == TPM_E_MUST_REBOOT ? 66 return (status == TPM_E_MUST_REBOOT ?
69 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); 67 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY);
70 } 68 }
71 69
72 /* Allocate our internal data */ 70 /* Allocate our internal data */
73 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); 71 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal));
74 if (!lfi) 72 if (!lfi)
75 return LOAD_FIRMWARE_RECOVERY; 73 return LOAD_FIRMWARE_RECOVERY;
76 params->load_firmware_internal = (uint8_t*)lfi; 74 params->load_firmware_internal = (uint8_t*)lfi;
77 75
78 /* Loop over indices */ 76 /* Loop over indices */
79 for (index = 0; index < 2; index++) { 77 for (index = 0; index < 2; index++) {
80 VbKeyBlockHeader* key_block; 78 VbKeyBlockHeader* key_block;
81 uint64_t vblock_size; 79 uint64_t vblock_size;
82 VbFirmwarePreambleHeader* preamble; 80 VbFirmwarePreambleHeader* preamble;
83 RSAPublicKey* data_key; 81 RSAPublicKey* data_key;
84 uint64_t key_version; 82 uint64_t key_version;
83 uint64_t combined_version;
85 uint8_t* body_digest; 84 uint8_t* body_digest;
86 85
87 /* Verify the key block */ 86 /* Verify the key block */
88 if (0 == index) { 87 if (0 == index) {
89 key_block = (VbKeyBlockHeader*)params->verification_block_0; 88 key_block = (VbKeyBlockHeader*)params->verification_block_0;
90 vblock_size = params->verification_size_0; 89 vblock_size = params->verification_size_0;
91 } else { 90 } else {
92 key_block = (VbKeyBlockHeader*)params->verification_block_1; 91 key_block = (VbKeyBlockHeader*)params->verification_block_1;
93 vblock_size = params->verification_size_1; 92 vblock_size = params->verification_size_1;
94 } 93 }
95 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) { 94 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) {
96 VBDEBUG(("Key block verification failed.\n")); 95 VBDEBUG(("Key block verification failed.\n"));
97 continue; 96 continue;
98 } 97 }
99 98
100 /* Check for rollback of key version. */ 99 /* Check for rollback of key version. */
101 key_version = key_block->data_key.key_version; 100 key_version = key_block->data_key.key_version;
102 if (key_version < tpm_key_version) { 101 if (key_version < (tpm_version >> 16)) {
103 VBDEBUG(("Key rollback detected.\n")); 102 VBDEBUG(("Key rollback detected.\n"));
104 continue; 103 continue;
105 } 104 }
106 105
107 /* Get the key for preamble/data verification from the key block. */ 106 /* Get the key for preamble/data verification from the key block. */
108 data_key = PublicKeyToRSA(&key_block->data_key); 107 data_key = PublicKeyToRSA(&key_block->data_key);
109 if (!data_key) { 108 if (!data_key) {
110 VBDEBUG(("Unable to parse data key.\n")); 109 VBDEBUG(("Unable to parse data key.\n"));
111 continue; 110 continue;
112 } 111 }
113 112
114 /* Verify the preamble, which follows the key block. */ 113 /* Verify the preamble, which follows the key block. */
115 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block + 114 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block +
116 key_block->key_block_size); 115 key_block->key_block_size);
117 if ((0 != VerifyFirmwarePreamble(preamble, 116 if ((0 != VerifyFirmwarePreamble(preamble,
118 vblock_size - key_block->key_block_size, 117 vblock_size - key_block->key_block_size,
119 data_key))) { 118 data_key))) {
120 VBDEBUG(("Preamble verfication failed.\n")); 119 VBDEBUG(("Preamble verfication failed.\n"));
121 RSAPublicKeyFree(data_key); 120 RSAPublicKeyFree(data_key);
122 continue; 121 continue;
123 } 122 }
124 123
125 /* Check for rollback of firmware version. */ 124 /* Check for rollback of firmware version. */
126 if (key_version == tpm_key_version && 125 combined_version = ((key_version << 16) |
127 preamble->firmware_version < tpm_fw_version) { 126 (preamble->firmware_version & 0xFFFF));
127 if (combined_version < tpm_version) {
128 VBDEBUG(("Firmware version rollback detected.\n")); 128 VBDEBUG(("Firmware version rollback detected.\n"));
129 RSAPublicKeyFree(data_key); 129 RSAPublicKeyFree(data_key);
130 continue; 130 continue;
131 } 131 }
132 132
133 /* Check for lowest key version from a valid header. */ 133 /* Check for lowest key version from a valid header. */
134 if (lowest_key_version > key_version) { 134 if (lowest_version > combined_version)
135 lowest_key_version = key_version; 135 lowest_version = combined_version;
136 lowest_fw_version = preamble->firmware_version;
137 }
138 else if (lowest_key_version == key_version &&
139 lowest_fw_version > preamble->firmware_version) {
140 lowest_fw_version = preamble->firmware_version;
141 }
142 136
143 /* If we already have good firmware, no need to read another one; 137 /* If we already have good firmware, no need to read another one;
144 * we only needed to look at the versions to check for 138 * we only needed to look at the versions to check for
145 * rollback. */ 139 * rollback. */
146 if (-1 != good_index) 140 if (-1 != good_index)
147 continue; 141 continue;
148 142
149 /* Read the firmware data */ 143 /* Read the firmware data */
150 DigestInit(&lfi->body_digest_context, data_key->algorithm); 144 DigestInit(&lfi->body_digest_context, data_key->algorithm);
151 lfi->body_size_accum = 0; 145 lfi->body_size_accum = 0;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 189
196 /* Save the good index, now that we're sure we can actually use 190 /* Save the good index, now that we're sure we can actually use
197 * this firmware. That's the one we'll boot. */ 191 * this firmware. That's the one we'll boot. */
198 good_index = index; 192 good_index = index;
199 params->firmware_index = index; 193 params->firmware_index = index;
200 194
201 /* If the good firmware's key version is the same as the tpm, 195 /* If the good firmware's key version is the same as the tpm,
202 * then the TPM doesn't need updating; we can stop now. 196 * then the TPM doesn't need updating; we can stop now.
203 * Otherwise, we'll check all the other headers to see if they 197 * Otherwise, we'll check all the other headers to see if they
204 * contain a newer key. */ 198 * contain a newer key. */
205 if (key_version == tpm_key_version && 199 if (combined_version == tpm_version)
206 preamble->firmware_version == tpm_fw_version)
207 break; 200 break;
208 } 201 }
209 } 202 }
210 203
211 /* Free internal data */ 204 /* Free internal data */
212 Free(lfi); 205 Free(lfi);
213 params->load_firmware_internal = NULL; 206 params->load_firmware_internal = NULL;
214 207
215 /* Handle finding good firmware */ 208 /* Handle finding good firmware */
216 if (good_index >= 0) { 209 if (good_index >= 0) {
217 210
218 /* Update TPM if necessary */ 211 /* Update TPM if necessary */
219 if ((lowest_key_version > tpm_key_version) || 212 if (lowest_version > tpm_version) {
220 (lowest_key_version == tpm_key_version && 213 status = RollbackFirmwareWrite((uint32_t)lowest_version);
221 lowest_fw_version > tpm_fw_version)) {
222
223 status = RollbackFirmwareWrite((uint16_t)lowest_key_version,
224 (uint16_t)lowest_fw_version);
225 if (0 != status) { 214 if (0 != status) {
226 VBDEBUG(("Unable to write stored versions.\n")); 215 VBDEBUG(("Unable to write stored versions.\n"));
227 return (status == TPM_E_MUST_REBOOT ? 216 return (status == TPM_E_MUST_REBOOT ?
228 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); 217 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY);
229 } 218 }
230 } 219 }
231 220
232 /* Lock firmware versions in TPM */ 221 /* Lock firmware versions in TPM */
233 status = RollbackFirmwareLock(); 222 status = RollbackFirmwareLock();
234 if (0 != status) { 223 if (0 != status) {
235 VBDEBUG(("Unable to lock firmware versions.\n")); 224 VBDEBUG(("Unable to lock firmware versions.\n"));
236 return (status == TPM_E_MUST_REBOOT ? 225 return (status == TPM_E_MUST_REBOOT ?
237 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY); 226 LOAD_FIRMWARE_REBOOT : LOAD_FIRMWARE_RECOVERY);
238 } 227 }
239 228
240 /* Success */ 229 /* Success */
241 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index)); 230 VBDEBUG(("Will boot firmware index %d\n", (int)params->firmware_index));
242 return LOAD_FIRMWARE_SUCCESS; 231 return LOAD_FIRMWARE_SUCCESS;
243 } 232 }
244 233
245 /* If we're still here, no good firmware, so go to recovery mode. */ 234 /* If we're still here, no good firmware, so go to recovery mode. */
246 VBDEBUG(("Alas, no good firmware.\n")); 235 VBDEBUG(("Alas, no good firmware.\n"));
247 return LOAD_FIRMWARE_RECOVERY; 236 return LOAD_FIRMWARE_RECOVERY;
248 } 237 }
OLDNEW
« no previous file with comments | « firmware/lib/rollback_index.c ('k') | firmware/lib/vboot_kernel.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698