xref: /aosp_15_r20/external/vboot_reference/tests/vb20_api_kernel_tests.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2015 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 kernel verification library, api layer
6  */
7 
8 #include <stdio.h>
9 
10 #include "2api.h"
11 #include "2common.h"
12 #include "2misc.h"
13 #include "2nvstorage.h"
14 #include "2rsa.h"
15 #include "2secdata.h"
16 #include "2sysincludes.h"
17 #include "common/tests.h"
18 #include "vboot_struct.h"
19 
20 /* Common context for tests */
21 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
22 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
23 static struct vb2_context *ctx;
24 static struct vb2_shared_data *sd;
25 static struct vb2_fw_preamble *fwpre;
26 static struct vb2_kernel_preamble *kpre;
27 static struct vb2_packed_key *kdkey;
28 static const char fw_kernel_key_data[36] = "Test kernel key data";
29 static char kernel_data[0x4008] = "Sure it's a kernel...";
30 
31 /* Mocked function data */
32 
33 static struct {
34 	struct vb2_gbb_header h;
35 	struct vb2_packed_key recovery_key;
36 	char recovery_key_data[32];
37 } mock_gbb;
38 
39 static int mock_read_res_fail_on_call;
40 static int mock_unpack_key_retval;
41 static int mock_load_kernel_keyblock_retval;
42 static int mock_load_kernel_preamble_retval;
43 static int mock_secdata_fwmp_check_retval;
44 
45 /* Type of test to reset for */
46 enum reset_type {
47 	FOR_PHASE1,
48 	FOR_PHASE2,
49 	FOR_PHASE3,
50 };
51 
reset_common_data(enum reset_type t)52 static void reset_common_data(enum reset_type t)
53 {
54 	struct vb2_packed_key *k;
55 
56 	memset(workbuf, 0xaa, sizeof(workbuf));
57 
58 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
59 		  "vb2api_init failed");
60 
61 	sd = vb2_get_sd(ctx);
62 	sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED;
63 	vb2_nv_init(ctx);
64 
65 	vb2api_secdata_kernel_create(ctx);
66 	vb2_secdata_kernel_init(ctx);
67 	vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, 0x20002);
68 
69 	mock_read_res_fail_on_call = 0;
70 	mock_unpack_key_retval = VB2_SUCCESS;
71 	mock_load_kernel_keyblock_retval = VB2_SUCCESS;
72 	mock_load_kernel_preamble_retval = VB2_SUCCESS;
73 	mock_secdata_fwmp_check_retval = VB2_SUCCESS;
74 
75 	/* Recovery key in mock GBB */
76 	memset(&mock_gbb, 0, sizeof(mock_gbb));
77 	mock_gbb.recovery_key.algorithm = 11;
78 	mock_gbb.recovery_key.key_offset =
79 		vb2_offset_of(&mock_gbb.recovery_key,
80 			      &mock_gbb.recovery_key_data);
81 	mock_gbb.recovery_key.key_size = sizeof(mock_gbb.recovery_key_data);
82 	strcpy(mock_gbb.recovery_key_data, "The recovery key");
83 	mock_gbb.h.recovery_key_offset =
84 		vb2_offset_of(&mock_gbb, &mock_gbb.recovery_key);
85 	mock_gbb.h.recovery_key_size =
86 		mock_gbb.recovery_key.key_offset +
87 		mock_gbb.recovery_key.key_size;
88 
89 
90 	if (t == FOR_PHASE1) {
91 		uint8_t *kdata;
92 
93 		/* Create mock firmware preamble in the context */
94 		sd->preamble_offset = sd->workbuf_used;
95 		fwpre = (struct vb2_fw_preamble *)
96 			vb2_member_of(sd, sd->preamble_offset);
97 		k = &fwpre->kernel_subkey;
98 		kdata = (uint8_t *)fwpre + sizeof(*fwpre);
99 		memcpy(kdata, fw_kernel_key_data, sizeof(fw_kernel_key_data));
100 		k->algorithm = 7;
101 		k->key_offset = vb2_offset_of(k, kdata);
102 		k->key_size = sizeof(fw_kernel_key_data);
103 		sd->preamble_size = sizeof(*fwpre) + k->key_size;
104 		vb2_set_workbuf_used(ctx,
105 				     sd->preamble_offset + sd->preamble_size);
106 
107 		/* Needed to check that secdata_kernel initialization is
108 		   performed by phase1 function. */
109 		sd->status &= ~VB2_SD_STATUS_SECDATA_KERNEL_INIT;
110 
111 	} else if (t == FOR_PHASE2) {
112 		struct vb2_signature *sig;
113 		struct vb2_digest_context dc;
114 		uint8_t *sdata;
115 
116 		/* Create mock kernel data key */
117 		sd->data_key_offset = sd->workbuf_used;
118 		kdkey = (struct vb2_packed_key *)
119 			vb2_member_of(sd, sd->data_key_offset);
120 		kdkey->algorithm = VB2_ALG_RSA2048_SHA256;
121 		sd->data_key_size = sizeof(*kdkey);
122 		vb2_set_workbuf_used(ctx,
123 				     sd->data_key_offset + sd->data_key_size);
124 
125 		/* Create mock kernel preamble in the context */
126 		sd->preamble_offset = sd->workbuf_used;
127 		kpre = (struct vb2_kernel_preamble *)
128 			vb2_member_of(sd, sd->preamble_offset);
129 		sdata = (uint8_t *)kpre + sizeof(*kpre);
130 
131 		sig = &kpre->body_signature;
132 		sig->data_size = sizeof(kernel_data);
133 		sig->sig_offset = vb2_offset_of(sig, sdata);
134 		sig->sig_size = VB2_SHA512_DIGEST_SIZE;
135 
136 		vb2_digest_init(&dc, false, VB2_HASH_SHA256, 0);
137 		vb2_digest_extend(&dc, (const uint8_t *)kernel_data,
138 				  sizeof(kernel_data));
139 		vb2_digest_finalize(&dc, sdata, sig->sig_size);
140 
141 		sd->preamble_size = sizeof(*kpre) + sig->sig_size;
142 		sd->vblock_preamble_offset =
143 			0x10000 - sd->preamble_size;
144 		vb2_set_workbuf_used(ctx,
145 				     sd->preamble_offset + sd->preamble_size);
146 
147 	} else {
148 		/* Set flags and versions for roll-forward */
149 		sd->kernel_version = 0x20004;
150 		sd->kernel_version_secdata = 0x20002;
151 		sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED;
152 		ctx->flags |= VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD;
153 	}
154 };
155 
156 /* Mocked functions */
157 
vb2api_secdata_fwmp_check(struct vb2_context * c,uint8_t * size)158 vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *c, uint8_t *size)
159 {
160 	return mock_secdata_fwmp_check_retval;
161 }
162 
vb2_get_gbb(struct vb2_context * c)163 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
164 {
165 	return &mock_gbb.h;
166 }
167 
vb2ex_read_resource(struct vb2_context * c,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)168 vb2_error_t vb2ex_read_resource(struct vb2_context *c,
169 				enum vb2_resource_index index, uint32_t offset,
170 				void *buf, uint32_t size)
171 {
172 	uint8_t *rptr;
173 	uint32_t rsize;
174 
175 	if (--mock_read_res_fail_on_call == 0)
176 		return VB2_ERROR_MOCK;
177 
178 	switch(index) {
179 	case VB2_RES_GBB:
180 		rptr = (uint8_t *)&mock_gbb;
181 		rsize = sizeof(mock_gbb);
182 		break;
183 	default:
184 		return VB2_ERROR_EX_READ_RESOURCE_INDEX;
185 	}
186 
187 	if (offset > rsize || offset + size > rsize)
188 		return VB2_ERROR_EX_READ_RESOURCE_SIZE;
189 
190 	memcpy(buf, rptr + offset, size);
191 	return VB2_SUCCESS;
192 }
193 
vb2_load_kernel_keyblock(struct vb2_context * c)194 vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *c)
195 {
196 	return mock_load_kernel_keyblock_retval;
197 }
198 
vb2_load_kernel_preamble(struct vb2_context * c)199 vb2_error_t vb2_load_kernel_preamble(struct vb2_context *c)
200 {
201 	return mock_load_kernel_preamble_retval;
202 }
203 
vb2_unpack_key_buffer(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)204 vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
205 				  const uint8_t *buf, uint32_t size)
206 {
207 	const struct vb2_packed_key *k = (const struct vb2_packed_key *)buf;
208 
209 	key->arrsize = 0;
210 	key->hash_alg = vb2_crypto_to_hash(k->algorithm);
211 	return mock_unpack_key_retval;
212 }
213 
vb2_verify_digest(const struct vb2_public_key * key,struct vb2_signature * sig,const uint8_t * digest,const struct vb2_workbuf * wb)214 vb2_error_t vb2_verify_digest(const struct vb2_public_key *key,
215 			      struct vb2_signature *sig, const uint8_t *digest,
216 			      const struct vb2_workbuf *wb)
217 {
218 	if (memcmp(digest, (uint8_t *)sig + sig->sig_offset, sig->sig_size))
219 		return VB2_ERROR_VDATA_VERIFY_DIGEST;
220 
221 	return VB2_SUCCESS;
222 }
223 
224 /* Tests */
225 
load_kernel_vblock_tests(void)226 static void load_kernel_vblock_tests(void)
227 {
228 	reset_common_data(FOR_PHASE1);
229 	TEST_SUCC(vb2api_load_kernel_vblock(ctx), "load vblock good");
230 
231 	reset_common_data(FOR_PHASE1);
232 	mock_load_kernel_keyblock_retval = VB2_ERROR_MOCK;
233 	TEST_EQ(vb2api_load_kernel_vblock(ctx), VB2_ERROR_MOCK,
234 		"load vblock bad keyblock");
235 
236 	reset_common_data(FOR_PHASE1);
237 	mock_load_kernel_preamble_retval = VB2_ERROR_MOCK;
238 	TEST_EQ(vb2api_load_kernel_vblock(ctx), VB2_ERROR_MOCK,
239 		"load vblock bad preamble");
240 }
241 
get_kernel_size_tests(void)242 static void get_kernel_size_tests(void)
243 {
244 	uint32_t offs, size;
245 
246 	reset_common_data(FOR_PHASE2);
247 	offs = size = 0;
248 	TEST_SUCC(vb2api_get_kernel_size(ctx, &offs, &size), "get size good");
249 	TEST_EQ(offs, 0x10000, "  offset");
250 	TEST_EQ(size, sizeof(kernel_data), "  size");
251 
252 	/* Don't need to pass pointers */
253 	reset_common_data(FOR_PHASE2);
254 	TEST_SUCC(vb2api_get_kernel_size(ctx, NULL, NULL), "get size null");
255 
256 	reset_common_data(FOR_PHASE2);
257 	sd->preamble_size = 0;
258 	TEST_EQ(vb2api_get_kernel_size(ctx, &offs, &size),
259 		VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
260 		"get size no preamble");
261 }
262 
verify_kernel_data_tests(void)263 static void verify_kernel_data_tests(void)
264 {
265 	reset_common_data(FOR_PHASE2);
266 	TEST_SUCC(vb2api_verify_kernel_data(ctx, kernel_data,
267 					    sizeof(kernel_data)),
268 		  "verify data good");
269 
270 	reset_common_data(FOR_PHASE2);
271 	sd->preamble_size = 0;
272 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
273 					  sizeof(kernel_data)),
274 		VB2_ERROR_API_VERIFY_KDATA_PREAMBLE, "verify no preamble");
275 
276 	reset_common_data(FOR_PHASE2);
277 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
278 					  sizeof(kernel_data) + 1),
279 		VB2_ERROR_API_VERIFY_KDATA_SIZE, "verify size");
280 
281 	reset_common_data(FOR_PHASE2);
282 	sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN -
283 			   vb2_wb_round_up(sizeof(struct vb2_digest_context));
284 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
285 					  sizeof(kernel_data)),
286 		VB2_ERROR_API_VERIFY_KDATA_WORKBUF, "verify workbuf");
287 
288 	reset_common_data(FOR_PHASE2);
289 	sd->data_key_size = 0;
290 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
291 					  sizeof(kernel_data)),
292 		VB2_ERROR_API_VERIFY_KDATA_KEY, "verify no key");
293 
294 	reset_common_data(FOR_PHASE2);
295 	mock_unpack_key_retval = VB2_ERROR_MOCK;
296 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
297 					  sizeof(kernel_data)),
298 		VB2_ERROR_MOCK, "verify unpack key");
299 
300 	reset_common_data(FOR_PHASE2);
301 	kdkey->algorithm = VB2_ALG_COUNT;
302 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
303 					  sizeof(kernel_data)),
304 		VB2_ERROR_SHA_INIT_ALGORITHM, "verify hash init");
305 
306 	reset_common_data(FOR_PHASE2);
307 	sd->workbuf_used = sd->workbuf_size -
308 			   vb2_wb_round_up(sizeof(struct vb2_digest_context));
309 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
310 					  sizeof(kernel_data)),
311 		VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST, "verify hash workbuf");
312 
313 	reset_common_data(FOR_PHASE2);
314 	kernel_data[3] ^= 0xd0;
315 	TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
316 					  sizeof(kernel_data)),
317 		VB2_ERROR_VDATA_VERIFY_DIGEST, "verify hash digest");
318 	kernel_data[3] ^= 0xd0;
319 }
320 
phase3_tests(void)321 static void phase3_tests(void)
322 {
323 	uint32_t v;
324 
325 	reset_common_data(FOR_PHASE3);
326 	TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 good");
327 	v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
328 	TEST_EQ(v, 0x20004, "  version");
329 
330 	reset_common_data(FOR_PHASE3);
331 	sd->kernel_version = 0x20001;
332 	TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 no rollback");
333 	v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
334 	TEST_EQ(v, 0x20002, "  version");
335 
336 	reset_common_data(FOR_PHASE3);
337 	sd->flags &= ~VB2_SD_FLAG_KERNEL_SIGNED;
338 	TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 unsigned kernel");
339 	v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
340 	TEST_EQ(v, 0x20002, "  version");
341 
342 	reset_common_data(FOR_PHASE3);
343 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
344 	TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 recovery");
345 	v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
346 	TEST_EQ(v, 0x20002, "  version");
347 
348 	reset_common_data(FOR_PHASE3);
349 	ctx->flags &= ~VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD;
350 	TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 no rollforward");
351 	v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
352 	TEST_EQ(v, 0x20002, "  version");
353 
354 	reset_common_data(FOR_PHASE3);
355 	sd->status &= ~VB2_SD_STATUS_SECDATA_KERNEL_INIT;
356 	TEST_ABORT(vb2api_kernel_phase3(ctx), "phase3 set fail");
357 }
358 
main(int argc,char * argv[])359 int main(int argc, char* argv[])
360 {
361 	load_kernel_vblock_tests();
362 	get_kernel_size_tests();
363 	verify_kernel_data_tests();
364 	phase3_tests();
365 
366 	return gTestSuccess ? 0 : 255;
367 }
368