blob: e0fc3aed5421041218ca1f7e8c5e505f7c90d9bf [file] [log] [blame]
Randall Spangler7141d732014-05-15 15:34:54 -07001/* 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 firmware image library.
6 */
7
8#include <stdint.h>
9#include <stdio.h>
10#include <string.h>
11
12#include "file_keys.h"
13#include "host_common.h"
14#include "host_key.h"
15#include "host_keyblock.h"
16#include "host_signature.h"
17#include "vboot_common.h"
18#include "test_common.h"
19
20#include "2common.h"
21#include "2rsa.h"
22
23static void resign_keyblock(struct vb2_keyblock *h, const VbPrivateKey *key)
24{
25 VbSignature *sig =
26 CalculateSignature((const uint8_t *)h,
27 h->keyblock_signature.data_size, key);
28
29 SignatureCopy((VbSignature *)&h->keyblock_signature, sig);
30 free(sig);
31}
32
33static void test_verify_keyblock(const VbPublicKey *public_key,
34 const VbPrivateKey *private_key,
35 const VbPublicKey *data_key)
36{
37 uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES];
38 struct vb2_workbuf wb;
39 struct vb2_public_key key;
40 struct vb2_keyblock *hdr;
41 struct vb2_keyblock *h;
42 uint32_t hsize;
43
44 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
45
46 /* Unpack public key */
47 TEST_EQ(vb2_unpack_key(&key, (uint8_t *)public_key,
48 public_key->key_offset + public_key->key_size),
49 0, "vb2_verify_keyblock public key");
50
51 hdr = (struct vb2_keyblock *)
52 KeyBlockCreate(data_key, private_key, 0x1234);
53 TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites");
54 if (!hdr)
55 return;
56 hsize = hdr->keyblock_size;
57 h = (struct vb2_keyblock *)malloc(hsize + 2048);
58
59 Memcpy(h, hdr, hsize);
60 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
61 0, "vb2_verify_keyblock() ok using key");
62
63 Memcpy(h, hdr, hsize);
64 TEST_NEQ(vb2_verify_keyblock(h, hsize - 1, &key, &wb),
65 0, "vb2_verify_keyblock() size--");
66
67 Memcpy(h, hdr, hsize);
68 TEST_EQ(vb2_verify_keyblock(h, hsize + 1, &key, &wb),
69 0, "vb2_verify_keyblock() size++");
70
71 Memcpy(h, hdr, hsize);
72 h->magic[0] &= 0x12;
73 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
74 0, "vb2_verify_keyblock() magic");
75
76 /* Care about major version but not minor */
77 Memcpy(h, hdr, hsize);
78 h->header_version_major++;
79 resign_keyblock(h, private_key);
80 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
81 0, "vb2_verify_keyblock() major++");
82
83 Memcpy(h, hdr, hsize);
84 h->header_version_major--;
85 resign_keyblock(h, private_key);
86 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
87 0, "vb2_verify_keyblock() major--");
88
89 Memcpy(h, hdr, hsize);
90 h->header_version_minor++;
91 resign_keyblock(h, private_key);
92 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
93 0, "vb2_verify_keyblock() minor++");
94
95 Memcpy(h, hdr, hsize);
96 h->header_version_minor--;
97 resign_keyblock(h, private_key);
98 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
99 0, "vb2_verify_keyblock() minor--");
100
101 /* Check signature */
102 Memcpy(h, hdr, hsize);
103 h->keyblock_signature.sig_offset = hsize;
104 resign_keyblock(h, private_key);
105 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
106 0, "vb2_verify_keyblock() sig off end");
107
108 Memcpy(h, hdr, hsize);
109 h->keyblock_signature.sig_size--;
110 resign_keyblock(h, private_key);
111 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
112 0, "vb2_verify_keyblock() sig too small");
113
114 Memcpy(h, hdr, hsize);
115 ((uint8_t *)vb2_packed_key_data(&h->data_key))[0] ^= 0x34;
116 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
117 0, "vb2_verify_keyblock() sig mismatch");
118
119 Memcpy(h, hdr, hsize);
120 h->keyblock_signature.data_size = h->keyblock_size + 1;
121 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
122 0, "vb2_verify_keyblock() sig data past end of block");
123
124 /* Check that we signed header and data key */
125 Memcpy(h, hdr, hsize);
126 h->keyblock_signature.data_size = 4;
127 h->data_key.key_offset = 0;
128 h->data_key.key_size = 0;
129 resign_keyblock(h, private_key);
130 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
131 0, "vb2_verify_keyblock() didn't sign header");
132
133 Memcpy(h, hdr, hsize);
134 h->data_key.key_offset = hsize;
135 resign_keyblock(h, private_key);
136 TEST_NEQ(vb2_verify_keyblock(h, hsize, &key, &wb),
137 0, "vb2_verify_keyblock() data key off end");
138
139 /* Corner cases for error checking */
140 TEST_NEQ(vb2_verify_keyblock(NULL, 4, &key, &wb),
141 0, "vb2_verify_keyblock size too small");
142
143 /*
144 * TODO: verify parser can support a bigger header (i.e., one where
145 * data_key.key_offset is bigger than expected).
146 */
147
148 free(h);
149 free(hdr);
150}
151
152static void resign_fw_preamble(struct vb2_fw_preamble *h,
153 const VbPrivateKey *key)
154{
155 VbSignature *sig = CalculateSignature(
156 (const uint8_t *)h, h->preamble_signature.data_size, key);
157
158 SignatureCopy((VbSignature *)&h->preamble_signature, sig);
159 free(sig);
160}
161
162static void test_verify_fw_preamble(const VbPublicKey *public_key,
163 const VbPrivateKey *private_key,
164 const VbPublicKey *kernel_subkey)
165{
166 struct vb2_fw_preamble *hdr;
167 struct vb2_fw_preamble *h;
168 struct vb2_public_key rsa;
169 uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES];
170 struct vb2_workbuf wb;
171 uint32_t hsize;
172
173 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
174
175 /* Create a dummy signature */
176 VbSignature *body_sig = SignatureAlloc(56, 78);
177
178 TEST_EQ(vb2_unpack_key(&rsa, (uint8_t *)public_key,
179 public_key->key_offset + public_key->key_size),
180 0, "vb2_verify_fw_preamble() prereq key");
181
182 hdr = (struct vb2_fw_preamble *)
183 CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig,
184 private_key, 0x5678);
185 TEST_PTR_NEQ(hdr, NULL,
186 "VerifyFirmwarePreamble() prereq test preamble");
187 if (!hdr)
188 return;
189 hsize = (uint32_t) hdr->preamble_size;
190 h = (struct vb2_fw_preamble *)malloc(hsize + 16384);
191
192 Memcpy(h, hdr, hsize);
193 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
194 0, "vb2_verify_fw_preamble() ok using key");
195
196 Memcpy(h, hdr, hsize);
197 TEST_NEQ(vb2_verify_fw_preamble(h, 4, &rsa, &wb),
198 0, "vb2_verify_fw_preamble() size tiny");
199
200 Memcpy(h, hdr, hsize);
201 TEST_NEQ(vb2_verify_fw_preamble(h, hsize - 1, &rsa, &wb),
202 0, "vb2_verify_fw_preamble() size--");
203
204 Memcpy(h, hdr, hsize);
205 TEST_EQ(vb2_verify_fw_preamble(h, hsize + 1, &rsa, &wb),
206 0, "vb2_verify_fw_preamble() size++");
207
208 /* Care about major version but not minor */
209 Memcpy(h, hdr, hsize);
210 h->header_version_major++;
211 resign_fw_preamble(h, private_key);
212 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
213 0, "vb2_verify_fw_preamble() major++");
214
215 Memcpy(h, hdr, hsize);
216 h->header_version_major--;
217 resign_fw_preamble(h, private_key);
218 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
219 0, "vb2_verify_fw_preamble() major--");
220
221 Memcpy(h, hdr, hsize);
222 h->header_version_minor++;
223 resign_fw_preamble(h, private_key);
224 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
225 0, "vb2_verify_fw_preamble() minor++");
226
227 Memcpy(h, hdr, hsize);
228 h->header_version_minor--;
229 resign_fw_preamble(h, private_key);
230 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
231 0, "vb2_verify_fw_preamble() 2.0 not supported");
232
233 /* Check signature */
234 Memcpy(h, hdr, hsize);
235 h->preamble_signature.sig_offset = hsize;
236 resign_fw_preamble(h, private_key);
237 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
238 0, "vb2_verify_fw_preamble() sig off end");
239
240 Memcpy(h, hdr, hsize);
241 h->preamble_signature.sig_size--;
242 resign_fw_preamble(h, private_key);
243 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
244 0, "vb2_verify_fw_preamble() sig too small");
245
246 Memcpy(h, hdr, hsize);
247 ((uint8_t *)vb2_packed_key_data(&h->kernel_subkey))[0] ^= 0x34;
248 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
249 0, "vb2_verify_fw_preamble() sig mismatch");
250
251 /* Check that we signed header, kernel subkey, and body sig */
252 Memcpy(h, hdr, hsize);
253 h->preamble_signature.data_size = 4;
254 h->kernel_subkey.key_offset = 0;
255 h->kernel_subkey.key_size = 0;
256 h->body_signature.sig_offset = 0;
257 h->body_signature.sig_size = 0;
258 resign_fw_preamble(h, private_key);
259 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
260 0, "vb2_verify_fw_preamble() didn't sign header");
261
262 Memcpy(h, hdr, hsize);
263 h->kernel_subkey.key_offset = hsize;
264 resign_fw_preamble(h, private_key);
265 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
266 0, "vb2_verify_fw_preamble() kernel subkey off end");
267
268 Memcpy(h, hdr, hsize);
269 h->body_signature.sig_offset = hsize;
270 resign_fw_preamble(h, private_key);
271 TEST_NEQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
272 0, "vb2_verify_fw_preamble() body sig off end");
273
274 /* TODO: verify with extra padding at end of header. */
275
276 free(h);
277 free(hdr);
278}
279
280int test_permutation(int signing_key_algorithm, int data_key_algorithm,
281 const char *keys_dir)
282{
283 char filename[1024];
284 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;
285 int data_rsa_len = siglen_map[data_key_algorithm] * 8;
286
287 VbPrivateKey *signing_private_key = NULL;
288 VbPublicKey *signing_public_key = NULL;
289 VbPublicKey *data_public_key = NULL;
290
291 printf("***Testing signing algorithm: %s\n",
292 algo_strings[signing_key_algorithm]);
293 printf("***With data key algorithm: %s\n",
294 algo_strings[data_key_algorithm]);
295
296 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len);
297 signing_private_key = PrivateKeyReadPem(filename,
298 signing_key_algorithm);
299 if (!signing_private_key) {
300 fprintf(stderr, "Error reading signing_private_key: %s\n",
301 filename);
302 return 1;
303 }
304
305 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len);
306 signing_public_key = PublicKeyReadKeyb(filename,
307 signing_key_algorithm, 1);
308 if (!signing_public_key) {
309 fprintf(stderr, "Error reading signing_public_key: %s\n",
310 filename);
311 return 1;
312 }
313
314 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len);
315 data_public_key = PublicKeyReadKeyb(filename,
316 data_key_algorithm, 1);
317 if (!data_public_key) {
318 fprintf(stderr, "Error reading data_public_key: %s\n",
319 filename);
320 return 1;
321 }
322
323 test_verify_keyblock(signing_public_key, signing_private_key,
324 data_public_key);
325 test_verify_fw_preamble(signing_public_key, signing_private_key,
326 data_public_key);
327
328 if (signing_public_key)
329 free(signing_public_key);
330 if (signing_private_key)
331 free(signing_private_key);
332 if (data_public_key)
333 free(data_public_key);
334
335 return 0;
336}
337
338struct test_perm
339{
340 int signing_algorithm;
341 int data_key_algorithm;
342};
343
344/* Permutations of signing and data key algorithms in active use */
345const struct test_perm test_perms[] = {
346 {VB2_ALG_RSA4096_SHA256, VB2_ALG_RSA2048_SHA256},
347 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA2048_SHA256},
348 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA4096_SHA256},
349};
350
351int main(int argc, char *argv[])
352{
353 if (argc == 2) {
354 /* Test only the algorithms we use */
355 int i;
356
357 for (i = 0; i < ARRAY_SIZE(test_perms); i++) {
358 if (test_permutation(test_perms[i].signing_algorithm,
359 test_perms[i].data_key_algorithm,
360 argv[1]))
361 return 1;
362 }
363
364 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
365 /* Test all the algorithms */
366 int sign_alg, data_alg;
367
368 for (sign_alg = 0; sign_alg < VB2_ALG_COUNT; sign_alg++) {
369 for (data_alg = 0; data_alg < VB2_ALG_COUNT;
370 data_alg++) {
371 if (test_permutation(sign_alg, data_alg,
372 argv[1]))
373 return 1;
374 }
375 }
376 } else {
377 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
378 return -1;
379 }
380
381 return gTestSuccess ? 0 : 255;
382}