bdb: Integrate bdb_test
[vboot.git] / tests / bdb_test.c
1 /* Copyright 2015 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  * Unit tests
6  */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "bdb.h"
13 #include "host.h"
14 #include "test_common.h"
15
16 #define TEST_EQ_S(result, expect) TEST_EQ(result, expect, #result "==" #expect)
17
18 void check_header_tests(void)
19 {
20         struct bdb_header sgood = {
21                 .struct_magic = BDB_HEADER_MAGIC,
22                 .struct_major_version = BDB_HEADER_VERSION_MAJOR,
23                 .struct_minor_version = BDB_HEADER_VERSION_MINOR,
24                 .struct_size = sizeof(struct bdb_header),
25                 .bdb_load_address = -1,
26                 .bdb_size = 1024,
27                 .signed_size = 512,
28                 .oem_area_0_size = 256,
29         };
30         const size_t ssize = sgood.struct_size;
31         struct bdb_header s;
32
33         s = sgood;
34         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_SUCCESS);
35         TEST_EQ_S(bdb_check_header(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
36
37         s = sgood;
38         s.struct_size++;
39         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_BUF_SIZE);
40
41         s = sgood;
42         s.struct_size--;
43         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_SIZE);
44
45         s = sgood;
46         s.struct_magic++;
47         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
48
49         s = sgood;
50         s.struct_major_version++;
51         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_STRUCT_VERSION);
52
53         s = sgood;
54         s.oem_area_0_size++;
55         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
56
57         s = sgood;
58         s.bdb_size = ssize - 1;
59         TEST_EQ_S(bdb_check_header(&s, ssize), BDB_ERROR_BDB_SIZE);
60 }
61
62 void check_key_tests(void)
63 {
64         struct bdb_key sgood = {
65                 .struct_magic = BDB_KEY_MAGIC,
66                 .struct_major_version = BDB_KEY_VERSION_MAJOR,
67                 .struct_minor_version = BDB_KEY_VERSION_MINOR,
68                 .struct_size = (sizeof(struct bdb_key) +
69                                 BDB_RSA4096_KEY_DATA_SIZE),
70                 .hash_alg = BDB_HASH_ALG_SHA256,
71                 .sig_alg = BDB_SIG_ALG_RSA4096,
72                 .key_version = 1,
73                 .description = "Test key",
74         };
75         const size_t ssize = sgood.struct_size;
76         struct bdb_key s;
77
78         s = sgood;
79         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_SUCCESS);
80         TEST_EQ_S(bdb_check_key(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
81
82         s = sgood;
83         s.struct_size++;
84         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_BUF_SIZE);
85
86         s = sgood;
87         s.struct_size--;
88         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_SIZE);
89
90         s = sgood;
91         s.struct_magic++;
92         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
93
94         s = sgood;
95         s.struct_major_version++;
96         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_STRUCT_VERSION);
97
98         /* Description must contain a null */
99         s = sgood;
100         memset(s.description, 'x', sizeof(s.description));
101         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_DESCRIPTION);
102
103         /* Data AFTER the null is explicitly allowed, though */
104         s = sgood;
105         s.description[100] = 'x';
106         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_SUCCESS);
107
108         /* Limited algorithm choices at present */
109         s = sgood;
110         s.hash_alg = BDB_HASH_ALG_INVALID;
111         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_HASH_ALG);
112
113         /* This works because ECDSA521 signatures are smaller than RSA4096 */
114         s = sgood;
115         s.sig_alg = BDB_SIG_ALG_ECSDSA521;
116         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_SUCCESS);
117
118         s = sgood;
119         s.sig_alg = BDB_SIG_ALG_INVALID;
120         TEST_EQ_S(bdb_check_key(&s, ssize), BDB_ERROR_SIG_ALG);
121 }
122
123 void check_sig_tests(void)
124 {
125         struct bdb_sig sgood = {
126                 .struct_magic = BDB_SIG_MAGIC,
127                 .struct_major_version = BDB_SIG_VERSION_MAJOR,
128                 .struct_minor_version = BDB_SIG_VERSION_MINOR,
129                 .struct_size = sizeof(struct bdb_sig) + BDB_RSA4096_SIG_SIZE,
130                 .hash_alg = BDB_HASH_ALG_SHA256,
131                 .sig_alg = BDB_SIG_ALG_RSA4096,
132                 .signed_size = 123,
133                 .description = "Test sig",
134         };
135         const size_t ssize = sgood.struct_size;
136         struct bdb_sig s;
137
138         s = sgood;
139         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_SUCCESS);
140         TEST_EQ_S(bdb_check_sig(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
141
142         s = sgood;
143         s.struct_size++;
144         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_BUF_SIZE);
145
146         s = sgood;
147         s.struct_size--;
148         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_SIZE);
149
150         s = sgood;
151         s.struct_magic++;
152         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
153
154         s = sgood;
155         s.struct_major_version++;
156         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_STRUCT_VERSION);
157
158         /* Description must contain a null */
159         s = sgood;
160         memset(s.description, 'x', sizeof(s.description));
161         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_DESCRIPTION);
162
163         /* Data AFTER the null is explicitly allowed, though */
164         s = sgood;
165         s.description[100] = 'x';
166         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_SUCCESS);
167
168         /* Limited algorithm choices at present */
169         s = sgood;
170         s.hash_alg = BDB_HASH_ALG_INVALID;
171         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_HASH_ALG);
172
173         /* This works because ECDSA521 signatures are smaller than RSA4096 */
174         s = sgood;
175         s.sig_alg = BDB_SIG_ALG_ECSDSA521;
176         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_SUCCESS);
177
178         s = sgood;
179         s.sig_alg = BDB_SIG_ALG_INVALID;
180         TEST_EQ_S(bdb_check_sig(&s, ssize), BDB_ERROR_SIG_ALG);
181 }
182
183 void check_data_tests(void)
184 {
185         struct bdb_data sgood = {
186                 .struct_magic = BDB_DATA_MAGIC,
187                 .struct_major_version = BDB_DATA_VERSION_MAJOR,
188                 .struct_minor_version = BDB_DATA_VERSION_MINOR,
189                 .struct_size = sizeof(struct bdb_data),
190                 .data_version = 1,
191                 .oem_area_1_size = 256,
192                 .num_hashes = 3,
193                 .hash_entry_size = sizeof(struct bdb_hash),
194                 .signed_size = 2048,
195                 .description = "Test data",
196         };
197         const size_t ssize = sgood.signed_size;
198         struct bdb_data s;
199
200         s = sgood;
201         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_SUCCESS);
202         TEST_EQ_S(bdb_check_data(&s, ssize - 1), BDB_ERROR_BUF_SIZE);
203
204         s = sgood;
205         s.struct_size--;
206         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_SIZE);
207
208         s = sgood;
209         s.struct_magic++;
210         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_MAGIC);
211
212         s = sgood;
213         s.struct_major_version++;
214         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_STRUCT_VERSION);
215
216         /* Description must contain a null */
217         s = sgood;
218         memset(s.description, 'x', sizeof(s.description));
219         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_DESCRIPTION);
220
221         /* Data AFTER the null is explicitly allowed, though */
222         s = sgood;
223         s.description[100] = 'x';
224         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_SUCCESS);
225
226         s = sgood;
227         s.hash_entry_size--;
228         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_HASH_ENTRY_SIZE);
229
230         s = sgood;
231         s.oem_area_1_size++;
232         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_OEM_AREA_SIZE);
233
234         /* Check exact size needed */
235         s = sgood;
236         s.signed_size = sizeof(s) + s.num_hashes * sizeof(struct bdb_hash) +
237                 s.oem_area_1_size;
238         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_SUCCESS);
239         s.signed_size--;
240         TEST_EQ_S(bdb_check_data(&s, ssize), BDB_ERROR_SIGNED_SIZE);
241
242         /*
243          * TODO: Verify wraparound check works.  That can only be tested on a
244          * platform where size_t is uint32_t, because otherwise a 32-bit
245          * oem_area_1_size can't cause wraparound.
246          */
247 }
248
249 /**
250  * Test bdb_verify() and bdb_create()
251  */
252 void check_bdb_verify(const char *key_dir)
253 {
254         uint8_t oem_area_0[32] = "Some OEM area.";
255         uint8_t oem_area_1[64] = "Some other OEM area.";
256         char filename[1024];
257
258         struct bdb_hash hash[2] = {
259                 {
260                         .offset = 0x10000,
261                         .size = 0x18000,
262                         .partition = 1,
263                         .type = BDB_DATA_SP_RW,
264                         .load_address = 0x100000,
265                         .digest = {0x11, 0x11, 0x11, 0x10},
266                 },
267                 {
268                         .offset = 0x28000,
269                         .size = 0x20000,
270                         .partition = 1,
271                         .type = BDB_DATA_AP_RW,
272                         .load_address = 0x200000,
273                         .digest = {0x22, 0x22, 0x22, 0x20},
274                 },
275         };
276
277         struct bdb_create_params p = {
278                 .bdb_load_address = 0x11223344,
279                 .oem_area_0 = oem_area_0,
280                 .oem_area_0_size = sizeof(oem_area_0),
281                 .oem_area_1 = oem_area_1,
282                 .oem_area_1_size = sizeof(oem_area_1),
283                 .header_sig_description = "The header sig",
284                 .data_sig_description = "The data sig",
285                 .data_description = "Test BDB data",
286                 .data_version = 3,
287                 .hash = hash,
288                 .num_hashes = 2,
289         };
290
291         uint8_t bdbkey_digest[BDB_SHA256_DIGEST_SIZE];
292         struct bdb_header *hgood, *h;
293         size_t hsize;
294
295         /* Load keys */
296         sprintf(filename, "%s/bdbkey.keyb", key_dir);
297         p.bdbkey = bdb_create_key(filename, 100, "BDB key");
298         sprintf(filename, "%s/subkey.keyb", key_dir);
299         p.subkey = bdb_create_key(filename, 200, "Subkey");
300         sprintf(filename, "%s/bdbkey.pem", key_dir);
301         p.private_bdbkey = read_pem(filename);
302         sprintf(filename, "%s/subkey.pem", key_dir);
303         p.private_subkey = read_pem(filename);
304         if (!p.bdbkey || !p.subkey || !p.private_bdbkey || !p.private_subkey) {
305                 fprintf(stderr, "Unable to load test keys\n");
306                 exit(2);
307         }
308
309         bdb_sha256(bdbkey_digest, p.bdbkey, p.bdbkey->struct_size);
310
311         /* Create the test BDB */
312         hgood = bdb_create(&p);
313         if (!hgood) {
314                 fprintf(stderr, "Unable to create test BDB\n");
315                 exit(2);
316         }
317         hsize = hgood->bdb_size;
318
319         /* Allocate a copy we can mangle */
320         h = calloc(hsize, 1);
321
322         /* As created, it should pass */
323         memcpy(h, hgood, hsize);
324         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_SUCCESS);
325
326         /* Mangle each component in turn */
327         memcpy(h, hgood, hsize);
328         h->struct_magic++;
329         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER);
330
331         memcpy(h, hgood, hsize);
332         ((struct bdb_key *)bdb_get_bdbkey(h))->struct_magic++;
333         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDBKEY);
334
335         memcpy(h, hgood, hsize);
336         ((struct bdb_key *)bdb_get_bdbkey(h))->key_version++;
337         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_GOOD_OTHER_THAN_KEY);
338
339         memcpy(h, hgood, hsize);
340         h->oem_area_0_size += hsize;
341         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_OEM_AREA_0);
342
343         memcpy(h, hgood, hsize);
344         ((struct bdb_key *)bdb_get_subkey(h))->struct_magic++;
345         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_SUBKEY);
346
347         memcpy(h, hgood, hsize);
348         ((struct bdb_key *)bdb_get_subkey(h))->struct_size += 4;
349         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_BDB_SIGNED_SIZE);
350
351         memcpy(h, hgood, hsize);
352         ((struct bdb_sig *)bdb_get_header_sig(h))->struct_magic++;
353         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
354
355         memcpy(h, hgood, hsize);
356         ((struct bdb_sig *)bdb_get_header_sig(h))->signed_size--;
357         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
358
359         memcpy(h, hgood, hsize);
360         ((struct bdb_sig *)bdb_get_header_sig(h))->sig_data[0] ^= 0x42;
361         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
362
363         /* Also make sure the header sig really covers all the fields */
364         memcpy(h, hgood, hsize);
365         ((struct bdb_key *)bdb_get_subkey(h))->key_version++;
366         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
367
368         memcpy(h, hgood, hsize);
369         ((uint8_t *)bdb_get_oem_area_0(h))[0] ^= 0x42;
370         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
371
372         memcpy(h, hgood, hsize);
373         ((uint8_t *)bdb_get_oem_area_0(h))[p.oem_area_0_size - 1] ^= 0x24;
374         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_HEADER_SIG);
375
376         /* Check data header */
377         memcpy(h, hgood, hsize);
378         ((struct bdb_data *)bdb_get_data(h))->struct_magic++;
379         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA);
380
381         memcpy(h, hgood, hsize);
382         ((struct bdb_sig *)bdb_get_data_sig(h))->struct_magic++;
383         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
384
385         memcpy(h, hgood, hsize);
386         ((struct bdb_sig *)bdb_get_data_sig(h))->signed_size--;
387         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
388
389         memcpy(h, hgood, hsize);
390         ((struct bdb_sig *)bdb_get_data_sig(h))->sig_data[0] ^= 0x42;
391         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
392
393         /* Also make sure the data sig really covers all the fields */
394         memcpy(h, hgood, hsize);
395         ((struct bdb_data *)bdb_get_data(h))->data_version--;
396         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
397
398         memcpy(h, hgood, hsize);
399         ((uint8_t *)bdb_get_oem_area_1(h))[0] ^= 0x42;
400         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
401
402         memcpy(h, hgood, hsize);
403         ((uint8_t *)bdb_get_oem_area_1(h))[p.oem_area_1_size - 1] ^= 0x24;
404         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
405
406         memcpy(h, hgood, hsize);
407         ((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_SP_RW))->offset++;
408         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
409
410         memcpy(h, hgood, hsize);
411         ((struct bdb_hash *)bdb_get_hash(h, BDB_DATA_AP_RW))->digest[0] ^= 0x96;
412         TEST_EQ_S(bdb_verify(h, hsize, bdbkey_digest), BDB_ERROR_DATA_SIG);
413
414         /*
415          * This is also a convenient place to test that all the parameters we
416          * fed into bdb_create() also worked.  That also tests all the
417          * bdb_get_*() functions.
418          */
419         memcpy(h, hgood, hsize);
420         TEST_EQ_S(h->bdb_load_address, p.bdb_load_address);
421
422         TEST_EQ_S(strcmp(bdb_get_bdbkey(h)->description, p.bdbkey->description),
423                   0);
424         TEST_EQ_S(bdb_get_bdbkey(h)->key_version, p.bdbkey->key_version);
425
426         TEST_EQ_S(h->oem_area_0_size, p.oem_area_0_size);
427         TEST_EQ_S(memcmp(bdb_get_oem_area_0(h), oem_area_0, sizeof(oem_area_0)),
428                 0);
429
430         TEST_EQ_S(strcmp(bdb_get_subkey(h)->description, p.subkey->description),
431                 0);
432         TEST_EQ_S(bdb_get_subkey(h)->key_version, p.subkey->key_version);
433
434         TEST_EQ_S(strcmp(bdb_get_header_sig(h)->description,
435                        p.header_sig_description), 0);
436
437         TEST_EQ_S(strcmp(bdb_get_data(h)->description, p.data_description), 0);
438         TEST_EQ_S(bdb_get_data(h)->data_version, p.data_version);
439         TEST_EQ_S(bdb_get_data(h)->num_hashes, p.num_hashes);
440
441         TEST_EQ_S(bdb_get_data(h)->oem_area_1_size, p.oem_area_1_size);
442         TEST_EQ_S(memcmp(bdb_get_oem_area_1(h), oem_area_1, sizeof(oem_area_1)),
443                 0);
444
445         TEST_EQ_S(strcmp(bdb_get_data_sig(h)->description,
446                        p.data_sig_description), 0);
447
448         /* Test getting hash entries */
449         memcpy(h, hgood, hsize);
450         TEST_EQ_S(bdb_get_hash(h, BDB_DATA_SP_RW)->offset, hash[0].offset);
451         TEST_EQ_S(bdb_get_hash(h, BDB_DATA_AP_RW)->offset, hash[1].offset);
452         /* And a non-existent one */
453         TEST_EQ_S(bdb_get_hash(h, BDB_DATA_MCU)!=NULL, 0);
454
455         /*
456          * TODO: Verify wraparound checks works.  That can only be tested on a
457          * platform where size_t is uint32_t, because otherwise a 32-bit
458          * oem_area_1_size can't cause wraparound.
459          */
460
461         /* Free keys and buffers */
462         free(p.bdbkey);
463         free(p.subkey);
464         RSA_free(p.private_bdbkey);
465         RSA_free(p.private_subkey);
466         free(hgood);
467         free(h);
468 }
469
470 /*****************************************************************************/
471
472 int main(int argc, char *argv[])
473 {
474         if (argc != 2) {
475                 fprintf(stderr, "Usage: %s <keys_dir>", argv[0]);
476                 return -1;
477         }
478         printf("Running BDB tests...\n");
479
480         check_header_tests();
481         check_key_tests();
482         check_sig_tests();
483         check_data_tests();
484         check_bdb_verify(argv[1]);
485
486         printf("All tests passed!\n");
487
488         return gTestSuccess ? 0 : 255;
489 }