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