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

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

Issue 2835006: Remove old firmware verification code (Closed) Base URL: ssh://gitrw.chromium.org/vboot_reference.git
Patch Set: 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/Makefile ('k') | vboot_firmware/lib/include/vboot_firmware.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 * Functions for verifying a verified boot firmware image.
6 * (Firmware Portion)
7 */
8
9 #include "firmware_image_fw.h"
10
11 #include "cryptolib.h"
12 #include "rollback_index.h"
13 #include "tss_constants.h"
14 #include "utility.h"
15
16 /* Macro to determine the size of a field structure in the FirmwareImage
17 * structure. */
18 #define FIELD_LEN(field) (sizeof(((FirmwareImage*)0)->field))
19
20 char* kVerifyFirmwareErrors[VERIFY_FIRMWARE_MAX] = {
21 "Success.",
22 "Invalid Image.",
23 "Root Key Signature Failed.",
24 "Invalid Verification Algorithm.",
25 "Preamble Signature Failed.",
26 "Firmware Signature Failed.",
27 "Wrong Firmware Magic.",
28 "Invalid Firmware Header Checksum.",
29 "Firmware Signing Key Rollback.",
30 "Firmware Version Rollback."
31 };
32
33 uint64_t GetFirmwarePreambleLen(int algorithm) {
34 return (FIELD_LEN(firmware_version) +
35 FIELD_LEN(firmware_len) +
36 FIELD_LEN(kernel_subkey_sign_algorithm) +
37 RSAProcessedKeySize(algorithm) +
38 FIELD_LEN(preamble));
39 }
40
41
42 int VerifyFirmwareHeader(const uint8_t* root_key_blob,
43 const uint8_t* header_blob,
44 int* algorithm,
45 int* header_len) {
46 int firmware_sign_key_len;
47 int root_key_len;
48 uint16_t hlen, algo;
49 uint8_t* header_checksum = NULL;
50
51 /* Base Offset for the header_checksum field. Actual offset is
52 * this + firmware_sign_key_len. */
53 int base_header_checksum_offset = (FIELD_LEN(header_len) +
54 FIELD_LEN(firmware_sign_algorithm) +
55 FIELD_LEN(firmware_key_version));
56
57
58 root_key_len = RSAProcessedKeySize(ROOT_SIGNATURE_ALGORITHM);
59 Memcpy(&hlen, header_blob, sizeof(hlen));
60 Memcpy(&algo,
61 header_blob + FIELD_LEN(firmware_sign_algorithm),
62 sizeof(algo));
63 if (algo >= kNumAlgorithms)
64 return VERIFY_FIRMWARE_INVALID_ALGORITHM;
65 *algorithm = (int) algo;
66 firmware_sign_key_len = RSAProcessedKeySize(*algorithm);
67
68 /* Verify that header len is correct. */
69 if (hlen != (base_header_checksum_offset +
70 firmware_sign_key_len +
71 FIELD_LEN(header_checksum)))
72 return VERIFY_FIRMWARE_INVALID_IMAGE;
73
74 *header_len = (int) hlen;
75
76 /* Verify if the hash of the header is correct. */
77 header_checksum = DigestBuf(header_blob,
78 *header_len - FIELD_LEN(header_checksum),
79 SHA512_DIGEST_ALGORITHM);
80 if (SafeMemcmp(header_checksum,
81 header_blob + (base_header_checksum_offset +
82 firmware_sign_key_len),
83 FIELD_LEN(header_checksum))) {
84 Free(header_checksum);
85 return VERIFY_FIRMWARE_WRONG_HEADER_CHECKSUM;
86 }
87 Free(header_checksum);
88
89 /* Root key signature on the firmware signing key is always checked
90 * irrespective of dev mode. */
91 if (!RSAVerifyBinary_f(root_key_blob, NULL, /* Key to use */
92 header_blob, /* Data to verify */
93 *header_len, /* Length of data */
94 header_blob + *header_len, /* Expected Signature */
95 ROOT_SIGNATURE_ALGORITHM))
96 return VERIFY_FIRMWARE_ROOT_SIGNATURE_FAILED;
97 return 0;
98 }
99
100 int VerifyFirmwarePreamble(RSAPublicKey* firmware_sign_key,
101 const uint8_t* preamble_blob,
102 int firmware_sign_algorithm,
103 uint64_t* firmware_len) {
104 uint64_t len;
105 int preamble_len;
106 uint16_t firmware_version;
107 uint16_t kernel_subkey_sign_algorithm;
108
109 Memcpy(&firmware_version, preamble_blob, sizeof(firmware_version));
110 Memcpy(&kernel_subkey_sign_algorithm,
111 preamble_blob + (FIELD_LEN(firmware_version) +
112 FIELD_LEN(firmware_len)),
113 FIELD_LEN(kernel_subkey_sign_algorithm));
114
115 if (kernel_subkey_sign_algorithm >= kNumAlgorithms)
116 return VERIFY_FIRMWARE_INVALID_ALGORITHM;
117
118 preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm);
119 if (!RSAVerifyBinary_f(NULL, firmware_sign_key, /* Key to use */
120 preamble_blob, /* Data to verify */
121 preamble_len, /* Length of data */
122 preamble_blob + preamble_len, /* Expected Signature */
123 firmware_sign_algorithm))
124 return VERIFY_FIRMWARE_PREAMBLE_SIGNATURE_FAILED;
125
126 Memcpy(&len, preamble_blob + FIELD_LEN(firmware_version),
127 sizeof(len));
128 *firmware_len = len;
129 return 0;
130 }
131
132 int VerifyFirmwareData(RSAPublicKey* firmware_sign_key,
133 const uint8_t* preamble_start,
134 const uint8_t* firmware_data,
135 uint64_t firmware_len,
136 int firmware_sign_algorithm) {
137 int signature_len = siglen_map[firmware_sign_algorithm];
138 int preamble_len;
139 uint16_t kernel_subkey_sign_algorithm;
140 uint8_t* digest = NULL;
141 const uint8_t* firmware_signature = NULL;
142 DigestContext ctx;
143 Memcpy(&kernel_subkey_sign_algorithm,
144 preamble_start + (FIELD_LEN(firmware_version) +
145 FIELD_LEN(firmware_len)),
146 FIELD_LEN(kernel_subkey_sign_algorithm));
147
148 if (kernel_subkey_sign_algorithm >= kNumAlgorithms)
149 return VERIFY_FIRMWARE_INVALID_ALGORITHM;
150
151 preamble_len = GetFirmwarePreambleLen(kernel_subkey_sign_algorithm);
152
153 /* Since the firmware signature is over the preamble and the firmware data,
154 * which does not form a contiguous region of memory, we calculate the
155 * message digest ourselves. */
156 DigestInit(&ctx, firmware_sign_algorithm);
157 DigestUpdate(&ctx, preamble_start, preamble_len);
158 DigestUpdate(&ctx, firmware_data, firmware_len);
159 digest = DigestFinal(&ctx);
160 /* Firmware signature is at the end of preamble and preamble signature. */
161 firmware_signature = preamble_start + preamble_len + signature_len;
162 if (!RSAVerifyBinaryWithDigest_f(
163 NULL, firmware_sign_key, /* Key to use. */
164 digest, /* Digest of the data to verify. */
165 firmware_signature, /* Expected Signature */
166 firmware_sign_algorithm)) {
167 Free(digest);
168 return VERIFY_FIRMWARE_SIGNATURE_FAILED;
169 }
170 Free(digest);
171 return 0;
172 }
173
174 int VerifyFirmware(const uint8_t* root_key_blob,
175 const uint8_t* verification_header_blob,
176 const uint8_t* firmware_blob) {
177 int error_code = 0;
178 int firmware_sign_algorithm; /* Signing key algorithm. */
179 RSAPublicKey* firmware_sign_key = NULL;
180 int firmware_sign_key_len, signature_len, header_len;
181 uint64_t firmware_len;
182 const uint8_t* header_ptr = NULL; /* Pointer to header. */
183 const uint8_t* firmware_sign_key_ptr = NULL; /* Pointer to signing key. */
184 const uint8_t* preamble_ptr = NULL; /* Pointer to preamble block. */
185
186 /* Note: All the offset calculations are based on struct FirmwareImage which
187 * is defined in include/firmware_image_fw.h. */
188
189 /* Compare magic bytes. */
190 if (SafeMemcmp(verification_header_blob, FIRMWARE_MAGIC,
191 FIRMWARE_MAGIC_SIZE)) {
192 debug("Wrong Firmware Magic.\n");
193 return VERIFY_FIRMWARE_WRONG_MAGIC;
194 }
195 header_ptr = verification_header_blob + FIRMWARE_MAGIC_SIZE;
196
197 /* Only continue if header verification succeeds. */
198 if ((error_code = VerifyFirmwareHeader(root_key_blob, header_ptr,
199 &firmware_sign_algorithm,
200 &header_len))) {
201 debug("Couldn't verify Firmware header.\n");
202 return error_code; /* AKA jump to revovery. */
203 }
204 /* Parse signing key into RSAPublicKey structure since it is required multiple
205 * times. */
206 firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm);
207 firmware_sign_key_ptr = header_ptr + (FIELD_LEN(header_len) +
208 FIELD_LEN(firmware_sign_algorithm) +
209 FIELD_LEN(firmware_key_version));
210 firmware_sign_key = RSAPublicKeyFromBuf(firmware_sign_key_ptr,
211 firmware_sign_key_len);
212 signature_len = siglen_map[firmware_sign_algorithm];
213
214 /* Only continue if preamble verification succeeds. */
215 preamble_ptr = (header_ptr + header_len +
216 FIELD_LEN(firmware_key_signature));
217 if ((error_code = VerifyFirmwarePreamble(firmware_sign_key, preamble_ptr,
218 firmware_sign_algorithm,
219 &firmware_len))) {
220 RSAPublicKeyFree(firmware_sign_key);
221 debug("Couldn't verify Firmware preamble.\n");
222 return error_code; /* AKA jump to recovery. */
223 }
224
225 if ((error_code = VerifyFirmwareData(firmware_sign_key, preamble_ptr,
226 firmware_blob,
227 firmware_len,
228 firmware_sign_algorithm))) {
229 RSAPublicKeyFree(firmware_sign_key);
230 debug("Couldn't verify Firmware data.\n");
231 return error_code; /* AKA jump to recovery. */
232 }
233
234 RSAPublicKeyFree(firmware_sign_key);
235 return VERIFY_FIRMWARE_SUCCESS; /* Success! */
236 }
237
238 uint32_t GetLogicalFirmwareVersion(uint8_t* verification_header_blob) {
239 uint16_t firmware_key_version;
240 uint16_t firmware_version;
241 uint16_t firmware_sign_algorithm;
242 int firmware_sign_key_len;
243 Memcpy(&firmware_sign_algorithm,
244 verification_header_blob + (FIELD_LEN(magic) + /* Offset to field. */
245 FIELD_LEN(header_len)),
246 sizeof(firmware_sign_algorithm));
247 Memcpy(&firmware_key_version,
248 verification_header_blob + (FIELD_LEN(magic) + /* Offset to field. */
249 FIELD_LEN(header_len) +
250 FIELD_LEN(firmware_sign_algorithm)),
251 sizeof(firmware_key_version));
252 if (firmware_sign_algorithm >= kNumAlgorithms)
253 return 0;
254 firmware_sign_key_len = RSAProcessedKeySize(firmware_sign_algorithm);
255 Memcpy(&firmware_version,
256 verification_header_blob + (FIELD_LEN(magic) + /* Offset to field. */
257 FIELD_LEN(header_len) +
258 FIELD_LEN(firmware_sign_algorithm) +
259 FIELD_LEN(firmware_key_version) +
260 firmware_sign_key_len +
261 FIELD_LEN(header_checksum) +
262 FIELD_LEN(firmware_key_signature)),
263 sizeof(firmware_version));
264 return CombineUint16Pair(firmware_key_version, firmware_version);
265 }
266
267 int VerifyFirmwareDriver_f(uint8_t* root_key_blob,
268 uint8_t* verification_headerA,
269 uint8_t* firmwareA,
270 uint8_t* verification_headerB,
271 uint8_t* firmwareB) {
272 /* Contains the logical firmware version (32-bit) which is calculated as
273 * (firmware_key_version << 16 | firmware_version) where
274 * [firmware_key_version] [firmware_version] are both 16-bit.
275 */
276 uint32_t firmwareA_lversion, firmwareB_lversion;
277 uint8_t firmwareA_is_verified = 0; /* Whether firmwareA verify succeeded. */
278 uint32_t min_lversion; /* Minimum of firmware A and firmware lversion. */
279 uint32_t stored_lversion; /* Stored logical version in the TPM. */
280 uint16_t version, key_version; /* Temporary variables */
281
282 /* Initialize the TPM since we'll be reading the rollback indices. */
283 SetupTPM(0, 0);
284
285 /* We get the key versions by reading directly from the image blobs without
286 * any additional (expensive) sanity checking on the blob since it's faster to
287 * outright reject a firmware with an older firmware key version. A malformed
288 * or corrupted firmware blob will still fail when VerifyFirmware() is called
289 * on it.
290 */
291 firmwareA_lversion = GetLogicalFirmwareVersion(verification_headerA);
292 firmwareB_lversion = GetLogicalFirmwareVersion(verification_headerB);
293 min_lversion = Min(firmwareA_lversion, firmwareB_lversion);
294 GetStoredVersions(FIRMWARE_VERSIONS, &key_version, &version);
295 stored_lversion = CombineUint16Pair(key_version, version);
296 /* Always try FirmwareA first. */
297 if (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob,
298 verification_headerA,
299 firmwareA))
300 firmwareA_is_verified = 1;
301 if (firmwareA_is_verified && (stored_lversion < firmwareA_lversion)) {
302 /* Stored version may need to be updated but only if FirmwareB
303 * is successfully verified and has a logical version greater than
304 * the stored logical version. */
305 if (stored_lversion < firmwareB_lversion) {
306 if (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob,
307 verification_headerB,
308 firmwareB)) {
309 WriteStoredVersions(FIRMWARE_VERSIONS,
310 (uint16_t) (min_lversion >> 16),
311 (uint16_t) (min_lversion & 0xFFFF));
312 stored_lversion = min_lversion; /* Update stored version as it's used
313 * later. */
314 }
315 }
316 }
317 /* Lock Firmware TPM rollback indices from further writes. In this design,
318 * this is done by setting the globalLock bit, which is cleared only by
319 * TPM_Init at reboot.
320 */
321 if (TPM_SUCCESS != LockFirmwareVersions()) {
322 return VERIFY_FIRMWARE_TPM_ERROR;
323 }
324
325 /* Determine which firmware (if any) to jump to.
326 *
327 * We always attempt to jump to FirmwareA first. If verification of FirmwareA
328 * fails, we try FirmwareB. In all cases, if the firmware successfully
329 * verified but is a rollback, we jump to recovery.
330 *
331 * Note: This means that if FirmwareA verified successfully and is a
332 * rollback, then no attempt is made to check FirmwareB. We still jump to
333 * recovery. FirmwareB is only used as a backup in case FirmwareA gets
334 * corrupted. Since newer firmware updates are always written to A,
335 * the case where firmware A is verified but a rollback should not occur in
336 * normal operation.
337 */
338 if (firmwareA_is_verified) {
339 if (stored_lversion <= firmwareA_lversion)
340 return BOOT_FIRMWARE_A_CONTINUE;
341 } else {
342 /* If FirmwareA was not valid, then we skipped over the
343 * check to update the rollback indices and a Verify of FirmwareB wasn't
344 * attempted.
345 * If FirmwareB is not a rollback, then we attempt to do the verification.
346 */
347 if (stored_lversion <= firmwareB_lversion &&
348 (VERIFY_FIRMWARE_SUCCESS == VerifyFirmware(root_key_blob,
349 verification_headerB,
350 firmwareB)))
351 return BOOT_FIRMWARE_B_CONTINUE;
352 }
353 /* D'oh: No bootable firmware. */
354 return BOOT_FIRMWARE_RECOVERY_CONTINUE;
355 }
OLDNEW
« no previous file with comments | « vboot_firmware/Makefile ('k') | vboot_firmware/lib/include/vboot_firmware.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698