1eba971cf1f39d54dcccc070e48dfaf71728bf94
[vboot.git] / tests / vboot_common3_tests.c
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 "2sysincludes.h"
14 #include "2common.h"
15 #include "2sha.h"
16 #include "cryptolib.h"
17 #include "file_keys.h"
18 #include "host_common.h"
19 #include "test_common.h"
20 #include "vboot_common.h"
21
22
23 static void ReChecksumKeyBlock(VbKeyBlockHeader *h)
24 {
25         vb2_digest_buffer((const uint8_t *)h,
26                           h->key_block_checksum.data_size,
27                           VB2_HASH_SHA512,
28                           GetSignatureData(&h->key_block_checksum),
29                           VB2_SHA512_DIGEST_SIZE);
30 }
31
32 static void KeyBlockVerifyTest(const VbPublicKey *public_key,
33                                const VbPrivateKey *private_key,
34                                const VbPublicKey *data_key)
35 {
36         VbKeyBlockHeader *hdr;
37         VbKeyBlockHeader *h;
38         unsigned hsize;
39
40         hdr = KeyBlockCreate(data_key, private_key, 0x1234);
41         TEST_NEQ((size_t)hdr, 0, "KeyBlockVerify() prerequisites");
42         if (!hdr)
43                 return;
44         hsize = (unsigned) hdr->key_block_size;
45         h = (VbKeyBlockHeader *)malloc(hsize + 1024);
46
47         TEST_EQ(KeyBlockVerify(hdr, hsize, NULL, 1), 0,
48                 "KeyBlockVerify() ok using checksum");
49         TEST_EQ(KeyBlockVerify(hdr, hsize, public_key, 0), 0,
50                 "KeyBlockVerify() ok using key");
51         TEST_NEQ(KeyBlockVerify(hdr, hsize, NULL, 0), 0,
52                  "KeyBlockVerify() missing key");
53
54         TEST_NEQ(KeyBlockVerify(hdr, hsize - 1, NULL, 1), 0,
55                  "KeyBlockVerify() size--");
56         TEST_EQ(KeyBlockVerify(hdr, hsize + 1, NULL, 1), 0,
57                 "KeyBlockVerify() size++");
58
59         Memcpy(h, hdr, hsize);
60         h->magic[0] &= 0x12;
61         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
62                  "KeyBlockVerify() magic");
63
64         /* Care about major version but not minor */
65         Memcpy(h, hdr, hsize);
66         h->header_version_major++;
67         ReChecksumKeyBlock(h);
68         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
69                  "KeyBlockVerify() major++");
70
71         Memcpy(h, hdr, hsize);
72         h->header_version_major--;
73         ReChecksumKeyBlock(h);
74         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
75                  "KeyBlockVerify() major--");
76
77         Memcpy(h, hdr, hsize);
78         h->header_version_minor++;
79         ReChecksumKeyBlock(h);
80         TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
81                 "KeyBlockVerify() minor++");
82
83         Memcpy(h, hdr, hsize);
84         h->header_version_minor--;
85         ReChecksumKeyBlock(h);
86         TEST_EQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
87                 "KeyBlockVerify() minor--");
88
89         /* Check hash */
90         Memcpy(h, hdr, hsize);
91         h->key_block_checksum.sig_offset = hsize;
92         ReChecksumKeyBlock(h);
93         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
94                  "KeyBlockVerify() checksum off end");
95
96         Memcpy(h, hdr, hsize);
97         h->key_block_checksum.sig_size /= 2;
98         ReChecksumKeyBlock(h);
99         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
100                  "KeyBlockVerify() checksum too small");
101
102         Memcpy(h, hdr, hsize);
103         GetPublicKeyData(&h->data_key)[0] ^= 0x34;
104         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
105                  "KeyBlockVerify() checksum mismatch");
106
107         /* Check signature */
108         Memcpy(h, hdr, hsize);
109         h->key_block_signature.sig_offset = hsize;
110         ReChecksumKeyBlock(h);
111         TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
112                  "KeyBlockVerify() sig off end");
113
114         Memcpy(h, hdr, hsize);
115         h->key_block_signature.sig_size--;
116         ReChecksumKeyBlock(h);
117         TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
118                  "KeyBlockVerify() sig too small");
119
120         Memcpy(h, hdr, hsize);
121         GetPublicKeyData(&h->data_key)[0] ^= 0x34;
122         TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 0), 0,
123                  "KeyBlockVerify() sig mismatch");
124
125         Memcpy(h, hdr, hsize);
126         h->key_block_checksum.data_size = h->key_block_size + 1;
127         TEST_NEQ(KeyBlockVerify(h, hsize, public_key, 1), 0,
128                  "KeyBlockVerify() checksum data past end of block");
129
130         /* Check that we signed header and data key */
131         Memcpy(h, hdr, hsize);
132         h->key_block_checksum.data_size = 4;
133         h->data_key.key_offset = 0;
134         h->data_key.key_size = 0;
135         ReChecksumKeyBlock(h);
136         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
137                  "KeyBlockVerify() didn't sign header");
138
139         Memcpy(h, hdr, hsize);
140         h->data_key.key_offset = hsize;
141         ReChecksumKeyBlock(h);
142         TEST_NEQ(KeyBlockVerify(h, hsize, NULL, 1), 0,
143                  "KeyBlockVerify() data key off end");
144
145         /* Corner cases for error checking */
146         TEST_NEQ(KeyBlockVerify(NULL, 4, NULL, 1), 0,
147                  "KeyBlockVerify size too small");
148
149         /*
150          * TODO: verify parser can support a bigger header (i.e., one where
151          * data_key.key_offset is bigger than expected).
152          */
153
154         free(h);
155         free(hdr);
156 }
157
158 int test_permutation(int signing_key_algorithm, int data_key_algorithm,
159                      const char *keys_dir)
160 {
161         char filename[1024];
162         int signing_rsa_len = siglen_map[signing_key_algorithm] * 8;
163         int data_rsa_len = siglen_map[data_key_algorithm] * 8;
164
165         VbPrivateKey *signing_private_key = NULL;
166         VbPublicKey *signing_public_key = NULL;
167         VbPublicKey *data_public_key = NULL;
168
169         printf("***Testing signing algorithm: %s\n",
170                algo_strings[signing_key_algorithm]);
171         printf("***With data key algorithm: %s\n",
172                algo_strings[data_key_algorithm]);
173
174         sprintf(filename, "%s/key_rsa%d.pem", keys_dir, signing_rsa_len);
175         signing_private_key = PrivateKeyReadPem(filename,
176                                                 signing_key_algorithm);
177         if (!signing_private_key) {
178                 fprintf(stderr, "Error reading signing_private_key: %s\n",
179                         filename);
180                 return 1;
181         }
182
183         sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, signing_rsa_len);
184         signing_public_key = PublicKeyReadKeyb(filename,
185                                                signing_key_algorithm, 1);
186         if (!signing_public_key) {
187                 fprintf(stderr, "Error reading signing_public_key: %s\n",
188                         filename);
189                 return 1;
190         }
191
192         sprintf(filename, "%s/key_rsa%d.keyb", keys_dir, data_rsa_len);
193         data_public_key = PublicKeyReadKeyb(filename,
194                                                data_key_algorithm, 1);
195         if (!data_public_key) {
196                 fprintf(stderr, "Error reading data_public_key: %s\n",
197                         filename);
198                 return 1;
199         }
200
201         KeyBlockVerifyTest(signing_public_key, signing_private_key,
202                            data_public_key);
203
204         if (signing_public_key)
205                 free(signing_public_key);
206         if (signing_private_key)
207                 free(signing_private_key);
208         if (data_public_key)
209                 free(data_public_key);
210
211         return 0;
212 }
213
214 struct test_perm
215 {
216         int signing_algorithm;
217         int data_key_algorithm;
218 };
219
220 /*
221  * Permutations of signing and data key algorithms in active use:
222  * 7 (rsa4096 sha256) - 4 (rsa2048 sha256)
223  * 11 (rsa8192 sha512) - 4 (rsa2048 sha256)
224  * 11 (rsa8192 sha512) - 7 (rsa4096 sha256)
225  */
226 const struct test_perm test_perms[] = {{7, 4}, {11, 4}, {11, 7}};
227
228 int main(int argc, char *argv[])
229 {
230         if (argc == 2) {
231                 /* Test only the algorithms we use */
232                 int i;
233
234                 for (i = 0; i < ARRAY_SIZE(test_perms); i++) {
235                         if (test_permutation(test_perms[i].signing_algorithm,
236                                              test_perms[i].data_key_algorithm,
237                                              argv[1]))
238                                 return 1;
239                 }
240
241         } else if (argc == 3 && !strcasecmp(argv[2], "--all")) {
242                 /* Test all the algorithms */
243                 int sign_alg, data_alg;
244
245                 for (sign_alg = 0; sign_alg < kNumAlgorithms; sign_alg++) {
246                         for (data_alg = 0; data_alg < kNumAlgorithms;
247                              data_alg++) {
248                                 if (test_permutation(sign_alg, data_alg,
249                                                      argv[1]))
250                                         return 1;
251                         }
252                 }
253         } else {
254                 fprintf(stderr, "Usage: %s <keys_dir> [--all]", argv[0]);
255                 return -1;
256         }
257
258         if (vboot_api_stub_check_memory())
259                 return 255;
260
261         return gTestSuccess ? 0 : 255;
262 }