• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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