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 */
20static uint8_t workbuf[VB2_WORKBUF_RECOMMENDED_SIZE]
21	__attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
22static struct vb2_context cc;
23static struct vb2_shared_data *sd;
24
25/* Mocked function data */
26
27static struct {
28	struct vb2_gbb_header h;
29	struct vb2_packed_key rootkey;
30	char rootkey_data[32];
31} mock_gbb;
32
33static 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
48static int mock_read_res_fail_on_call;
49static int mock_unpack_key_retval;
50static int mock_verify_keyblock_retval;
51static int mock_verify_preamble_retval;
52
53/* Type of test to reset for */
54enum reset_type {
55	FOR_KEYBLOCK,
56	FOR_PREAMBLE
57};
58
59static 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
116int 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
148int 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
155int 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
163int 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
173static 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
271static 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
372int main(int argc, char* argv[])
373{
374	verify_keyblock_tests();
375	verify_preamble_tests();
376
377	return gTestSuccess ? 0 : 255;
378}
379