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