OLD | NEW |
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 Loading... |
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 } |
OLD | NEW |