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