xref: /freebsd-src/contrib/bearssl/tools/certs.c (revision 2aaf9152a852aba9eb2036b95f4948ee77988826)
1*0957b409SSimon J. Gerraty /*
2*0957b409SSimon J. Gerraty  * Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
3*0957b409SSimon J. Gerraty  *
4*0957b409SSimon J. Gerraty  * Permission is hereby granted, free of charge, to any person obtaining
5*0957b409SSimon J. Gerraty  * a copy of this software and associated documentation files (the
6*0957b409SSimon J. Gerraty  * "Software"), to deal in the Software without restriction, including
7*0957b409SSimon J. Gerraty  * without limitation the rights to use, copy, modify, merge, publish,
8*0957b409SSimon J. Gerraty  * distribute, sublicense, and/or sell copies of the Software, and to
9*0957b409SSimon J. Gerraty  * permit persons to whom the Software is furnished to do so, subject to
10*0957b409SSimon J. Gerraty  * the following conditions:
11*0957b409SSimon J. Gerraty  *
12*0957b409SSimon J. Gerraty  * The above copyright notice and this permission notice shall be
13*0957b409SSimon J. Gerraty  * included in all copies or substantial portions of the Software.
14*0957b409SSimon J. Gerraty  *
15*0957b409SSimon J. Gerraty  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*0957b409SSimon J. Gerraty  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*0957b409SSimon J. Gerraty  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*0957b409SSimon J. Gerraty  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*0957b409SSimon J. Gerraty  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*0957b409SSimon J. Gerraty  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*0957b409SSimon J. Gerraty  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*0957b409SSimon J. Gerraty  * SOFTWARE.
23*0957b409SSimon J. Gerraty  */
24*0957b409SSimon J. Gerraty 
25*0957b409SSimon J. Gerraty #include <stdio.h>
26*0957b409SSimon J. Gerraty #include <stdlib.h>
27*0957b409SSimon J. Gerraty #include <string.h>
28*0957b409SSimon J. Gerraty #include <stdint.h>
29*0957b409SSimon J. Gerraty #include <errno.h>
30*0957b409SSimon J. Gerraty 
31*0957b409SSimon J. Gerraty #include "brssl.h"
32*0957b409SSimon J. Gerraty 
33*0957b409SSimon J. Gerraty static void
dn_append(void * ctx,const void * buf,size_t len)34*0957b409SSimon J. Gerraty dn_append(void *ctx, const void *buf, size_t len)
35*0957b409SSimon J. Gerraty {
36*0957b409SSimon J. Gerraty 	VEC_ADDMANY(*(bvector *)ctx, buf, len);
37*0957b409SSimon J. Gerraty }
38*0957b409SSimon J. Gerraty 
39*0957b409SSimon J. Gerraty static int
certificate_to_trust_anchor_inner(br_x509_trust_anchor * ta,br_x509_certificate * xc)40*0957b409SSimon J. Gerraty certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta,
41*0957b409SSimon J. Gerraty 	br_x509_certificate *xc)
42*0957b409SSimon J. Gerraty {
43*0957b409SSimon J. Gerraty 	br_x509_decoder_context dc;
44*0957b409SSimon J. Gerraty 	bvector vdn = VEC_INIT;
45*0957b409SSimon J. Gerraty 	br_x509_pkey *pk;
46*0957b409SSimon J. Gerraty 
47*0957b409SSimon J. Gerraty 	br_x509_decoder_init(&dc, dn_append, &vdn);
48*0957b409SSimon J. Gerraty 	br_x509_decoder_push(&dc, xc->data, xc->data_len);
49*0957b409SSimon J. Gerraty 	pk = br_x509_decoder_get_pkey(&dc);
50*0957b409SSimon J. Gerraty 	if (pk == NULL) {
51*0957b409SSimon J. Gerraty 		fprintf(stderr, "ERROR: CA decoding failed with error %d\n",
52*0957b409SSimon J. Gerraty 			br_x509_decoder_last_error(&dc));
53*0957b409SSimon J. Gerraty 		VEC_CLEAR(vdn);
54*0957b409SSimon J. Gerraty 		return -1;
55*0957b409SSimon J. Gerraty 	}
56*0957b409SSimon J. Gerraty 	ta->dn.data = VEC_TOARRAY(vdn);
57*0957b409SSimon J. Gerraty 	ta->dn.len = VEC_LEN(vdn);
58*0957b409SSimon J. Gerraty 	VEC_CLEAR(vdn);
59*0957b409SSimon J. Gerraty 	ta->flags = 0;
60*0957b409SSimon J. Gerraty 	if (br_x509_decoder_isCA(&dc)) {
61*0957b409SSimon J. Gerraty 		ta->flags |= BR_X509_TA_CA;
62*0957b409SSimon J. Gerraty 	}
63*0957b409SSimon J. Gerraty 	switch (pk->key_type) {
64*0957b409SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
65*0957b409SSimon J. Gerraty 		ta->pkey.key_type = BR_KEYTYPE_RSA;
66*0957b409SSimon J. Gerraty 		ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
67*0957b409SSimon J. Gerraty 		ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
68*0957b409SSimon J. Gerraty 		ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
69*0957b409SSimon J. Gerraty 		ta->pkey.key.rsa.elen = pk->key.rsa.elen;
70*0957b409SSimon J. Gerraty 		break;
71*0957b409SSimon J. Gerraty 	case BR_KEYTYPE_EC:
72*0957b409SSimon J. Gerraty 		ta->pkey.key_type = BR_KEYTYPE_EC;
73*0957b409SSimon J. Gerraty 		ta->pkey.key.ec.curve = pk->key.ec.curve;
74*0957b409SSimon J. Gerraty 		ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
75*0957b409SSimon J. Gerraty 		ta->pkey.key.ec.qlen = pk->key.ec.qlen;
76*0957b409SSimon J. Gerraty 		break;
77*0957b409SSimon J. Gerraty 	default:
78*0957b409SSimon J. Gerraty 		fprintf(stderr, "ERROR: unsupported public key type in CA\n");
79*0957b409SSimon J. Gerraty 		xfree(ta->dn.data);
80*0957b409SSimon J. Gerraty 		return -1;
81*0957b409SSimon J. Gerraty 	}
82*0957b409SSimon J. Gerraty 	return 0;
83*0957b409SSimon J. Gerraty }
84*0957b409SSimon J. Gerraty 
85*0957b409SSimon J. Gerraty /* see brssl.h */
86*0957b409SSimon J. Gerraty br_x509_trust_anchor *
certificate_to_trust_anchor(br_x509_certificate * xc)87*0957b409SSimon J. Gerraty certificate_to_trust_anchor(br_x509_certificate *xc)
88*0957b409SSimon J. Gerraty {
89*0957b409SSimon J. Gerraty 	br_x509_trust_anchor ta;
90*0957b409SSimon J. Gerraty 
91*0957b409SSimon J. Gerraty 	if (certificate_to_trust_anchor_inner(&ta, xc) < 0) {
92*0957b409SSimon J. Gerraty 		return NULL;
93*0957b409SSimon J. Gerraty 	} else {
94*0957b409SSimon J. Gerraty 		return xblobdup(&ta, sizeof ta);
95*0957b409SSimon J. Gerraty 	}
96*0957b409SSimon J. Gerraty }
97*0957b409SSimon J. Gerraty 
98*0957b409SSimon J. Gerraty /* see brssl.h */
99*0957b409SSimon J. Gerraty void
free_ta_contents(br_x509_trust_anchor * ta)100*0957b409SSimon J. Gerraty free_ta_contents(br_x509_trust_anchor *ta)
101*0957b409SSimon J. Gerraty {
102*0957b409SSimon J. Gerraty 	xfree(ta->dn.data);
103*0957b409SSimon J. Gerraty 	switch (ta->pkey.key_type) {
104*0957b409SSimon J. Gerraty 	case BR_KEYTYPE_RSA:
105*0957b409SSimon J. Gerraty 		xfree(ta->pkey.key.rsa.n);
106*0957b409SSimon J. Gerraty 		xfree(ta->pkey.key.rsa.e);
107*0957b409SSimon J. Gerraty 		break;
108*0957b409SSimon J. Gerraty 	case BR_KEYTYPE_EC:
109*0957b409SSimon J. Gerraty 		xfree(ta->pkey.key.ec.q);
110*0957b409SSimon J. Gerraty 		break;
111*0957b409SSimon J. Gerraty 	}
112*0957b409SSimon J. Gerraty }
113*0957b409SSimon J. Gerraty 
114*0957b409SSimon J. Gerraty /* see brssl.h */
115*0957b409SSimon J. Gerraty size_t
read_trust_anchors(anchor_list * dst,const char * fname)116*0957b409SSimon J. Gerraty read_trust_anchors(anchor_list *dst, const char *fname)
117*0957b409SSimon J. Gerraty {
118*0957b409SSimon J. Gerraty 	br_x509_certificate *xcs;
119*0957b409SSimon J. Gerraty 	anchor_list tas = VEC_INIT;
120*0957b409SSimon J. Gerraty 	size_t u, num;
121*0957b409SSimon J. Gerraty 
122*0957b409SSimon J. Gerraty 	xcs = read_certificates(fname, &num);
123*0957b409SSimon J. Gerraty 	if (xcs == NULL) {
124*0957b409SSimon J. Gerraty 		return 0;
125*0957b409SSimon J. Gerraty 	}
126*0957b409SSimon J. Gerraty 	for (u = 0; u < num; u ++) {
127*0957b409SSimon J. Gerraty 		br_x509_trust_anchor ta;
128*0957b409SSimon J. Gerraty 
129*0957b409SSimon J. Gerraty 		if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) < 0) {
130*0957b409SSimon J. Gerraty 			VEC_CLEAREXT(tas, free_ta_contents);
131*0957b409SSimon J. Gerraty 			free_certificates(xcs, num);
132*0957b409SSimon J. Gerraty 			return 0;
133*0957b409SSimon J. Gerraty 		}
134*0957b409SSimon J. Gerraty 		VEC_ADD(tas, ta);
135*0957b409SSimon J. Gerraty 	}
136*0957b409SSimon J. Gerraty 	VEC_ADDMANY(*dst, &VEC_ELT(tas, 0), num);
137*0957b409SSimon J. Gerraty 	VEC_CLEAR(tas);
138*0957b409SSimon J. Gerraty 	free_certificates(xcs, num);
139*0957b409SSimon J. Gerraty 	return num;
140*0957b409SSimon J. Gerraty }
141*0957b409SSimon J. Gerraty 
142*0957b409SSimon J. Gerraty /* see brssl.h */
143*0957b409SSimon J. Gerraty int
get_cert_signer_algo(br_x509_certificate * xc)144*0957b409SSimon J. Gerraty get_cert_signer_algo(br_x509_certificate *xc)
145*0957b409SSimon J. Gerraty {
146*0957b409SSimon J. Gerraty 	br_x509_decoder_context dc;
147*0957b409SSimon J. Gerraty 	int err;
148*0957b409SSimon J. Gerraty 
149*0957b409SSimon J. Gerraty 	br_x509_decoder_init(&dc, 0, 0);
150*0957b409SSimon J. Gerraty 	br_x509_decoder_push(&dc, xc->data, xc->data_len);
151*0957b409SSimon J. Gerraty 	err = br_x509_decoder_last_error(&dc);
152*0957b409SSimon J. Gerraty 	if (err != 0) {
153*0957b409SSimon J. Gerraty 		fprintf(stderr,
154*0957b409SSimon J. Gerraty 			"ERROR: certificate decoding failed with error %d\n",
155*0957b409SSimon J. Gerraty 			-err);
156*0957b409SSimon J. Gerraty 		return 0;
157*0957b409SSimon J. Gerraty 	}
158*0957b409SSimon J. Gerraty 	return br_x509_decoder_get_signer_key_type(&dc);
159*0957b409SSimon J. Gerraty }
160*0957b409SSimon J. Gerraty 
161*0957b409SSimon J. Gerraty static void
xwc_start_chain(const br_x509_class ** ctx,const char * server_name)162*0957b409SSimon J. Gerraty xwc_start_chain(const br_x509_class **ctx, const char *server_name)
163*0957b409SSimon J. Gerraty {
164*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
165*0957b409SSimon J. Gerraty 
166*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
167*0957b409SSimon J. Gerraty 	(*xwc->inner)->start_chain(xwc->inner, server_name);
168*0957b409SSimon J. Gerraty }
169*0957b409SSimon J. Gerraty 
170*0957b409SSimon J. Gerraty static void
xwc_start_cert(const br_x509_class ** ctx,uint32_t length)171*0957b409SSimon J. Gerraty xwc_start_cert(const br_x509_class **ctx, uint32_t length)
172*0957b409SSimon J. Gerraty {
173*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
174*0957b409SSimon J. Gerraty 
175*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
176*0957b409SSimon J. Gerraty 	(*xwc->inner)->start_cert(xwc->inner, length);
177*0957b409SSimon J. Gerraty }
178*0957b409SSimon J. Gerraty 
179*0957b409SSimon J. Gerraty static void
xwc_append(const br_x509_class ** ctx,const unsigned char * buf,size_t len)180*0957b409SSimon J. Gerraty xwc_append(const br_x509_class **ctx, const unsigned char *buf, size_t len)
181*0957b409SSimon J. Gerraty {
182*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
183*0957b409SSimon J. Gerraty 
184*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
185*0957b409SSimon J. Gerraty 	(*xwc->inner)->append(xwc->inner, buf, len);
186*0957b409SSimon J. Gerraty }
187*0957b409SSimon J. Gerraty 
188*0957b409SSimon J. Gerraty static void
xwc_end_cert(const br_x509_class ** ctx)189*0957b409SSimon J. Gerraty xwc_end_cert(const br_x509_class **ctx)
190*0957b409SSimon J. Gerraty {
191*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
192*0957b409SSimon J. Gerraty 
193*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
194*0957b409SSimon J. Gerraty 	(*xwc->inner)->end_cert(xwc->inner);
195*0957b409SSimon J. Gerraty }
196*0957b409SSimon J. Gerraty 
197*0957b409SSimon J. Gerraty static unsigned
xwc_end_chain(const br_x509_class ** ctx)198*0957b409SSimon J. Gerraty xwc_end_chain(const br_x509_class **ctx)
199*0957b409SSimon J. Gerraty {
200*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
201*0957b409SSimon J. Gerraty 	unsigned r;
202*0957b409SSimon J. Gerraty 
203*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
204*0957b409SSimon J. Gerraty 	r = (*xwc->inner)->end_chain(xwc->inner);
205*0957b409SSimon J. Gerraty 	if (r == BR_ERR_X509_NOT_TRUSTED) {
206*0957b409SSimon J. Gerraty 		r = 0;
207*0957b409SSimon J. Gerraty 	}
208*0957b409SSimon J. Gerraty 	return r;
209*0957b409SSimon J. Gerraty }
210*0957b409SSimon J. Gerraty 
211*0957b409SSimon J. Gerraty static const br_x509_pkey *
xwc_get_pkey(const br_x509_class * const * ctx,unsigned * usages)212*0957b409SSimon J. Gerraty xwc_get_pkey(const br_x509_class *const *ctx, unsigned *usages)
213*0957b409SSimon J. Gerraty {
214*0957b409SSimon J. Gerraty 	x509_noanchor_context *xwc;
215*0957b409SSimon J. Gerraty 
216*0957b409SSimon J. Gerraty 	xwc = (x509_noanchor_context *)ctx;
217*0957b409SSimon J. Gerraty 	return (*xwc->inner)->get_pkey(xwc->inner, usages);
218*0957b409SSimon J. Gerraty }
219*0957b409SSimon J. Gerraty 
220*0957b409SSimon J. Gerraty /* see brssl.h */
221*0957b409SSimon J. Gerraty const br_x509_class x509_noanchor_vtable = {
222*0957b409SSimon J. Gerraty 	sizeof(x509_noanchor_context),
223*0957b409SSimon J. Gerraty 	xwc_start_chain,
224*0957b409SSimon J. Gerraty 	xwc_start_cert,
225*0957b409SSimon J. Gerraty 	xwc_append,
226*0957b409SSimon J. Gerraty 	xwc_end_cert,
227*0957b409SSimon J. Gerraty 	xwc_end_chain,
228*0957b409SSimon J. Gerraty 	xwc_get_pkey
229*0957b409SSimon J. Gerraty };
230*0957b409SSimon J. Gerraty 
231*0957b409SSimon J. Gerraty /* see brssl.h */
232*0957b409SSimon J. Gerraty void
x509_noanchor_init(x509_noanchor_context * xwc,const br_x509_class ** inner)233*0957b409SSimon J. Gerraty x509_noanchor_init(x509_noanchor_context *xwc, const br_x509_class **inner)
234*0957b409SSimon J. Gerraty {
235*0957b409SSimon J. Gerraty 	xwc->vtable = &x509_noanchor_vtable;
236*0957b409SSimon J. Gerraty 	xwc->inner = inner;
237*0957b409SSimon J. Gerraty }
238