1 /* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
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 misc library, new-style structs
6  */
7 
8 #include <stdio.h>
9 
10 #include "2sysincludes.h"
11 #include "2api.h"
12 #include "2common.h"
13 #include "2misc.h"
14 #include "2nvstorage.h"
15 #include "2secdata.h"
16 
17 #include "vb2_common.h"
18 
19 #include "test_common.h"
20 
21 /* Common context for tests */
22 static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
23 	__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
24 static struct vb2_context ctx;
25 static struct vb2_shared_data *sd;
26 
27 /* Mocked function data */
28 
29 static struct {
30 	struct vb2_gbb_header h;
31 	struct vb2_packed_key rootkey;
32 	char rootkey_data[32];
33 } mock_gbb;
34 
35 static struct {
36 	/* Keyblock */
37 	struct {
38 		struct vb2_keyblock kb;
39 		struct vb2_packed_key data_key;
40 		char data_key_data[16];
41 		uint8_t kbdata[128];
42 	} k;
43 	/* Preamble follows keyblock */
44 	struct {
45 		struct vb2_fw_preamble pre;
46 		uint8_t predata[128];
47 	} p;
48 } mock_vblock;
49 
50 static int mock_read_res_fail_on_call;
51 static int mock_unpack_key_retval;
52 static int mock_verify_keyblock_retval;
53 static int mock_verify_preamble_retval;
54 
55 /* Type of test to reset for */
56 enum reset_type {
57 	FOR_KEYBLOCK,
58 	FOR_PREAMBLE
59 };
60 
reset_common_data(enum reset_type t)61 static void reset_common_data(enum reset_type t)
62 {
63 	struct vb2_keyblock *kb = &mock_vblock.k.kb;
64 	struct vb2_packed_key *dk = &mock_vblock.k.data_key;
65 	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;
66 
67 	memset(workbuf, 0xaa, sizeof(workbuf));
68 
69 	memset(&ctx, 0, sizeof(ctx));
70 	ctx.workbuf = workbuf;
71 	ctx.workbuf_size = sizeof(workbuf);
72 
73 	vb2_init_context(&ctx);
74 	sd = vb2_get_sd(&ctx);
75 
76 	vb2_nv_init(&ctx);
77 
78 	vb2_secdata_create(&ctx);
79 	vb2_secdata_init(&ctx);
80 
81 	mock_read_res_fail_on_call = 0;
82 	mock_unpack_key_retval = VB2_SUCCESS;
83 	mock_verify_keyblock_retval = VB2_SUCCESS;
84 	mock_verify_preamble_retval = VB2_SUCCESS;
85 
86 	/* Set up mock data for verifying keyblock */
87 	sd->fw_version_secdata = 0x20002;
88 	vb2_secdata_set(&ctx, VB2_SECDATA_VERSIONS, sd->fw_version_secdata);
89 
90 	sd->gbb_rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey);
91 	sd->gbb_rootkey_size = sizeof(mock_gbb.rootkey_data);
92 	sd->last_fw_result = VB2_FW_RESULT_SUCCESS;
93 
94 	mock_gbb.rootkey.sig_alg = VB2_SIG_RSA8192;
95 	mock_gbb.rootkey.key_offset =
96 		vb2_offset_of(&mock_gbb.rootkey,
97 			      &mock_gbb.rootkey_data);
98 	mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data);
99 
100 	kb->c.total_size = sizeof(mock_vblock.k);
101 	kb->key_offset = vb2_offset_of(&mock_vblock.k.kb,
102 				       &mock_vblock.k.data_key);
103 
104 	dk->c.fixed_size = sizeof(mock_vblock.k.data_key);
105 	dk->sig_alg = VB2_SIG_RSA4096;
106 	dk->key_version = 2;
107 	dk->key_offset = dk->c.fixed_size;
108 	dk->key_size = sizeof(mock_vblock.k.data_key_data);
109 	dk->c.total_size = dk->key_offset + dk->key_size;
110 	strcpy(mock_vblock.k.data_key_data, "data key data!!");
111 
112 	pre->c.total_size = sizeof(mock_vblock.p);
113 	pre->fw_version = 2;
114 
115 	/* If verifying preamble, verify keyblock first to set up data key */
116 	if (t == FOR_PREAMBLE)
117 		vb2_load_fw_keyblock(&ctx);
118 };
119 
120 /* Mocked functions */
121 
vb2ex_read_resource(struct vb2_context * ctx,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)122 int vb2ex_read_resource(struct vb2_context *ctx,
123 			enum vb2_resource_index index,
124 			uint32_t offset,
125 			void *buf,
126 			uint32_t size)
127 {
128 	uint8_t *rptr;
129 	uint32_t rsize;
130 
131 	if (--mock_read_res_fail_on_call == 0)
132 		return VB2_ERROR_EX_READ_RESOURCE_INDEX;
133 
134 	switch(index) {
135 	case VB2_RES_GBB:
136 		rptr = (uint8_t *)&mock_gbb;
137 		rsize = sizeof(mock_gbb);
138 		break;
139 	case VB2_RES_FW_VBLOCK:
140 		rptr = (uint8_t *)&mock_vblock;
141 		rsize = sizeof(mock_vblock);
142 		break;
143 	default:
144 		return VB2_ERROR_EX_READ_RESOURCE_INDEX;
145 	}
146 
147 	if (offset > rsize || offset + size > rsize)
148 		return VB2_ERROR_EX_READ_RESOURCE_SIZE;
149 
150 	memcpy(buf, rptr + offset, size);
151 	return VB2_SUCCESS;
152 }
153 
vb2_unpack_key(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)154 int vb2_unpack_key(struct vb2_public_key *key,
155 		    const uint8_t *buf,
156 		    uint32_t size)
157 {
158 	return mock_unpack_key_retval;
159 }
160 
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)161 int vb2_verify_keyblock(struct vb2_keyblock *block,
162 			 uint32_t size,
163 			 const struct vb2_public_key *key,
164 			 const struct vb2_workbuf *wb)
165 {
166 	return mock_verify_keyblock_retval;
167 }
168 
vb2_verify_fw_preamble(struct vb2_fw_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)169 int vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
170 			    uint32_t size,
171 			    const struct vb2_public_key *key,
172 			    const struct vb2_workbuf *wb)
173 {
174 	return mock_verify_preamble_retval;
175 }
176 
177 /* Tests */
178 
load_keyblock_tests(void)179 static void load_keyblock_tests(void)
180 {
181 	struct vb2_keyblock *kb = &mock_vblock.k.kb;
182 	struct vb2_packed_key *dk = &mock_vblock.k.data_key;
183 	struct vb2_packed_key *k;
184 	int wb_used_before;
185 
186 	/* Test successful call */
187 	reset_common_data(FOR_KEYBLOCK);
188 	wb_used_before = ctx.workbuf_used;
189 	TEST_SUCC(vb2_load_fw_keyblock(&ctx), "keyblock verify");
190 	TEST_EQ(sd->fw_version, 0x20000, "keyblock version");
191 	TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k),
192 		"preamble offset");
193 	TEST_EQ(sd->workbuf_data_key_offset,
194 		(wb_used_before + (VB2_WORKBUF_ALIGN - 1)) &
195 		~(VB2_WORKBUF_ALIGN - 1),
196 		"keyblock data key offset");
197 	TEST_EQ(ctx.workbuf_used,
198 		sd->workbuf_data_key_offset + sd->workbuf_data_key_size,
199 		"workbuf used");
200 
201 	/* Make sure data key was properly saved */
202 	k = (struct vb2_packed_key *)(ctx.workbuf +
203 				      sd->workbuf_data_key_offset);
204 	TEST_EQ(k->sig_alg, VB2_SIG_RSA4096, "data key algorithm");
205 	TEST_EQ(k->key_version, 2, "data key version");
206 	TEST_EQ(k->key_size, sizeof(mock_vblock.k.data_key_data),
207 		"data key size");
208 	TEST_EQ(memcmp(ctx.workbuf + sd->workbuf_data_key_offset +
209 		       k->key_offset, mock_vblock.k.data_key_data,
210 		       sizeof(mock_vblock.k.data_key_data)),
211 		0, "data key data");
212 	TEST_EQ(ctx.workbuf_used,
213 		sd->workbuf_data_key_offset + sd->workbuf_data_key_size,
214 		"workbuf used after");
215 
216 	/* Test failures */
217 	reset_common_data(FOR_KEYBLOCK);
218 	ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size + 8;
219 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
220 		VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
221 		"keyblock not enough workbuf for root key");
222 
223 	reset_common_data(FOR_KEYBLOCK);
224 	sd->gbb_rootkey_size = sizeof(mock_gbb);
225 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
226 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
227 		"keyblock read root key");
228 
229 	reset_common_data(FOR_KEYBLOCK);
230 	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM;
231 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
232 		VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM,
233 		"keyblock unpack root key");
234 
235 	reset_common_data(FOR_KEYBLOCK);
236 	ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size - 8;
237 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
238 		VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
239 		"keyblock not enough workbuf for header");
240 
241 	reset_common_data(FOR_KEYBLOCK);
242 	mock_read_res_fail_on_call = 2;
243 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
244 		VB2_ERROR_EX_READ_RESOURCE_INDEX,
245 		"keyblock read keyblock header");
246 
247 	reset_common_data(FOR_KEYBLOCK);
248 	ctx.workbuf_used = ctx.workbuf_size - sd->gbb_rootkey_size
249 		- sizeof(struct vb2_keyblock);
250 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
251 		VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
252 		"keyblock not enough workbuf for entire keyblock");
253 
254 	reset_common_data(FOR_KEYBLOCK);
255 	kb->c.total_size = sizeof(mock_vblock) + 1;
256 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
257 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
258 		"keyblock read keyblock");
259 
260 	reset_common_data(FOR_KEYBLOCK);
261 	mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC;
262 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
263 		VB2_ERROR_KEYBLOCK_MAGIC,
264 		"keyblock verify keyblock");
265 
266 	reset_common_data(FOR_KEYBLOCK);
267 	dk->key_version = 0x10000;
268 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
269 		VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
270 		"keyblock version range");
271 
272 	reset_common_data(FOR_KEYBLOCK);
273 	dk->key_version = 1;
274 	TEST_EQ(vb2_load_fw_keyblock(&ctx),
275 		VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
276 		"keyblock rollback");
277 }
278 
load_preamble_tests(void)279 static void load_preamble_tests(void)
280 {
281 	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;
282 	int data_key_offset_before;
283 	uint32_t v;
284 
285 	/* Test successful call */
286 	reset_common_data(FOR_PREAMBLE);
287 	data_key_offset_before = sd->workbuf_data_key_offset;
288 	TEST_SUCC(vb2_load_fw_preamble(&ctx), "preamble good");
289 	TEST_EQ(sd->fw_version, 0x20002, "combined version");
290 	TEST_EQ(sd->workbuf_preamble_offset, data_key_offset_before,
291 		"preamble offset");
292 	TEST_EQ(sd->workbuf_preamble_size, pre->c.total_size, "preamble size");
293 	TEST_EQ(ctx.workbuf_used,
294 		sd->workbuf_preamble_offset + sd->workbuf_preamble_size,
295 		"workbuf used");
296 	TEST_EQ(sd->workbuf_data_key_offset, 0, "data key offset gone");
297 	TEST_EQ(sd->workbuf_data_key_size, 0, "data key size gone");
298 
299 	/* Expected failures */
300 	reset_common_data(FOR_PREAMBLE);
301 	sd->workbuf_data_key_size = 0;
302 	TEST_EQ(vb2_load_fw_preamble(&ctx),
303 		VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
304 		"preamble no data key");
305 
306 	reset_common_data(FOR_PREAMBLE);
307 	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
308 	TEST_EQ(vb2_load_fw_preamble(&ctx),
309 		VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM,
310 		"preamble unpack data key");
311 
312 	reset_common_data(FOR_PREAMBLE);
313 	ctx.workbuf_used = ctx.workbuf_size
314 		- sizeof(struct vb2_fw_preamble) + 8;
315 	TEST_EQ(vb2_load_fw_preamble(&ctx),
316 		VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
317 		"preamble not enough workbuf for header");
318 
319 	reset_common_data(FOR_PREAMBLE);
320 	sd->vblock_preamble_offset = sizeof(mock_vblock);
321 	TEST_EQ(vb2_load_fw_preamble(&ctx),
322 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
323 		"preamble read header");
324 
325 	reset_common_data(FOR_PREAMBLE);
326 	ctx.workbuf_used = ctx.workbuf_size - sizeof(mock_vblock.p) + 8;
327 	TEST_EQ(vb2_load_fw_preamble(&ctx),
328 		VB2_ERROR_READ_RESOURCE_OBJECT_BUF,
329 		"preamble not enough workbuf");
330 
331 	reset_common_data(FOR_PREAMBLE);
332 	pre->c.total_size = sizeof(mock_vblock);
333 	TEST_EQ(vb2_load_fw_preamble(&ctx),
334 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
335 		"preamble read full");
336 
337 	reset_common_data(FOR_PREAMBLE);
338 	mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID;
339 	TEST_EQ(vb2_load_fw_preamble(&ctx),
340 		VB2_ERROR_PREAMBLE_SIG_INVALID,
341 		"preamble verify");
342 
343 	reset_common_data(FOR_PREAMBLE);
344 	pre->fw_version = 0x10000;
345 	TEST_EQ(vb2_load_fw_preamble(&ctx),
346 		VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
347 		"preamble version range");
348 
349 	reset_common_data(FOR_PREAMBLE);
350 	pre->fw_version = 1;
351 	TEST_EQ(vb2_load_fw_preamble(&ctx),
352 		VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
353 		"preamble version rollback");
354 
355 	reset_common_data(FOR_PREAMBLE);
356 	pre->fw_version = 3;
357 	TEST_SUCC(vb2_load_fw_preamble(&ctx),
358 		  "preamble version roll forward");
359 	vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v);
360 	TEST_EQ(v, 0x20003, "roll forward");
361 
362 	/* Newer version without result success doesn't roll forward */
363 	reset_common_data(FOR_PREAMBLE);
364 	pre->fw_version = 3;
365 	sd->last_fw_result = VB2_FW_RESULT_UNKNOWN;
366 	TEST_SUCC(vb2_load_fw_preamble(&ctx),
367 		  "preamble version no roll forward 1");
368 	vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v);
369 	TEST_EQ(v, 0x20002, "no roll forward");
370 
371 	/* Newer version with success but for other slot doesn't roll forward */
372 	reset_common_data(FOR_PREAMBLE);
373 	pre->fw_version = 3;
374 	sd->last_fw_slot = 1;
375 	TEST_SUCC(vb2_load_fw_preamble(&ctx),
376 		  "preamble version no roll forward 2");
377 	vb2_secdata_get(&ctx, VB2_SECDATA_VERSIONS, &v);
378 	TEST_EQ(v, 0x20002, "no roll forward");
379 }
380 
main(int argc,char * argv[])381 int main(int argc, char* argv[])
382 {
383 	load_keyblock_tests();
384 	load_preamble_tests();
385 
386 	return gTestSuccess ? 0 : 255;
387 }
388