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