1 /* Copyright (c) 2013 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 * Common functions between firmware and kernel verified boot.
6 * (Firmware portion)
7 */
8
9 #include "sysincludes.h"
10
11 #include "vboot_api.h"
12 #include "vboot_common.h"
13 #include "utility.h"
14
15 const char *kVbootErrors[VBOOT_ERROR_MAX] = {
16 "Success.",
17 "Key block invalid.",
18 "Key block signature failed.",
19 "Key block hash failed.",
20 "Public key invalid.",
21 "Preamble invalid.",
22 "Preamble signature check failed.",
23 "Shared data invalid."
24 };
25
OffsetOf(const void * base,const void * ptr)26 uint64_t OffsetOf(const void *base, const void *ptr)
27 {
28 return (uint64_t)(size_t)ptr - (uint64_t)(size_t)base;
29 }
30
31 /* Helper functions to get data pointed to by a public key or signature. */
32
GetPublicKeyData(VbPublicKey * key)33 uint8_t *GetPublicKeyData(VbPublicKey *key)
34 {
35 return (uint8_t *)key + key->key_offset;
36 }
37
GetPublicKeyDataC(const VbPublicKey * key)38 const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
39 {
40 return (const uint8_t *)key + key->key_offset;
41 }
42
GetSignatureData(VbSignature * sig)43 uint8_t *GetSignatureData(VbSignature *sig)
44 {
45 return (uint8_t *)sig + sig->sig_offset;
46 }
47
GetSignatureDataC(const VbSignature * sig)48 const uint8_t *GetSignatureDataC(const VbSignature *sig)
49 {
50 return (const uint8_t *)sig + sig->sig_offset;
51 }
52
53 /*
54 * Helper functions to verify the data pointed to by a subfield is inside
55 * the parent data. Returns 0 if inside, 1 if error.
56 */
57
VerifyMemberInside(const void * parent,uint64_t parent_size,const void * member,uint64_t member_size,uint64_t member_data_offset,uint64_t member_data_size)58 int VerifyMemberInside(const void *parent, uint64_t parent_size,
59 const void *member, uint64_t member_size,
60 uint64_t member_data_offset,
61 uint64_t member_data_size)
62 {
63 uint64_t end = OffsetOf(parent, member);
64
65 if (end > parent_size)
66 return 1;
67
68 if (UINT64_MAX - end < member_size)
69 return 1; /* Detect wraparound in integer math */
70 if (end + member_size > parent_size)
71 return 1;
72
73 if (UINT64_MAX - end < member_data_offset)
74 return 1;
75 end += member_data_offset;
76 if (end > parent_size)
77 return 1;
78
79 if (UINT64_MAX - end < member_data_size)
80 return 1;
81 if (end + member_data_size > parent_size)
82 return 1;
83
84 return 0;
85 }
86
VerifyPublicKeyInside(const void * parent,uint64_t parent_size,const VbPublicKey * key)87 int VerifyPublicKeyInside(const void *parent, uint64_t parent_size,
88 const VbPublicKey *key)
89 {
90 return VerifyMemberInside(parent, parent_size,
91 key, sizeof(VbPublicKey),
92 key->key_offset, key->key_size);
93 }
94
VerifySignatureInside(const void * parent,uint64_t parent_size,const VbSignature * sig)95 int VerifySignatureInside(const void *parent, uint64_t parent_size,
96 const VbSignature *sig)
97 {
98 return VerifyMemberInside(parent, parent_size,
99 sig, sizeof(VbSignature),
100 sig->sig_offset, sig->sig_size);
101 }
102
PublicKeyInit(VbPublicKey * key,uint8_t * key_data,uint64_t key_size)103 void PublicKeyInit(VbPublicKey *key, uint8_t *key_data, uint64_t key_size)
104 {
105 key->key_offset = OffsetOf(key, key_data);
106 key->key_size = key_size;
107 key->algorithm = kNumAlgorithms; /* Key not present yet */
108 key->key_version = 0;
109 }
110
PublicKeyCopy(VbPublicKey * dest,const VbPublicKey * src)111 int PublicKeyCopy(VbPublicKey *dest, const VbPublicKey *src)
112 {
113 if (dest->key_size < src->key_size)
114 return 1;
115
116 dest->key_size = src->key_size;
117 dest->algorithm = src->algorithm;
118 dest->key_version = src->key_version;
119 Memcpy(GetPublicKeyData(dest), GetPublicKeyDataC(src), src->key_size);
120 return 0;
121 }
122
PublicKeyToRSA(const VbPublicKey * key)123 RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
124 {
125 RSAPublicKey *rsa;
126 uint64_t key_size;
127
128 if (kNumAlgorithms <= key->algorithm) {
129 VBDEBUG(("Invalid algorithm.\n"));
130 return NULL;
131 }
132 if (!RSAProcessedKeySize(key->algorithm, &key_size) ||
133 key_size != key->key_size) {
134 VBDEBUG(("Wrong key size for algorithm\n"));
135 return NULL;
136 }
137
138 rsa = RSAPublicKeyFromBuf(GetPublicKeyDataC(key), key->key_size);
139 if (!rsa)
140 return NULL;
141
142 rsa->algorithm = (unsigned int)key->algorithm;
143 return rsa;
144 }
145
VerifyData(const uint8_t * data,uint64_t size,const VbSignature * sig,const RSAPublicKey * key)146 int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
147 const RSAPublicKey *key)
148 {
149 VBDEBUG((" - sig_size=%d, expecting %d for algorithm %d\n",
150 (unsigned)sig->sig_size, siglen_map[key->algorithm],
151 key->algorithm));
152 if (sig->sig_size != siglen_map[key->algorithm]) {
153 VBDEBUG(("Wrong data signature size for algorithm, "
154 "sig_size=%d, expected %d for algorithm %d.\n",
155 (int)sig->sig_size, siglen_map[key->algorithm],
156 key->algorithm));
157 return 1;
158 }
159 if (sig->data_size > size) {
160 VBDEBUG(("Data buffer smaller than length of signed data.\n"));
161 return 1;
162 }
163
164 if (!RSAVerifyBinary_f(NULL, key, data, sig->data_size,
165 GetSignatureDataC(sig), key->algorithm))
166 return 1;
167
168 return 0;
169 }
170
VerifyDigest(const uint8_t * digest,const VbSignature * sig,const RSAPublicKey * key)171 int VerifyDigest(const uint8_t *digest, const VbSignature *sig,
172 const RSAPublicKey *key)
173 {
174 if (sig->sig_size != siglen_map[key->algorithm]) {
175 VBDEBUG(("Wrong digest signature size for algorithm.\n"));
176 return 1;
177 }
178
179 if (!RSAVerifyBinaryWithDigest_f(NULL, key, digest,
180 GetSignatureDataC(sig),
181 key->algorithm))
182 return 1;
183
184 return 0;
185 }
186
KeyBlockVerify(const VbKeyBlockHeader * block,uint64_t size,const VbPublicKey * key,int hash_only)187 int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
188 const VbPublicKey *key, int hash_only)
189 {
190 const VbSignature *sig;
191
192 /* Sanity checks before attempting signature of data */
193 if(size < sizeof(VbKeyBlockHeader)) {
194 VBDEBUG(("Not enough space for key block header.\n"));
195 return VBOOT_KEY_BLOCK_INVALID;
196 }
197 if (SafeMemcmp(block->magic, KEY_BLOCK_MAGIC, KEY_BLOCK_MAGIC_SIZE)) {
198 VBDEBUG(("Not a valid verified boot key block.\n"));
199 return VBOOT_KEY_BLOCK_INVALID;
200 }
201 if (block->header_version_major != KEY_BLOCK_HEADER_VERSION_MAJOR) {
202 VBDEBUG(("Incompatible key block header version.\n"));
203 return VBOOT_KEY_BLOCK_INVALID;
204 }
205 if (size < block->key_block_size) {
206 VBDEBUG(("Not enough data for key block.\n"));
207 return VBOOT_KEY_BLOCK_INVALID;
208 }
209 if (!hash_only && !key) {
210 VBDEBUG(("Missing required public key.\n"));
211 return VBOOT_PUBLIC_KEY_INVALID;
212 }
213
214 /*
215 * Check signature or hash, depending on the hash_only parameter. Note
216 * that we don't require a key even if the keyblock has a signature,
217 * because the caller may not care if the keyblock itself is signed
218 * (for example, booting a Google-signed kernel in developer mode).
219 */
220 if (hash_only) {
221 /* Check hash */
222 uint8_t *header_checksum = NULL;
223 int rv;
224
225 sig = &block->key_block_checksum;
226
227 if (VerifySignatureInside(block, block->key_block_size, sig)) {
228 VBDEBUG(("Key block hash off end of block\n"));
229 return VBOOT_KEY_BLOCK_INVALID;
230 }
231 if (sig->sig_size != SHA512_DIGEST_SIZE) {
232 VBDEBUG(("Wrong hash size for key block.\n"));
233 return VBOOT_KEY_BLOCK_INVALID;
234 }
235
236 /* Make sure advertised signature data sizes are sane. */
237 if (block->key_block_size < sig->data_size) {
238 VBDEBUG(("Signature calculated past end of block\n"));
239 return VBOOT_KEY_BLOCK_INVALID;
240 }
241
242 VBDEBUG(("Checking key block hash only...\n"));
243 header_checksum = DigestBuf((const uint8_t *)block,
244 sig->data_size,
245 SHA512_DIGEST_ALGORITHM);
246 rv = SafeMemcmp(header_checksum, GetSignatureDataC(sig),
247 SHA512_DIGEST_SIZE);
248 VbExFree(header_checksum);
249 if (rv) {
250 VBDEBUG(("Invalid key block hash.\n"));
251 return VBOOT_KEY_BLOCK_HASH;
252 }
253 } else {
254 /* Check signature */
255 RSAPublicKey *rsa;
256 int rv;
257
258 sig = &block->key_block_signature;
259
260 if (VerifySignatureInside(block, block->key_block_size, sig)) {
261 VBDEBUG(("Key block signature off end of block\n"));
262 return VBOOT_KEY_BLOCK_INVALID;
263 }
264
265 rsa = PublicKeyToRSA(key);
266 if (!rsa) {
267 VBDEBUG(("Invalid public key\n"));
268 return VBOOT_PUBLIC_KEY_INVALID;
269 }
270
271 /* Make sure advertised signature data sizes are sane. */
272 if (block->key_block_size < sig->data_size) {
273 VBDEBUG(("Signature calculated past end of block\n"));
274 RSAPublicKeyFree(rsa);
275 return VBOOT_KEY_BLOCK_INVALID;
276 }
277
278 VBDEBUG(("Checking key block signature...\n"));
279 rv = VerifyData((const uint8_t *)block, size, sig, rsa);
280 RSAPublicKeyFree(rsa);
281 if (rv) {
282 VBDEBUG(("Invalid key block signature.\n"));
283 return VBOOT_KEY_BLOCK_SIGNATURE;
284 }
285 }
286
287 /* Verify we signed enough data */
288 if (sig->data_size < sizeof(VbKeyBlockHeader)) {
289 VBDEBUG(("Didn't sign enough data\n"));
290 return VBOOT_KEY_BLOCK_INVALID;
291 }
292
293 /* Verify data key is inside the block and inside signed data */
294 if (VerifyPublicKeyInside(block, block->key_block_size,
295 &block->data_key)) {
296 VBDEBUG(("Data key off end of key block\n"));
297 return VBOOT_KEY_BLOCK_INVALID;
298 }
299 if (VerifyPublicKeyInside(block, sig->data_size, &block->data_key)) {
300 VBDEBUG(("Data key off end of signed data\n"));
301 return VBOOT_KEY_BLOCK_INVALID;
302 }
303
304 /* Success */
305 return VBOOT_SUCCESS;
306 }
307
VerifyFirmwarePreamble(const VbFirmwarePreambleHeader * preamble,uint64_t size,const RSAPublicKey * key)308 int VerifyFirmwarePreamble(const VbFirmwarePreambleHeader *preamble,
309 uint64_t size, const RSAPublicKey *key)
310 {
311 const VbSignature *sig = &preamble->preamble_signature;
312
313 VBDEBUG(("Verifying preamble.\n"));
314 /* Sanity checks before attempting signature of data */
315 if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_0_SIZE) {
316 VBDEBUG(("Not enough data for preamble header 2.0.\n"));
317 return VBOOT_PREAMBLE_INVALID;
318 }
319 if (preamble->header_version_major !=
320 FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
321 VBDEBUG(("Incompatible firmware preamble header version.\n"));
322 return VBOOT_PREAMBLE_INVALID;
323 }
324 if (size < preamble->preamble_size) {
325 VBDEBUG(("Not enough data for preamble.\n"));
326 return VBOOT_PREAMBLE_INVALID;
327 }
328
329 /* Check signature */
330 if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
331 VBDEBUG(("Preamble signature off end of preamble\n"));
332 return VBOOT_PREAMBLE_INVALID;
333 }
334
335 /* Make sure advertised signature data sizes are sane. */
336 if (preamble->preamble_size < sig->data_size) {
337 VBDEBUG(("Signature calculated past end of the block\n"));
338 return VBOOT_PREAMBLE_INVALID;
339 }
340
341 if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
342 VBDEBUG(("Preamble signature validation failed\n"));
343 return VBOOT_PREAMBLE_SIGNATURE;
344 }
345
346 /* Verify we signed enough data */
347 if (sig->data_size < sizeof(VbFirmwarePreambleHeader)) {
348 VBDEBUG(("Didn't sign enough data\n"));
349 return VBOOT_PREAMBLE_INVALID;
350 }
351
352 /* Verify body signature is inside the signed data */
353 if (VerifySignatureInside(preamble, sig->data_size,
354 &preamble->body_signature)) {
355 VBDEBUG(("Firmware body signature off end of preamble\n"));
356 return VBOOT_PREAMBLE_INVALID;
357 }
358
359 /* Verify kernel subkey is inside the signed data */
360 if (VerifyPublicKeyInside(preamble, sig->data_size,
361 &preamble->kernel_subkey)) {
362 VBDEBUG(("Kernel subkey off end of preamble\n"));
363 return VBOOT_PREAMBLE_INVALID;
364 }
365
366 /*
367 * If the preamble header version is at least 2.1, verify we have space
368 * for the added fields from 2.1.
369 */
370 if (preamble->header_version_minor >= 1) {
371 if(size < EXPECTED_VBFIRMWAREPREAMBLEHEADER2_1_SIZE) {
372 VBDEBUG(("Not enough data for preamble header 2.1.\n"));
373 return VBOOT_PREAMBLE_INVALID;
374 }
375 }
376
377 /* Success */
378 return VBOOT_SUCCESS;
379 }
380
VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader * preamble)381 uint32_t VbGetFirmwarePreambleFlags(const VbFirmwarePreambleHeader *preamble)
382 {
383 if (preamble->header_version_minor < 1) {
384 /*
385 * Old structure; return default flags. (Note that we don't
386 * need to check header_version_major; if that's not 2 then
387 * VerifyFirmwarePreamble() would have already failed.
388 */
389 return 0;
390 }
391
392 return preamble->flags;
393 }
394
VerifyKernelPreamble(const VbKernelPreambleHeader * preamble,uint64_t size,const RSAPublicKey * key)395 int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
396 uint64_t size, const RSAPublicKey *key)
397 {
398 const VbSignature *sig = &preamble->preamble_signature;
399
400 /* Sanity checks before attempting signature of data */
401 if(size < sizeof(VbKernelPreambleHeader)) {
402 VBDEBUG(("Not enough data for preamble header.\n"));
403 return VBOOT_PREAMBLE_INVALID;
404 }
405 if (preamble->header_version_major !=
406 KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
407 VBDEBUG(("Incompatible kernel preamble header version.\n"));
408 return VBOOT_PREAMBLE_INVALID;
409 }
410 if (size < preamble->preamble_size) {
411 VBDEBUG(("Not enough data for preamble.\n"));
412 return VBOOT_PREAMBLE_INVALID;
413 }
414
415 /* Check signature */
416 if (VerifySignatureInside(preamble, preamble->preamble_size, sig)) {
417 VBDEBUG(("Preamble signature off end of preamble\n"));
418 return VBOOT_PREAMBLE_INVALID;
419 }
420 if (VerifyData((const uint8_t *)preamble, size, sig, key)) {
421 VBDEBUG(("Preamble signature validation failed\n"));
422 return VBOOT_PREAMBLE_SIGNATURE;
423 }
424
425 /* Verify we signed enough data */
426 if (sig->data_size < sizeof(VbKernelPreambleHeader)) {
427 VBDEBUG(("Didn't sign enough data\n"));
428 return VBOOT_PREAMBLE_INVALID;
429 }
430
431 /* Verify body signature is inside the signed data */
432 if (VerifySignatureInside(preamble, sig->data_size,
433 &preamble->body_signature)) {
434 VBDEBUG(("Kernel body signature off end of preamble\n"));
435 return VBOOT_PREAMBLE_INVALID;
436 }
437
438 /*
439 * If the preamble header version is at least 2.1, verify we have space
440 * for the added fields from >2.1.
441 */
442 if (preamble->header_version_minor >= 1) {
443 if((preamble->header_version_minor == 1) &&
444 (size < EXPECTED_VBKERNELPREAMBLEHEADER2_1_SIZE)) {
445 VBDEBUG(("Not enough data for preamble header 2.1.\n"));
446 return VBOOT_PREAMBLE_INVALID;
447 }
448
449 if((preamble->header_version_minor == 2) &&
450 (size < EXPECTED_VBKERNELPREAMBLEHEADER2_2_SIZE)) {
451 VBDEBUG(("Not enough data for preamble header 2.2.\n"));
452 return VBOOT_PREAMBLE_INVALID;
453 }
454 }
455
456 /* Success */
457 return VBOOT_SUCCESS;
458 }
459
VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader * preamble,uint64_t * vmlinuz_header_address,uint64_t * vmlinuz_header_size)460 int VbGetKernelVmlinuzHeader(const VbKernelPreambleHeader *preamble,
461 uint64_t *vmlinuz_header_address,
462 uint64_t *vmlinuz_header_size)
463 {
464 *vmlinuz_header_address = 0;
465 *vmlinuz_header_size = 0;
466 if (preamble->header_version_minor > 0) {
467 /*
468 * Set header and size only if the preamble header version is >
469 * 2.1 as they don't exist in version 2.0 (Note that we don't
470 * need to check header_version_major; if that's not 2 then
471 * VerifyKernelPreamble() would have already failed.
472 */
473 *vmlinuz_header_address = preamble->vmlinuz_header_address;
474 *vmlinuz_header_size = preamble->vmlinuz_header_size;
475 }
476 return VBOOT_SUCCESS;
477 }
478
VbKernelHasFlags(const VbKernelPreambleHeader * preamble)479 int VbKernelHasFlags(const VbKernelPreambleHeader *preamble)
480 {
481 if (preamble->header_version_minor > 1)
482 return VBOOT_SUCCESS;
483
484 return VBOOT_KERNEL_PREAMBLE_NO_FLAGS;
485 }
486
VerifyVmlinuzInsideKBlob(uint64_t kblob,uint64_t kblob_size,uint64_t header,uint64_t header_size)487 int VerifyVmlinuzInsideKBlob(uint64_t kblob, uint64_t kblob_size,
488 uint64_t header, uint64_t header_size)
489 {
490 uint64_t end = header-kblob;
491 if (end > kblob_size)
492 return VBOOT_PREAMBLE_INVALID;
493 if (UINT64_MAX - end < header_size)
494 return VBOOT_PREAMBLE_INVALID;
495 if (end + header_size > kblob_size)
496 return VBOOT_PREAMBLE_INVALID;
497
498 return VBOOT_SUCCESS;
499 }
500
VbSharedDataReserve(VbSharedDataHeader * header,uint64_t size)501 uint64_t VbSharedDataReserve(VbSharedDataHeader *header, uint64_t size)
502 {
503 uint64_t offs = header->data_used;
504
505 VBDEBUG(("VbSharedDataReserve %d bytes at %d\n", (int)size, (int)offs));
506
507 if (!header || size > header->data_size - header->data_used) {
508 VBDEBUG(("VbSharedData buffer out of space.\n"));
509 return 0; /* Not initialized, or not enough space left. */
510 }
511 header->data_used += size;
512 return offs;
513 }
514
VbSharedDataSetKernelKey(VbSharedDataHeader * header,const VbPublicKey * src)515 int VbSharedDataSetKernelKey(VbSharedDataHeader *header, const VbPublicKey *src)
516 {
517 VbPublicKey *kdest;
518
519 if (!header)
520 return VBOOT_SHARED_DATA_INVALID;
521 if (!src)
522 return VBOOT_PUBLIC_KEY_INVALID;
523
524 kdest = &header->kernel_subkey;
525
526 VBDEBUG(("Saving kernel subkey to shared data: size %d, algo %d\n",
527 siglen_map[src->algorithm], (int)src->algorithm));
528
529 /* Attempt to allocate space for key, if it hasn't been allocated yet */
530 if (!header->kernel_subkey_data_offset) {
531 header->kernel_subkey_data_offset =
532 VbSharedDataReserve(header, src->key_size);
533 if (!header->kernel_subkey_data_offset)
534 return VBOOT_SHARED_DATA_INVALID;
535 header->kernel_subkey_data_size = src->key_size;
536 }
537
538 /* Copy the kernel sign key blob into the destination buffer */
539 PublicKeyInit(kdest,
540 (uint8_t *)header + header->kernel_subkey_data_offset,
541 header->kernel_subkey_data_size);
542
543 return PublicKeyCopy(kdest, src);
544 }
545