xref: /freebsd/lib/libsecureboot/brf.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
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