xref: /aosp_15_r20/external/vboot_reference/tests/vb2_gbb_tests.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1 /* Copyright 2019 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 GBB library.
6  */
7 
8 #include "2common.h"
9 #include "2misc.h"
10 #include "common/tests.h"
11 
12 /* Mock data */
13 static char gbb_data[4096 + sizeof(struct vb2_gbb_header)];
14 static struct vb2_gbb_header *gbb = (struct vb2_gbb_header *)gbb_data;
15 static struct vb2_packed_key *rootkey;
16 static struct vb2_context *ctx;
17 static struct vb2_workbuf wb;
18 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
19 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
20 
set_gbb_hwid(const char * hwid,size_t size)21 static void set_gbb_hwid(const char *hwid, size_t size)
22 {
23 	memcpy(gbb_data + gbb->hwid_offset, hwid, size);
24 	gbb->hwid_size = size;
25 }
26 
reset_common_data(void)27 static void reset_common_data(void)
28 {
29 	int gbb_used;
30 
31 	memset(gbb_data, 0, sizeof(gbb_data));
32 	gbb->header_size = sizeof(*gbb);
33 	gbb->major_version = VB2_GBB_MAJOR_VER;
34 	gbb->minor_version = VB2_GBB_MINOR_VER;
35 	gbb->flags = 0;
36 	gbb_used = sizeof(struct vb2_gbb_header);
37 
38 	gbb->recovery_key_offset = gbb_used;
39 	gbb->recovery_key_size = 64;
40 	gbb_used += gbb->recovery_key_size;
41 	gbb->rootkey_offset = gbb_used;
42 	gbb->rootkey_size = sizeof(struct vb2_packed_key);
43 	gbb_used += gbb->rootkey_size;
44 
45 	rootkey = ((void *)gbb + gbb->rootkey_offset);
46 	rootkey->key_offset = sizeof(*rootkey);
47 
48 	gbb->hwid_offset = gbb_used;
49 	const char hwid_src[] = "Test HWID";
50 	set_gbb_hwid(hwid_src, sizeof(hwid_src));
51 
52 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
53 		  "vb2api_init failed");
54 	vb2_workbuf_from_ctx(ctx, &wb);
55 }
56 
57 /* Mocks */
vb2_get_gbb(struct vb2_context * c)58 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
59 {
60 	return gbb;
61 }
62 
vb2ex_read_resource(struct vb2_context * c,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)63 vb2_error_t vb2ex_read_resource(struct vb2_context *c,
64 				enum vb2_resource_index index, uint32_t offset,
65 				void *buf, uint32_t size)
66 {
67 	uint8_t *rptr;
68 	uint32_t rsize;
69 
70 	switch(index) {
71 	case VB2_RES_GBB:
72 		rptr = (uint8_t *)&gbb_data;
73 		rsize = sizeof(gbb_data);
74 		break;
75 	default:
76 		return VB2_ERROR_EX_READ_RESOURCE_INDEX;
77 	}
78 
79 	if (offset + size >= rsize)
80 		return VB2_ERROR_EX_READ_RESOURCE_SIZE;
81 
82 	memcpy(buf, rptr + offset, size);
83 	return VB2_SUCCESS;
84 }
85 
86 /* Tests */
flag_tests(void)87 static void flag_tests(void)
88 {
89 	reset_common_data();
90 	gbb->flags = 0xdeadbeef;
91 	TEST_EQ(vb2api_gbb_get_flags(ctx), gbb->flags,
92 		"retrieve GBB flags");
93 }
94 
key_tests(void)95 static void key_tests(void)
96 {
97 	/* Assume that root key and recovery key are dealt with using the same
98 	   code in our GBB library functions. */
99 	struct vb2_packed_key *keyp;
100 	struct vb2_workbuf wborig;
101 	const char key_data[] = "HELLOWORLD";
102 	uint32_t size;
103 
104 	/* gbb.offset < sizeof(vb2_gbb_header) */
105 	reset_common_data();
106 	wborig = wb;
107 	gbb->rootkey_offset = sizeof(*gbb) - 1;
108 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
109 		VB2_ERROR_GBB_INVALID,
110 		"gbb.rootkey offset too small");
111 	TEST_TRUE(wb.buf == wborig.buf,
112 		  "  workbuf restored on error");
113 
114 	/* gbb.offset > gbb_data */
115 	reset_common_data();
116 	wborig = wb;
117 	gbb->rootkey_offset = sizeof(gbb_data) + 1;
118 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
119 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
120 		"gbb.rootkey offset too large");
121 	TEST_TRUE(wb.buf == wborig.buf,
122 		  "  workbuf restored on error");
123 
124 	/* gbb.size < sizeof(vb2_packed_key) */
125 	reset_common_data();
126 	wborig = wb;
127 	gbb->rootkey_size = sizeof(*rootkey) - 1;
128 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
129 		VB2_ERROR_GBB_INVALID,
130 		"gbb.rootkey size too small");
131 	TEST_TRUE(wb.buf == wborig.buf,
132 		  "  workbuf restored on error");
133 
134 	/* sizeof(vb2_packed_key) > workbuf.size */
135 	reset_common_data();
136 	wborig = wb;
137 	wb.size = sizeof(*rootkey) - 1;
138 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
139 		VB2_ERROR_GBB_WORKBUF,
140 		"workbuf size too small for vb2_packed_key header");
141 	TEST_TRUE(wb.buf == wborig.buf,
142 		  "  workbuf restored on error");
143 
144 	/* packed_key.offset < sizeof(vb2_packed_key) */
145 	reset_common_data();
146 	wborig = wb;
147 	rootkey->key_size = 1;
148 	rootkey->key_offset = sizeof(*rootkey) - 1;
149 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
150 		VB2_ERROR_INSIDE_DATA_OVERLAP,
151 		"rootkey offset too small");
152 	TEST_TRUE(wb.buf == wborig.buf,
153 		  "  workbuf restored on error");
154 
155 	/* packed_key.offset > gbb_data */
156 	reset_common_data();
157 	wborig = wb;
158 	rootkey->key_size = 1;
159 	rootkey->key_offset = sizeof(gbb_data) + 1;
160 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
161 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
162 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
163 		"rootkey size too large");
164 	TEST_TRUE(wb.buf == wborig.buf,
165 		  "  workbuf restored on error");
166 
167 	/* packed_key.size > workbuf.size */
168 	reset_common_data();
169 	wborig = wb;
170 	rootkey->key_size = wb.size + 1;
171 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
172 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
173 		VB2_ERROR_GBB_WORKBUF,
174 		"workbuf size too small for vb2_packed_key contents");
175 	TEST_TRUE(wb.buf == wborig.buf,
176 		  "  workbuf restored on error");
177 
178 	/* gbb.size < sizeof(vb2_packed_key) + packed_key.size */
179 	reset_common_data();
180 	wborig = wb;
181 	rootkey->key_size = 2;
182 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size - 1;
183 	TEST_EQ(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
184 		VB2_ERROR_INSIDE_DATA_OUTSIDE,
185 		"rootkey size exceeds gbb.rootkey size");
186 	TEST_TRUE(wb.buf == wborig.buf,
187 		  "  workbuf restored on error");
188 
189 	/* gbb.size == sizeof(vb2_packed_key) + packed_key.size */
190 	reset_common_data();
191 	wborig = wb;
192 	rootkey->key_size = sizeof(key_data);
193 	memcpy((void *)rootkey + rootkey->key_offset,
194 	       key_data, sizeof(key_data));
195 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
196 	TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
197 		  "succeeds when gbb.rootkey and rootkey sizes agree");
198 	TEST_TRUE(wb.size < wborig.size,
199 		  "  workbuf shrank on success");
200 	TEST_EQ(memcmp(rootkey, keyp, rootkey->key_offset + rootkey->key_size),
201 		0, "  copied key data successfully");
202 	TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
203 		"  correct size returned");
204 
205 	/* gbb.size > sizeof(vb2_packed_key) + packed_key.size
206 	   packed_key.offset = +0 */
207 	reset_common_data();
208 	wborig = wb;
209 	rootkey->key_size = 1;
210 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
211 	TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
212 		  "succeeds when gbb.rootkey is padded after key");
213 	TEST_TRUE(wb.size < wborig.size,
214 		  "  workbuf shrank on success");
215 	TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
216 		"  correct size returned");
217 
218 	/* gbb.size > sizeof(vb2_packed_key) + packed_key.size
219 	   packed_key.offset = +1 */
220 	reset_common_data();
221 	wborig = wb;
222 	rootkey->key_offset = sizeof(*rootkey) + 1;
223 	rootkey->key_size = 1;
224 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size;
225 	TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
226 		  "succeeds when gbb.rootkey is padded before key");
227 	TEST_TRUE(wb.size < wborig.size,
228 		  "  workbuf shrank on success");
229 	TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
230 		"  correct size returned");
231 
232 	/* packed_key.size = 0, packed_key.offset = +1 */
233 	reset_common_data();
234 	wborig = wb;
235 	rootkey->key_offset = sizeof(*rootkey) + 1;
236 	rootkey->key_size = 0;
237 	gbb->rootkey_size = rootkey->key_offset + rootkey->key_size + 1;
238 	TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
239 		  "succeeds when gbb.rootkey is padded; empty test key");
240 	TEST_TRUE(wb.size < wborig.size,
241 		  "  workbuf shrank on success");
242 	TEST_EQ(size, rootkey->key_offset + rootkey->key_size,
243 		"  correct size returned");
244 
245 	/* packed_key.size = 0, packed_key.offset = -1 */
246 	reset_common_data();
247 	wborig = wb;
248 	rootkey->key_offset = sizeof(*rootkey) - 1;
249 	rootkey->key_size = 0;
250 	gbb->rootkey_size = sizeof(*rootkey) + rootkey->key_size + 1;
251 	TEST_SUCC(vb2_gbb_read_root_key(ctx, &keyp, &size, &wb),
252 		  "succeeds when gbb.rootkey is padded; empty test key");
253 	TEST_TRUE(wb.size < wborig.size,
254 		  "  workbuf shrank on success");
255 	TEST_EQ(size, sizeof(*rootkey), "  correct size returned");
256 }
257 
hwid_tests(void)258 static void hwid_tests(void)
259 {
260 	char hwid[VB2_GBB_HWID_MAX_SIZE];
261 	uint32_t size;
262 
263 	/* GBB HWID size = 0 */
264 	{
265 		reset_common_data();
266 		gbb->hwid_size = 0;
267 		size = VB2_GBB_HWID_MAX_SIZE;
268 		TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
269 			VB2_ERROR_GBB_INVALID,
270 			"GBB HWID size invalid (HWID missing)");
271 	}
272 
273 	/* GBB HWID offset > GBB size */
274 	{
275 		reset_common_data();
276 		gbb->hwid_offset = sizeof(gbb_data) + 1;
277 		size = VB2_GBB_HWID_MAX_SIZE;
278 		TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
279 			VB2_ERROR_EX_READ_RESOURCE_SIZE,
280 			"GBB HWID offset invalid");
281 	}
282 
283 	/* buffer size < HWID size */
284 	{
285 		const char hwid_src[] = "Test HWID";
286 		reset_common_data();
287 		set_gbb_hwid(hwid_src, sizeof(hwid_src));
288 		size = sizeof(hwid_src) - 1;
289 		TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
290 			VB2_ERROR_INVALID_PARAMETER,
291 			"HWID too large for buffer");
292 	}
293 
294 	/* GBB HWID size < HWID size */
295 	{
296 		const char hwid_src[] = "Test HWID";
297 		reset_common_data();
298 		set_gbb_hwid(hwid_src, sizeof(hwid_src) - 1);
299 		size = sizeof(hwid_src);
300 		TEST_EQ(vb2api_gbb_read_hwid(ctx, hwid, &size),
301 			VB2_ERROR_INVALID_PARAMETER,
302 			"HWID larger than GBB HWID size");
303 	}
304 
305 	/* buffer size == HWID size */
306 	{
307 		const char hwid_src[] = "Test HWID";
308 		reset_common_data();
309 		set_gbb_hwid(hwid_src, sizeof(hwid_src));
310 		size = sizeof(hwid_src);
311 		TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
312 			  "read normal HWID");
313 		TEST_EQ(strcmp(hwid, "Test HWID"), 0, "  HWID correct");
314 		TEST_EQ(strlen(hwid) + 1, size, "  HWID size consistent");
315 		TEST_EQ(strlen(hwid), strlen("Test HWID"),
316 			"  HWID size correct");
317 	}
318 
319 	/* buffer size > HWID size */
320 	{
321 		const char hwid_src[] = "Test HWID";
322 		reset_common_data();
323 		set_gbb_hwid(hwid_src, sizeof(hwid_src));
324 		size = sizeof(hwid_src) + 1;
325 		TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
326 			  "read normal HWID");
327 		TEST_EQ(strcmp(hwid, "Test HWID"), 0, "  HWID correct");
328 		TEST_EQ(strlen(hwid) + 1, size, "  HWID size consistent");
329 		TEST_EQ(strlen(hwid), strlen("Test HWID"),
330 			"  HWID size correct");
331 	}
332 
333 	/* HWID with garbage */
334 	{
335 		const char hwid_src[] = "Test HWID\0garbagegarbage";
336 		reset_common_data();
337 		set_gbb_hwid(hwid_src, sizeof(hwid_src));
338 		size = VB2_GBB_HWID_MAX_SIZE;
339 		TEST_SUCC(vb2api_gbb_read_hwid(ctx, hwid, &size),
340 			  "read HWID with garbage");
341 		TEST_EQ(strcmp(hwid, "Test HWID"), 0, "  HWID correct");
342 		TEST_EQ(strlen(hwid) + 1, size, "  HWID size consistent");
343 		TEST_EQ(strlen(hwid), strlen("Test HWID"),
344 			"  HWID size correct");
345 	}
346 }
347 
main(int argc,char * argv[])348 int main(int argc, char* argv[])
349 {
350 	flag_tests();
351 	key_tests();
352 	hwid_tests();
353 
354 	return gTestSuccess ? 0 : 255;
355 }
356