• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2014 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 firmware verification library
6  */
7 
8 #include <stdio.h>
9 
10 #include "2api.h"
11 #include "2common.h"
12 #include "2misc.h"
13 #include "2nvstorage.h"
14 #include "2rsa.h"
15 #include "2secdata.h"
16 #include "2sysincludes.h"
17 #include "common/tests.h"
18 
19 /* Common context for tests */
20 static uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
21 	__attribute__((aligned(VB2_WORKBUF_ALIGN)));
22 static struct vb2_context *ctx;
23 static struct vb2_shared_data *sd;
24 static struct vb2_gbb_header gbb;
25 
26 /* Mocked function data */
27 
28 static struct {
29 	struct vb2_gbb_header h;
30 	struct vb2_packed_key rootkey;
31 	char rootkey_data[32];
32 } mock_gbb;
33 
34 static struct {
35 	/* Keyblock */
36 	struct {
37 		struct vb2_keyblock kb;
38 		char data_key_data[16];
39 		uint8_t kbdata[128];
40 	} k;
41 	/* Preamble follows keyblock */
42 	struct {
43 		struct vb2_fw_preamble pre;
44 		uint8_t predata[128];
45 	} p;
46 
47 } mock_vblock;
48 
49 static int mock_read_res_fail_on_call;
50 static int mock_unpack_key_retval;
51 static int mock_verify_keyblock_retval;
52 static int mock_verify_preamble_retval;
53 
54 /* Type of test to reset for */
55 enum reset_type {
56 	FOR_KEYBLOCK,
57 	FOR_PREAMBLE
58 };
59 
reset_common_data(enum reset_type t)60 static void reset_common_data(enum reset_type t)
61 {
62 	struct vb2_keyblock *kb = &mock_vblock.k.kb;
63 	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;
64 
65 	memset(workbuf, 0xaa, sizeof(workbuf));
66 
67 	TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
68 		  "vb2api_init failed");
69 
70 	memset(&gbb, 0, sizeof(gbb));
71 	sd = vb2_get_sd(ctx);
72 
73 	vb2_nv_init(ctx);
74 
75 	vb2api_secdata_firmware_create(ctx);
76 	vb2_secdata_firmware_init(ctx);
77 
78 	vb2api_secdata_kernel_create(ctx);
79 	vb2_secdata_kernel_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_firmware_set(ctx, VB2_SECDATA_FIRMWARE_VERSIONS,
89 				 sd->fw_version_secdata);
90 
91 	gbb.rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey);
92 	gbb.rootkey_size = sizeof(mock_gbb.rootkey_data);
93 	sd->last_fw_result = VB2_FW_RESULT_SUCCESS;
94 
95 	mock_gbb.rootkey.algorithm = 11;
96 	mock_gbb.rootkey.key_offset =
97 		vb2_offset_of(&mock_gbb.rootkey,
98 			      &mock_gbb.rootkey_data);
99 	mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data);
100 
101 	kb->keyblock_size = sizeof(mock_vblock.k);
102 	kb->data_key.algorithm = 7;
103 	kb->data_key.key_version = 2;
104 	kb->data_key.key_offset =
105 		vb2_offset_of(&mock_vblock.k, &mock_vblock.k.data_key_data) -
106 		vb2_offset_of(&mock_vblock.k, &kb->data_key);
107 	kb->data_key.key_size = sizeof(mock_vblock.k.data_key_data);
108 	strcpy(mock_vblock.k.data_key_data, "data key data!!");
109 
110 	pre->preamble_size = sizeof(mock_vblock.p);
111 	pre->firmware_version = 2;
112 
113 	/* If verifying preamble, verify keyblock first to set up data key */
114 	if (t == FOR_PREAMBLE)
115 		vb2_load_fw_keyblock(ctx);
116 };
117 
118 /* Mocked functions */
vb2_get_gbb(struct vb2_context * c)119 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
120 {
121 	return &gbb;
122 }
123 
vb2ex_read_resource(struct vb2_context * c,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)124 vb2_error_t vb2ex_read_resource(struct vb2_context *c,
125 				enum vb2_resource_index index, uint32_t offset,
126 				void *buf, 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_buffer(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)154 vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
155 				  const uint8_t *buf, uint32_t size)
156 {
157 	key->arrsize = 0;
158 	return mock_unpack_key_retval;
159 }
160 
161 static struct vb2_public_key last_used_key;
162 
vb2_verify_keyblock(struct vb2_keyblock * block,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)163 vb2_error_t vb2_verify_keyblock(struct vb2_keyblock *block, uint32_t size,
164 				const struct vb2_public_key *key,
165 				const struct vb2_workbuf *wb)
166 {
167 	memcpy(&last_used_key, key, sizeof(struct vb2_public_key));
168 	return mock_verify_keyblock_retval;
169 }
170 
vb2_verify_fw_preamble(struct vb2_fw_preamble * preamble,uint32_t size,const struct vb2_public_key * key,const struct vb2_workbuf * wb)171 vb2_error_t vb2_verify_fw_preamble(struct vb2_fw_preamble *preamble,
172 				   uint32_t size,
173 				   const struct vb2_public_key *key,
174 				   const struct vb2_workbuf *wb)
175 {
176 	memcpy(&last_used_key, key, sizeof(struct vb2_public_key));
177 	return mock_verify_preamble_retval;
178 }
179 
180 /* Tests */
181 
verify_keyblock_tests(void)182 static void verify_keyblock_tests(void)
183 {
184 	struct vb2_keyblock *kb = &mock_vblock.k.kb;
185 	struct vb2_packed_key *k;
186 	int expected_offset;
187 
188 	/* Test successful call */
189 	reset_common_data(FOR_KEYBLOCK);
190 	expected_offset = sd->workbuf_used;
191 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify");
192 	TEST_EQ(sd->fw_version, 0x20000, "keyblock version");
193 	TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k),
194 		"preamble offset");
195 	TEST_EQ(sd->data_key_offset, expected_offset,
196 		"keyblock data key offset");
197 	TEST_EQ(sd->workbuf_used,
198 		vb2_wb_round_up(sd->data_key_offset +
199 				sd->data_key_size),
200 		"workbuf used");
201 
202 	/* Make sure data key was properly saved */
203 	k = vb2_member_of(sd, sd->data_key_offset);
204 	TEST_EQ(k->algorithm, 7, "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(vb2_member_of(k, k->key_offset),
209 		       mock_vblock.k.data_key_data,
210 		       sizeof(mock_vblock.k.data_key_data)),
211 		0, "data key data");
212 	TEST_EQ(sd->workbuf_used,
213 		vb2_wb_round_up(sd->data_key_offset +
214 				sd->data_key_size),
215 		"workbuf used after");
216 
217 	/* Test hwcrypto conditions */
218 	reset_common_data(FOR_KEYBLOCK);
219 
220 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify");
221 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
222 		"hwcrypto is forbidden by TPM flag");
223 
224 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
225 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify");
226 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
227 		"hwcrypto is forbidden by TPM flag on recovery mode");
228 
229 	vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS,
230 			VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED);
231 
232 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify");
233 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
234 		"hwcrypto is forbidden on recovery mode");
235 
236 	ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE;
237 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock verify");
238 	TEST_EQ(last_used_key.allow_hwcrypto, 1, "hwcrypto is allowed");
239 
240 	/* Test failures */
241 	reset_common_data(FOR_KEYBLOCK);
242 	sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN -
243 			   vb2_wb_round_up(gbb.rootkey_size);
244 	TEST_EQ(vb2_load_fw_keyblock(ctx),
245 		VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
246 		"keyblock not enough workbuf for root key");
247 
248 	reset_common_data(FOR_KEYBLOCK);
249 	gbb.rootkey_size = sizeof(mock_gbb);
250 	TEST_EQ(vb2_load_fw_keyblock(ctx),
251 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
252 		"keyblock read root key");
253 
254 	reset_common_data(FOR_KEYBLOCK);
255 	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM;
256 	TEST_EQ(vb2_load_fw_keyblock(ctx),
257 		VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM,
258 		"keyblock unpack root key");
259 
260 	reset_common_data(FOR_KEYBLOCK);
261 	sd->workbuf_used = sd->workbuf_size -
262 			   vb2_wb_round_up(gbb.rootkey_size);
263 	TEST_EQ(vb2_load_fw_keyblock(ctx),
264 		VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER,
265 		"keyblock not enough workbuf for header");
266 
267 	reset_common_data(FOR_KEYBLOCK);
268 	mock_read_res_fail_on_call = 2;
269 	TEST_EQ(vb2_load_fw_keyblock(ctx),
270 		VB2_ERROR_EX_READ_RESOURCE_INDEX,
271 		"keyblock read keyblock header");
272 
273 	reset_common_data(FOR_KEYBLOCK);
274 	sd->workbuf_used = sd->workbuf_size -
275 			   vb2_wb_round_up(gbb.rootkey_size) -
276 			   vb2_wb_round_up(sizeof(struct vb2_keyblock));
277 	TEST_EQ(vb2_load_fw_keyblock(ctx),
278 		VB2_ERROR_FW_KEYBLOCK_WORKBUF,
279 		"keyblock not enough workbuf for entire keyblock");
280 
281 	reset_common_data(FOR_KEYBLOCK);
282 	kb->keyblock_size = sizeof(mock_vblock) + 1;
283 	TEST_EQ(vb2_load_fw_keyblock(ctx),
284 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
285 		"keyblock read keyblock");
286 
287 	reset_common_data(FOR_KEYBLOCK);
288 	mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC;
289 	TEST_EQ(vb2_load_fw_keyblock(ctx),
290 		VB2_ERROR_KEYBLOCK_MAGIC,
291 		"keyblock verify keyblock");
292 
293 	reset_common_data(FOR_KEYBLOCK);
294 	kb->data_key.key_version = 0x10000;
295 	TEST_EQ(vb2_load_fw_keyblock(ctx),
296 		VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
297 		"keyblock version range");
298 
299 	reset_common_data(FOR_KEYBLOCK);
300 	kb->data_key.key_version = 1;
301 	TEST_EQ(vb2_load_fw_keyblock(ctx),
302 		VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
303 		"keyblock rollback");
304 
305 	reset_common_data(FOR_KEYBLOCK);
306 	kb->data_key.key_version = 1;
307 	gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK;
308 	TEST_SUCC(vb2_load_fw_keyblock(ctx), "keyblock rollback with GBB flag");
309 }
310 
verify_preamble_tests(void)311 static void verify_preamble_tests(void)
312 {
313 	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;
314 	int expected_offset;
315 	uint32_t v;
316 
317 	/* Test successful call */
318 	reset_common_data(FOR_PREAMBLE);
319 	expected_offset = sd->workbuf_used;
320 	TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good");
321 	TEST_EQ(sd->fw_version, 0x20002, "combined version");
322 	TEST_EQ(sd->preamble_offset, expected_offset,
323 		"preamble offset");
324 	TEST_EQ(sd->preamble_size, pre->preamble_size, "preamble size");
325 	TEST_EQ(sd->workbuf_used,
326 		vb2_wb_round_up(sd->preamble_offset +
327 				sd->preamble_size),
328 		"workbuf used");
329 
330 	/* Test hwcrypto conditions */
331 	reset_common_data(FOR_PREAMBLE);
332 
333 	TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good");
334 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
335 		"hwcrypto is forbidden by TPM flag");
336 
337 	ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
338 	TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good");
339 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
340 		"hwcrypto is forbidden by TPM flag on recovery mode");
341 
342 	vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS,
343 			VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED);
344 
345 	TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good");
346 	TEST_EQ(last_used_key.allow_hwcrypto, 0,
347 		"hwcrypto is forbidden on recovery mode");
348 
349 	ctx->flags &= ~VB2_CONTEXT_RECOVERY_MODE;
350 	TEST_SUCC(vb2_load_fw_preamble(ctx), "preamble good");
351 	TEST_EQ(last_used_key.allow_hwcrypto, 1,
352 		"hwcrypto is allowed");
353 
354 
355 	/* Expected failures */
356 	reset_common_data(FOR_PREAMBLE);
357 	sd->data_key_size = 0;
358 	TEST_EQ(vb2_load_fw_preamble(ctx),
359 		VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
360 		"preamble no data key");
361 
362 	reset_common_data(FOR_PREAMBLE);
363 	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
364 	TEST_EQ(vb2_load_fw_preamble(ctx),
365 		VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM,
366 		"preamble unpack data key");
367 
368 	reset_common_data(FOR_PREAMBLE);
369 	sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN -
370 			   vb2_wb_round_up(sizeof(struct vb2_fw_preamble));
371 	TEST_EQ(vb2_load_fw_preamble(ctx),
372 		VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER,
373 		"preamble not enough workbuf for header");
374 
375 	reset_common_data(FOR_PREAMBLE);
376 	sd->vblock_preamble_offset = sizeof(mock_vblock);
377 	TEST_EQ(vb2_load_fw_preamble(ctx),
378 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
379 		"preamble read header");
380 
381 	reset_common_data(FOR_PREAMBLE);
382 	sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN -
383 			   vb2_wb_round_up(sizeof(mock_vblock.p));
384 	TEST_EQ(vb2_load_fw_preamble(ctx),
385 		VB2_ERROR_FW_PREAMBLE2_WORKBUF,
386 		"preamble not enough workbuf");
387 
388 	reset_common_data(FOR_PREAMBLE);
389 	pre->preamble_size = sizeof(mock_vblock);
390 	TEST_EQ(vb2_load_fw_preamble(ctx),
391 		VB2_ERROR_EX_READ_RESOURCE_SIZE,
392 		"preamble read full");
393 
394 	reset_common_data(FOR_PREAMBLE);
395 	mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID;
396 	TEST_EQ(vb2_load_fw_preamble(ctx),
397 		VB2_ERROR_PREAMBLE_SIG_INVALID,
398 		"preamble verify");
399 
400 	reset_common_data(FOR_PREAMBLE);
401 	pre->firmware_version = 0x10000;
402 	TEST_EQ(vb2_load_fw_preamble(ctx),
403 		VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
404 		"preamble version range");
405 
406 	reset_common_data(FOR_PREAMBLE);
407 	pre->firmware_version = 1;
408 	TEST_EQ(vb2_load_fw_preamble(ctx),
409 		VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
410 		"preamble version rollback");
411 
412 	reset_common_data(FOR_PREAMBLE);
413 	pre->firmware_version = 1;
414 	gbb.flags |= VB2_GBB_FLAG_DISABLE_FW_ROLLBACK_CHECK;
415 	TEST_SUCC(vb2_load_fw_preamble(ctx), "version rollback with GBB flag");
416 
417 	reset_common_data(FOR_PREAMBLE);
418 	pre->firmware_version = 3;
419 	TEST_SUCC(vb2_load_fw_preamble(ctx),
420 		  "preamble version roll forward");
421 	v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS);
422 	TEST_EQ(v, 0x20003, "roll forward");
423 
424 	/* Newer version without result success doesn't roll forward */
425 	reset_common_data(FOR_PREAMBLE);
426 	pre->firmware_version = 3;
427 	sd->last_fw_result = VB2_FW_RESULT_UNKNOWN;
428 	TEST_SUCC(vb2_load_fw_preamble(ctx),
429 		  "preamble version no roll forward 1");
430 	v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS);
431 	TEST_EQ(v, 0x20002, "no roll forward");
432 
433 	/* Newer version with success but for other slot doesn't roll forward */
434 	reset_common_data(FOR_PREAMBLE);
435 	pre->firmware_version = 3;
436 	sd->last_fw_slot = 1;
437 	TEST_SUCC(vb2_load_fw_preamble(ctx),
438 		  "preamble version no roll forward 2");
439 	v = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_VERSIONS);
440 	TEST_EQ(v, 0x20002, "no roll forward");
441 }
442 
main(int argc,char * argv[])443 int main(int argc, char* argv[])
444 {
445 	verify_keyblock_tests();
446 	verify_preamble_tests();
447 
448 	return gTestSuccess ? 0 : 255;
449 }
450