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 
VerifyPublicKeyToRSA(const VbPublicKey * orig_key)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 
VerifyDataTest(const VbPublicKey * public_key,const VbPrivateKey * private_key)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 
VerifyDigestTest(const VbPublicKey * public_key,const VbPrivateKey * private_key)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 
ReSignKernelPreamble(VbKernelPreambleHeader * h,const VbPrivateKey * key)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 
VerifyKernelPreambleTest(const VbPublicKey * public_key,const VbPrivateKey * private_key)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 
test_algorithm(int key_algorithm,const char * keys_dir)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 
main(int argc,char * argv[])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