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

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

Issue 2849021: Even more integration fixes. (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: (resend to gen email) 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 | « firmware/lib/include/vboot_struct.h ('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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 int index; 44 int index;
45 45
46 /* Clear output params in case we fail */ 46 /* Clear output params in case we fail */
47 params->firmware_index = 0; 47 params->firmware_index = 0;
48 params->kernel_sign_key_blob = NULL; 48 params->kernel_sign_key_blob = NULL;
49 params->kernel_sign_key_size = 0; 49 params->kernel_sign_key_size = 0;
50 50
51 debug("LoadFirmware started...\n"); 51 debug("LoadFirmware started...\n");
52 52
53 /* Must have a root key */ 53 /* Must have a root key */
54 if (!root_key) 54 if (!root_key) {
55 debug("No root key\n");
55 return LOAD_FIRMWARE_RECOVERY; 56 return LOAD_FIRMWARE_RECOVERY;
57 }
56 58
57 /* Initialize the TPM and read rollback indices. */ 59 /* Initialize the TPM and read rollback indices. */
58 /* TODO: fix SetupTPM parameter for developer mode */ 60 /* TODO: fix SetupTPM parameter for developer mode */
59 if (0 != SetupTPM(RO_NORMAL_MODE, 0) ) 61 if (0 != SetupTPM(RO_NORMAL_MODE, 0)) {
62 debug("SetupTPM failed\n");
60 return LOAD_FIRMWARE_RECOVERY; 63 return LOAD_FIRMWARE_RECOVERY;
64 }
61 if (0 != GetStoredVersions(FIRMWARE_VERSIONS, 65 if (0 != GetStoredVersions(FIRMWARE_VERSIONS,
62 &tpm_key_version, &tpm_fw_version)) 66 &tpm_key_version, &tpm_fw_version)) {
67 debug("Unable to get stored versions.\n");
63 return LOAD_FIRMWARE_RECOVERY; 68 return LOAD_FIRMWARE_RECOVERY;
69 }
64 70
65 /* Allocate our internal data */ 71 /* Allocate our internal data */
66 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal)); 72 lfi = (VbLoadFirmwareInternal*)Malloc(sizeof(VbLoadFirmwareInternal));
67 if (!lfi) 73 if (!lfi)
68 return LOAD_FIRMWARE_RECOVERY; 74 return LOAD_FIRMWARE_RECOVERY;
69 params->load_firmware_internal = (uint8_t*)lfi; 75 params->load_firmware_internal = (uint8_t*)lfi;
70 76
71 /* Loop over indices */ 77 /* Loop over indices */
72 for (index = 0; index < 2; index++) { 78 for (index = 0; index < 2; index++) {
73 VbKeyBlockHeader* key_block; 79 VbKeyBlockHeader* key_block;
74 uint64_t vblock_size; 80 uint64_t vblock_size;
75 VbFirmwarePreambleHeader* preamble; 81 VbFirmwarePreambleHeader* preamble;
76 RSAPublicKey* data_key; 82 RSAPublicKey* data_key;
77 uint64_t key_version; 83 uint64_t key_version;
78 uint8_t* body_digest; 84 uint8_t* body_digest;
79 85
80 /* Verify the key block */ 86 /* Verify the key block */
81 if (0 == index) { 87 if (0 == index) {
82 key_block = (VbKeyBlockHeader*)params->verification_block_0; 88 key_block = (VbKeyBlockHeader*)params->verification_block_0;
83 vblock_size = params->verification_size_0; 89 vblock_size = params->verification_size_0;
84 } else { 90 } else {
85 key_block = (VbKeyBlockHeader*)params->verification_block_1; 91 key_block = (VbKeyBlockHeader*)params->verification_block_1;
86 vblock_size = params->verification_size_1; 92 vblock_size = params->verification_size_1;
87 } 93 }
88 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) 94 if ((0 != KeyBlockVerify(key_block, vblock_size, root_key))) {
95 debug("Key block verification failed.\n");
89 continue; 96 continue;
97 }
90 98
91 /* Check for rollback of key version. */ 99 /* Check for rollback of key version. */
92 key_version = key_block->data_key.key_version; 100 key_version = key_block->data_key.key_version;
93 if (key_version < tpm_key_version) 101 if (key_version < tpm_key_version) {
102 debug("Key rollback detected.\n");
94 continue; 103 continue;
104 }
95 105
96 /* Get the key for preamble/data verification from the key block. */ 106 /* Get the key for preamble/data verification from the key block. */
97 data_key = PublicKeyToRSA(&key_block->data_key); 107 data_key = PublicKeyToRSA(&key_block->data_key);
98 if (!data_key) 108 if (!data_key) {
109 debug("Unable to parse data key.\n");
99 continue; 110 continue;
111 }
100 112
101 /* Verify the preamble, which follows the key block. */ 113 /* Verify the preamble, which follows the key block. */
102 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block + 114 preamble = (VbFirmwarePreambleHeader*)((uint8_t*)key_block +
103 key_block->key_block_size); 115 key_block->key_block_size);
104 if ((0 != VerifyFirmwarePreamble2(preamble, 116 if ((0 != VerifyFirmwarePreamble2(preamble,
105 vblock_size - key_block->key_block_size, 117 vblock_size - key_block->key_block_size,
106 data_key))) { 118 data_key))) {
119 debug("Preamble verfication failed.\n");
107 RSAPublicKeyFree(data_key); 120 RSAPublicKeyFree(data_key);
108 continue; 121 continue;
109 } 122 }
110 123
111 /* Check for rollback of firmware version. */ 124 /* Check for rollback of firmware version. */
112 if (key_version == tpm_key_version && 125 if (key_version == tpm_key_version &&
113 preamble->firmware_version < tpm_fw_version) { 126 preamble->firmware_version < tpm_fw_version) {
127 debug("Firmware version rollback detected.\n");
114 RSAPublicKeyFree(data_key); 128 RSAPublicKeyFree(data_key);
115 continue; 129 continue;
116 } 130 }
117 131
118 /* Check for lowest key version from a valid header. */ 132 /* Check for lowest key version from a valid header. */
119 if (lowest_key_version > key_version) { 133 if (lowest_key_version > key_version) {
120 lowest_key_version = key_version; 134 lowest_key_version = key_version;
121 lowest_fw_version = preamble->firmware_version; 135 lowest_fw_version = preamble->firmware_version;
122 } 136 }
123 else if (lowest_key_version == key_version && 137 else if (lowest_key_version == key_version &&
124 lowest_fw_version > preamble->firmware_version) { 138 lowest_fw_version > preamble->firmware_version) {
125 lowest_fw_version = preamble->firmware_version; 139 lowest_fw_version = preamble->firmware_version;
126 } 140 }
127 141
128 /* If we already have good firmware, no need to read another one; 142 /* If we already have good firmware, no need to read another one;
129 * we only needed to look at the versions to check for 143 * we only needed to look at the versions to check for
130 * rollback. */ 144 * rollback. */
131 if (-1 != good_index) 145 if (-1 != good_index)
132 continue; 146 continue;
133 147
134 /* Read the firmware data */ 148 /* Read the firmware data */
135 DigestInit(&lfi->body_digest_context, data_key->algorithm); 149 DigestInit(&lfi->body_digest_context, data_key->algorithm);
136 lfi->body_size_accum = 0; 150 lfi->body_size_accum = 0;
137 if ((0 != GetFirmwareBody(params, index)) || 151 if (0 != GetFirmwareBody(params, index)) {
138 (lfi->body_size_accum != preamble->body_signature.data_size)) { 152 debug("GetFirmwareBody() failed for index %d\n", index);
139 RSAPublicKeyFree(data_key); 153 RSAPublicKeyFree(data_key);
140 continue; 154 continue;
141 } 155 }
156 if (lfi->body_size_accum != preamble->body_signature.data_size) {
157 debug("Hash updated %d bytes but expected %d\n",
158 (int)lfi->body_size_accum, (int)preamble->body_signature.data_size);
159 RSAPublicKeyFree(data_key);
160 continue;
161 }
142 162
143 /* Verify firmware data */ 163 /* Verify firmware data */
144 body_digest = DigestFinal(&lfi->body_digest_context); 164 body_digest = DigestFinal(&lfi->body_digest_context);
145 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) { 165 if (0 != VerifyDigest(body_digest, &preamble->body_signature, data_key)) {
166 debug("Firmware body verification failed.\n");
146 RSAPublicKeyFree(data_key); 167 RSAPublicKeyFree(data_key);
147 Free(body_digest); 168 Free(body_digest);
148 continue; 169 continue;
149 } 170 }
150 171
151 /* Done with the digest and data key, so can free them now */ 172 /* Done with the digest and data key, so can free them now */
152 RSAPublicKeyFree(data_key); 173 RSAPublicKeyFree(data_key);
153 Free(body_digest); 174 Free(body_digest);
154 175
155 /* If we're still here, the firmware is valid. */ 176 /* If we're still here, the firmware is valid. */
177 debug("Firmware %d is valid.\n", index);
156 if (-1 == good_index) { 178 if (-1 == good_index) {
157 VbPublicKey *kdest = (VbPublicKey*)params->kernel_sign_key_blob; 179 VbPublicKey *kdest = (VbPublicKey*)params->kernel_sign_key_blob;
158 180
159 /* Copy the kernel sign key blob into the destination buffer */ 181 /* Copy the kernel sign key blob into the destination buffer */
160 PublicKeyInit(kdest, (uint8_t*)(kdest + 1), 182 PublicKeyInit(kdest, (uint8_t*)(kdest + 1),
161 (params->kernel_sign_key_size - sizeof(VbPublicKey))); 183 (params->kernel_sign_key_size - sizeof(VbPublicKey)));
162 184
163 if (0 != PublicKeyCopy(kdest, &preamble->kernel_subkey)) 185 if (0 != PublicKeyCopy(kdest, &preamble->kernel_subkey)) {
186 debug("Kernel subkey too big for buffer.\n");
164 continue; /* The firmware signature was good, but the public 187 continue; /* The firmware signature was good, but the public
165 * key was bigger that the caller can handle. */ 188 * key was bigger that the caller can handle. */
189 }
166 190
167 /* Save the key size we actually used */ 191 /* Save the key size we actually used */
168 params->kernel_sign_key_size = kdest->key_offset + kdest->key_size; 192 params->kernel_sign_key_size = kdest->key_offset + kdest->key_size;
169 193
170 /* Save the good index, now that we're sure we can actually use 194 /* Save the good index, now that we're sure we can actually use
171 * this firmware. That's the one we'll boot. */ 195 * this firmware. That's the one we'll boot. */
172 good_index = index; 196 good_index = index;
173 params->firmware_index = index; 197 params->firmware_index = index;
174 198
175 /* If the good firmware's key version is the same as the tpm, 199 /* If the good firmware's key version is the same as the tpm,
(...skipping 12 matching lines...) Expand all
188 212
189 /* Handle finding good firmware */ 213 /* Handle finding good firmware */
190 if (good_index >= 0) { 214 if (good_index >= 0) {
191 215
192 /* Update TPM if necessary */ 216 /* Update TPM if necessary */
193 if ((lowest_key_version > tpm_key_version) || 217 if ((lowest_key_version > tpm_key_version) ||
194 (lowest_key_version == tpm_key_version && 218 (lowest_key_version == tpm_key_version &&
195 lowest_fw_version > tpm_fw_version)) { 219 lowest_fw_version > tpm_fw_version)) {
196 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS, 220 if (0 != WriteStoredVersions(FIRMWARE_VERSIONS,
197 (uint16_t)lowest_key_version, 221 (uint16_t)lowest_key_version,
198 (uint16_t)lowest_fw_version)) 222 (uint16_t)lowest_fw_version)) {
223 debug("Unable to write stored versions.\n");
199 return LOAD_FIRMWARE_RECOVERY; 224 return LOAD_FIRMWARE_RECOVERY;
225 }
200 } 226 }
201 227
202 /* Lock Firmware TPM rollback indices from further writes. In 228 /* Lock Firmware TPM rollback indices from further writes. In
203 * this design, this is done by setting the globalLock bit, which 229 * this design, this is done by setting the globalLock bit, which
204 * is cleared only by TPM_Init at reboot. */ 230 * is cleared only by TPM_Init at reboot. */
205 if (0 != LockFirmwareVersions()) 231 if (0 != LockFirmwareVersions()) {
232 debug("Unable to lock firmware versions.\n");
206 return LOAD_FIRMWARE_RECOVERY; 233 return LOAD_FIRMWARE_RECOVERY;
234 }
207 235
208 /* Success */ 236 /* Success */
237 debug("Will boot firmware index %d\n", (int)params->firmware_index);
209 return LOAD_FIRMWARE_SUCCESS; 238 return LOAD_FIRMWARE_SUCCESS;
210 } 239 }
211 240
212 /* If we're still here, no good firmware, so go to recovery mode. */ 241 /* If we're still here, no good firmware, so go to recovery mode. */
242 debug("Alas, no good firmware.\n");
213 return LOAD_FIRMWARE_RECOVERY; 243 return LOAD_FIRMWARE_RECOVERY;
214 } 244 }
OLDNEW
« no previous file with comments | « firmware/lib/include/vboot_struct.h ('k') | firmware/lib/vboot_kernel.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698