blob: ce818a4c71edcf3ff7d595a475810458bc7291fb [file] [log] [blame]
Randall Spanglere061a252013-01-22 15:34:07 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Randall Spanglerd1836442010-06-10 09:59:04 -07002 * 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#include <stdlib.h>
Randall Spanglere061a252013-01-22 15:34:07 -080010#include <string.h>
Randall Spanglerd1836442010-06-10 09:59:04 -070011
12#include "cryptolib.h"
13#include "file_keys.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070014#include "host_common.h"
15#include "test_common.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070016#include "vboot_common.h"
17
18
19static void ReChecksumKeyBlock(VbKeyBlockHeader *h) {
20 uint8_t* newchk = DigestBuf((const uint8_t*)h,
21 h->key_block_checksum.data_size,
22 SHA512_DIGEST_ALGORITHM);
23 Memcpy(GetSignatureData(&h->key_block_checksum), newchk, SHA512_DIGEST_SIZE);
Randall Spangler32a65262011-06-27 10:49:11 -070024 free(newchk);
Randall Spanglerd1836442010-06-10 09:59:04 -070025}
26
27
Randall Spangler729b8722010-06-11 11:16:20 -070028static void KeyBlockVerifyTest(const VbPublicKey* public_key,
Randall Spanglerd1836442010-06-10 09:59:04 -070029 const VbPrivateKey* private_key,
30 const VbPublicKey* data_key) {
31
32 VbKeyBlockHeader *hdr;
33 VbKeyBlockHeader *h;
vbendeb3ecaf772010-06-24 16:19:53 -070034 unsigned hsize;
Randall Spanglerd1836442010-06-10 09:59:04 -070035
Randall Spangler729b8722010-06-11 11:16:20 -070036 hdr = KeyBlockCreate(data_key, private_key, 0x1234);
37 TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites");
Randall Spanglerd1836442010-06-10 09:59:04 -070038 if (!hdr)
39 return;
vbendeb3ecaf772010-06-24 16:19:53 -070040 hsize = (unsigned) hdr->key_block_size;
Randall Spangler32a65262011-06-27 10:49:11 -070041 h = (VbKeyBlockHeader*)malloc(hsize + 1024);
Randall Spanglerd1836442010-06-10 09:59:04 -070042
Randall Spangler138acfe2010-08-17 15:45:21 -070043 TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -070044 "KeyBlockVerify() ok using checksum");
Randall Spangler138acfe2010-08-17 15:45:21 -070045 TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0,
Randall Spangler729b8722010-06-11 11:16:20 -070046 "KeyBlockVerify() ok using key");
Randall Spangler138acfe2010-08-17 15:45:21 -070047 TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0,
48 "KeyBlockVerify() missing key");
Randall Spanglerd1836442010-06-10 09:59:04 -070049
Randall Spangler138acfe2010-08-17 15:45:21 -070050 TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0,
51 "KeyBlockVerify() size--");
52 TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0,
53 "KeyBlockVerify() size++");
Randall Spanglerd1836442010-06-10 09:59:04 -070054
55 Memcpy(h, hdr, hsize);
56 h->magic[0] &= 0x12;
Randall Spangler138acfe2010-08-17 15:45:21 -070057 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() magic");
Randall Spanglerd1836442010-06-10 09:59:04 -070058
59 /* Care about major version but not minor */
60 Memcpy(h, hdr, hsize);
61 h->header_version_major++;
62 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070063 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major++");
Randall Spanglerd1836442010-06-10 09:59:04 -070064
65 Memcpy(h, hdr, hsize);
66 h->header_version_major--;
67 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070068 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() major--");
Randall Spanglerd1836442010-06-10 09:59:04 -070069
70 Memcpy(h, hdr, hsize);
71 h->header_version_minor++;
72 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070073 TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor++");
Randall Spanglerd1836442010-06-10 09:59:04 -070074
75 Memcpy(h, hdr, hsize);
76 h->header_version_minor--;
77 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070078 TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0, "KeyBlockVerify() minor--");
Randall Spanglerd1836442010-06-10 09:59:04 -070079
80 /* Check hash */
81 Memcpy(h, hdr, hsize);
82 h->key_block_checksum.sig_offset = hsize;
83 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070084 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -070085 "KeyBlockVerify() checksum off end");
Randall Spanglerd1836442010-06-10 09:59:04 -070086
87 Memcpy(h, hdr, hsize);
88 h->key_block_checksum.sig_size /= 2;
89 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -070090 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -070091 "KeyBlockVerify() checksum too small");
Randall Spanglerd1836442010-06-10 09:59:04 -070092
93 Memcpy(h, hdr, hsize);
94 GetPublicKeyData(&h->data_key)[0] ^= 0x34;
Randall Spangler138acfe2010-08-17 15:45:21 -070095 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -070096 "KeyBlockVerify() checksum mismatch");
Randall Spanglerd1836442010-06-10 09:59:04 -070097
98 /* Check signature */
99 Memcpy(h, hdr, hsize);
100 h->key_block_signature.sig_offset = hsize;
101 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -0700102 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700103 "KeyBlockVerify() sig off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700104
105 Memcpy(h, hdr, hsize);
106 h->key_block_signature.sig_size--;
107 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -0700108 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700109 "KeyBlockVerify() sig too small");
Randall Spanglerd1836442010-06-10 09:59:04 -0700110
111 Memcpy(h, hdr, hsize);
112 GetPublicKeyData(&h->data_key)[0] ^= 0x34;
Randall Spangler138acfe2010-08-17 15:45:21 -0700113 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700114 "KeyBlockVerify() sig mismatch");
Randall Spanglerd1836442010-06-10 09:59:04 -0700115
116 /* Check that we signed header and data key */
117 Memcpy(h, hdr, hsize);
118 h->key_block_checksum.data_size = 4;
119 h->data_key.key_offset = 0;
120 h->data_key.key_size = 0;
121 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -0700122 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700123 "KeyBlockVerify() didn't sign header");
Randall Spanglerd1836442010-06-10 09:59:04 -0700124
125 Memcpy(h, hdr, hsize);
126 h->data_key.key_offset = hsize;
127 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -0700128 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700129 "KeyBlockVerify() data key off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700130
131 /* TODO: verify parser can support a bigger header (i.e., one where
132 * data_key.key_offset is bigger than expected). */
133
Randall Spangler32a65262011-06-27 10:49:11 -0700134 free(h);
135 free(hdr);
Randall Spanglerd1836442010-06-10 09:59:04 -0700136}
137
138
Randall Spanglera712e012011-07-13 09:48:41 -0700139static void ReSignFirmwarePreamble(VbFirmwarePreambleHeader* h,
140 const VbPrivateKey* key) {
Randall Spanglerd1836442010-06-10 09:59:04 -0700141 VbSignature *sig = CalculateSignature((const uint8_t*)h,
142 h->preamble_signature.data_size, key);
143
144 SignatureCopy(&h->preamble_signature, sig);
Randall Spangler32a65262011-06-27 10:49:11 -0700145 free(sig);
Randall Spanglerd1836442010-06-10 09:59:04 -0700146}
147
148
149static void VerifyFirmwarePreambleTest(const VbPublicKey* public_key,
150 const VbPrivateKey* private_key,
151 const VbPublicKey* kernel_subkey) {
152
Randall Spanglera712e012011-07-13 09:48:41 -0700153 VbFirmwarePreambleHeader* hdr;
154 VbFirmwarePreambleHeader* h;
Randall Spanglerd1836442010-06-10 09:59:04 -0700155 RSAPublicKey* rsa;
vbendeb3ecaf772010-06-24 16:19:53 -0700156 unsigned hsize;
Randall Spanglerd1836442010-06-10 09:59:04 -0700157
158 /* Create a dummy signature */
Randall Spanglera712e012011-07-13 09:48:41 -0700159 VbSignature* body_sig = SignatureAlloc(56, 78);
Randall Spanglerd1836442010-06-10 09:59:04 -0700160
161 rsa = PublicKeyToRSA(public_key);
Randall Spanglera712e012011-07-13 09:48:41 -0700162 hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, private_key,
163 0x5678);
Randall Spangler87c13d82010-07-19 10:35:40 -0700164 TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites");
Randall Spanglerd1836442010-06-10 09:59:04 -0700165 if (!hdr)
166 return;
vbendeb3ecaf772010-06-24 16:19:53 -0700167 hsize = (unsigned) hdr->preamble_size;
Randall Spangler32a65262011-06-27 10:49:11 -0700168 h = (VbFirmwarePreambleHeader*)malloc(hsize + 16384);
Randall Spanglerd1836442010-06-10 09:59:04 -0700169
Randall Spangler87c13d82010-07-19 10:35:40 -0700170 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0,
171 "VerifyFirmwarePreamble() ok using key");
172 TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0,
173 "VerifyFirmwarePreamble() size--");
174 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0,
175 "VerifyFirmwarePreamble() size++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700176
177 /* Care about major version but not minor */
178 Memcpy(h, hdr, hsize);
179 h->header_version_major++;
180 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700181 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
182 "VerifyFirmwarePreamble() major++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700183
184 Memcpy(h, hdr, hsize);
185 h->header_version_major--;
186 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700187 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
188 "VerifyFirmwarePreamble() major--");
Randall Spanglerd1836442010-06-10 09:59:04 -0700189
190 Memcpy(h, hdr, hsize);
191 h->header_version_minor++;
192 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700193 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
194 "VerifyFirmwarePreamble() minor++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700195
196 Memcpy(h, hdr, hsize);
197 h->header_version_minor--;
198 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700199 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
200 "VerifyFirmwarePreamble() minor--");
Randall Spanglerd1836442010-06-10 09:59:04 -0700201
202 /* Check signature */
203 Memcpy(h, hdr, hsize);
204 h->preamble_signature.sig_offset = hsize;
205 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700206 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
207 "VerifyFirmwarePreamble() sig off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700208
209 Memcpy(h, hdr, hsize);
210 h->preamble_signature.sig_size--;
211 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700212 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
213 "VerifyFirmwarePreamble() sig too small");
Randall Spanglerd1836442010-06-10 09:59:04 -0700214
215 Memcpy(h, hdr, hsize);
216 GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34;
Randall Spangler87c13d82010-07-19 10:35:40 -0700217 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
218 "VerifyFirmwarePreamble() sig mismatch");
Randall Spanglerd1836442010-06-10 09:59:04 -0700219
220 /* Check that we signed header, kernel subkey, and body sig */
221 Memcpy(h, hdr, hsize);
222 h->preamble_signature.data_size = 4;
223 h->kernel_subkey.key_offset = 0;
224 h->kernel_subkey.key_size = 0;
225 h->body_signature.sig_offset = 0;
226 h->body_signature.sig_size = 0;
227 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700228 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
229 "VerifyFirmwarePreamble() didn't sign header");
Randall Spanglerd1836442010-06-10 09:59:04 -0700230
231 Memcpy(h, hdr, hsize);
232 h->kernel_subkey.key_offset = hsize;
233 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700234 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
235 "VerifyFirmwarePreamble() kernel subkey off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700236
237 Memcpy(h, hdr, hsize);
238 h->body_signature.sig_offset = hsize;
239 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700240 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
241 "VerifyFirmwarePreamble() body sig off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700242
Randall Spanglera712e012011-07-13 09:48:41 -0700243 /* Check that we return flags properly for new and old structs */
244 Memcpy(h, hdr, hsize);
245 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678,
246 "VbGetFirmwarePreambleFlags() v2.1");
247 h->header_version_minor = 0;
248 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0,
249 "VbGetFirmwarePreambleFlags() v2.0");
250
251 /* TODO: verify with extra padding at end of header. */
Randall Spanglerd1836442010-06-10 09:59:04 -0700252
Randall Spangler32a65262011-06-27 10:49:11 -0700253 free(h);
Randall Spanglerd1836442010-06-10 09:59:04 -0700254 RSAPublicKeyFree(rsa);
Randall Spangler32a65262011-06-27 10:49:11 -0700255 free(hdr);
Randall Spanglerd1836442010-06-10 09:59:04 -0700256}
257
Randall Spanglere061a252013-01-22 15:34:07 -0800258int test_permutation(int signing_key_algorithm, int data_key_algorithm,
259 const char *keys_dir)
260{
261 char filename[1024];
262 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;;
263 int data_rsa_len = siglen_map[data_key_algorithm] * 8;;
Randall Spanglerd1836442010-06-10 09:59:04 -0700264
Randall Spanglere061a252013-01-22 15:34:07 -0800265 VbPrivateKey* signing_private_key = NULL;
266 VbPublicKey* signing_public_key = NULL;
267 VbPublicKey* data_public_key = NULL;
Randall Spanglerd1836442010-06-10 09:59:04 -0700268
Randall Spanglere061a252013-01-22 15:34:07 -0800269 printf("***Testing signing algorithm: %s\n",
270 algo_strings[signing_key_algorithm]);
271 printf("***With data key algorithm: %s\n",
272 algo_strings[data_key_algorithm]);
Randall Spanglerd1836442010-06-10 09:59:04 -0700273
Randall Spanglere061a252013-01-22 15:34:07 -0800274 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len);
275 signing_private_key = PrivateKeyReadPem(filename,
276 signing_key_algorithm);
277 if (!signing_private_key) {
278 fprintf(stderr, "Error reading signing_private_key: %s\n",
279 filename);
280 return 1;
281 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700282
Randall Spanglere061a252013-01-22 15:34:07 -0800283 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len);
284 signing_public_key = PublicKeyReadKeyb(filename,
285 signing_key_algorithm, 1);
286 if (!signing_public_key) {
287 fprintf(stderr, "Error reading signing_public_key: %s\n",
288 filename);
289 return 1;
290 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700291
Randall Spanglere061a252013-01-22 15:34:07 -0800292 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len);
293 data_public_key = PublicKeyReadKeyb(filename,
294 data_key_algorithm, 1);
295 if (!data_public_key) {
296 fprintf(stderr, "Error reading data_public_key: %s\n",
297 filename);
298 return 1;
299 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700300
Randall Spanglere061a252013-01-22 15:34:07 -0800301 KeyBlockVerifyTest(signing_public_key, signing_private_key,
302 data_public_key);
303 VerifyFirmwarePreambleTest(signing_public_key, signing_private_key,
304 data_public_key);
Randall Spanglerd1836442010-06-10 09:59:04 -0700305
Randall Spanglere061a252013-01-22 15:34:07 -0800306 if (signing_public_key)
307 free(signing_public_key);
308 if (signing_private_key)
309 free(signing_private_key);
310 if (data_public_key)
311 free(data_public_key);
Randall Spanglerd1836442010-06-10 09:59:04 -0700312
Randall Spanglere061a252013-01-22 15:34:07 -0800313 return 0;
314}
Randall Spanglerd1836442010-06-10 09:59:04 -0700315
Randall Spanglere061a252013-01-22 15:34:07 -0800316struct test_perm
317{
318 int signing_algorithm;
319 int data_key_algorithm;
320};
Randall Spanglerd1836442010-06-10 09:59:04 -0700321
Randall Spanglere061a252013-01-22 15:34:07 -0800322/*
323 * Permutations of signing and data key algorithms in active use:
324 * 7 (rsa4096 sha256) - 4 (rsa2048 sha256)
325 * 11 (rsa8192 sha512) - 4 (rsa2048 sha256)
326 * 11 (rsa8192 sha512) - 7 (rsa4096 sha256)
327 */
328const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}};
Randall Spanglerd1836442010-06-10 09:59:04 -0700329
Randall Spanglere061a252013-01-22 15:34:07 -0800330int main(int argc, char* argv[])
331{
332 if (argc == 2) {
333 /* Test only the algorithms we use */
334 int i;
335
336 for (i = 0; i < ARRAY_SIZE(test_perms); i++) {
337 if (test_permutation(test_perms[i].signing_algorithm,
338 test_perms[i].data_key_algorithm,
339 argv[1]))
340 return 1;
341 }
342
343 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
344 /* Test all the algorithms */
345 int sign_alg, data_alg;
346
347 for (sign_alg = 0; sign_alg < kNumAlgorithms; sign_alg++) {
348 for (data_alg = 0; data_alg < kNumAlgorithms;
349 data_alg++) {
350 if (test_permutation(sign_alg, data_alg,
351 argv[1]))
352 return 1;
353 }
354 }
355 } else {
356 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
357 return -1;
358 }
359
360 return gTestSuccess ? 0 : 255;
Randall Spanglerd1836442010-06-10 09:59:04 -0700361}