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