blob: 61484fb51fd1ba2a6a0e40b56c055debd3babcea [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
Randall Spangler7141d732014-05-15 15:34:54 -07008#include <stdio.h>
Randall Spangler224f5ac2014-06-06 09:42:30 -07009
10#include "2sysincludes.h"
11#include "2common.h"
12#include "2rsa.h"
Randall Spangler7141d732014-05-15 15:34:54 -070013
14#include "file_keys.h"
15#include "host_common.h"
16#include "host_key.h"
17#include "host_keyblock.h"
18#include "host_signature.h"
19#include "vboot_common.h"
20#include "test_common.h"
21
Randall Spangler7141d732014-05-15 15:34:54 -070022static void resign_keyblock(struct vb2_keyblock *h, const VbPrivateKey *key)
23{
24 VbSignature *sig =
25 CalculateSignature((const uint8_t *)h,
26 h->keyblock_signature.data_size, key);
27
28 SignatureCopy((VbSignature *)&h->keyblock_signature, sig);
29 free(sig);
30}
31
32static void test_verify_keyblock(const VbPublicKey *public_key,
33 const VbPrivateKey *private_key,
34 const VbPublicKey *data_key)
35{
36 uint8_t workbuf[VB2_KEY_BLOCK_VERIFY_WORKBUF_BYTES];
37 struct vb2_workbuf wb;
38 struct vb2_public_key key;
39 struct vb2_keyblock *hdr;
40 struct vb2_keyblock *h;
41 uint32_t hsize;
42
43 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
44
45 /* Unpack public key */
Randall Spangler224f5ac2014-06-06 09:42:30 -070046 TEST_SUCC(vb2_unpack_key(&key, (uint8_t *)public_key,
47 public_key->key_offset + public_key->key_size),
48 "vb2_verify_keyblock public key");
Randall Spangler7141d732014-05-15 15:34:54 -070049
50 hdr = (struct vb2_keyblock *)
51 KeyBlockCreate(data_key, private_key, 0x1234);
52 TEST_NEQ((size_t)hdr, 0, "vb2_verify_keyblock() prerequisites");
53 if (!hdr)
54 return;
55 hsize = hdr->keyblock_size;
56 h = (struct vb2_keyblock *)malloc(hsize + 2048);
57
58 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -070059 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb),
60 "vb2_verify_keyblock() ok using key");
Randall Spangler7141d732014-05-15 15:34:54 -070061
62 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -070063 TEST_EQ(vb2_verify_keyblock(h, hsize - 1, &key, &wb),
64 VB2_ERROR_KEYBLOCK_SIZE, "vb2_verify_keyblock() size--");
Randall Spangler7141d732014-05-15 15:34:54 -070065
Randall Spangler224f5ac2014-06-06 09:42:30 -070066 /* Buffer is allowed to be bigger than keyblock */
Randall Spangler7141d732014-05-15 15:34:54 -070067 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -070068 TEST_SUCC(vb2_verify_keyblock(h, hsize + 1, &key, &wb),
69 "vb2_verify_keyblock() size++");
Randall Spangler7141d732014-05-15 15:34:54 -070070
71 Memcpy(h, hdr, hsize);
72 h->magic[0] &= 0x12;
Randall Spangler224f5ac2014-06-06 09:42:30 -070073 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
74 VB2_ERROR_KEYBLOCK_MAGIC, "vb2_verify_keyblock() magic");
Randall Spangler7141d732014-05-15 15:34:54 -070075
76 /* Care about major version but not minor */
77 Memcpy(h, hdr, hsize);
78 h->header_version_major++;
79 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -070080 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
81 VB2_ERROR_KEYBLOCK_HEADER_VERSION,
82 "vb2_verify_keyblock() major++");
Randall Spangler7141d732014-05-15 15:34:54 -070083
84 Memcpy(h, hdr, hsize);
85 h->header_version_major--;
86 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -070087 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
88 VB2_ERROR_KEYBLOCK_HEADER_VERSION,
89 "vb2_verify_keyblock() major--");
Randall Spangler7141d732014-05-15 15:34:54 -070090
91 Memcpy(h, hdr, hsize);
92 h->header_version_minor++;
93 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -070094 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb),
95 "vb2_verify_keyblock() minor++");
Randall Spangler7141d732014-05-15 15:34:54 -070096
97 Memcpy(h, hdr, hsize);
98 h->header_version_minor--;
99 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700100 TEST_SUCC(vb2_verify_keyblock(h, hsize, &key, &wb),
101 "vb2_verify_keyblock() minor--");
Randall Spangler7141d732014-05-15 15:34:54 -0700102
103 /* Check signature */
104 Memcpy(h, hdr, hsize);
105 h->keyblock_signature.sig_offset = hsize;
106 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700107 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
108 VB2_ERROR_KEYBLOCK_SIG_OUTSIDE,
109 "vb2_verify_keyblock() sig off end");
Randall Spangler7141d732014-05-15 15:34:54 -0700110
111 Memcpy(h, hdr, hsize);
112 h->keyblock_signature.sig_size--;
113 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700114 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
115 VB2_ERROR_KEYBLOCK_SIG_INVALID,
116 "vb2_verify_keyblock() sig too small");
Randall Spangler7141d732014-05-15 15:34:54 -0700117
118 Memcpy(h, hdr, hsize);
119 ((uint8_t *)vb2_packed_key_data(&h->data_key))[0] ^= 0x34;
Randall Spangler224f5ac2014-06-06 09:42:30 -0700120 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
121 VB2_ERROR_KEYBLOCK_SIG_INVALID,
122 "vb2_verify_keyblock() sig mismatch");
Randall Spangler7141d732014-05-15 15:34:54 -0700123
124 Memcpy(h, hdr, hsize);
125 h->keyblock_signature.data_size = h->keyblock_size + 1;
Randall Spangler224f5ac2014-06-06 09:42:30 -0700126 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
127 VB2_ERROR_KEYBLOCK_SIGNED_TOO_MUCH,
128 "vb2_verify_keyblock() sig data past end of block");
Randall Spangler7141d732014-05-15 15:34:54 -0700129
130 /* Check that we signed header and data key */
131 Memcpy(h, hdr, hsize);
132 h->keyblock_signature.data_size = 4;
133 h->data_key.key_offset = 0;
134 h->data_key.key_size = 0;
135 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700136 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
137 VB2_ERROR_KEYBLOCK_SIGNED_TOO_LITTLE,
138 "vb2_verify_keyblock() didn't sign header");
Randall Spangler7141d732014-05-15 15:34:54 -0700139
140 Memcpy(h, hdr, hsize);
141 h->data_key.key_offset = hsize;
142 resign_keyblock(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700143 TEST_EQ(vb2_verify_keyblock(h, hsize, &key, &wb),
144 VB2_ERROR_KEYBLOCK_DATA_KEY_OUTSIDE,
145 "vb2_verify_keyblock() data key off end");
Randall Spangler7141d732014-05-15 15:34:54 -0700146
147 /* Corner cases for error checking */
Randall Spangler224f5ac2014-06-06 09:42:30 -0700148 TEST_EQ(vb2_verify_keyblock(NULL, 4, &key, &wb),
149 VB2_ERROR_KEYBLOCK_TOO_SMALL_FOR_HEADER,
150 "vb2_verify_keyblock size too small");
Randall Spangler7141d732014-05-15 15:34:54 -0700151
152 /*
153 * TODO: verify parser can support a bigger header (i.e., one where
154 * data_key.key_offset is bigger than expected).
155 */
156
157 free(h);
158 free(hdr);
159}
160
161static void resign_fw_preamble(struct vb2_fw_preamble *h,
162 const VbPrivateKey *key)
163{
164 VbSignature *sig = CalculateSignature(
165 (const uint8_t *)h, h->preamble_signature.data_size, key);
166
167 SignatureCopy((VbSignature *)&h->preamble_signature, sig);
168 free(sig);
169}
170
171static void test_verify_fw_preamble(const VbPublicKey *public_key,
172 const VbPrivateKey *private_key,
173 const VbPublicKey *kernel_subkey)
174{
175 struct vb2_fw_preamble *hdr;
176 struct vb2_fw_preamble *h;
177 struct vb2_public_key rsa;
178 uint8_t workbuf[VB2_VERIFY_FIRMWARE_PREAMBLE_WORKBUF_BYTES];
179 struct vb2_workbuf wb;
180 uint32_t hsize;
181
182 vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
183
184 /* Create a dummy signature */
185 VbSignature *body_sig = SignatureAlloc(56, 78);
186
Randall Spangler224f5ac2014-06-06 09:42:30 -0700187 TEST_SUCC(vb2_unpack_key(&rsa, (uint8_t *)public_key,
188 public_key->key_offset + public_key->key_size),
189 "vb2_verify_fw_preamble() prereq key");
Randall Spangler7141d732014-05-15 15:34:54 -0700190
191 hdr = (struct vb2_fw_preamble *)
192 CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig,
193 private_key, 0x5678);
194 TEST_PTR_NEQ(hdr, NULL,
195 "VerifyFirmwarePreamble() prereq test preamble");
196 if (!hdr)
197 return;
198 hsize = (uint32_t) hdr->preamble_size;
199 h = (struct vb2_fw_preamble *)malloc(hsize + 16384);
200
201 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700202 TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
203 "vb2_verify_fw_preamble() ok using key");
Randall Spangler7141d732014-05-15 15:34:54 -0700204
205 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700206 TEST_EQ(vb2_verify_fw_preamble(h, 4, &rsa, &wb),
207 VB2_ERROR_PREAMBLE_TOO_SMALL_FOR_HEADER,
208 "vb2_verify_fw_preamble() size tiny");
Randall Spangler7141d732014-05-15 15:34:54 -0700209
210 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700211 TEST_EQ(vb2_verify_fw_preamble(h, hsize - 1, &rsa, &wb),
212 VB2_ERROR_PREAMBLE_SIZE,
213 "vb2_verify_fw_preamble() size--");
Randall Spangler7141d732014-05-15 15:34:54 -0700214
Randall Spangler224f5ac2014-06-06 09:42:30 -0700215 /* Buffer is allowed to be bigger than preamble */
Randall Spangler7141d732014-05-15 15:34:54 -0700216 Memcpy(h, hdr, hsize);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700217 TEST_SUCC(vb2_verify_fw_preamble(h, hsize + 1, &rsa, &wb),
218 "vb2_verify_fw_preamble() size++");
Randall Spangler7141d732014-05-15 15:34:54 -0700219
220 /* Care about major version but not minor */
221 Memcpy(h, hdr, hsize);
222 h->header_version_major++;
223 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700224 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
225 VB2_ERROR_PREAMBLE_HEADER_VERSION
226 , "vb2_verify_fw_preamble() major++");
Randall Spangler7141d732014-05-15 15:34:54 -0700227
228 Memcpy(h, hdr, hsize);
229 h->header_version_major--;
230 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700231 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
232 VB2_ERROR_PREAMBLE_HEADER_VERSION,
233 "vb2_verify_fw_preamble() major--");
Randall Spangler7141d732014-05-15 15:34:54 -0700234
235 Memcpy(h, hdr, hsize);
236 h->header_version_minor++;
237 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700238 TEST_SUCC(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
239 "vb2_verify_fw_preamble() minor++");
Randall Spangler7141d732014-05-15 15:34:54 -0700240
241 Memcpy(h, hdr, hsize);
242 h->header_version_minor--;
243 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700244 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
245 VB2_ERROR_PREAMBLE_HEADER_OLD,
246 "vb2_verify_fw_preamble() 2.0 not supported");
Randall Spangler7141d732014-05-15 15:34:54 -0700247
248 /* Check signature */
249 Memcpy(h, hdr, hsize);
250 h->preamble_signature.sig_offset = hsize;
251 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700252 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
253 VB2_ERROR_PREAMBLE_SIG_OUTSIDE,
254 "vb2_verify_fw_preamble() sig off end");
Randall Spangler7141d732014-05-15 15:34:54 -0700255
256 Memcpy(h, hdr, hsize);
257 h->preamble_signature.sig_size--;
258 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700259 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
260 VB2_ERROR_PREAMBLE_SIG_INVALID,
261 "vb2_verify_fw_preamble() sig too small");
Randall Spangler7141d732014-05-15 15:34:54 -0700262
263 Memcpy(h, hdr, hsize);
264 ((uint8_t *)vb2_packed_key_data(&h->kernel_subkey))[0] ^= 0x34;
Randall Spangler224f5ac2014-06-06 09:42:30 -0700265 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
266 VB2_ERROR_PREAMBLE_SIG_INVALID,
267 "vb2_verify_fw_preamble() sig mismatch");
Randall Spangler7141d732014-05-15 15:34:54 -0700268
269 /* Check that we signed header, kernel subkey, and body sig */
270 Memcpy(h, hdr, hsize);
271 h->preamble_signature.data_size = 4;
272 h->kernel_subkey.key_offset = 0;
273 h->kernel_subkey.key_size = 0;
274 h->body_signature.sig_offset = 0;
275 h->body_signature.sig_size = 0;
276 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700277 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
278 VB2_ERROR_PREAMBLE_SIGNED_TOO_LITTLE,
279 "vb2_verify_fw_preamble() didn't sign header");
Randall Spangler7141d732014-05-15 15:34:54 -0700280
281 Memcpy(h, hdr, hsize);
282 h->kernel_subkey.key_offset = hsize;
283 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700284 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
285 VB2_ERROR_PREAMBLE_KERNEL_SUBKEY_OUTSIDE,
286 "vb2_verify_fw_preamble() kernel subkey off end");
Randall Spangler7141d732014-05-15 15:34:54 -0700287
288 Memcpy(h, hdr, hsize);
289 h->body_signature.sig_offset = hsize;
290 resign_fw_preamble(h, private_key);
Randall Spangler224f5ac2014-06-06 09:42:30 -0700291 TEST_EQ(vb2_verify_fw_preamble(h, hsize, &rsa, &wb),
292 VB2_ERROR_PREAMBLE_BODY_SIG_OUTSIDE,
293 "vb2_verify_fw_preamble() body sig off end");
Randall Spangler7141d732014-05-15 15:34:54 -0700294
295 /* TODO: verify with extra padding at end of header. */
296
297 free(h);
298 free(hdr);
299}
300
301int test_permutation(int signing_key_algorithm, int data_key_algorithm,
302 const char *keys_dir)
303{
304 char filename[1024];
305 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;
306 int data_rsa_len = siglen_map[data_key_algorithm] * 8;
307
308 VbPrivateKey *signing_private_key = NULL;
309 VbPublicKey *signing_public_key = NULL;
310 VbPublicKey *data_public_key = NULL;
311
312 printf("***Testing signing algorithm: %s\n",
313 algo_strings[signing_key_algorithm]);
314 printf("***With data key algorithm: %s\n",
315 algo_strings[data_key_algorithm]);
316
317 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len);
318 signing_private_key = PrivateKeyReadPem(filename,
319 signing_key_algorithm);
320 if (!signing_private_key) {
321 fprintf(stderr, "Error reading signing_private_key: %s\n",
322 filename);
323 return 1;
324 }
325
326 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len);
327 signing_public_key = PublicKeyReadKeyb(filename,
328 signing_key_algorithm, 1);
329 if (!signing_public_key) {
330 fprintf(stderr, "Error reading signing_public_key: %s\n",
331 filename);
332 return 1;
333 }
334
335 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len);
336 data_public_key = PublicKeyReadKeyb(filename,
337 data_key_algorithm, 1);
338 if (!data_public_key) {
339 fprintf(stderr, "Error reading data_public_key: %s\n",
340 filename);
341 return 1;
342 }
343
344 test_verify_keyblock(signing_public_key, signing_private_key,
345 data_public_key);
346 test_verify_fw_preamble(signing_public_key, signing_private_key,
347 data_public_key);
348
349 if (signing_public_key)
350 free(signing_public_key);
351 if (signing_private_key)
352 free(signing_private_key);
353 if (data_public_key)
354 free(data_public_key);
355
356 return 0;
357}
358
359struct test_perm
360{
361 int signing_algorithm;
362 int data_key_algorithm;
363};
364
365/* Permutations of signing and data key algorithms in active use */
366const struct test_perm test_perms[] = {
367 {VB2_ALG_RSA4096_SHA256, VB2_ALG_RSA2048_SHA256},
368 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA2048_SHA256},
369 {VB2_ALG_RSA8192_SHA512, VB2_ALG_RSA4096_SHA256},
370};
371
372int main(int argc, char *argv[])
373{
374 if (argc == 2) {
375 /* Test only the algorithms we use */
376 int i;
377
378 for (i = 0; i < ARRAY_SIZE(test_perms); i++) {
379 if (test_permutation(test_perms[i].signing_algorithm,
380 test_perms[i].data_key_algorithm,
381 argv[1]))
382 return 1;
383 }
384
385 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
386 /* Test all the algorithms */
387 int sign_alg, data_alg;
388
389 for (sign_alg = 0; sign_alg < VB2_ALG_COUNT; sign_alg++) {
390 for (data_alg = 0; data_alg < VB2_ALG_COUNT;
391 data_alg++) {
392 if (test_permutation(sign_alg, data_alg,
393 argv[1]))
394 return 1;
395 }
396 }
397 } else {
398 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
399 return -1;
400 }
401
402 return gTestSuccess ? 0 : 255;
403}