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