blob: 69c54a8067af6e317bdff428ba92b90800d3a824 [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
Randall Spangler3b806ea2013-01-25 13:56:55 -0800116 Memcpy(h, hdr, hsize);
117 //ReChecksumKeyBlock(h);
118 h->key_block_checksum.data_size = h->key_block_size + 1;
119 TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0,
120 "KeyBlockVerify() checksum data past end of block");
121
Randall Spanglerd1836442010-06-10 09:59:04 -0700122 /* Check that we signed header and data key */
123 Memcpy(h, hdr, hsize);
124 h->key_block_checksum.data_size = 4;
125 h->data_key.key_offset = 0;
126 h->data_key.key_size = 0;
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() didn't sign header");
Randall Spanglerd1836442010-06-10 09:59:04 -0700130
131 Memcpy(h, hdr, hsize);
132 h->data_key.key_offset = hsize;
133 ReChecksumKeyBlock(h);
Randall Spangler138acfe2010-08-17 15:45:21 -0700134 TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
Randall Spangler729b8722010-06-11 11:16:20 -0700135 "KeyBlockVerify() data key off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700136
Randall Spangler3b806ea2013-01-25 13:56:55 -0800137 /* Corner cases for error checking */
138 TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0,
139 "KeyBlockVerify size too small");
140
Randall Spanglerd1836442010-06-10 09:59:04 -0700141 /* TODO: verify parser can support a bigger header (i.e., one where
142 * data_key.key_offset is bigger than expected). */
143
Randall Spangler32a65262011-06-27 10:49:11 -0700144 free(h);
145 free(hdr);
Randall Spanglerd1836442010-06-10 09:59:04 -0700146}
147
148
Randall Spanglera712e012011-07-13 09:48:41 -0700149static void ReSignFirmwarePreamble(VbFirmwarePreambleHeader* h,
150 const VbPrivateKey* key) {
Randall Spanglerd1836442010-06-10 09:59:04 -0700151 VbSignature *sig = CalculateSignature((const uint8_t*)h,
152 h->preamble_signature.data_size, key);
153
154 SignatureCopy(&h->preamble_signature, sig);
Randall Spangler32a65262011-06-27 10:49:11 -0700155 free(sig);
Randall Spanglerd1836442010-06-10 09:59:04 -0700156}
157
158
159static void VerifyFirmwarePreambleTest(const VbPublicKey* public_key,
160 const VbPrivateKey* private_key,
161 const VbPublicKey* kernel_subkey) {
162
Randall Spanglera712e012011-07-13 09:48:41 -0700163 VbFirmwarePreambleHeader* hdr;
164 VbFirmwarePreambleHeader* h;
Randall Spanglerd1836442010-06-10 09:59:04 -0700165 RSAPublicKey* rsa;
vbendeb3ecaf772010-06-24 16:19:53 -0700166 unsigned hsize;
Randall Spanglerd1836442010-06-10 09:59:04 -0700167
168 /* Create a dummy signature */
Randall Spanglera712e012011-07-13 09:48:41 -0700169 VbSignature* body_sig = SignatureAlloc(56, 78);
Randall Spanglerd1836442010-06-10 09:59:04 -0700170
171 rsa = PublicKeyToRSA(public_key);
Randall Spanglera712e012011-07-13 09:48:41 -0700172 hdr = CreateFirmwarePreamble(0x1234, kernel_subkey, body_sig, private_key,
173 0x5678);
Randall Spangler87c13d82010-07-19 10:35:40 -0700174 TEST_NEQ(hdr && rsa, 0, "VerifyFirmwarePreamble() prerequisites");
Randall Spanglerd1836442010-06-10 09:59:04 -0700175 if (!hdr)
176 return;
vbendeb3ecaf772010-06-24 16:19:53 -0700177 hsize = (unsigned) hdr->preamble_size;
Randall Spangler32a65262011-06-27 10:49:11 -0700178 h = (VbFirmwarePreambleHeader*)malloc(hsize + 16384);
Randall Spanglerd1836442010-06-10 09:59:04 -0700179
Randall Spangler87c13d82010-07-19 10:35:40 -0700180 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize, rsa), 0,
181 "VerifyFirmwarePreamble() ok using key");
Randall Spangler3b806ea2013-01-25 13:56:55 -0800182 TEST_NEQ(VerifyFirmwarePreamble(hdr, 4, rsa), 0,
183 "VerifyFirmwarePreamble() size tiny");
Randall Spangler87c13d82010-07-19 10:35:40 -0700184 TEST_NEQ(VerifyFirmwarePreamble(hdr, hsize - 1, rsa), 0,
185 "VerifyFirmwarePreamble() size--");
186 TEST_EQ(VerifyFirmwarePreamble(hdr, hsize + 1, rsa), 0,
187 "VerifyFirmwarePreamble() size++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700188
189 /* Care about major version but not minor */
190 Memcpy(h, hdr, hsize);
191 h->header_version_major++;
192 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700193 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
194 "VerifyFirmwarePreamble() major++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700195
196 Memcpy(h, hdr, hsize);
197 h->header_version_major--;
198 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700199 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
200 "VerifyFirmwarePreamble() major--");
Randall Spanglerd1836442010-06-10 09:59:04 -0700201
202 Memcpy(h, hdr, hsize);
203 h->header_version_minor++;
204 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700205 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
206 "VerifyFirmwarePreamble() minor++");
Randall Spanglerd1836442010-06-10 09:59:04 -0700207
208 Memcpy(h, hdr, hsize);
209 h->header_version_minor--;
210 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700211 TEST_EQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
212 "VerifyFirmwarePreamble() minor--");
Randall Spanglerd1836442010-06-10 09:59:04 -0700213
214 /* Check signature */
215 Memcpy(h, hdr, hsize);
216 h->preamble_signature.sig_offset = hsize;
217 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700218 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
219 "VerifyFirmwarePreamble() sig off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700220
221 Memcpy(h, hdr, hsize);
222 h->preamble_signature.sig_size--;
223 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700224 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
225 "VerifyFirmwarePreamble() sig too small");
Randall Spanglerd1836442010-06-10 09:59:04 -0700226
227 Memcpy(h, hdr, hsize);
228 GetPublicKeyData(&h->kernel_subkey)[0] ^= 0x34;
Randall Spangler87c13d82010-07-19 10:35:40 -0700229 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
230 "VerifyFirmwarePreamble() sig mismatch");
Randall Spanglerd1836442010-06-10 09:59:04 -0700231
232 /* Check that we signed header, kernel subkey, and body sig */
233 Memcpy(h, hdr, hsize);
234 h->preamble_signature.data_size = 4;
235 h->kernel_subkey.key_offset = 0;
236 h->kernel_subkey.key_size = 0;
237 h->body_signature.sig_offset = 0;
238 h->body_signature.sig_size = 0;
239 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700240 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
241 "VerifyFirmwarePreamble() didn't sign header");
Randall Spanglerd1836442010-06-10 09:59:04 -0700242
243 Memcpy(h, hdr, hsize);
244 h->kernel_subkey.key_offset = hsize;
245 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700246 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
247 "VerifyFirmwarePreamble() kernel subkey off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700248
249 Memcpy(h, hdr, hsize);
250 h->body_signature.sig_offset = hsize;
251 ReSignFirmwarePreamble(h, private_key);
Randall Spangler87c13d82010-07-19 10:35:40 -0700252 TEST_NEQ(VerifyFirmwarePreamble(h, hsize, rsa), 0,
253 "VerifyFirmwarePreamble() body sig off end");
Randall Spanglerd1836442010-06-10 09:59:04 -0700254
Randall Spanglera712e012011-07-13 09:48:41 -0700255 /* Check that we return flags properly for new and old structs */
256 Memcpy(h, hdr, hsize);
257 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0x5678,
258 "VbGetFirmwarePreambleFlags() v2.1");
259 h->header_version_minor = 0;
260 TEST_EQ(VbGetFirmwarePreambleFlags(h), 0,
261 "VbGetFirmwarePreambleFlags() v2.0");
262
263 /* TODO: verify with extra padding at end of header. */
Randall Spanglerd1836442010-06-10 09:59:04 -0700264
Randall Spangler32a65262011-06-27 10:49:11 -0700265 free(h);
Randall Spanglerd1836442010-06-10 09:59:04 -0700266 RSAPublicKeyFree(rsa);
Randall Spangler32a65262011-06-27 10:49:11 -0700267 free(hdr);
Randall Spanglerd1836442010-06-10 09:59:04 -0700268}
269
Randall Spanglere061a252013-01-22 15:34:07 -0800270int test_permutation(int signing_key_algorithm, int data_key_algorithm,
271 const char *keys_dir)
272{
273 char filename[1024];
274 int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;;
275 int data_rsa_len = siglen_map[data_key_algorithm] * 8;;
Randall Spanglerd1836442010-06-10 09:59:04 -0700276
Randall Spanglere061a252013-01-22 15:34:07 -0800277 VbPrivateKey* signing_private_key = NULL;
278 VbPublicKey* signing_public_key = NULL;
279 VbPublicKey* data_public_key = NULL;
Randall Spanglerd1836442010-06-10 09:59:04 -0700280
Randall Spanglere061a252013-01-22 15:34:07 -0800281 printf("***Testing signing algorithm: %s\n",
282 algo_strings[signing_key_algorithm]);
283 printf("***With data key algorithm: %s\n",
284 algo_strings[data_key_algorithm]);
Randall Spanglerd1836442010-06-10 09:59:04 -0700285
Randall Spanglere061a252013-01-22 15:34:07 -0800286 sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len);
287 signing_private_key = PrivateKeyReadPem(filename,
288 signing_key_algorithm);
289 if (!signing_private_key) {
290 fprintf(stderr, "Error reading signing_private_key: %s\n",
291 filename);
292 return 1;
293 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700294
Randall Spanglere061a252013-01-22 15:34:07 -0800295 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len);
296 signing_public_key = PublicKeyReadKeyb(filename,
297 signing_key_algorithm, 1);
298 if (!signing_public_key) {
299 fprintf(stderr, "Error reading signing_public_key: %s\n",
300 filename);
301 return 1;
302 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700303
Randall Spanglere061a252013-01-22 15:34:07 -0800304 sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len);
305 data_public_key = PublicKeyReadKeyb(filename,
306 data_key_algorithm, 1);
307 if (!data_public_key) {
308 fprintf(stderr, "Error reading data_public_key: %s\n",
309 filename);
310 return 1;
311 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700312
Randall Spanglere061a252013-01-22 15:34:07 -0800313 KeyBlockVerifyTest(signing_public_key, signing_private_key,
314 data_public_key);
315 VerifyFirmwarePreambleTest(signing_public_key, signing_private_key,
316 data_public_key);
Randall Spanglerd1836442010-06-10 09:59:04 -0700317
Randall Spanglere061a252013-01-22 15:34:07 -0800318 if (signing_public_key)
319 free(signing_public_key);
320 if (signing_private_key)
321 free(signing_private_key);
322 if (data_public_key)
323 free(data_public_key);
Randall Spanglerd1836442010-06-10 09:59:04 -0700324
Randall Spanglere061a252013-01-22 15:34:07 -0800325 return 0;
326}
Randall Spanglerd1836442010-06-10 09:59:04 -0700327
Randall Spanglere061a252013-01-22 15:34:07 -0800328struct test_perm
329{
330 int signing_algorithm;
331 int data_key_algorithm;
332};
Randall Spanglerd1836442010-06-10 09:59:04 -0700333
Randall Spanglere061a252013-01-22 15:34:07 -0800334/*
335 * Permutations of signing and data key algorithms in active use:
336 * 7 (rsa4096 sha256) - 4 (rsa2048 sha256)
337 * 11 (rsa8192 sha512) - 4 (rsa2048 sha256)
338 * 11 (rsa8192 sha512) - 7 (rsa4096 sha256)
339 */
340const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}};
Randall Spanglerd1836442010-06-10 09:59:04 -0700341
Randall Spanglere061a252013-01-22 15:34:07 -0800342int main(int argc, char* argv[])
343{
344 if (argc == 2) {
345 /* Test only the algorithms we use */
346 int i;
347
348 for (i = 0; i < ARRAY_SIZE(test_perms); i++) {
349 if (test_permutation(test_perms[i].signing_algorithm,
350 test_perms[i].data_key_algorithm,
351 argv[1]))
352 return 1;
353 }
354
355 } else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
356 /* Test all the algorithms */
357 int sign_alg, data_alg;
358
359 for (sign_alg = 0; sign_alg < kNumAlgorithms; sign_alg++) {
360 for (data_alg = 0; data_alg < kNumAlgorithms;
361 data_alg++) {
362 if (test_permutation(sign_alg, data_alg,
363 argv[1]))
364 return 1;
365 }
366 }
367 } else {
368 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
369 return -1;
370 }
371
372 return gTestSuccess ? 0 : 255;
Randall Spanglerd1836442010-06-10 09:59:04 -0700373}