xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2struct.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2021 The ChromiumOS Authors
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 reading, checking and verifying firmware and
6  * kernel data structures.
7  */
8 
9 #include "2common.h"
10 
vb2_check_keyblock(const struct vb2_keyblock * block,uint32_t size,const struct vb2_signature * sig)11 vb2_error_t vb2_check_keyblock(const struct vb2_keyblock *block, uint32_t size,
12 			       const struct vb2_signature *sig)
13 {
14 	if (size < sizeof(*block)) {
15 		VB2_DEBUG("Not enough space for keyblock header.\n");
16 		return VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER;
17 	}
18 
19 	if (memcmp(block->magic, VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE)) {
20 		VB2_DEBUG("Not a valid verified boot keyblock.\n");
21 		return VB2_ERROR_KEYBLOCK_MAGIC;
22 	}
23 
24 	if (block->header_version_major != VB2_KEYBLOCK_VERSION_MAJOR) {
25 		VB2_DEBUG("Incompatible keyblock header version.\n");
26 		return VB2_ERROR_KEYBLOCK_HEADER_VERSION;
27 	}
28 
29 	if (size < block->keyblock_size) {
30 		VB2_DEBUG("Not enough data for keyblock.\n");
31 		return VB2_ERROR_KEYBLOCK_SIZE;
32 	}
33 
34 	if (vb2_verify_signature_inside(block, block->keyblock_size, sig)) {
35 		VB2_DEBUG("Keyblock signature off end of block\n");
36 		return VB2_ERROR_KEYBLOCK_SIG_OUTSIDE;
37 	}
38 
39 	/* Make sure advertised signature data sizes are valid. */
40 	if (block->keyblock_size < sig->data_size) {
41 		VB2_DEBUG("Signature calculated past end of block\n");
42 		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH;
43 	}
44 
45 	/* Verify we signed enough data */
46 	if (sig->data_size < sizeof(struct vb2_keyblock)) {
47 		VB2_DEBUG("Didn't sign enough data\n");
48 		return VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE;
49 	}
50 
51 	/* Verify data key is inside the block and inside signed data */
52 	if (vb2_verify_packed_key_inside(block, block->keyblock_size,
53 					 &block->data_key)) {
54 		VB2_DEBUG("Data key off end of keyblock\n");
55 		return VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE;
56 	}
57 	if (vb2_verify_packed_key_inside(block, sig->data_size,
58 					 &block->data_key)) {
59 		VB2_DEBUG("Data key off end of signed data\n");
60 		return VB2_ERROR_KEYBLOCK_DATA_KEY_UNSIGNED;
61 	}
62 
63 	return VB2_SUCCESS;
64 }
65 
66 test_mockable
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)67 vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
68 				const struct vb2_public_key *key,
69 				const struct vb2_workbuf *wb)
70 {
71 	struct vb2_signature *sig = &block->keyblock_signature;
72 	vb2_error_t rv;
73 
74 	/* Validity check keyblock before attempting signature check of data */
75 	VB2_TRY(vb2_check_keyblock(block, size, sig));
76 
77 	VB2_DEBUG("Checking keyblock signature...\n");
78 	rv = vb2_verify_data((const uint8_t *)block, size, sig, key, wb);
79 	if (rv) {
80 		VB2_DEBUG("Invalid keyblock signature.\n");
81 		return VB2_ERROR_KEYBLOCK_SIG_INVALID;
82 	}
83 
84 	/* Success */
85 	return VB2_SUCCESS;
86 }
87 
vb2_verify_fw_preamble(struct vb2_fw_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)88 vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
89 				   uint32_t size,
90 				   const struct vb2_public_key *key,
91 				   const struct vb2_workbuf *wb)
92 {
93 	struct vb2_signature *sig = &preamble->preamble_signature;
94 
95 	VB2_DEBUG("Verifying preamble.\n");
96 
97 	/* Validity checks before attempting signature of data */
98 	if (size < sizeof(*preamble)) {
99 		VB2_DEBUG("Not enough data for preamble header\n");
100 		return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
101 	}
102 	if (preamble->header_version_major !=
103 	    VB2_FIRMWARE_PREAMBLE_HEADER_VERSION_MAJOR) {
104 		VB2_DEBUG("Incompatible firmware preamble header version.\n");
105 		return VB2_ERROR_PREAMBLE_HEADER_VERSION;
106 	}
107 
108 	if (preamble->header_version_minor < 1) {
109 		VB2_DEBUG("Only preamble header 2.1+ supported\n");
110 		return VB2_ERROR_PREAMBLE_HEADER_OLD;
111 	}
112 
113 	if (size < preamble->preamble_size) {
114 		VB2_DEBUG("Not enough data for preamble.\n");
115 		return VB2_ERROR_PREAMBLE_SIZE;
116 	}
117 
118 	/* Check signature */
119 	if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
120 					sig)) {
121 		VB2_DEBUG("Preamble signature off end of preamble\n");
122 		return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
123 	}
124 
125 	/* Make sure advertised signature data sizes are valid. */
126 	if (preamble->preamble_size < sig->data_size) {
127 		VB2_DEBUG("Signature calculated past end of the block\n");
128 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
129 	}
130 
131 	if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
132 		VB2_DEBUG("Preamble signature validation failed\n");
133 		return VB2_ERROR_PREAMBLE_SIG_INVALID;
134 	}
135 
136 	/* Verify we signed enough data */
137 	if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
138 		VB2_DEBUG("Didn't sign enough data\n");
139 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
140 	}
141 
142 	/* Verify body signature is inside the signed data */
143 	if (vb2_verify_signature_inside(preamble, sig->data_size,
144 					&preamble->body_signature)) {
145 		VB2_DEBUG("Firmware body signature off end of preamble\n");
146 		return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
147 	}
148 
149 	/* Verify kernel subkey is inside the signed data */
150 	if (vb2_verify_packed_key_inside(preamble, sig->data_size,
151 					 &preamble->kernel_subkey)) {
152 		VB2_DEBUG("Kernel subkey off end of preamble\n");
153 		return VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE;
154 	}
155 
156 	/* Success */
157 	return VB2_SUCCESS;
158 }
159 
vb2_kernel_get_flags(const struct vb2_kernel_preamble * preamble)160 uint32_t vb2_kernel_get_flags(const struct vb2_kernel_preamble *preamble)
161 {
162 	if (preamble->header_version_minor < 2)
163 		return 0;
164 
165 	return preamble->flags;
166 }
167 
168 test_mockable
vb2_verify_keyblock_hash(const struct vb2_keyblock * block,uint32_t size,const struct vb2_workbuf * wb)169 vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
170 				     uint32_t size,
171 				     const struct vb2_workbuf *wb)
172 {
173 	const struct vb2_signature *sig = &block->keyblock_hash;
174 	struct vb2_hash hash;
175 
176 	/* Validity check keyblock before attempting hash check of data */
177 	VB2_TRY(vb2_check_keyblock(block, size, sig));
178 
179 	VB2_DEBUG("Checking keyblock hash...\n");
180 
181 	/* This is only used in developer mode, so hwcrypto not important. */
182 	VB2_TRY(vb2_hash_calculate(false, block, sig->data_size,
183 				   VB2_HASH_SHA512, &hash));
184 
185 	if (vb2_safe_memcmp(vb2_signature_data(sig), hash.sha512,
186 			    sizeof(hash.sha512)) != 0) {
187 		VB2_DEBUG("Invalid keyblock hash.\n");
188 		return VB2_ERROR_KEYBLOCK_HASH_INVALID_IN_DEV_MODE;
189 	}
190 
191 	/* Success */
192 	return VB2_SUCCESS;
193 }
194 
195 test_mockable
vb2_verify_kernel_preamble(struct vb2_kernel_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)196 vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
197 				       uint32_t size,
198 				       const struct vb2_public_key *key,
199 				       const struct vb2_workbuf *wb)
200 {
201 	struct vb2_signature *sig = &preamble->preamble_signature;
202 	uint32_t min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_0_SIZE;
203 
204 	VB2_DEBUG("Verifying kernel preamble.\n");
205 
206 	/* Make sure it's even safe to look at the struct */
207 	if (size < min_size) {
208 		VB2_DEBUG("Not enough data for preamble header.\n");
209 		return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
210 	}
211 	if (preamble->header_version_major !=
212 	    VB2_KERNEL_PREAMBLE_HEADER_VERSION_MAJOR) {
213 		VB2_DEBUG("Incompatible kernel preamble header version.\n");
214 		return VB2_ERROR_PREAMBLE_HEADER_VERSION;
215 	}
216 
217 	if (preamble->header_version_minor >= 2)
218 		min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_2_SIZE;
219 	else if (preamble->header_version_minor == 1)
220 		min_size = EXPECTED_VB2_KERNEL_PREAMBLE_2_1_SIZE;
221 	if (preamble->preamble_size < min_size) {
222 		VB2_DEBUG("Preamble size too small for header.\n");
223 		return VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER;
224 	}
225 	if (size < preamble->preamble_size) {
226 		VB2_DEBUG("Not enough data for preamble.\n");
227 		return VB2_ERROR_PREAMBLE_SIZE;
228 	}
229 
230 	/* Check signature */
231 	if (vb2_verify_signature_inside(preamble, preamble->preamble_size,
232 					sig)) {
233 		VB2_DEBUG("Preamble signature off end of preamble\n");
234 		return VB2_ERROR_PREAMBLE_SIG_OUTSIDE;
235 	}
236 
237 	/* Make sure advertised signature data sizes are valid. */
238 	if (preamble->preamble_size < sig->data_size) {
239 		VB2_DEBUG("Signature calculated past end of the block\n");
240 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_MUCH;
241 	}
242 
243 	if (vb2_verify_data((const uint8_t *)preamble, size, sig, key, wb)) {
244 		VB2_DEBUG("Preamble signature validation failed\n");
245 		return VB2_ERROR_PREAMBLE_SIG_INVALID;
246 	}
247 
248 	/* Verify we signed enough data */
249 	if (sig->data_size < sizeof(struct vb2_fw_preamble)) {
250 		VB2_DEBUG("Didn't sign enough data\n");
251 		return VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE;
252 	}
253 
254 	/* Verify body signature is inside the signed data */
255 	if (vb2_verify_signature_inside(preamble, sig->data_size,
256 					&preamble->body_signature)) {
257 		VB2_DEBUG("Body signature off end of preamble\n");
258 		return VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE;
259 	}
260 
261 	/*
262 	 * If bootloader is present, verify it's covered by the body
263 	 * signature.
264 	 */
265 	if (preamble->bootloader_size) {
266 		const void *body_ptr =
267 			(const void *)(uintptr_t)preamble->body_load_address;
268 		const void *bootloader_ptr =
269 			(const void *)(uintptr_t)preamble->bootloader_address;
270 		if (vb2_verify_member_inside(body_ptr,
271 					     preamble->body_signature.data_size,
272 					     bootloader_ptr,
273 					     preamble->bootloader_size,
274 					     0, 0)) {
275 			VB2_DEBUG("Bootloader off end of signed data\n");
276 			return VB2_ERROR_PREAMBLE_BOOTLOADER_OUTSIDE;
277 		}
278 	}
279 
280 	/*
281 	 * If vmlinuz header is present, verify it's covered by the body
282 	 * signature.
283 	 */
284 	if (preamble->header_version_minor >= 1 &&
285 	    preamble->vmlinuz_header_size) {
286 		const void *body_ptr =
287 			(const void *)(uintptr_t)preamble->body_load_address;
288 		const void *vmlinuz_header_ptr = (const void *)
289 			(uintptr_t)preamble->vmlinuz_header_address;
290 		if (vb2_verify_member_inside(body_ptr,
291 					     preamble->body_signature.data_size,
292 					     vmlinuz_header_ptr,
293 					     preamble->vmlinuz_header_size,
294 					     0, 0)) {
295 			VB2_DEBUG("Vmlinuz header off end of signed data\n");
296 			return VB2_ERROR_PREAMBLE_VMLINUZ_HEADER_OUTSIDE;
297 		}
298 	}
299 
300 	/* Success */
301 	return VB2_SUCCESS;
302 }
303