1 /* Copyright 2015 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 kernel verification library, api layer
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 #include "vboot_struct.h"
19
20 /* Common context for tests */
21 static uint8_t workbuf[VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE]
22 __attribute__((aligned(VB2_WORKBUF_ALIGN)));
23 static struct vb2_context *ctx;
24 static struct vb2_shared_data *sd;
25 static struct vb2_fw_preamble *fwpre;
26 static struct vb2_kernel_preamble *kpre;
27 static struct vb2_packed_key *kdkey;
28 static const char fw_kernel_key_data[36] = "Test kernel key data";
29 static char kernel_data[0x4008] = "Sure it's a kernel...";
30
31 /* Mocked function data */
32
33 static struct {
34 struct vb2_gbb_header h;
35 struct vb2_packed_key recovery_key;
36 char recovery_key_data[32];
37 } mock_gbb;
38
39 static int mock_read_res_fail_on_call;
40 static int mock_unpack_key_retval;
41 static int mock_load_kernel_keyblock_retval;
42 static int mock_load_kernel_preamble_retval;
43 static int mock_secdata_fwmp_check_retval;
44
45 /* Type of test to reset for */
46 enum reset_type {
47 FOR_PHASE1,
48 FOR_PHASE2,
49 FOR_PHASE3,
50 };
51
reset_common_data(enum reset_type t)52 static void reset_common_data(enum reset_type t)
53 {
54 struct vb2_packed_key *k;
55
56 memset(workbuf, 0xaa, sizeof(workbuf));
57
58 TEST_SUCC(vb2api_init(workbuf, sizeof(workbuf), &ctx),
59 "vb2api_init failed");
60
61 sd = vb2_get_sd(ctx);
62 sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED;
63 vb2_nv_init(ctx);
64
65 vb2api_secdata_kernel_create(ctx);
66 vb2_secdata_kernel_init(ctx);
67 vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS, 0x20002);
68
69 mock_read_res_fail_on_call = 0;
70 mock_unpack_key_retval = VB2_SUCCESS;
71 mock_load_kernel_keyblock_retval = VB2_SUCCESS;
72 mock_load_kernel_preamble_retval = VB2_SUCCESS;
73 mock_secdata_fwmp_check_retval = VB2_SUCCESS;
74
75 /* Recovery key in mock GBB */
76 memset(&mock_gbb, 0, sizeof(mock_gbb));
77 mock_gbb.recovery_key.algorithm = 11;
78 mock_gbb.recovery_key.key_offset =
79 vb2_offset_of(&mock_gbb.recovery_key,
80 &mock_gbb.recovery_key_data);
81 mock_gbb.recovery_key.key_size = sizeof(mock_gbb.recovery_key_data);
82 strcpy(mock_gbb.recovery_key_data, "The recovery key");
83 mock_gbb.h.recovery_key_offset =
84 vb2_offset_of(&mock_gbb, &mock_gbb.recovery_key);
85 mock_gbb.h.recovery_key_size =
86 mock_gbb.recovery_key.key_offset +
87 mock_gbb.recovery_key.key_size;
88
89
90 if (t == FOR_PHASE1) {
91 uint8_t *kdata;
92
93 /* Create mock firmware preamble in the context */
94 sd->preamble_offset = sd->workbuf_used;
95 fwpre = (struct vb2_fw_preamble *)
96 vb2_member_of(sd, sd->preamble_offset);
97 k = &fwpre->kernel_subkey;
98 kdata = (uint8_t *)fwpre + sizeof(*fwpre);
99 memcpy(kdata, fw_kernel_key_data, sizeof(fw_kernel_key_data));
100 k->algorithm = 7;
101 k->key_offset = vb2_offset_of(k, kdata);
102 k->key_size = sizeof(fw_kernel_key_data);
103 sd->preamble_size = sizeof(*fwpre) + k->key_size;
104 vb2_set_workbuf_used(ctx,
105 sd->preamble_offset + sd->preamble_size);
106
107 /* Needed to check that secdata_kernel initialization is
108 performed by phase1 function. */
109 sd->status &= ~VB2_SD_STATUS_SECDATA_KERNEL_INIT;
110
111 } else if (t == FOR_PHASE2) {
112 struct vb2_signature *sig;
113 struct vb2_digest_context dc;
114 uint8_t *sdata;
115
116 /* Create mock kernel data key */
117 sd->data_key_offset = sd->workbuf_used;
118 kdkey = (struct vb2_packed_key *)
119 vb2_member_of(sd, sd->data_key_offset);
120 kdkey->algorithm = VB2_ALG_RSA2048_SHA256;
121 sd->data_key_size = sizeof(*kdkey);
122 vb2_set_workbuf_used(ctx,
123 sd->data_key_offset + sd->data_key_size);
124
125 /* Create mock kernel preamble in the context */
126 sd->preamble_offset = sd->workbuf_used;
127 kpre = (struct vb2_kernel_preamble *)
128 vb2_member_of(sd, sd->preamble_offset);
129 sdata = (uint8_t *)kpre + sizeof(*kpre);
130
131 sig = &kpre->body_signature;
132 sig->data_size = sizeof(kernel_data);
133 sig->sig_offset = vb2_offset_of(sig, sdata);
134 sig->sig_size = VB2_SHA512_DIGEST_SIZE;
135
136 vb2_digest_init(&dc, false, VB2_HASH_SHA256, 0);
137 vb2_digest_extend(&dc, (const uint8_t *)kernel_data,
138 sizeof(kernel_data));
139 vb2_digest_finalize(&dc, sdata, sig->sig_size);
140
141 sd->preamble_size = sizeof(*kpre) + sig->sig_size;
142 sd->vblock_preamble_offset =
143 0x10000 - sd->preamble_size;
144 vb2_set_workbuf_used(ctx,
145 sd->preamble_offset + sd->preamble_size);
146
147 } else {
148 /* Set flags and versions for roll-forward */
149 sd->kernel_version = 0x20004;
150 sd->kernel_version_secdata = 0x20002;
151 sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED;
152 ctx->flags |= VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD;
153 }
154 };
155
156 /* Mocked functions */
157
vb2api_secdata_fwmp_check(struct vb2_context * c,uint8_t * size)158 vb2_error_t vb2api_secdata_fwmp_check(struct vb2_context *c, uint8_t *size)
159 {
160 return mock_secdata_fwmp_check_retval;
161 }
162
vb2_get_gbb(struct vb2_context * c)163 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *c)
164 {
165 return &mock_gbb.h;
166 }
167
vb2ex_read_resource(struct vb2_context * c,enum vb2_resource_index index,uint32_t offset,void * buf,uint32_t size)168 vb2_error_t vb2ex_read_resource(struct vb2_context *c,
169 enum vb2_resource_index index, uint32_t offset,
170 void *buf, uint32_t size)
171 {
172 uint8_t *rptr;
173 uint32_t rsize;
174
175 if (--mock_read_res_fail_on_call == 0)
176 return VB2_ERROR_MOCK;
177
178 switch(index) {
179 case VB2_RES_GBB:
180 rptr = (uint8_t *)&mock_gbb;
181 rsize = sizeof(mock_gbb);
182 break;
183 default:
184 return VB2_ERROR_EX_READ_RESOURCE_INDEX;
185 }
186
187 if (offset > rsize || offset + size > rsize)
188 return VB2_ERROR_EX_READ_RESOURCE_SIZE;
189
190 memcpy(buf, rptr + offset, size);
191 return VB2_SUCCESS;
192 }
193
vb2_load_kernel_keyblock(struct vb2_context * c)194 vb2_error_t vb2_load_kernel_keyblock(struct vb2_context *c)
195 {
196 return mock_load_kernel_keyblock_retval;
197 }
198
vb2_load_kernel_preamble(struct vb2_context * c)199 vb2_error_t vb2_load_kernel_preamble(struct vb2_context *c)
200 {
201 return mock_load_kernel_preamble_retval;
202 }
203
vb2_unpack_key_buffer(struct vb2_public_key * key,const uint8_t * buf,uint32_t size)204 vb2_error_t vb2_unpack_key_buffer(struct vb2_public_key *key,
205 const uint8_t *buf, uint32_t size)
206 {
207 const struct vb2_packed_key *k = (const struct vb2_packed_key *)buf;
208
209 key->arrsize = 0;
210 key->hash_alg = vb2_crypto_to_hash(k->algorithm);
211 return mock_unpack_key_retval;
212 }
213
vb2_verify_digest(const struct vb2_public_key * key,struct vb2_signature * sig,const uint8_t * digest,const struct vb2_workbuf * wb)214 vb2_error_t vb2_verify_digest(const struct vb2_public_key *key,
215 struct vb2_signature *sig, const uint8_t *digest,
216 const struct vb2_workbuf *wb)
217 {
218 if (memcmp(digest, (uint8_t *)sig + sig->sig_offset, sig->sig_size))
219 return VB2_ERROR_VDATA_VERIFY_DIGEST;
220
221 return VB2_SUCCESS;
222 }
223
224 /* Tests */
225
load_kernel_vblock_tests(void)226 static void load_kernel_vblock_tests(void)
227 {
228 reset_common_data(FOR_PHASE1);
229 TEST_SUCC(vb2api_load_kernel_vblock(ctx), "load vblock good");
230
231 reset_common_data(FOR_PHASE1);
232 mock_load_kernel_keyblock_retval = VB2_ERROR_MOCK;
233 TEST_EQ(vb2api_load_kernel_vblock(ctx), VB2_ERROR_MOCK,
234 "load vblock bad keyblock");
235
236 reset_common_data(FOR_PHASE1);
237 mock_load_kernel_preamble_retval = VB2_ERROR_MOCK;
238 TEST_EQ(vb2api_load_kernel_vblock(ctx), VB2_ERROR_MOCK,
239 "load vblock bad preamble");
240 }
241
get_kernel_size_tests(void)242 static void get_kernel_size_tests(void)
243 {
244 uint32_t offs, size;
245
246 reset_common_data(FOR_PHASE2);
247 offs = size = 0;
248 TEST_SUCC(vb2api_get_kernel_size(ctx, &offs, &size), "get size good");
249 TEST_EQ(offs, 0x10000, " offset");
250 TEST_EQ(size, sizeof(kernel_data), " size");
251
252 /* Don't need to pass pointers */
253 reset_common_data(FOR_PHASE2);
254 TEST_SUCC(vb2api_get_kernel_size(ctx, NULL, NULL), "get size null");
255
256 reset_common_data(FOR_PHASE2);
257 sd->preamble_size = 0;
258 TEST_EQ(vb2api_get_kernel_size(ctx, &offs, &size),
259 VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
260 "get size no preamble");
261 }
262
verify_kernel_data_tests(void)263 static void verify_kernel_data_tests(void)
264 {
265 reset_common_data(FOR_PHASE2);
266 TEST_SUCC(vb2api_verify_kernel_data(ctx, kernel_data,
267 sizeof(kernel_data)),
268 "verify data good");
269
270 reset_common_data(FOR_PHASE2);
271 sd->preamble_size = 0;
272 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
273 sizeof(kernel_data)),
274 VB2_ERROR_API_VERIFY_KDATA_PREAMBLE, "verify no preamble");
275
276 reset_common_data(FOR_PHASE2);
277 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
278 sizeof(kernel_data) + 1),
279 VB2_ERROR_API_VERIFY_KDATA_SIZE, "verify size");
280
281 reset_common_data(FOR_PHASE2);
282 sd->workbuf_used = sd->workbuf_size + VB2_WORKBUF_ALIGN -
283 vb2_wb_round_up(sizeof(struct vb2_digest_context));
284 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
285 sizeof(kernel_data)),
286 VB2_ERROR_API_VERIFY_KDATA_WORKBUF, "verify workbuf");
287
288 reset_common_data(FOR_PHASE2);
289 sd->data_key_size = 0;
290 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
291 sizeof(kernel_data)),
292 VB2_ERROR_API_VERIFY_KDATA_KEY, "verify no key");
293
294 reset_common_data(FOR_PHASE2);
295 mock_unpack_key_retval = VB2_ERROR_MOCK;
296 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
297 sizeof(kernel_data)),
298 VB2_ERROR_MOCK, "verify unpack key");
299
300 reset_common_data(FOR_PHASE2);
301 kdkey->algorithm = VB2_ALG_COUNT;
302 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
303 sizeof(kernel_data)),
304 VB2_ERROR_SHA_INIT_ALGORITHM, "verify hash init");
305
306 reset_common_data(FOR_PHASE2);
307 sd->workbuf_used = sd->workbuf_size -
308 vb2_wb_round_up(sizeof(struct vb2_digest_context));
309 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
310 sizeof(kernel_data)),
311 VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST, "verify hash workbuf");
312
313 reset_common_data(FOR_PHASE2);
314 kernel_data[3] ^= 0xd0;
315 TEST_EQ(vb2api_verify_kernel_data(ctx, kernel_data,
316 sizeof(kernel_data)),
317 VB2_ERROR_VDATA_VERIFY_DIGEST, "verify hash digest");
318 kernel_data[3] ^= 0xd0;
319 }
320
phase3_tests(void)321 static void phase3_tests(void)
322 {
323 uint32_t v;
324
325 reset_common_data(FOR_PHASE3);
326 TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 good");
327 v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
328 TEST_EQ(v, 0x20004, " version");
329
330 reset_common_data(FOR_PHASE3);
331 sd->kernel_version = 0x20001;
332 TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 no rollback");
333 v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
334 TEST_EQ(v, 0x20002, " version");
335
336 reset_common_data(FOR_PHASE3);
337 sd->flags &= ~VB2_SD_FLAG_KERNEL_SIGNED;
338 TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 unsigned kernel");
339 v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
340 TEST_EQ(v, 0x20002, " version");
341
342 reset_common_data(FOR_PHASE3);
343 ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
344 TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 recovery");
345 v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
346 TEST_EQ(v, 0x20002, " version");
347
348 reset_common_data(FOR_PHASE3);
349 ctx->flags &= ~VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD;
350 TEST_SUCC(vb2api_kernel_phase3(ctx), "phase3 no rollforward");
351 v = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
352 TEST_EQ(v, 0x20002, " version");
353
354 reset_common_data(FOR_PHASE3);
355 sd->status &= ~VB2_SD_STATUS_SECDATA_KERNEL_INIT;
356 TEST_ABORT(vb2api_kernel_phase3(ctx), "phase3 set fail");
357 }
358
main(int argc,char * argv[])359 int main(int argc, char* argv[])
360 {
361 load_kernel_vblock_tests();
362 get_kernel_size_tests();
363 verify_kernel_data_tests();
364 phase3_tests();
365
366 return gTestSuccess ? 0 : 255;
367 }
368