1 /* $OpenBSD$ */
2 /*
3 * Copyright (c) 2014 Jeremie Courreges-Anglas <jca@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 #include "tls_compat.h"
19
20 #ifdef USUAL_LIBSSL_FOR_TLS
21
22 #include <openssl/bn.h>
23 #include <openssl/err.h>
24 #include <openssl/x509v3.h>
25
26 #include "tls_internal.h"
27
28 #define TLS_CERT_INTERNAL_FUNCS
29 #include "tls_cert.h"
30
31 /*
32 * Load cert data from X509 cert.
33 */
34
35 /* Upper bounds */
36 #define UB_COMMON_NAME 255
37 #define UB_COUNTRY_NAME 255
38 #define UB_STATE_NAME 255
39 #define UB_LOCALITY_NAME 255
40 #define UB_STREET_ADDRESS 255
41 #define UB_ORGANIZATION_NAME 255
42 #define UB_ORGANIZATIONAL_UNIT_NAME 255
43
44 #define UB_GNAME_DNS 255
45 #define UB_GNAME_EMAIL 255
46 #define UB_GNAME_URI 255
47
48 /* Convert ASN1_INTEGER to decimal string string */
49 static int
tls_parse_bigint(struct tls * ctx,const ASN1_INTEGER * asn1int,const char ** dst_p)50 tls_parse_bigint(struct tls *ctx, const ASN1_INTEGER *asn1int, const char **dst_p)
51 {
52 long small;
53 BIGNUM *big;
54 char *tmp, buf[64];
55
56 *dst_p = NULL;
57 small = ASN1_INTEGER_get(asn1int);
58 if (small < 0) {
59 big = ASN1_INTEGER_to_BN(asn1int, NULL);
60 if (big) {
61 tmp = BN_bn2dec(big);
62 if (tmp)
63 *dst_p = strdup(tmp);
64 OPENSSL_free(tmp);
65 }
66 BN_free(big);
67 } else {
68 snprintf(buf, sizeof buf, "%lu", small);
69 *dst_p = strdup(buf);
70 }
71 if (*dst_p)
72 return 0;
73
74 tls_set_errorx(ctx, "cannot parse serial");
75 return -1;
76 }
77
78 /*
79 * Decode all string types used in RFC5280.
80 *
81 * OpenSSL used (before Jun 1 2014 commit) to pick between PrintableString,
82 * T61String, BMPString and UTF8String, depending on data. This code
83 * tries to match that.
84 *
85 * Disallow any ancient ASN.1 escape sequences.
86 */
87
88 static int
check_invalid_bytes(struct tls * ctx,const unsigned char * data,unsigned int len,int ascii_only,const char * desc)89 check_invalid_bytes(struct tls *ctx, const unsigned char *data, unsigned int len,
90 int ascii_only, const char *desc)
91 {
92 unsigned int i, c;
93
94 /* data is utf8 string, check for crap */
95 for (i = 0; i < len; i++) {
96 c = data[i];
97
98 if (ascii_only && (c & 0x80) != 0) {
99 tls_set_errorx(ctx, "invalid %s: contains non-ascii in ascii string", desc);
100 goto failed;
101 } else if (c < 0x20) {
102 /* ascii control chars, including NUL */
103 if (c != '\t' && c != '\n' && c != '\r') {
104 tls_set_errorx(ctx, "invalid %s: contains C0 control char", desc);
105 goto failed;
106 }
107 } else if (c == 0xC2 && (i + 1) < len) {
108 /* C1 control chars in UTF-8: \xc2\x80 - \xc2\x9f */
109 c = data[i + 1];
110 if (c >= 0x80 && c <= 0x9F) {
111 tls_set_errorx(ctx, "invalid %s: contains C1 control char", desc);
112 goto failed;
113 }
114 } else if (c == 0x7F) {
115 tls_set_errorx(ctx, "invalid %s: contains DEL char", desc);
116 goto failed;
117 }
118 }
119 return 0;
120 failed:
121 return -1;
122 }
123
124 static int
tls_parse_asn1string(struct tls * ctx,ASN1_STRING * a1str,const char ** dst_p,int minchars,int maxchars,const char * desc)125 tls_parse_asn1string(struct tls *ctx, ASN1_STRING *a1str, const char **dst_p, int minchars, int maxchars, const char *desc)
126 {
127 int format, len, ret = -1;
128 const unsigned char *data;
129 ASN1_STRING *a1utf = NULL;
130 int ascii_only = 0;
131 char *cstr = NULL;
132 int mbres, mbconvert = -1;
133
134 *dst_p = NULL;
135
136 format = ASN1_STRING_type(a1str);
137 data = ASN1_STRING_get0_data(a1str);
138 len = ASN1_STRING_length(a1str);
139 if (len < minchars) {
140 tls_set_errorx(ctx, "invalid %s: string too short", desc);
141 goto failed;
142 }
143
144 switch (format) {
145 case V_ASN1_NUMERICSTRING:
146 case V_ASN1_VISIBLESTRING:
147 case V_ASN1_PRINTABLESTRING:
148 case V_ASN1_IA5STRING:
149 /* Ascii */
150 if (len > maxchars) {
151 tls_set_errorx(ctx, "invalid %s: string too long", desc);
152 goto failed;
153 }
154 ascii_only = 1;
155 break;
156 case V_ASN1_T61STRING:
157 /* Latin1 */
158 mbconvert = MBSTRING_ASC;
159 break;
160 case V_ASN1_BMPSTRING:
161 /* UCS-2 big-endian */
162 mbconvert = MBSTRING_BMP;
163 break;
164 case V_ASN1_UNIVERSALSTRING:
165 /* UCS-4 big-endian */
166 mbconvert = MBSTRING_UNIV;
167 break;
168 case V_ASN1_UTF8STRING:
169 /*
170 * UTF-8 - could be used directly if OpenSSL has already
171 * validated the data. ATM be safe and validate here.
172 */
173 mbconvert = MBSTRING_UTF8;
174 break;
175 default:
176 tls_set_errorx(ctx, "invalid %s: unexpected string type", desc);
177 goto failed;
178 }
179
180 /* Convert to UTF-8 */
181 if (mbconvert != -1) {
182 mbres = ASN1_mbstring_ncopy(&a1utf, data, len, mbconvert, B_ASN1_UTF8STRING, minchars, maxchars);
183 if (mbres < 0) {
184 tls_set_error_libssl(ctx, "invalid %s", desc);
185 goto failed;
186 }
187 if (mbres != V_ASN1_UTF8STRING) {
188 tls_set_errorx(ctx, "multibyte conversion failed: expected UTF8 result");
189 goto failed;
190 }
191 data = ASN1_STRING_get0_data(a1utf);
192 len = ASN1_STRING_length(a1utf);
193 }
194
195 /* must not allow \0 */
196 if (memchr(data, 0, len) != NULL) {
197 tls_set_errorx(ctx, "invalid %s: contains NUL", desc);
198 goto failed;
199 }
200
201 /* no escape codes please */
202 if (check_invalid_bytes(ctx, data, len, ascii_only, desc) < 0)
203 goto failed;
204
205 /* copy to new string */
206 cstr = malloc(len + 1);
207 if (!cstr) {
208 tls_set_error(ctx, "malloc");
209 goto failed;
210 }
211 memcpy(cstr, data, len);
212 cstr[len] = 0;
213 *dst_p = cstr;
214 ret = len;
215 failed:
216 ASN1_STRING_free(a1utf);
217 return ret;
218 }
219
220 static int
tls_cert_get_dname_string(struct tls * ctx,X509_NAME * name,int nid,const char ** str_p,int minchars,int maxchars,const char * desc)221 tls_cert_get_dname_string(struct tls *ctx, X509_NAME *name, int nid, const char **str_p, int minchars, int maxchars, const char *desc)
222 {
223 int loc, len;
224 X509_NAME_ENTRY *ne;
225 ASN1_STRING *a1str;
226
227 *str_p = NULL;
228
229 loc = X509_NAME_get_index_by_NID(name, nid, -1);
230 if (loc < 0)
231 return 0;
232 ne = X509_NAME_get_entry(name, loc);
233 if (!ne)
234 return 0;
235 a1str = X509_NAME_ENTRY_get_data(ne);
236 if (!a1str)
237 return 0;
238 len = tls_parse_asn1string(ctx, a1str, str_p, minchars, maxchars, desc);
239 if (len < 0)
240 return -1;
241 return 0;
242 }
243
244 static int
tls_load_alt_ia5string(struct tls * ctx,ASN1_IA5STRING * ia5str,struct tls_cert * cert,int slot_type,int minchars,int maxchars,const char * desc)245 tls_load_alt_ia5string(struct tls *ctx, ASN1_IA5STRING *ia5str, struct tls_cert *cert, int slot_type, int minchars, int maxchars, const char *desc)
246 {
247 struct tls_cert_general_name *slot;
248 const char *data;
249 int len;
250
251 slot = &cert->subject_alt_names[cert->subject_alt_name_count];
252
253 len = tls_parse_asn1string(ctx, ia5str, &data, minchars, maxchars, desc);
254 if (len < 0)
255 return 0;
256
257 /*
258 * Per RFC 5280 section 4.2.1.6:
259 * " " is a legal domain name, but that
260 * dNSName must be rejected.
261 */
262 if (len == 1 && data[0] == ' ') {
263 tls_set_errorx(ctx, "invalid %s: single space", desc);
264 return -1;
265 }
266
267 slot->name_value = data;
268 slot->name_type = slot_type;
269
270 cert->subject_alt_name_count++;
271 return 0;
272 }
273
274 static int
tls_load_alt_ipaddr(struct tls * ctx,ASN1_OCTET_STRING * bin,struct tls_cert * cert)275 tls_load_alt_ipaddr(struct tls *ctx, ASN1_OCTET_STRING *bin, struct tls_cert *cert)
276 {
277 struct tls_cert_general_name *slot;
278 const void *data;
279 int len;
280
281 slot = &cert->subject_alt_names[cert->subject_alt_name_count];
282 len = ASN1_STRING_length(bin);
283 data = ASN1_STRING_get0_data(bin);
284 if (len < 0) {
285 tls_set_errorx(ctx, "negative length for ipaddress");
286 return -1;
287 }
288
289 /*
290 * Per RFC 5280 section 4.2.1.6:
291 * IPv4 must use 4 octets and IPv6 must use 16 octets.
292 */
293 if (len == 4) {
294 slot->name_type = TLS_CERT_GNAME_IPv4;
295 } else if (len == 16) {
296 slot->name_type = TLS_CERT_GNAME_IPv6;
297 } else {
298 tls_set_errorx(ctx, "invalid length for ipaddress");
299 return -1;
300 }
301
302 slot->name_value = malloc(len);
303 if (slot->name_value == NULL) {
304 tls_set_error(ctx, "malloc");
305 return -1;
306 }
307
308 memcpy((void *)slot->name_value, data, len);
309 cert->subject_alt_name_count++;
310 return 0;
311 }
312
313 /* See RFC 5280 section 4.2.1.6 for SubjectAltName details. */
314 static int
tls_cert_get_altnames(struct tls * ctx,struct tls_cert * cert,X509 * x509_cert)315 tls_cert_get_altnames(struct tls *ctx, struct tls_cert *cert, X509 *x509_cert)
316 {
317 STACK_OF(GENERAL_NAME) *altname_stack = NULL;
318 GENERAL_NAME *altname;
319 int count, i;
320 int rv = -1;
321
322 altname_stack = X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL);
323 if (altname_stack == NULL)
324 return 0;
325
326 count = sk_GENERAL_NAME_num(altname_stack);
327 if (count == 0) {
328 rv = 0;
329 goto out;
330 }
331
332 cert->subject_alt_names = calloc(sizeof (struct tls_cert_general_name), count);
333 if (cert->subject_alt_names == NULL) {
334 tls_set_error(ctx, "calloc");
335 goto out;
336 }
337
338 for (i = 0; i < count; i++) {
339 altname = sk_GENERAL_NAME_value(altname_stack, i);
340
341 if (altname->type == GEN_DNS) {
342 rv = tls_load_alt_ia5string(ctx, altname->d.dNSName, cert, TLS_CERT_GNAME_DNS, 1, UB_GNAME_DNS, "dns");
343 } else if (altname->type == GEN_EMAIL) {
344 rv = tls_load_alt_ia5string(ctx, altname->d.rfc822Name, cert, TLS_CERT_GNAME_EMAIL, 1, UB_GNAME_EMAIL, "email");
345 } else if (altname->type == GEN_URI) {
346 rv = tls_load_alt_ia5string(ctx, altname->d.uniformResourceIdentifier, cert, TLS_CERT_GNAME_URI, 1, UB_GNAME_URI, "uri");
347 } else if (altname->type == GEN_IPADD) {
348 rv = tls_load_alt_ipaddr(ctx, altname->d.iPAddress, cert);
349 } else {
350 /* ignore unknown types */
351 rv = 0;
352 }
353 if (rv < 0)
354 goto out;
355 }
356 rv = 0;
357 out:
358 sk_GENERAL_NAME_pop_free(altname_stack, GENERAL_NAME_free);
359 return rv;
360 }
361
362 static int
tls_get_dname(struct tls * ctx,X509_NAME * name,struct tls_cert_dname * dname)363 tls_get_dname(struct tls *ctx, X509_NAME *name, struct tls_cert_dname *dname)
364 {
365 int ret;
366 ret = tls_cert_get_dname_string(ctx, name, NID_commonName, &dname->common_name,
367 0, UB_COMMON_NAME, "commonName");
368 if (ret == 0)
369 ret = tls_cert_get_dname_string(ctx, name, NID_countryName, &dname->country_name,
370 0, UB_COUNTRY_NAME, "countryName");
371 if (ret == 0)
372 ret = tls_cert_get_dname_string(ctx, name, NID_stateOrProvinceName, &dname->state_or_province_name,
373 0, UB_STATE_NAME, "stateName");
374 if (ret == 0)
375 ret = tls_cert_get_dname_string(ctx, name, NID_localityName, &dname->locality_name,
376 0, UB_LOCALITY_NAME, "localityName");
377 if (ret == 0)
378 ret = tls_cert_get_dname_string(ctx, name, NID_streetAddress, &dname->street_address,
379 0, UB_STREET_ADDRESS, "streetAddress");
380 if (ret == 0)
381 ret = tls_cert_get_dname_string(ctx, name, NID_organizationName, &dname->organization_name,
382 0, UB_ORGANIZATION_NAME, "organizationName");
383 if (ret == 0)
384 ret = tls_cert_get_dname_string(ctx, name, NID_organizationalUnitName, &dname->organizational_unit_name,
385 0, UB_ORGANIZATIONAL_UNIT_NAME, "organizationalUnitName");
386 return ret;
387 }
388
389 static int
tls_get_basic_constraints(struct tls * ctx,struct tls_cert * cert,X509 * x509)390 tls_get_basic_constraints(struct tls *ctx, struct tls_cert *cert, X509 *x509)
391 {
392 BASIC_CONSTRAINTS *bc;
393 int crit;
394 int ret = -1;
395
396 bc = X509_get_ext_d2i(x509, NID_basic_constraints, &crit, NULL);
397 if (!bc)
398 return 0;
399
400 cert->ext_set |= TLS_EXT_BASIC;
401 if (crit)
402 cert->ext_crit |= TLS_EXT_BASIC;
403
404 cert->basic_constraints_ca = bc->ca ? 1 : 0;
405 if (bc->pathlen) {
406 cert->basic_constraints_pathlen = ASN1_INTEGER_get(bc->pathlen);
407 if (cert->basic_constraints_pathlen < 0) {
408 tls_set_error(ctx, "BasicConstraints has invalid pathlen");
409 goto failed;
410 }
411 } else {
412 cert->basic_constraints_pathlen = -1;
413 }
414 ret = 0;
415 failed:
416 BASIC_CONSTRAINTS_free(bc);
417 return ret;
418 }
419
map_bits(const uint32_t map[][2],uint32_t input)420 static uint32_t map_bits(const uint32_t map[][2], uint32_t input)
421 {
422 uint32_t i, out = 0;
423 for (i = 0; map[i][0]; i++) {
424 if (map[i][0] & input)
425 out |= map[i][1];
426 }
427 return out;
428 }
429
430 static int
tls_get_key_usage(struct tls * ctx,struct tls_cert * cert,X509 * x509)431 tls_get_key_usage(struct tls *ctx, struct tls_cert *cert, X509 *x509)
432 {
433 static const uint32_t ku_map[][2] = {
434 {KU_DIGITAL_SIGNATURE, KU_DIGITAL_SIGNATURE},
435 {KU_NON_REPUDIATION, KU_NON_REPUDIATION},
436 {KU_KEY_ENCIPHERMENT, KU_KEY_ENCIPHERMENT},
437 {KU_DATA_ENCIPHERMENT, KU_DATA_ENCIPHERMENT},
438 {KU_KEY_AGREEMENT, KU_KEY_AGREEMENT},
439 {KU_KEY_CERT_SIGN, KU_KEY_CERT_SIGN},
440 {KU_CRL_SIGN, KU_CRL_SIGN},
441 {KU_ENCIPHER_ONLY, KU_ENCIPHER_ONLY},
442 {KU_DECIPHER_ONLY, KU_DECIPHER_ONLY},
443 {0, 0},
444 };
445 ASN1_BIT_STRING *ku;
446 int crit;
447
448 ku = X509_get_ext_d2i(x509, NID_key_usage, &crit, NULL);
449 if (!ku)
450 return 0;
451
452 cert->ext_set |= TLS_EXT_KEY_USAGE;
453 if (crit)
454 cert->ext_crit |= TLS_EXT_KEY_USAGE;
455 ASN1_BIT_STRING_free(ku);
456
457 cert->key_usage_flags = map_bits(ku_map, X509_get_key_usage(x509));
458 return 0;
459 }
460
461 static int
tls_get_ext_key_usage(struct tls * ctx,struct tls_cert * cert,X509 * x509)462 tls_get_ext_key_usage(struct tls *ctx, struct tls_cert *cert, X509 *x509)
463 {
464 static const uint32_t xku_map[][2] = {
465 {XKU_SSL_SERVER, TLS_XKU_SSL_SERVER},
466 {XKU_SSL_CLIENT, TLS_XKU_SSL_CLIENT},
467 {XKU_SMIME, TLS_XKU_SMIME},
468 {XKU_CODE_SIGN, TLS_XKU_CODE_SIGN},
469 {XKU_SGC, TLS_XKU_SGC},
470 {XKU_OCSP_SIGN, TLS_XKU_OCSP_SIGN},
471 {XKU_TIMESTAMP, TLS_XKU_TIMESTAMP},
472 {XKU_DVCS, TLS_XKU_DVCS},
473 {0, 0},
474 };
475 EXTENDED_KEY_USAGE *xku;
476 int crit;
477
478 xku = X509_get_ext_d2i(x509, NID_ext_key_usage, &crit, NULL);
479 if (!xku)
480 return 0;
481 sk_ASN1_OBJECT_pop_free(xku, ASN1_OBJECT_free);
482
483 cert->ext_set |= TLS_EXT_EXTENDED_KEY_USAGE;
484 if (crit)
485 cert->ext_crit |= TLS_EXT_EXTENDED_KEY_USAGE;
486
487 cert->extended_key_usage_flags = map_bits(xku_map, X509_get_extended_key_usage(x509));
488 return 0;
489 }
490
491 static int
tls_load_extensions(struct tls * ctx,struct tls_cert * cert,X509 * x509)492 tls_load_extensions(struct tls *ctx, struct tls_cert *cert, X509 *x509)
493 {
494 int ret;
495
496 /*
497 * Force libssl to fill extension fields under X509 struct.
498 * Then libtls does not need to parse raw data.
499 */
500 X509_check_ca(x509);
501
502 ret = tls_get_basic_constraints(ctx, cert, x509);
503 if (ret == 0)
504 ret = tls_get_key_usage(ctx, cert, x509);
505 if (ret == 0)
506 ret = tls_get_ext_key_usage(ctx, cert, x509);
507 if (ret == 0)
508 ret = tls_cert_get_altnames(ctx, cert, x509);
509 return ret;
510 }
511
512 static void *
tls_calc_fingerprint(struct tls * ctx,X509 * x509,const char * algo,size_t * outlen)513 tls_calc_fingerprint(struct tls *ctx, X509 *x509, const char *algo, size_t *outlen)
514 {
515 const EVP_MD *md;
516 void *res;
517 int ret;
518 unsigned int tmplen, mdlen;
519
520 if (outlen)
521 *outlen = 0;
522
523 if (strcasecmp(algo, "sha1") == 0) {
524 md = EVP_sha1();
525 } else if (strcasecmp(algo, "sha256") == 0) {
526 md = EVP_sha256();
527 } else {
528 tls_set_errorx(ctx, "invalid fingerprint algorithm");
529 return NULL;
530 }
531
532 mdlen = EVP_MD_size(md);
533 res = malloc(mdlen);
534 if (!res) {
535 tls_set_error(ctx, "malloc");
536 return NULL;
537 }
538
539 ret = X509_digest(x509, md, res, &tmplen);
540 if (ret != 1 || tmplen != mdlen) {
541 free(res);
542 tls_set_errorx(ctx, "X509_digest failed");
543 return NULL;
544 }
545
546 if (outlen)
547 *outlen = mdlen;
548
549 return res;
550 }
551
552 static void
check_verify_error(struct tls * ctx,struct tls_cert * cert)553 check_verify_error(struct tls *ctx, struct tls_cert *cert)
554 {
555 long vres = SSL_get_verify_result(ctx->ssl_conn);
556 if (vres == X509_V_OK) {
557 cert->successful_verify = 1;
558 } else {
559 cert->successful_verify = 0;
560 }
561 }
562
563 int
tls_parse_cert(struct tls * ctx,struct tls_cert ** cert_p,const char * fingerprint_algo,X509 * x509)564 tls_parse_cert(struct tls *ctx, struct tls_cert **cert_p, const char *fingerprint_algo, X509 *x509)
565 {
566 struct tls_cert *cert = NULL;
567 X509_NAME *subject, *issuer;
568 int ret = -1;
569 long version;
570
571 *cert_p = NULL;
572
573 version = X509_get_version(x509);
574 if (version < 0) {
575 tls_set_errorx(ctx, "invalid version");
576 return -1;
577 }
578
579 subject = X509_get_subject_name(x509);
580 if (!subject) {
581 tls_set_errorx(ctx, "cert does not have subject");
582 return -1;
583 }
584
585 issuer = X509_get_issuer_name(x509);
586 if (!issuer) {
587 tls_set_errorx(ctx, "cert does not have issuer");
588 return -1;
589 }
590
591 cert = calloc(sizeof *cert, 1);
592 if (!cert) {
593 tls_set_error(ctx, "calloc");
594 goto failed;
595 }
596 cert->version = version;
597
598 if (fingerprint_algo) {
599 cert->fingerprint = tls_calc_fingerprint(ctx, x509, fingerprint_algo, &cert->fingerprint_size);
600 if (!cert->fingerprint)
601 goto failed;
602 }
603
604 ret = tls_get_dname(ctx, subject, &cert->subject);
605 if (ret == 0)
606 ret = tls_get_dname(ctx, issuer, &cert->issuer);
607 if (ret == 0)
608 ret = tls_asn1_parse_time(ctx, X509_get_notBefore(x509), &cert->not_before);
609 if (ret == 0)
610 ret = tls_asn1_parse_time(ctx, X509_get_notAfter(x509), &cert->not_after);
611 if (ret == 0)
612 ret = tls_parse_bigint(ctx, X509_get_serialNumber(x509), &cert->serial);
613 if (ret == 0)
614 ret = tls_load_extensions(ctx, cert, x509);
615 if (ret == 0) {
616 *cert_p = cert;
617 return 0;
618 }
619 failed:
620 tls_cert_free(cert);
621 return ret;
622 }
623
624 int
tls_get_peer_cert(struct tls * ctx,struct tls_cert ** cert_p,const char * fingerprint_algo)625 tls_get_peer_cert(struct tls *ctx, struct tls_cert **cert_p, const char *fingerprint_algo)
626 {
627 X509 *peer = ctx->ssl_peer_cert;
628 int res;
629
630 *cert_p = NULL;
631
632 if (!peer) {
633 tls_set_errorx(ctx, "peer does not have cert");
634 return TLS_NO_CERT;
635 }
636
637 ERR_clear_error();
638 res = tls_parse_cert(ctx, cert_p, fingerprint_algo, peer);
639 if (res == 0)
640 check_verify_error(ctx, *cert_p);
641 ERR_clear_error();
642 return res;
643 }
644
645 static void
tls_cert_free_dname(struct tls_cert_dname * dname)646 tls_cert_free_dname(struct tls_cert_dname *dname)
647 {
648 free((void*)dname->common_name);
649 free((void*)dname->country_name);
650 free((void*)dname->state_or_province_name);
651 free((void*)dname->locality_name);
652 free((void*)dname->street_address);
653 free((void*)dname->organization_name);
654 free((void*)dname->organizational_unit_name);
655 }
656
657 void
tls_cert_free(struct tls_cert * cert)658 tls_cert_free(struct tls_cert *cert)
659 {
660 int i;
661 if (!cert)
662 return;
663
664 tls_cert_free_dname(&cert->issuer);
665 tls_cert_free_dname(&cert->subject);
666
667 if (cert->subject_alt_name_count) {
668 for (i = 0; i < cert->subject_alt_name_count; i++)
669 free((void*)cert->subject_alt_names[i].name_value);
670 }
671 free(cert->subject_alt_names);
672
673 free((void*)cert->serial);
674 free((void*)cert->fingerprint);
675 free(cert);
676 }
677
678 #endif /* USUAL_LIBSSL_FOR_TLS */
679