1 // The functions here are derrived from BearSSL/tools/*.c
2 // When that is refactored suitably we can use them directly.
3 /*
4 * Copyright (c) 2016 Thomas Pornin <[email protected]>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 * SOFTWARE.
25 */
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28
29 #define NEED_BRSSL_H
30 #include "libsecureboot-priv.h"
31 #include <brssl.h>
32
33
34 static int
is_ign(int c)35 is_ign(int c)
36 {
37 if (c == 0) {
38 return (0);
39 }
40 if (c <= 32 || c == '-' || c == '_' || c == '.'
41 || c == '/' || c == '+' || c == ':')
42 {
43 return (1);
44 }
45 return (0);
46 }
47
48 /*
49 * Get next non-ignored character, normalised:
50 * ASCII letters are converted to lowercase
51 * control characters, space, '-', '_', '.', '/', '+' and ':' are ignored
52 * A terminating zero is returned as 0.
53 */
54 static int
next_char(const char ** ps,const char * limit)55 next_char(const char **ps, const char *limit)
56 {
57 for (;;) {
58 int c;
59
60 if (*ps == limit) {
61 return (0);
62 }
63 c = *(*ps) ++;
64 if (c == 0) {
65 return (0);
66 }
67 if (c >= 'A' && c <= 'Z') {
68 c += 'a' - 'A';
69 }
70 if (!is_ign(c)) {
71 return (c);
72 }
73 }
74 }
75
76 /*
77 * Partial string equality comparison, with normalisation.
78 */
79 static int
eqstr_chunk(const char * s1,size_t s1_len,const char * s2,size_t s2_len)80 eqstr_chunk(const char *s1, size_t s1_len, const char *s2, size_t s2_len)
81 {
82 const char *lim1, *lim2;
83
84 lim1 = s1 + s1_len;
85 lim2 = s2 + s2_len;
86 for (;;) {
87 int c1, c2;
88
89 c1 = next_char(&s1, lim1);
90 c2 = next_char(&s2, lim2);
91 if (c1 != c2) {
92 return (0);
93 }
94 if (c1 == 0) {
95 return (1);
96 }
97 }
98 }
99
100 /* see brssl.h */
101 int
eqstr(const char * s1,const char * s2)102 eqstr(const char *s1, const char *s2)
103 {
104 return (eqstr_chunk(s1, strlen(s1), s2, strlen(s2)));
105 }
106
107 int
looks_like_DER(const unsigned char * buf,size_t len)108 looks_like_DER(const unsigned char *buf, size_t len)
109 {
110 int fb;
111 size_t dlen;
112
113 if (len < 2) {
114 return (0);
115 }
116 if (*buf ++ != 0x30) {
117 return (0);
118 }
119 fb = *buf ++;
120 len -= 2;
121 if (fb < 0x80) {
122 return ((size_t)fb == len);
123 } else if (fb == 0x80) {
124 return (0);
125 } else {
126 fb -= 0x80;
127 if (len < (size_t)fb + 2) {
128 return (0);
129 }
130 len -= (size_t)fb;
131 dlen = 0;
132 while (fb -- > 0) {
133 if (dlen > (len >> 8)) {
134 return (0);
135 }
136 dlen = (dlen << 8) + (size_t)*buf ++;
137 }
138 return (dlen == len);
139 }
140 }
141
142 static void
vblob_append(void * cc,const void * data,size_t len)143 vblob_append(void *cc, const void *data, size_t len)
144 {
145 bvector *bv;
146
147 bv = cc;
148 VEC_ADDMANY(*bv, data, len);
149 }
150
151 void
free_pem_object_contents(pem_object * po)152 free_pem_object_contents(pem_object *po)
153 {
154 if (po != NULL) {
155 xfree(po->name);
156 xfree(po->data);
157 }
158 }
159
160 pem_object *
decode_pem(const void * src,size_t len,size_t * num)161 decode_pem(const void *src, size_t len, size_t *num)
162 {
163 VECTOR(pem_object) pem_list = VEC_INIT;
164 br_pem_decoder_context pc;
165 pem_object po, *pos;
166 const unsigned char *buf;
167 bvector bv = VEC_INIT;
168 int inobj;
169 int extra_nl;
170
171 *num = 0;
172 br_pem_decoder_init(&pc);
173 buf = src;
174 inobj = 0;
175 po.name = NULL;
176 po.data = NULL;
177 po.data_len = 0;
178 extra_nl = 1;
179 while (len > 0) {
180 size_t tlen;
181
182 tlen = br_pem_decoder_push(&pc, buf, len);
183 buf += tlen;
184 len -= tlen;
185 switch (br_pem_decoder_event(&pc)) {
186
187 case BR_PEM_BEGIN_OBJ:
188 po.name = xstrdup(br_pem_decoder_name(&pc));
189 br_pem_decoder_setdest(&pc, vblob_append, &bv);
190 inobj = 1;
191 break;
192
193 case BR_PEM_END_OBJ:
194 if (inobj) {
195 po.data = VEC_TOARRAY(bv);
196 po.data_len = VEC_LEN(bv);
197 VEC_ADD(pem_list, po);
198 VEC_CLEAR(bv);
199 po.name = NULL;
200 po.data = NULL;
201 po.data_len = 0;
202 inobj = 0;
203 }
204 break;
205
206 case BR_PEM_ERROR:
207 xfree(po.name);
208 VEC_CLEAR(bv);
209 ve_error_set("ERROR: invalid PEM encoding");
210 VEC_CLEAREXT(pem_list, &free_pem_object_contents);
211 return (NULL);
212 }
213
214 /*
215 * We add an extra newline at the end, in order to
216 * support PEM files that lack the newline on their last
217 * line (this is somwehat invalid, but PEM format is not
218 * standardised and such files do exist in the wild, so
219 * we'd better accept them).
220 */
221 if (len == 0 && extra_nl) {
222 extra_nl = 0;
223 buf = (const unsigned char *)"\n";
224 len = 1;
225 }
226 }
227 if (inobj) {
228 ve_error_set("ERROR: unfinished PEM object");
229 xfree(po.name);
230 VEC_CLEAR(bv);
231 VEC_CLEAREXT(pem_list, &free_pem_object_contents);
232 return (NULL);
233 }
234
235 *num = VEC_LEN(pem_list);
236 VEC_ADD(pem_list, po);
237 pos = VEC_TOARRAY(pem_list);
238 VEC_CLEAR(pem_list);
239 return (pos);
240 }
241
242 br_x509_certificate *
parse_certificates(unsigned char * buf,size_t len,size_t * num)243 parse_certificates(unsigned char *buf, size_t len, size_t *num)
244 {
245 VECTOR(br_x509_certificate) cert_list = VEC_INIT;
246 pem_object *pos;
247 size_t u, num_pos;
248 br_x509_certificate *xcs;
249 br_x509_certificate dummy;
250
251 *num = 0;
252
253 /*
254 * Check for a DER-encoded certificate.
255 */
256 if (looks_like_DER(buf, len)) {
257 xcs = xmalloc(2 * sizeof *xcs);
258 xcs[0].data = buf;
259 xcs[0].data_len = len;
260 xcs[1].data = NULL;
261 xcs[1].data_len = 0;
262 *num = 1;
263 return (xcs);
264 }
265
266 pos = decode_pem(buf, len, &num_pos);
267 if (pos == NULL) {
268 return (NULL);
269 }
270 for (u = 0; u < num_pos; u ++) {
271 if (eqstr(pos[u].name, "CERTIFICATE")
272 || eqstr(pos[u].name, "X509 CERTIFICATE"))
273 {
274 br_x509_certificate xc;
275
276 xc.data = pos[u].data;
277 xc.data_len = pos[u].data_len;
278 pos[u].data = NULL;
279 VEC_ADD(cert_list, xc);
280 }
281 }
282 for (u = 0; u < num_pos; u ++) {
283 free_pem_object_contents(&pos[u]);
284 }
285 xfree(pos);
286
287 if (VEC_LEN(cert_list) == 0) {
288 return (NULL);
289 }
290 *num = VEC_LEN(cert_list);
291 dummy.data = NULL;
292 dummy.data_len = 0;
293 VEC_ADD(cert_list, dummy);
294 xcs = VEC_TOARRAY(cert_list);
295 VEC_CLEAR(cert_list);
296 return (xcs);
297 }
298
299 br_x509_certificate *
read_certificates(const char * fname,size_t * num)300 read_certificates(const char *fname, size_t *num)
301 {
302 br_x509_certificate *xcs;
303 unsigned char *buf;
304 size_t len;
305
306 *num = 0;
307
308 /*
309 * TODO: reading the whole file is crude; we could parse them
310 * in a streamed fashion. But it does not matter much in practice.
311 */
312 buf = read_file(fname, &len);
313 if (buf == NULL) {
314 return (NULL);
315 }
316 xcs = parse_certificates(buf, len, num);
317 if (xcs == NULL) {
318 ve_error_set("ERROR: no certificate in file '%s'\n", fname);
319 }
320 xfree(buf);
321 return (xcs);
322 }
323
324 /* see brssl.h */
325 void
free_certificates(br_x509_certificate * certs,size_t num)326 free_certificates(br_x509_certificate *certs, size_t num)
327 {
328 size_t u;
329
330 for (u = 0; u < num; u ++) {
331 xfree(certs[u].data);
332 }
333 xfree(certs);
334 }
335
336
337 static void
dn_append(void * ctx,const void * buf,size_t len)338 dn_append(void *ctx, const void *buf, size_t len)
339 {
340 VEC_ADDMANY(*(bvector *)ctx, buf, len);
341 }
342
343 int
certificate_to_trust_anchor_inner(br_x509_trust_anchor * ta,br_x509_certificate * xc)344 certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
345 br_x509_certificate *xc)
346 {
347 br_x509_decoder_context dc;
348 bvector vdn = VEC_INIT;
349 br_x509_pkey *pk;
350
351 br_x509_decoder_init(&dc, dn_append, &vdn);
352 br_x509_decoder_push(&dc, xc->data, xc->data_len);
353 pk = br_x509_decoder_get_pkey(&dc);
354 if (pk == NULL) {
355 ve_error_set("ERROR: CA decoding failed with error %d\n",
356 br_x509_decoder_last_error(&dc));
357 VEC_CLEAR(vdn);
358 return (-1);
359 }
360 ta->dn.data = VEC_TOARRAY(vdn);
361 ta->dn.len = VEC_LEN(vdn);
362 VEC_CLEAR(vdn);
363 ta->flags = 0;
364 if (br_x509_decoder_isCA(&dc)) {
365 ta->flags |= BR_X509_TA_CA;
366 }
367 switch (pk->key_type) {
368 case BR_KEYTYPE_RSA:
369 ta->pkey.key_type = BR_KEYTYPE_RSA;
370 ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
371 ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
372 ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
373 ta->pkey.key.rsa.elen = pk->key.rsa.elen;
374 break;
375 case BR_KEYTYPE_EC:
376 ta->pkey.key_type = BR_KEYTYPE_EC;
377 ta->pkey.key.ec.curve = pk->key.ec.curve;
378 ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
379 ta->pkey.key.ec.qlen = pk->key.ec.qlen;
380 break;
381 default:
382 ve_error_set("ERROR: unsupported public key type in CA\n");
383 xfree(ta->dn.data);
384 return (-1);
385 }
386 return (0);
387 }
388
389 /* see brssl.h */
390 void
free_ta_contents(br_x509_trust_anchor * ta)391 free_ta_contents(br_x509_trust_anchor *ta)
392 {
393 xfree(ta->dn.data);
394 switch (ta->pkey.key_type) {
395 case BR_KEYTYPE_RSA:
396 xfree(ta->pkey.key.rsa.n);
397 xfree(ta->pkey.key.rsa.e);
398 break;
399 case BR_KEYTYPE_EC:
400 xfree(ta->pkey.key.ec.q);
401 break;
402 }
403 }
404