xref: /aosp_15_r20/external/vboot_reference/tests/vb2_inject_kernel_subkey_tests.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2022 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  * Tests for using vb2api_inject_kernel_subkey with vb2api_load_kernel.
6  */
7 
8 #include "2api.h"
9 #include "2common.h"
10 #include "2misc.h"
11 #include "2nvstorage.h"
12 #include "2secdata.h"
13 #include "2secdata_struct.h"
14 #include "cgptlib.h"
15 #include "cgptlib_internal.h"
16 #include "common/tests.h"
17 #include "gpt.h"
18 #include "vboot_api.h"
19 
20 /* Mock kernel partition */
21 struct mock_part {
22 	uint32_t start;
23 	uint32_t size;
24 };
25 
26 /* Partition list; ends with a 0-size partition. */
27 #define MOCK_PART_COUNT 8
28 static struct mock_part mock_parts[MOCK_PART_COUNT];
29 static int mock_part_next;
30 
31 /* Mock data */
32 static uint8_t kernel_buffer[80000];
33 static int disk_read_to_fail;
34 static int keyblock_verify_fail;  /* 0=ok, 1=sig, 2=hash */
35 static int preamble_verify_fail;
36 static int verify_data_fail;
37 static int unpack_key_fail;
38 static int gpt_flag_external;
39 
40 static struct vb2_kernel_params lkp;
41 static struct vb2_disk_info disk_info;
42 static struct vb2_keyblock kbh;
43 static struct vb2_kernel_preamble kph;
44 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
45 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
46 static struct vb2_context *ctx;
47 static struct vb2_shared_data *sd;
48 static uint8_t kernel_packed_key_data[sizeof(struct vb2_packed_key) + 32];
49 
50 /**
51  * Reset mock data (for use before each test)
52  */
ResetMocks(void)53 static void ResetMocks(void)
54 {
55 	struct vb2_packed_key *kernel_packed_key;
56 
57 	disk_read_to_fail = -1;
58 
59 	keyblock_verify_fail = 0;
60 	preamble_verify_fail = 0;
61 	verify_data_fail = 0;
62 	unpack_key_fail = 0;
63 
64 	gpt_flag_external = 0;
65 
66 	memset(&lkp, 0, sizeof(lkp));
67 	lkp.kernel_buffer = kernel_buffer;
68 	lkp.kernel_buffer_size = sizeof(kernel_buffer);
69 
70 	memset(&disk_info, 0, sizeof(disk_info));
71 	disk_info.bytes_per_lba = 512;
72 	disk_info.streaming_lba_count = 1024;
73 	disk_info.lba_count = 1024;
74 	disk_info.handle = (vb2ex_disk_handle_t)1;
75 
76 	memset(&kbh, 0, sizeof(kbh));
77 	kbh.data_key.key_version = 2;
78 	kbh.keyblock_flags = -1;
79 	kbh.keyblock_size = sizeof(kbh);
80 
81 	memset(&kph, 0, sizeof(kph));
82 	kph.kernel_version = 1;
83 	kph.preamble_size = 4096 - kbh.keyblock_size;
84 	kph.body_signature.data_size = 70144;
85 	kph.bootloader_address = 0xbeadd008;
86 	kph.bootloader_size = 0x1234;
87 
88 	memset(mock_parts, 0, sizeof(mock_parts));
89 	mock_parts[0].start = 100;
90 	mock_parts[0].size = 150;  /* 75 KB */
91 	mock_part_next = 0;
92 
93 	memset(&kernel_packed_key_data, 0, sizeof(kernel_packed_key_data));
94 	kernel_packed_key = (struct vb2_packed_key *)kernel_packed_key_data;
95 	kernel_packed_key->key_offset = sizeof(struct vb2_packed_key);
96 	kernel_packed_key->key_size = sizeof(kernel_packed_key_data) -
97 			sizeof(struct vb2_packed_key);
98 	kernel_packed_key->algorithm = VB2_ALG_RSA4096_SHA256;
99 	kernel_packed_key->key_version = 0;
100 
101 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
102 		  "vb2api_init failed");
103 
104 	sd = vb2_get_sd(ctx);
105 }
106 
107 /* Mocks */
VbExDiskRead(vb2ex_disk_handle_t h,uint64_t lba_start,uint64_t lba_count,void * buffer)108 vb2_error_t VbExDiskRead(vb2ex_disk_handle_t h, uint64_t lba_start,
109 			 uint64_t lba_count, void *buffer)
110 {
111 	if ((int)lba_start == disk_read_to_fail)
112 		return VB2_ERROR_MOCK;
113 
114 	return VB2_SUCCESS;
115 }
116 
AllocAndReadGptData(vb2ex_disk_handle_t disk_handle,GptData * gptdata)117 int AllocAndReadGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
118 {
119 	return GPT_SUCCESS;
120 }
121 
GptInit(GptData * gpt)122 int GptInit(GptData *gpt)
123 {
124 	return GPT_SUCCESS;
125 }
126 
GptNextKernelEntry(GptData * gpt,uint64_t * start_sector,uint64_t * size)127 int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
128 {
129 	struct mock_part *p = mock_parts + mock_part_next;
130 
131 	if (!p->size)
132 		return GPT_ERROR_NO_VALID_KERNEL;
133 
134 	if (gpt->flags & GPT_FLAG_EXTERNAL)
135 		gpt_flag_external++;
136 
137 	gpt->current_kernel = mock_part_next;
138 	*start_sector = p->start;
139 	*size = p->size;
140 	mock_part_next++;
141 	return GPT_SUCCESS;
142 }
143 
GptUpdateKernelEntry(GptData * gpt,uint32_t update_type)144 int GptUpdateKernelEntry(GptData *gpt, uint32_t update_type)
145 {
146 	return GPT_SUCCESS;
147 }
148 
WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle,GptData * gptdata)149 int WriteAndFreeGptData(vb2ex_disk_handle_t disk_handle, GptData *gptdata)
150 {
151 	return GPT_SUCCESS;
152 }
153 
GetCurrentKernelUniqueGuid(GptData * gpt,void * dest)154 void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
155 {
156 	static const char fake_guid[] = "FakeGuid";
157 
158 	memcpy(dest, fake_guid, sizeof(fake_guid));
159 }
160 
vb2_unpack_key_buffer(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)161 vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
162 				  const uint8_t *buf, uint32_t size)
163 {
164 	if (--unpack_key_fail == 0)
165 		return VB2_ERROR_MOCK;
166 
167 	return VB2_SUCCESS;
168 }
169 
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)170 vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
171 				const struct vb2_public_key *key,
172 				const struct vb2_workbuf *wb)
173 {
174 	if (keyblock_verify_fail >= 1)
175 		return VB2_ERROR_MOCK;
176 
177 	/* Use this as an opportunity to override the keyblock */
178 	memcpy((void *)block, &kbh, sizeof(kbh));
179 	return VB2_SUCCESS;
180 }
181 
vb2_verify_keyblock_hash(const struct vb2_keyblock * block,uint32_t size,const struct vb2_workbuf * wb)182 vb2_error_t vb2_verify_keyblock_hash(const struct vb2_keyblock *block,
183 				     uint32_t size,
184 				     const struct vb2_workbuf *wb)
185 {
186 	if (keyblock_verify_fail >= 2)
187 		return VB2_ERROR_MOCK;
188 
189 	/* Use this as an opportunity to override the keyblock */
190 	memcpy((void *)block, &kbh, sizeof(kbh));
191 	return VB2_SUCCESS;
192 }
193 
vb2_verify_kernel_preamble(struct vb2_kernel_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)194 vb2_error_t vb2_verify_kernel_preamble(struct vb2_kernel_preamble *preamble,
195 				       uint32_t size,
196 				       const struct vb2_public_key *key,
197 				       const struct vb2_workbuf *wb)
198 {
199 	if (preamble_verify_fail)
200 		return VB2_ERROR_MOCK;
201 
202 	/* Use this as an opportunity to override the preamble */
203 	memcpy((void *)preamble, &kph, sizeof(kph));
204 	return VB2_SUCCESS;
205 }
206 
vb2_verify_data(const uint8_t * data,uint32_t size,struct vb2_signature * sig,const struct vb2_public_key * key,const struct vb2_workbuf * wb)207 vb2_error_t vb2_verify_data(const uint8_t *data, uint32_t size,
208 			    struct vb2_signature *sig,
209 			    const struct vb2_public_key *key,
210 			    const struct vb2_workbuf *wb)
211 {
212 	if (verify_data_fail)
213 		return VB2_ERROR_MOCK;
214 
215 	return VB2_SUCCESS;
216 }
217 
218 /* Make sure nothing tested here ever calls this directly. */
vb2api_fail(struct vb2_context * c,uint8_t reason,uint8_t subcode)219 void vb2api_fail(struct vb2_context *c, uint8_t reason, uint8_t subcode)
220 {
221 	TEST_TRUE(0, "  called vb2api fail");
222 }
223 
test_load_kernel(vb2_error_t expect_retval,const char * test_name)224 static void test_load_kernel(vb2_error_t expect_retval, const char *test_name)
225 {
226 	TEST_SUCC(vb2api_inject_kernel_subkey(ctx, kernel_packed_key_data,
227 					      sizeof(kernel_packed_key_data)),
228 		  "vb2api_inject_kernel_subkey failed");
229 
230 	TEST_EQ(vb2api_load_kernel(ctx, &lkp, &disk_info), expect_retval,
231 		test_name);
232 	if (expect_retval == VB2_SUCCESS)
233 		TEST_PTR_EQ(lkp.disk_handle, disk_info.handle,
234 			    "  fill disk_handle when success");
235 }
236 
237 /* These tests are copied from tests/vb2_load_kernel_tests.c, but with
238  * tests that rely on vb2_secdata_fwmp excluded. */
load_kernel_tests(void)239 static void load_kernel_tests(void)
240 {
241 	ResetMocks();
242 	test_load_kernel(VB2_SUCCESS, "First kernel good");
243 	TEST_EQ(lkp.partition_number, 1, "  part num");
244 	TEST_EQ(lkp.bootloader_offset, 0xbeadd008, "  bootloader offset");
245 	TEST_EQ(lkp.bootloader_size, 0x1234, "  bootloader size");
246 	TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", "  guid");
247 	TEST_EQ(gpt_flag_external, 0, "GPT was internal");
248 	TEST_NEQ(sd->flags & VB2_SD_FLAG_KERNEL_SIGNED, 0, "  use signature");
249 
250 	ResetMocks();
251 	/* Make the version match kernel_version_secdata so that the
252 	   search stops at the first valid partition. */
253 	kbh.data_key.key_version = 0;
254 	kph.kernel_version = 0;
255 	mock_parts[1].start = 300;
256 	mock_parts[1].size = 150;
257 	test_load_kernel(VB2_SUCCESS, "Two good kernels");
258 	TEST_EQ(lkp.partition_number, 1, "  part num");
259 	TEST_EQ(mock_part_next, 1, "  didn't read second one");
260 
261 	/* Fail if no kernels found */
262 	ResetMocks();
263 	mock_parts[0].size = 0;
264 	test_load_kernel(VB2_ERROR_LK_NO_KERNEL_FOUND, "No kernels");
265 
266 	/* Skip kernels which are too small */
267 	ResetMocks();
268 	mock_parts[0].size = 10;
269 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Too small");
270 
271 	ResetMocks();
272 	disk_read_to_fail = 100;
273 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
274 			 "Fail reading kernel start");
275 
276 	ResetMocks();
277 	keyblock_verify_fail = 1;
278 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
279 			 "Fail key block sig");
280 
281 	/* Check keyblock flags */
282 	ResetMocks();
283 	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
284 		| VB2_KEYBLOCK_FLAG_DEVELOPER_1
285 		| VB2_KEYBLOCK_FLAG_MINIOS_0;
286 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
287 			 "Keyblock dev flag mismatch");
288 
289 	ResetMocks();
290 	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_1
291 		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
292 		| VB2_KEYBLOCK_FLAG_MINIOS_0;
293 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
294 			 "Keyblock rec flag mismatch");
295 
296 	ResetMocks();
297 	kbh.keyblock_flags = VB2_KEYBLOCK_FLAG_RECOVERY_0
298 		| VB2_KEYBLOCK_FLAG_DEVELOPER_0
299 		| VB2_KEYBLOCK_FLAG_MINIOS_1;
300 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
301 			 "Keyblock minios flag mismatch");
302 
303 	ResetMocks();
304 	kbh.data_key.key_version = 0x10000;
305 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
306 			 "Keyblock kernel key version too big");
307 
308 	ResetMocks();
309 	kbh.data_key.key_version = 3;
310 	test_load_kernel(VB2_SUCCESS, "Keyblock version roll forward");
311 	TEST_EQ(sd->kernel_version, 0x30001, "  SD version");
312 
313 	ResetMocks();
314 	kbh.data_key.key_version = 3;
315 	mock_parts[1].start = 300;
316 	mock_parts[1].size = 150;
317 	test_load_kernel(VB2_SUCCESS, "Two kernels roll forward");
318 	TEST_EQ(mock_part_next, 2, "  read both");
319 	TEST_EQ(sd->kernel_version, 0x30001, "  SD version");
320 
321 	ResetMocks();
322 	unpack_key_fail = 2;
323 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data key");
324 
325 	ResetMocks();
326 	preamble_verify_fail = 1;
327 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad preamble");
328 
329 	ResetMocks();
330 	kph.preamble_size |= 0x07;
331 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
332 			 "Kernel body offset");
333 
334 	ResetMocks();
335 	kph.preamble_size += 65536;
336 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
337 			 "Kernel body offset huge");
338 
339 	/* Check getting kernel load address from header */
340 	ResetMocks();
341 	kph.body_load_address = (size_t)kernel_buffer;
342 	lkp.kernel_buffer = NULL;
343 	test_load_kernel(VB2_SUCCESS, "Get load address from preamble");
344 	TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, "  address");
345 	/* Size is rounded up to nearest sector */
346 	TEST_EQ(lkp.kernel_buffer_size, 70144, "  size");
347 
348 	ResetMocks();
349 	lkp.kernel_buffer_size = 8192;
350 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
351 			 "Kernel too big for buffer");
352 
353 	ResetMocks();
354 	mock_parts[0].size = 130;
355 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
356 			 "Kernel too big for partition");
357 
358 	ResetMocks();
359 	kph.body_signature.data_size = 8192;
360 	test_load_kernel(VB2_SUCCESS, "Kernel tiny");
361 
362 	ResetMocks();
363 	disk_read_to_fail = 228;
364 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND,
365 			 "Fail reading kernel data");
366 
367 	ResetMocks();
368 	verify_data_fail = 1;
369 	test_load_kernel(VB2_ERROR_LK_INVALID_KERNEL_FOUND, "Bad data");
370 
371 	/* Check that EXTERNAL_GPT flag makes it down */
372 	ResetMocks();
373 	disk_info.flags |= VB2_DISK_FLAG_EXTERNAL_GPT;
374 	test_load_kernel(VB2_SUCCESS, "Succeed external GPT");
375 	TEST_EQ(gpt_flag_external, 1, "GPT was external");
376 
377 	/* Check recovery from unreadble primary GPT */
378 	ResetMocks();
379 	disk_read_to_fail = 1;
380 	test_load_kernel(VB2_SUCCESS, "Can't read disk");
381 }
382 
main(void)383 int main(void)
384 {
385 	load_kernel_tests();
386 
387 	return gTestSuccess ? 0 : 255;
388 }
389