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