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 
ReChecksumKeyBlock(VbKeyBlockHeader * h)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 
KeyBlockVerifyTest(const VbPublicKey * public_key,const VbPrivateKey * private_key,const VbPublicKey * data_key)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 
ReSignFirmwarePreamble(VbFirmwarePreambleHeader * h,const VbPrivateKey * key)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 
VerifyFirmwarePreambleTest(const VbPublicKey * public_key,const VbPrivateKey * private_key,const VbPublicKey * kernel_subkey)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 
test_permutation(int signing_key_algorithm,int data_key_algorithm,const char * keys_dir)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 
main(int argc,char * argv[])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