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
15const 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
26uint64_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
33uint8_t *GetPublicKeyData(VbPublicKey *key)
34{
35	return (uint8_t *)key + key->key_offset;
36}
37
38const uint8_t *GetPublicKeyDataC(const VbPublicKey *key)
39{
40	return (const uint8_t *)key + key->key_offset;
41}
42
43uint8_t *GetSignatureData(VbSignature *sig)
44{
45	return (uint8_t *)sig + sig->sig_offset;
46}
47
48const 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
58int 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
87int 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
95int 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
103void 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
111int 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
123RSAPublicKey *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
146int 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
171int 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
187int 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
308int 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
381uint32_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
395int 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
460int 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
479int 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
487int 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
501uint64_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
515int 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