bdb: Replace sha functions with vb2 library
[vboot.git] / firmware / bdb / bdb.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  * Boot descriptor block firmware functions
6  */
7
8 #include <string.h>
9 #include "2sha.h"
10 #include "bdb.h"
11
12 /*****************************************************************************/
13
14 /**
15  * Check if string contains a null terminator.
16  *
17  * Bytes after the null terminator do not need to be null.
18  *
19  * @param s             String to check
20  * @param size          Size of string buffer in characters
21  * @return 1 if string has a null terminator, 0 if not
22  */
23 int string_has_null(const char *s, size_t size)
24 {
25         for (; size; size--) {
26                 if (*s++ == 0)
27                         return 1;
28         }
29         return 0;
30 }
31
32 int bdb_check_header(const struct bdb_header *p, size_t size)
33 {
34         if (size < sizeof(*p) || size < p->struct_size)
35                 return BDB_ERROR_BUF_SIZE;
36
37         if (p->struct_magic != BDB_HEADER_MAGIC)
38                 return BDB_ERROR_STRUCT_MAGIC;
39
40         if (p->struct_major_version != BDB_HEADER_VERSION_MAJOR)
41                 return BDB_ERROR_STRUCT_VERSION;
42
43         /* Note that minor version doesn't matter yet */
44
45         if (p->struct_size < sizeof(*p))
46                 return BDB_ERROR_STRUCT_SIZE;
47
48         if (p->oem_area_0_size & 3)
49                 return BDB_ERROR_OEM_AREA_SIZE;  /* Not 32-bit aligned */
50
51         /*
52          * Make sure the BDB is at least big enough for us.  At this point, all
53          * the caller may have loaded is this header We'll check if there's
54          * space for everything else after we load it.
55          */
56         if (p->bdb_size < sizeof(*p))
57                 return BDB_ERROR_BDB_SIZE;
58
59         /*
60          * The rest of the fields don't matter yet; we'll check them when we
61          * check the BDB itself.
62          */
63         return BDB_SUCCESS;
64 }
65
66 int bdb_check_key(const struct bdb_key *p, size_t size)
67 {
68         size_t expect_key_size = 0;
69
70         if (size < sizeof(*p) || size < p->struct_size)
71                 return BDB_ERROR_BUF_SIZE;
72
73         if (p->struct_magic != BDB_KEY_MAGIC)
74                 return BDB_ERROR_STRUCT_MAGIC;
75
76         if (p->struct_major_version != BDB_KEY_VERSION_MAJOR)
77                 return BDB_ERROR_STRUCT_VERSION;
78
79         /* Note that minor version doesn't matter yet */
80
81         if (!string_has_null(p->description, sizeof(p->description)))
82                 return BDB_ERROR_DESCRIPTION;
83
84         /* We currently only support SHA-256 */
85         if (p->hash_alg != BDB_HASH_ALG_SHA256)
86                 return BDB_ERROR_HASH_ALG;
87
88         /* Make sure signature algorithm and size are correct */
89         switch (p->sig_alg) {
90         case BDB_SIG_ALG_RSA4096:
91                 expect_key_size = BDB_RSA4096_KEY_DATA_SIZE;
92                 break;
93         case BDB_SIG_ALG_ECSDSA521:
94                 expect_key_size = BDB_ECDSA521_KEY_DATA_SIZE;
95                 break;
96         case BDB_SIG_ALG_RSA3072B:
97                 expect_key_size = BDB_RSA3072B_KEY_DATA_SIZE;
98                 break;
99         default:
100                 return BDB_ERROR_SIG_ALG;
101         }
102
103         if (p->struct_size < sizeof(*p) + expect_key_size)
104                 return BDB_ERROR_STRUCT_SIZE;
105
106         return BDB_SUCCESS;
107 }
108
109 int bdb_check_sig(const struct bdb_sig *p, size_t size)
110 {
111         size_t expect_sig_size = 0;
112
113         if (size < sizeof(*p) || size < p->struct_size)
114                 return BDB_ERROR_BUF_SIZE;
115
116         if (p->struct_magic != BDB_SIG_MAGIC)
117                 return BDB_ERROR_STRUCT_MAGIC;
118
119         if (p->struct_major_version != BDB_SIG_VERSION_MAJOR)
120                 return BDB_ERROR_STRUCT_VERSION;
121
122         /* Note that minor version doesn't matter yet */
123
124         if (!string_has_null(p->description, sizeof(p->description)))
125                 return BDB_ERROR_DESCRIPTION;
126
127         /* We currently only support SHA-256 */
128         if (p->hash_alg != BDB_HASH_ALG_SHA256)
129                 return BDB_ERROR_HASH_ALG;
130
131         /* Make sure signature algorithm and size are correct */
132         switch (p->sig_alg) {
133         case BDB_SIG_ALG_RSA4096:
134                 expect_sig_size = BDB_RSA4096_SIG_SIZE;
135                 break;
136         case BDB_SIG_ALG_ECSDSA521:
137                 expect_sig_size = BDB_ECDSA521_SIG_SIZE;
138                 break;
139         case BDB_SIG_ALG_RSA3072B:
140                 expect_sig_size = BDB_RSA3072B_SIG_SIZE;
141                 break;
142         default:
143                 return BDB_ERROR_SIG_ALG;
144         }
145
146         if (p->struct_size < sizeof(*p) + expect_sig_size)
147                 return BDB_ERROR_STRUCT_SIZE;
148
149         return BDB_SUCCESS;
150 }
151
152 int bdb_check_data(const struct bdb_data *p, size_t size)
153 {
154         size_t need_size;
155
156         if (size < sizeof(*p) || size < p->signed_size)
157                 return BDB_ERROR_BUF_SIZE;
158
159         if (p->struct_magic != BDB_DATA_MAGIC)
160                 return BDB_ERROR_STRUCT_MAGIC;
161
162         if (p->struct_major_version != BDB_DATA_VERSION_MAJOR)
163                 return BDB_ERROR_STRUCT_VERSION;
164
165         /* Note that minor version doesn't matter yet */
166
167         if (!string_has_null(p->description, sizeof(p->description)))
168                 return BDB_ERROR_DESCRIPTION;
169
170         if (p->struct_size < sizeof(*p))
171                 return BDB_ERROR_STRUCT_SIZE;
172
173         if (p->hash_entry_size < sizeof(struct bdb_hash))
174                 return BDB_ERROR_HASH_ENTRY_SIZE;
175
176         /* Calculate expected size */
177         need_size = p->struct_size + p->num_hashes * p->hash_entry_size;
178
179         /* Make sure OEM area size doesn't cause wraparound */
180         if (need_size + p->oem_area_1_size < need_size)
181                 return BDB_ERROR_OEM_AREA_SIZE;
182         if (p->oem_area_1_size & 3)
183                 return BDB_ERROR_OEM_AREA_SIZE;  /* Not 32-bit aligned */
184         need_size += p->oem_area_1_size;
185
186         if (p->signed_size < need_size)
187                 return BDB_ERROR_SIGNED_SIZE;
188
189         return BDB_SUCCESS;
190 }
191
192 /*****************************************************************************/
193
194 const struct bdb_header *bdb_get_header(const void *buf)
195 {
196         return buf;
197 }
198
199 const struct bdb_key *bdb_get_bdbkey(const void *buf)
200 {
201         const struct bdb_header *h = bdb_get_header(buf);
202         const uint8_t *b8 = buf;
203
204         /* BDB key follows header */
205         return (const struct bdb_key *)(b8 + h->struct_size);
206 }
207
208 const void *bdb_get_oem_area_0(const void *buf)
209 {
210         const struct bdb_key *k = bdb_get_bdbkey(buf);
211         const uint8_t *b8 = (const uint8_t *)k;
212
213         /* OEM area 0 follows BDB key */
214         return b8 + k->struct_size;
215 }
216
217 const struct bdb_key *bdb_get_subkey(const void *buf)
218 {
219         const struct bdb_header *h = bdb_get_header(buf);
220         const uint8_t *b8 = bdb_get_oem_area_0(buf);
221
222         /* Subkey follows OEM area 0 */
223         return (const struct bdb_key *)(b8 + h->oem_area_0_size);
224 }
225
226 const struct bdb_sig *bdb_get_header_sig(const void *buf)
227 {
228         const struct bdb_header *h = bdb_get_header(buf);
229         const uint8_t *b8 = bdb_get_oem_area_0(buf);
230
231         /* Header signature starts after signed data */
232         return (const struct bdb_sig *)(b8 + h->signed_size);
233 }
234
235 const struct bdb_data *bdb_get_data(const void *buf)
236 {
237         const struct bdb_sig *s = bdb_get_header_sig(buf);
238         const uint8_t *b8 = (const uint8_t *)s;
239
240         /* Data follows header signature */
241         return (const struct bdb_data *)(b8 + s->struct_size);
242 }
243
244 const void *bdb_get_oem_area_1(const void *buf)
245 {
246         const struct bdb_data *p = bdb_get_data(buf);
247         const uint8_t *b8 = (const uint8_t *)p;
248
249         /* OEM area 1 follows BDB data */
250         return b8 + p->struct_size;
251 }
252
253 const struct bdb_hash *bdb_get_hash(const void *buf, enum bdb_data_type type)
254 {
255         const struct bdb_data *data = bdb_get_data(buf);
256         const uint8_t *b8 = bdb_get_oem_area_1(buf);
257         int i;
258
259         /* Hashes follow OEM area 0 */
260         b8 += data->oem_area_1_size;
261
262         /* Search for a matching hash */
263         for (i = 0; i < data->num_hashes; i++, b8 += data->hash_entry_size) {
264                 const struct bdb_hash *h = (const struct bdb_hash *)b8;
265
266                 if (h->type == type)
267                         return h;
268         }
269
270         return NULL;
271 }
272
273 const struct bdb_sig *bdb_get_data_sig(const void *buf)
274 {
275         const struct bdb_data *data = bdb_get_data(buf);
276         const uint8_t *b8 = (const uint8_t *)data;
277
278         /* Data signature starts after signed data */
279         return (const struct bdb_sig *)(b8 + data->signed_size);
280 }
281
282 /*****************************************************************************/
283
284 int bdb_verify_sig(const struct bdb_key *key,
285                    const struct bdb_sig *sig,
286                    const uint8_t *digest)
287 {
288         /* Key and signature algorithms must match */
289         if (key->sig_alg != sig->sig_alg)
290                 return BDB_ERROR_SIG_ALG;
291
292         switch (key->sig_alg) {
293         case BDB_SIG_ALG_RSA4096:
294                 if (bdb_rsa4096_verify(key->key_data, sig->sig_data, digest))
295                         return BDB_ERROR_VERIFY_SIG;
296                 break;
297         case BDB_SIG_ALG_ECSDSA521:
298                 if (bdb_ecdsa521_verify(key->key_data, sig->sig_data, digest))
299                         return BDB_ERROR_VERIFY_SIG;
300                 break;
301         case BDB_SIG_ALG_RSA3072B:
302                 if (bdb_rsa3072b_verify(key->key_data, sig->sig_data, digest))
303                         return BDB_ERROR_VERIFY_SIG;
304                 break;
305         default:
306                 return BDB_ERROR_VERIFY_SIG;
307         }
308
309         return BDB_SUCCESS;
310 }
311
312 int bdb_verify(const void *buf, size_t size, const uint8_t *bdb_key_digest)
313 {
314         const uint8_t *end = (const uint8_t *)buf + size;
315         const struct bdb_header *h;
316         const struct bdb_key *bdbkey, *subkey;
317         const struct bdb_sig *sig;
318         const struct bdb_data *data;
319         const void *oem;
320         uint8_t digest[BDB_SHA256_DIGEST_SIZE];
321         int bdb_digest_mismatch;
322
323         /* Make sure buffer doesn't wrap around address space */
324         if (end < (const uint8_t *)buf)
325                 return BDB_ERROR_BUF_SIZE;
326
327         /*
328          * Check header now that we've actually loaded it.  We can't guarantee
329          * this is the same header which was checked before.
330          */
331         h = bdb_get_header(buf);
332         if (bdb_check_header(h, size))
333                 return BDB_ERROR_HEADER;
334
335         /* Sanity-check BDB key */
336         bdbkey = bdb_get_bdbkey(buf);
337         if (bdb_check_key(bdbkey, end - (const uint8_t *)bdbkey))
338                 return BDB_ERROR_BDBKEY;
339
340         /* Calculate BDB key digest and compare with expected */
341         if (vb2_digest_buffer((uint8_t *)bdbkey, bdbkey->struct_size,
342                               VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
343                 return BDB_ERROR_DIGEST;
344
345         bdb_digest_mismatch = memcmp(digest, bdb_key_digest, sizeof(digest));
346
347         /* Make sure OEM area 0 fits */
348         oem = bdb_get_oem_area_0(buf);
349         if (h->oem_area_0_size > end - (const uint8_t *)oem)
350                 return BDB_ERROR_OEM_AREA_0;
351
352         /* Sanity-check subkey */
353         subkey = bdb_get_subkey(buf);
354         if (bdb_check_key(subkey, end - (const uint8_t *)subkey))
355                 return BDB_ERROR_SUBKEY;
356
357         /* Make sure enough data was signed, and the signed data fits */
358         if (h->oem_area_0_size + subkey->struct_size > h->signed_size ||
359             h->signed_size > end - (const uint8_t *)oem)
360                 return BDB_ERROR_BDB_SIGNED_SIZE;
361
362         /* Sanity-check header signature */
363         sig = bdb_get_header_sig(buf);
364         if (bdb_check_sig(sig, end - (const uint8_t *)sig))
365                 return BDB_ERROR_HEADER_SIG;
366
367         /* Make sure it signed the right amount of data */
368         if (sig->signed_size != h->signed_size)
369                 return BDB_ERROR_HEADER_SIG;
370
371         /* Calculate header digest and compare with expected signature */
372         if (vb2_digest_buffer((uint8_t *)oem, h->signed_size,
373                               VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
374                 return BDB_ERROR_DIGEST;
375         if (bdb_verify_sig(bdbkey, sig, digest))
376                 return BDB_ERROR_HEADER_SIG;
377
378         /*
379          * Sanity-check data struct.  This also checks that OEM area 1 and the
380          * hashes fit in the remaining buffer.
381          */
382         data = bdb_get_data(buf);
383         if (bdb_check_data(data, end - (const uint8_t *)data))
384                 return BDB_ERROR_DATA;
385
386         /* Sanity-check data signature */
387         sig = bdb_get_data_sig(buf);
388         if (bdb_check_sig(sig, end - (const uint8_t *)sig))
389                 return BDB_ERROR_DATA_SIG;
390         if (sig->signed_size != data->signed_size)
391                 return BDB_ERROR_DATA_SIG;
392
393         /* Calculate data digest and compare with expected signature */
394         if (vb2_digest_buffer((uint8_t *)data, data->signed_size,
395                               VB2_HASH_SHA256, digest, BDB_SHA256_DIGEST_SIZE))
396                 return BDB_ERROR_DIGEST;
397         if (bdb_verify_sig(subkey, sig, digest))
398                 return BDB_ERROR_DATA_SIG;
399
400         /* Return success or success-other-than-BDB-key-mismatch */
401         return bdb_digest_mismatch ? BDB_GOOD_OTHER_THAN_KEY : BDB_SUCCESS;
402 }