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 */
22static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
23	__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
24static struct vb2_context ctx;
25static struct vb2_shared_data *sd;
26
27/* Mocked function data */
28
29static struct {
30	struct vb2_gbb_header h;
31	struct vb2_packed_key rootkey;
32	char rootkey_data[32];
33} mock_gbb;
34
35static 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
50static int mock_read_res_fail_on_call;
51static int mock_unpack_key_retval;
52static int mock_verify_keyblock_retval;
53static int mock_verify_preamble_retval;
54
55/* Type of test to reset for */
56enum reset_type {
57	FOR_KEYBLOCK,
58	FOR_PREAMBLE
59};
60
61static 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
122int 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
154int 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
161int 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
169int 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
179static 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
279static 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
381int main(int argc, char* argv[])
382{
383	load_keyblock_tests();
384	load_preamble_tests();
385
386	return gTestSuccess ? 0 : 255;
387}
388