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 static void VerifyPublicKeyToRSA(const VbPublicKey *orig_key)
     20 {
     21 	RSAPublicKey *rsa;
     22 	VbPublicKey *key = PublicKeyAlloc(orig_key->key_size, 0, 0);
     23 
     24 	PublicKeyCopy(key, orig_key);
     25 	key->algorithm = kNumAlgorithms;
     26 	TEST_EQ((size_t)PublicKeyToRSA(key), 0,
     27 		"PublicKeyToRSA() invalid algorithm");
     28 
     29 	PublicKeyCopy(key, orig_key);
     30 	key->key_size -= 1;
     31 	TEST_EQ((size_t)PublicKeyToRSA(key), 0,
     32 		"PublicKeyToRSA() invalid size");
     33 
     34 	rsa = PublicKeyToRSA(orig_key);
     35 	TEST_NEQ((size_t)rsa, 0, "PublicKeyToRSA() ok");
     36 	if (rsa) {
     37 		TEST_EQ((int)rsa->algorithm, (int)key->algorithm,
     38 			"PublicKeyToRSA() algorithm");
     39 		RSAPublicKeyFree(rsa);
     40 	}
     41 }
     42 
     43 static void VerifyDataTest(const VbPublicKey *public_key,
     44                            const VbPrivateKey *private_key)
     45 {
     46 	const uint8_t test_data[] = "This is some test data to sign.";
     47 	const uint64_t test_size = sizeof(test_data);
     48 	VbSignature *sig;
     49 	RSAPublicKey *rsa;
     50 
     51 	sig = CalculateSignature(test_data, test_size, private_key);
     52 	TEST_PTR_NEQ(sig, 0, "VerifyData() calculate signature");
     53 
     54 	rsa = PublicKeyToRSA(public_key);
     55 	TEST_PTR_NEQ(rsa, 0, "VerifyData() calculate rsa");
     56 
     57 	if (!sig || !rsa)
     58 		return;
     59 
     60 	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 0,
     61 		"VerifyData() ok");
     62 
     63 	sig->sig_size -= 16;
     64 	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1,
     65 		"VerifyData() wrong sig size");
     66 	sig->sig_size += 16;
     67 
     68 	TEST_EQ(VerifyData(test_data, test_size - 1, sig, rsa), 1,
     69 		"VerifyData() input buffer too small");
     70 
     71 	GetSignatureData(sig)[0] ^= 0x5A;
     72 	TEST_EQ(VerifyData(test_data, test_size, sig, rsa), 1,
     73 		"VerifyData() wrong sig");
     74 
     75 	RSAPublicKeyFree(rsa);
     76 	free(sig);
     77 }
     78 
     79 static void VerifyDigestTest(const VbPublicKey *public_key,
     80                              const VbPrivateKey *private_key)
     81 {
     82 	const uint8_t test_data[] = "This is some other test data to sign.";
     83 	VbSignature *sig;
     84 	RSAPublicKey *rsa;
     85 	uint8_t *digest;
     86 
     87 	sig = CalculateSignature(test_data, sizeof(test_data), private_key);
     88 	rsa = PublicKeyToRSA(public_key);
     89 	digest = DigestBuf(test_data, sizeof(test_data),
     90 			   (int)public_key->algorithm);
     91 	TEST_NEQ(sig && rsa && digest, 0, "VerifyData() prerequisites");
     92 	if (!sig || !rsa || !digest)
     93 		return;
     94 
     95 	TEST_EQ(VerifyDigest(digest, sig, rsa), 0, "VerifyDigest() ok");
     96 
     97 	GetSignatureData(sig)[0] ^= 0x5A;
     98 	TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() wrong sig");
     99 
    100 	sig->sig_size = 1;
    101 	TEST_EQ(VerifyDigest(digest, sig, rsa), 1, "VerifyDigest() sig size");
    102 
    103 	RSAPublicKeyFree(rsa);
    104 	free(sig);
    105 	VbExFree(digest);
    106 }
    107 
    108 static void ReSignKernelPreamble(VbKernelPreambleHeader *h,
    109                                  const VbPrivateKey *key)
    110 {
    111 	VbSignature *sig = CalculateSignature((const uint8_t *)h,
    112 			h->preamble_signature.data_size, key);
    113 
    114 	SignatureCopy(&h->preamble_signature, sig);
    115 	free(sig);
    116 }
    117 
    118 static void VerifyKernelPreambleTest(const VbPublicKey *public_key,
    119                                      const VbPrivateKey *private_key)
    120 {
    121 	VbKernelPreambleHeader *hdr;
    122 	VbKernelPreambleHeader *h;
    123 	RSAPublicKey *rsa;
    124 	unsigned hsize;
    125 
    126 	/* Create a dummy signature */
    127 	VbSignature *body_sig = SignatureAlloc(56, 78);
    128 
    129 	rsa = PublicKeyToRSA(public_key);
    130 	hdr = CreateKernelPreamble(0x1234, 0x100000, 0x300000, 0x4000, body_sig,
    131 				   0, 0, 0, 0, private_key);
    132 	TEST_NEQ(hdr && rsa, 0, "VerifyKernelPreamble() prerequisites");
    133 	if (!hdr)
    134 		return;
    135 	hsize = (unsigned) hdr->preamble_size;
    136 	h = (VbKernelPreambleHeader *)malloc(hsize + 16384);
    137 
    138 	TEST_EQ(VerifyKernelPreamble(hdr, hsize, rsa), 0,
    139 		"VerifyKernelPreamble() ok using key");
    140 	TEST_NEQ(VerifyKernelPreamble(hdr, hsize - 1, rsa), 0,
    141 		 "VerifyKernelPreamble() size--");
    142 	TEST_NEQ(VerifyKernelPreamble(hdr, 4, rsa), 0,
    143 		 "VerifyKernelPreamble() size tiny");
    144 	TEST_EQ(VerifyKernelPreamble(hdr, hsize + 1, rsa), 0,
    145 		"VerifyKernelPreamble() size++");
    146 
    147 	/* Care about major version but not minor */
    148 	Memcpy(h, hdr, hsize);
    149 	h->header_version_major++;
    150 	ReSignKernelPreamble(h, private_key);
    151 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    152 		 "VerifyKernelPreamble() major++");
    153 
    154 	Memcpy(h, hdr, hsize);
    155 	h->header_version_major--;
    156 	ReSignKernelPreamble(h, private_key);
    157 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    158 		 "VerifyKernelPreamble() major--");
    159 
    160 	Memcpy(h, hdr, hsize);
    161 	h->header_version_minor++;
    162 	ReSignKernelPreamble(h, private_key);
    163 	TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    164 		"VerifyKernelPreamble() minor++");
    165 
    166 	Memcpy(h, hdr, hsize);
    167 	h->header_version_minor--;
    168 	ReSignKernelPreamble(h, private_key);
    169 	TEST_EQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    170 		"VerifyKernelPreamble() minor--");
    171 
    172 	/* Check signature */
    173 	Memcpy(h, hdr, hsize);
    174 	h->preamble_signature.sig_offset = hsize;
    175 	ReSignKernelPreamble(h, private_key);
    176 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    177 		 "VerifyKernelPreamble() sig off end");
    178 
    179 	Memcpy(h, hdr, hsize);
    180 	h->preamble_signature.sig_size--;
    181 	ReSignKernelPreamble(h, private_key);
    182 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    183 		 "VerifyKernelPreamble() sig too small");
    184 
    185 	Memcpy(h, hdr, hsize);
    186 	GetSignatureData(&h->body_signature)[0] ^= 0x34;
    187 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    188 		 "VerifyKernelPreamble() sig mismatch");
    189 
    190 	/* Check that we signed header and body sig */
    191 	Memcpy(h, hdr, hsize);
    192 	h->preamble_signature.data_size = 4;
    193 	h->body_signature.sig_offset = 0;
    194 	h->body_signature.sig_size = 0;
    195 	ReSignKernelPreamble(h, private_key);
    196 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    197 		 "VerifyKernelPreamble() didn't sign header");
    198 
    199 	Memcpy(h, hdr, hsize);
    200 	h->body_signature.sig_offset = hsize;
    201 	ReSignKernelPreamble(h, private_key);
    202 	TEST_NEQ(VerifyKernelPreamble(h, hsize, rsa), 0,
    203 		 "VerifyKernelPreamble() body sig off end");
    204 
    205 	/* TODO: verify parser can support a bigger header. */
    206 
    207 	free(h);
    208 	RSAPublicKeyFree(rsa);
    209 	free(hdr);
    210 }
    211 
    212 int test_algorithm(int key_algorithm, const char *keys_dir)
    213 {
    214 	char filename[1024];
    215 	int rsa_len = siglen_map[key_algorithm] * 8;
    216 
    217 	VbPrivateKey *private_key = NULL;
    218 	VbPublicKey *public_key = NULL;
    219 
    220 	printf("***Testing algorithm: %s\n", algo_strings[key_algorithm]);
    221 
    222 	sprintf(filename, "%s/key_rsa%d.pem", keys_dir, rsa_len);
    223 	private_key = PrivateKeyReadPem(filename, key_algorithm);
    224 	if (!private_key) {
    225 		fprintf(stderr, "Error reading private_key: %s\n", filename);
    226 		return 1;
    227 	}
    228 
    229 	sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, rsa_len);
    230 	public_key = PublicKeyReadKeyb(filename, key_algorithm, 1);
    231 	if (!public_key) {
    232 		fprintf(stderr, "Error reading public_key: %s\n", filename);
    233 		return 1;
    234 	}
    235 
    236 	VerifyPublicKeyToRSA(public_key);
    237 	VerifyDataTest(public_key, private_key);
    238 	VerifyDigestTest(public_key, private_key);
    239 	VerifyKernelPreambleTest(public_key, private_key);
    240 
    241 	if (public_key)
    242 		free(public_key);
    243 	if (private_key)
    244 		free(private_key);
    245 
    246 	return 0;
    247 }
    248 
    249 /*
    250  * Test only the algorithms we use:
    251  * 4 (rsa2048 sha256)
    252  * 7 (rsa4096 sha256)
    253  * 11 (rsa8192 sha512)
    254  */
    255 const int key_algs[] = {4, 7, 11};
    256 
    257 int main(int argc, char *argv[]) {
    258 	if (argc == 2) {
    259 		int i;
    260 
    261 		for (i = 0; i < ARRAY_SIZE(key_algs); i++) {
    262 			if (test_algorithm(key_algs[i], argv[1]))
    263 				return 1;
    264 		}
    265 
    266 	} else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
    267 		/* Test all the algorithms */
    268 		int alg;
    269 
    270 		for (alg = 0; alg < kNumAlgorithms; alg++) {
    271 			if (test_algorithm(alg, argv[1]))
    272 				return 1;
    273 		}
    274 
    275 	} else {
    276 		fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
    277 		return -1;
    278 	}
    279 
    280 	if (vboot_api_stub_check_memory())
    281 		return 255;
    282 
    283 	return gTestSuccess ? 0 : 255;
    284 }
    285