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