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