X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=src%2Fsrc%2Fdane-openssl.c;h=6ed3529293257d73f432540eda4497654ccd40ab;hb=8e9fdd6369f0a7a81f0ca195e24edd372f7ca3ef;hp=e5f9f978490ad9b1f84db0cff771cd4c12f7d10a;hpb=bfe645c1570343d3adca657ab67998e122ca8792;p=exim.git diff --git a/src/src/dane-openssl.c b/src/src/dane-openssl.c index e5f9f9784..6ed352929 100644 --- a/src/src/dane-openssl.c +++ b/src/src/dane-openssl.c @@ -1,6 +1,8 @@ /* * Author: Viktor Dukhovni * License: THIS CODE IS IN THE PUBLIC DOMAIN. + * + * Copyright (c) The Exim Maintainers 2014 - 2019 */ #include #include @@ -18,11 +20,44 @@ #if OPENSSL_VERSION_NUMBER < 0x1000000fL # error "OpenSSL 1.0.0 or higher required" -#else /* remainder of file */ +#endif -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +# define X509_up_ref(x) CRYPTO_add(&((x)->references), 1, CRYPTO_LOCK_X509) +#endif + +/* LibreSSL 2.9.0 and later - 2.9.0 has removed a number of macros ... */ +#ifdef LIBRESSL_VERSION_NUMBER +# if LIBRESSL_VERSION_NUMBER >= 0x2090000fL +# define EXIM_HAVE_ASN1_MACROS +# endif #endif +/* OpenSSL */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +# define EXIM_HAVE_ASN1_MACROS +# define EXIM_OPAQUE_X509 +/* Older OpenSSL and all LibreSSL */ +#else +# define X509_STORE_CTX_get_verify(ctx) (ctx)->verify +# define X509_STORE_CTX_get_verify_cb(ctx) (ctx)->verify_cb +# define X509_STORE_CTX_get0_cert(ctx) (ctx)->cert +# define X509_STORE_CTX_get0_chain(ctx) (ctx)->chain +# define X509_STORE_CTX_get0_untrusted(ctx) (ctx)->untrusted + +# define X509_STORE_CTX_set_verify(ctx, verify_chain) (ctx)->verify = (verify_chain) +# define X509_STORE_CTX_set0_verified_chain(ctx, sk) (ctx)->chain = (sk) +# define X509_STORE_CTX_set_error_depth(ctx, val) (ctx)->error_depth = (val) +# define X509_STORE_CTX_set_current_cert(ctx, cert) (ctx)->current_cert = (cert) + +# define ASN1_STRING_get0_data ASN1_STRING_data +# define X509_getm_notBefore X509_get_notBefore +# define X509_getm_notAfter X509_get_notAfter + +# define CRYPTO_ONCE_STATIC_INIT 0 +# define CRYPTO_THREAD_run_once run_once +typedef int CRYPTO_ONCE; +#endif + #include "danessl.h" @@ -39,6 +74,7 @@ #define DANESSL_F_SET_TRUST_ANCHOR 110 #define DANESSL_F_VERIFY_CERT 111 #define DANESSL_F_WRAP_CERT 112 +#define DANESSL_F_DANESSL_VERIFY_CHAIN 113 #define DANESSL_R_BAD_CERT 100 #define DANESSL_R_BAD_CERT_PKEY 101 @@ -57,6 +93,7 @@ #ifndef OPENSSL_NO_ERR #define DANESSL_F_PLACEHOLDER 0 /* FIRST! Value TBD */ static ERR_STRING_DATA dane_str_functs[] = { + /* error string */ {DANESSL_F_PLACEHOLDER, "DANE library"}, /* FIRST!!! */ {DANESSL_F_ADD_SKID, "add_skid"}, {DANESSL_F_ADD_TLSA, "DANESSL_add_tlsa"}, @@ -74,6 +111,7 @@ static ERR_STRING_DATA dane_str_functs[] = { {0, NULL} }; static ERR_STRING_DATA dane_str_reasons[] = { + /* error string */ {DANESSL_R_BAD_CERT, "Bad TLSA record certificate"}, {DANESSL_R_BAD_CERT_PKEY, "Bad TLSA record certificate public key"}, {DANESSL_R_BAD_DATA_LENGTH, "Bad TLSA record digest length"}, @@ -91,7 +129,7 @@ static ERR_STRING_DATA dane_str_reasons[] = { }; #endif -#define DANEerr(f, r) ERR_PUT_error(err_lib_dane, (f), (r), __FILE__, __LINE__) +#define DANEerr(f, r) ERR_PUT_error(err_lib_dane, (f), (r), __FUNCTION__, __LINE__) static int err_lib_dane = -1; static int dane_idx = -1; @@ -211,7 +249,6 @@ int matched; */ for (matched = 0; !matched && slist; slist = slist->next) { - dane_mtype_list m; unsigned char mdbuf[EVP_MAX_MD_SIZE]; unsigned char *buf = NULL; unsigned char *buf2; @@ -224,12 +261,12 @@ for (matched = 0; !matched && slist; slist = slist->next) { case DANESSL_SELECTOR_CERT: len = i2d_X509(cert, NULL); - buf2 = buf = (unsigned char *) OPENSSL_malloc(len); + buf2 = buf = US OPENSSL_malloc(len); if(buf) i2d_X509(cert, &buf2); break; case DANESSL_SELECTOR_SPKI: len = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); - buf2 = buf = (unsigned char *) OPENSSL_malloc(len); + buf2 = buf = US OPENSSL_malloc(len); if(buf) i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &buf2); break; } @@ -244,9 +281,8 @@ for (matched = 0; !matched && slist; slist = slist->next) /* * Loop over each mtype and data element */ - for (m = slist->value->mtype; !matched && m; m = m->next) + for (dane_mtype_list m = slist->value->mtype; !matched && m; m = m->next) { - dane_data_list d; unsigned char *cmpbuf = buf; unsigned int cmplen = len; @@ -260,7 +296,7 @@ for (matched = 0; !matched && slist; slist = slist->next) if (!EVP_Digest(buf, len, cmpbuf, &cmplen, m->value->md, 0)) matched = -1; } - for (d = m->value->data; !matched && d; d = d->next) + for (dane_data_list d = m->value->data; !matched && d; d = d->next) if ( cmplen == d->value->datalen && memcmp(cmpbuf, d->value->data, cmplen) == 0) matched = slist->value->selector + 1; @@ -275,13 +311,14 @@ return matched; static int push_ext(X509 *cert, X509_EXTENSION *ext) { - if (ext) { - if (X509_add_ext(cert, ext, -1)) - return 1; - X509_EXTENSION_free(ext); - } - DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE); - return 0; +if (ext) + { + if (X509_add_ext(cert, ext, -1)) + return 1; + X509_EXTENSION_free(ext); + } +DANEerr(DANESSL_F_PUSH_EXT, ERR_R_MALLOC_FAILURE); +return 0; } static int @@ -320,7 +357,7 @@ static int add_akid(X509 *cert, AUTHORITY_KEYID *akid) { int nid = NID_authority_key_identifier; -ASN1_STRING *id; +ASN1_OCTET_STRING *id; unsigned char c = 0; int ret = 0; @@ -331,13 +368,17 @@ int ret = 0; * exempt from any potential (off by default for now in OpenSSL) * self-signature checks! */ -id = (akid && akid->keyid) ? akid->keyid : 0; -if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_data(id) == c) +id = akid && akid->keyid ? akid->keyid : 0; +if (id && ASN1_STRING_length(id) == 1 && *ASN1_STRING_get0_data(id) == c) c = 1; if ( (akid = AUTHORITY_KEYID_new()) != 0 && (akid->keyid = ASN1_OCTET_STRING_new()) != 0 +#ifdef EXIM_HAVE_ASN1_MACROS + && ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1) +#else && M_ASN1_OCTET_STRING_set(akid->keyid, (void *) &c, 1) +#endif && X509_add1_ext_i2d(cert, nid, akid, 0, X509V3_ADD_APPEND)) ret = 1; if (akid) @@ -360,10 +401,9 @@ akid_issuer_name(AUTHORITY_KEYID *akid) { if (akid && akid->issuer) { - int i; GENERAL_NAMES *gens = akid->issuer; - for (i = 0; i < sk_GENERAL_NAME_num(gens); ++i) + for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i) { GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i); @@ -375,16 +415,16 @@ return 0; } static int -set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid) +set_issuer_name(X509 *cert, AUTHORITY_KEYID *akid, X509_NAME *subj) { X509_NAME *name = akid_issuer_name(akid); /* - * If subject's akid specifies an authority key identifer issuer name, we + * If subject's akid specifies an authority key identifier issuer name, we * must use that. */ return X509_set_issuer_name(cert, - name ? name : X509_get_subject_name(cert)); + name ? name : subj); } static int @@ -412,7 +452,11 @@ if (cert) { if (trusted && !X509_add1_trust_object(cert, serverAuth)) return 0; +#ifdef EXIM_OPAQUE_X509 + X509_up_ref(cert); +#else CRYPTO_add(&cert->references, 1, CRYPTO_LOCK_X509); +#endif if (!sk_X509_push(*xs, cert)) { X509_free(cert); @@ -462,10 +506,10 @@ akid = X509_get_ext_d2i(subject, NID_authority_key_identifier, 0, 0); */ if ( !X509_set_version(cert, 2) || !set_serial(cert, akid, subject) + || !set_issuer_name(cert, akid, name) + || !X509_gmtime_adj(X509_getm_notBefore(cert), -30 * 86400L) + || !X509_gmtime_adj(X509_getm_notAfter(cert), 30 * 86400L) || !X509_set_subject_name(cert, name) - || !set_issuer_name(cert, akid) - || !X509_gmtime_adj(X509_get_notBefore(cert), -30 * 86400L) - || !X509_gmtime_adj(X509_get_notAfter(cert), 30 * 86400L) || !X509_set_pubkey(cert, newkey) || !add_ext(0, cert, NID_basic_constraints, "CA:TRUE") || (!top && !add_akid(cert, akid)) @@ -493,7 +537,7 @@ if (dane->depth < 0) /* * If the TA certificate is self-issued, or need not be, use it directly. - * Otherwise, synthesize requisuite ancestors. + * Otherwise, synthesize requisite ancestors. */ if ( !wrap_to_root || X509_check_issued(tacert, tacert) == X509_V_OK) @@ -507,8 +551,6 @@ return 0; static int ta_signed(ssl_dane *dane, X509 *cert, int depth) { -dane_cert_list x; -dane_pkey_list k; EVP_PKEY *pk; int done = 0; @@ -519,7 +561,7 @@ int done = 0; * first (name comparisons), before we bother with signature checks * (public key operations). */ -for (x = dane->certs; !done && x; x = x->next) +for (dane_cert_list x = dane->certs; !done && x; x = x->next) { if (X509_check_issued(x->value, cert) == X509_V_OK) { @@ -559,7 +601,7 @@ for (x = dane->certs; !done && x; x = x->next) * This may push errors onto the stack when the certificate signature is * not of the right type or length, throw these away, */ -for (k = dane->pkeys; !done && k; k = k->next) +for (dane_pkey_list k = dane->pkeys; !done && k; k = k->next) if (X509_verify(cert, k->value) > 0) done = wrap_issuer(dane, k->value, cert, depth, WRAP_MID) ? 1 : -1; else @@ -572,12 +614,10 @@ static int set_trust_anchor(X509_STORE_CTX *ctx, ssl_dane *dane, X509 *cert) { int matched = 0; -int n; -int i; int depth = 0; EVP_PKEY *takey; X509 *ca; -STACK_OF(X509) *in = ctx->untrusted; /* XXX: Accessor? */ +STACK_OF(X509) *in = X509_STORE_CTX_get0_untrusted(ctx); if (!grow_chain(dane, UNTRUSTED, 0)) return -1; @@ -609,8 +649,9 @@ if (!(in = sk_X509_dup(in))) * * Caller ensures that the initial certificate is not self-signed. */ -for (n = sk_X509_num(in); n > 0; --n, ++depth) +for (int n = sk_X509_num(in); n > 0; --n, ++depth) { + int i; for (i = 0; i < n; ++i) if (X509_check_issued(sk_X509_value(in, i), cert) == X509_V_OK) break; @@ -631,7 +672,7 @@ for (n = sk_X509_num(in); n > 0; --n, ++depth) { if (grow_chain(dane, UNTRUSTED, ca)) { - if (!X509_check_issued(ca, ca) == X509_V_OK) + if (X509_check_issued(ca, ca) != X509_V_OK) { /* Restart with issuer as subject */ cert = ca; @@ -688,13 +729,17 @@ if (matched > 0) dane->mdpth = 0; dane->match = cert; X509_up_ref(cert); - if(!ctx->chain) + if(!X509_STORE_CTX_get0_chain(ctx)) { - if ( (ctx->chain = sk_X509_new_null()) != 0 - && sk_X509_push(ctx->chain, cert)) + STACK_OF(X509) * sk = sk_X509_new_null(); + if (sk && sk_X509_push(sk, cert)) + { X509_up_ref(cert); + X509_STORE_CTX_set0_verified_chain(ctx, sk); + } else { + if (sk) sk_X509_free(sk); DANEerr(DANESSL_F_CHECK_END_ENTITY, ERR_R_MALLOC_FAILURE); return -1; } @@ -707,9 +752,8 @@ static int match_name(const char *certid, ssl_dane *dane) { int multi = dane->multi; -dane_host_list hosts; -for (hosts = dane->hosts; hosts; hosts = hosts->next) +for (dane_host_list hosts = dane->hosts; hosts; hosts = hosts->next) { int match_subdomain = 0; const char *domain = hosts->value; @@ -751,10 +795,10 @@ for (hosts = dane->hosts; hosts; hosts = hosts->next) return 0; } -static char * -check_name(char *name, int len) +static const char * +check_name(const char *name, int len) { -char *cp = name + len; +const char *cp = name + len; while (len > 0 && !*--cp) --len; /* Ignore trailing NULs */ @@ -775,14 +819,14 @@ if (cp - name != len) /* Guard against internal NULs */ return name; } -static char * +static const char * parse_dns_name(const GENERAL_NAME *gn) { if (gn->type != GEN_DNS) return 0; if (ASN1_STRING_type(gn->d.ia5) != V_ASN1_IA5STRING) return 0; -return check_name((char *) ASN1_STRING_data(gn->d.ia5), +return check_name(CCS ASN1_STRING_get0_data(gn->d.ia5), ASN1_STRING_length(gn->d.ia5)); } @@ -806,12 +850,12 @@ if (!(entry_str = X509_NAME_ENTRY_get_data(entry))) if ((len = ASN1_STRING_to_UTF8(&namebuf, entry_str)) < 0) return 0; -if (len <= 0 || check_name((char *) namebuf, len) == 0) +if (len <= 0 || check_name(CS namebuf, len) == 0) { OPENSSL_free(namebuf); return 0; } -return (char *) namebuf; +return CS namebuf; } static int @@ -825,9 +869,8 @@ gens = X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0); if (gens) { int n = sk_GENERAL_NAME_num(gens); - int i; - for (i = 0; i < n; ++i) + for (int i = 0; i < n; ++i) { const GENERAL_NAME *gn = sk_GENERAL_NAME_value(gens, i); const char *certid; @@ -870,21 +913,21 @@ return matched; static int verify_chain(X509_STORE_CTX *ctx) { -dane_selector_list issuer_rrs; -dane_selector_list leaf_rrs; -int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb; +int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx); +X509 *cert = X509_STORE_CTX_get0_cert(ctx); +STACK_OF(X509) * chain = X509_STORE_CTX_get0_chain(ctx); +int chain_length = sk_X509_num(chain); int ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx); ssl_dane *dane = SSL_get_ex_data(ssl, dane_idx); -X509 *cert = ctx->cert; /* XXX: accessor? */ +dane_selector_list issuer_rrs = dane->selectors[DANESSL_USAGE_PKIX_TA]; +dane_selector_list leaf_rrs = dane->selectors[DANESSL_USAGE_PKIX_EE]; int matched = 0; -int chain_length = sk_X509_num(ctx->chain); DEBUG(D_tls) debug_printf("Dane verify_chain\n"); -issuer_rrs = dane->selectors[DANESSL_USAGE_PKIX_TA]; -leaf_rrs = dane->selectors[DANESSL_USAGE_PKIX_EE]; -ctx->verify = dane->verify; +/* Restore OpenSSL's internal_verify() as the signature check function */ +X509_STORE_CTX_set_verify(ctx, dane->verify); if ((matched = name_check(dane, cert)) < 0) { @@ -894,8 +937,8 @@ if ((matched = name_check(dane, cert)) < 0) if (!matched) { - ctx->error_depth = 0; - ctx->current_cert = cert; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH); if (!cb(0, ctx)) return 0; @@ -907,28 +950,28 @@ matched = 0; * matched a usage 2 trust anchor. * * XXX: internal_verify() doesn't callback with top certs that are not - * self-issued. This should be fixed in a future OpenSSL. + * self-issued. This is fixed in OpenSSL 1.1.0. */ if (dane->roots && sk_X509_num(dane->roots)) { - X509 *top = sk_X509_value(ctx->chain, dane->depth); + X509 *top = sk_X509_value(chain, dane->depth); dane->mdpth = dane->depth; dane->match = top; X509_up_ref(top); -#ifndef NO_CALLBACK_WORKAROUND +#if OPENSSL_VERSION_NUMBER < 0x10100000L if (X509_check_issued(top, top) != X509_V_OK) { - ctx->error_depth = dane->depth; - ctx->current_cert = top; + X509_STORE_CTX_set_error_depth(ctx, dane->depth); + X509_STORE_CTX_set_current_cert(ctx, top); if (!cb(1, ctx)) return 0; } #endif /* Pop synthetic trust-anchor ancestors off the chain! */ while (--chain_length > dane->depth) - X509_free(sk_X509_pop(ctx->chain)); + X509_free(sk_X509_pop(chain)); } else { @@ -946,7 +989,7 @@ else if (!matched && issuer_rrs) for (n = chain_length-1; !matched && n >= 0; --n) { - xn = sk_X509_value(ctx->chain, n); + xn = sk_X509_value(chain, n); if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK) matched = match(issuer_rrs, xn, n); } @@ -955,8 +998,8 @@ else if (!matched) { - ctx->current_cert = cert; - ctx->error_depth = 0; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_UNTRUSTED); if (!cb(0, ctx)) return 0; @@ -969,7 +1012,8 @@ else } } -return ctx->verify(ctx); +/* Tail recurse into OpenSSL's internal_verify */ +return dane->verify(ctx); } static void @@ -1005,9 +1049,9 @@ verify_cert(X509_STORE_CTX *ctx, void *unused_ctx) static int ssl_idx = -1; SSL *ssl; ssl_dane *dane; -int (*cb)(int, X509_STORE_CTX *) = ctx->verify_cb; +int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx); +X509 *cert = X509_STORE_CTX_get0_cert(ctx); int matched; -X509 *cert = ctx->cert; /* XXX: accessor? */ DEBUG(D_tls) debug_printf("Dane verify_cert\n"); @@ -1030,8 +1074,8 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) { if ((matched = check_end_entity(ctx, dane, cert)) > 0) { - ctx->error_depth = 0; - ctx->current_cert = cert; + X509_STORE_CTX_set_error_depth(ctx, 0); + X509_STORE_CTX_set_current_cert(ctx, cert); return cb(1, ctx); } if (matched < 0) @@ -1041,52 +1085,52 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) } } - if (dane->selectors[DANESSL_USAGE_DANE_TA]) +if (dane->selectors[DANESSL_USAGE_DANE_TA]) + { + if ((matched = set_trust_anchor(ctx, dane, cert)) < 0) { - if ((matched = set_trust_anchor(ctx, dane, cert)) < 0) - { - X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM); - return -1; - } - if (matched) - { - /* - * Check that setting the untrusted chain updates the expected - * structure member at the expected offset. - */ - X509_STORE_CTX_trusted_stack(ctx, dane->roots); - X509_STORE_CTX_set_chain(ctx, dane->chain); - OPENSSL_assert(ctx->untrusted == dane->chain); - } + X509_STORE_CTX_set_error(ctx, X509_V_ERR_OUT_OF_MEM); + return -1; + } + if (matched) + { + /* + * Check that setting the untrusted chain updates the expected + * structure member at the expected offset. + */ + X509_STORE_CTX_trusted_stack(ctx, dane->roots); + X509_STORE_CTX_set_chain(ctx, dane->chain); + OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx)); } + } - /* - * Name checks and usage 0/1 constraint enforcement are delayed until - * X509_verify_cert() builds the full chain and calls our verify_chain() - * wrapper. - */ - dane->verify = ctx->verify; - ctx->verify = verify_chain; +/* + * Name checks and usage 0/1 constraint enforcement are delayed until + * X509_verify_cert() builds the full chain and calls our verify_chain() + * wrapper. + */ +dane->verify = X509_STORE_CTX_get_verify(ctx); +X509_STORE_CTX_set_verify(ctx, verify_chain); - if (X509_verify_cert(ctx)) - return 1; +if (X509_verify_cert(ctx)) + return 1; - /* - * If the chain is invalid, clear any matching cert or hostname, to - * protect callers that might erroneously rely on these alone without - * checking the validation status. - */ - if (dane->match) - { - X509_free(dane->match); - dane->match = 0; - } - if (dane->mhost) - { - OPENSSL_free(dane->mhost); - dane->mhost = 0; - } - return 0; +/* + * If the chain is invalid, clear any matching cert or hostname, to + * protect callers that might erroneously rely on these alone without + * checking the validation status. + */ +if (dane->match) + { + X509_free(dane->match); + dane->match = 0; + } +if (dane->mhost) + { + OPENSSL_free(dane->mhost); + dane->mhost = 0; + } + return 0; } static dane_list @@ -1114,10 +1158,9 @@ return l; static void list_free(void *list, void (*f)(void *)) { -dane_list head; dane_list next; -for (head = (dane_list) list; head; head = next) +for (dane_list head = (dane_list) list; head; head = next) { next = head->next; if (f && head->value) @@ -1126,10 +1169,16 @@ for (head = (dane_list) list; head; head = next) } } +static void +ossl_free(void * p) +{ +OPENSSL_free(p); +} + static void dane_mtype_free(void *p) { -list_free(((dane_mtype) p)->data, CRYPTO_free); +list_free(((dane_mtype) p)->data, ossl_free); OPENSSL_free(p); } @@ -1160,7 +1209,6 @@ void DANESSL_cleanup(SSL *ssl) { ssl_dane *dane; -int u; DEBUG(D_tls) debug_printf("Dane lib-cleanup\n"); @@ -1170,8 +1218,8 @@ if (dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx))) dane_reset(dane); if (dane->hosts) - list_free(dane->hosts, CRYPTO_free); -for (u = 0; u <= DANESSL_USAGE_LAST; ++u) + list_free(dane->hosts, ossl_free); +for (int u = 0; u <= DANESSL_USAGE_LAST; ++u) if (dane->selectors[u]) list_free(dane->selectors[u], dane_selector_free); if (dane->pkeys) @@ -1191,7 +1239,7 @@ while (*src) dane_host_list elem = (dane_host_list) OPENSSL_malloc(sizeof(*elem)); if (elem == 0) { - list_free(head, CRYPTO_free); + list_free(head, ossl_free); return 0; } elem->value = OPENSSL_strdup(*src++); @@ -1232,28 +1280,36 @@ DANESSL_verify_chain(SSL *ssl, STACK_OF(X509) *chain) { int ret; X509 *cert; -X509_STORE_CTX store_ctx; +X509_STORE_CTX * store_ctx; SSL_CTX *ssl_ctx = SSL_get_SSL_CTX(ssl); X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); int store_ctx_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); cert = sk_X509_value(chain, 0); -if (!X509_STORE_CTX_init(&store_ctx, store, cert, chain)) +if (!(store_ctx = X509_STORE_CTX_new())) + { + DANEerr(DANESSL_F_DANESSL_VERIFY_CHAIN, ERR_R_MALLOC_FAILURE); return 0; -X509_STORE_CTX_set_ex_data(&store_ctx, store_ctx_idx, ssl); + } +if (!X509_STORE_CTX_init(store_ctx, store, cert, chain)) + { + X509_STORE_CTX_free(store_ctx); + return 0; + } +X509_STORE_CTX_set_ex_data(store_ctx, store_ctx_idx, ssl); -X509_STORE_CTX_set_default(&store_ctx, +X509_STORE_CTX_set_default(store_ctx, SSL_is_server(ssl) ? "ssl_client" : "ssl_server"); -X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&store_ctx), +X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(store_ctx), SSL_get0_param(ssl)); if (SSL_get_verify_callback(ssl)) - X509_STORE_CTX_set_verify_cb(&store_ctx, SSL_get_verify_callback(ssl)); + X509_STORE_CTX_set_verify_cb(store_ctx, SSL_get_verify_callback(ssl)); -ret = verify_cert(&store_ctx, NULL); +ret = verify_cert(store_ctx, NULL); -SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(&store_ctx)); -X509_STORE_CTX_cleanup(&store_ctx); +SSL_set_verify_result(ssl, X509_STORE_CTX_get_error(store_ctx)); +X509_STORE_CTX_cleanup(store_ctx); return (ret); } @@ -1313,38 +1369,38 @@ if (selector > DANESSL_SELECTOR_LAST) return 0; } - /* Support built-in standard one-digit mtypes */ - if (mdname && *mdname && mdname[1] == '\0') - switch (*mdname - '0') - { - case DANESSL_MATCHING_FULL: mdname = 0; break; - case DANESSL_MATCHING_2256: mdname = "sha256"; break; - case DANESSL_MATCHING_2512: mdname = "sha512"; break; - } - if (mdname && *mdname && (md = EVP_get_digestbyname(mdname)) == 0) - { - DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DIGEST); - return 0; - } - if (mdname && *mdname && dlen != EVP_MD_size(md)) - { - DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DATA_LENGTH); - return 0; - } - if (!data) - { - DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_NULL_DATA); - return 0; - } +/* Support built-in standard one-digit mtypes */ +if (mdname && *mdname && mdname[1] == '\0') + switch (*mdname - '0') + { + case DANESSL_MATCHING_FULL: mdname = 0; break; + case DANESSL_MATCHING_2256: mdname = "sha256"; break; + case DANESSL_MATCHING_2512: mdname = "sha512"; break; + } +if (mdname && *mdname && !(md = EVP_get_digestbyname(mdname))) + { + DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DIGEST); + return 0; + } +if (mdname && *mdname && dlen != EVP_MD_size(md)) + { + DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_DATA_LENGTH); + return 0; + } +if (!data) + { + DANEerr(DANESSL_F_ADD_TLSA, DANESSL_R_BAD_NULL_DATA); + return 0; + } - /* - * Full Certificate or Public Key when NULL or empty digest name - */ - if (!mdname || !*mdname) - { - X509 *x = 0; - EVP_PKEY *k = 0; - const unsigned char *p = data; +/* + * Full Certificate or Public Key when NULL or empty digest name + */ +if (!mdname || !*mdname) + { + X509 *x = 0; + EVP_PKEY *k = 0; + const unsigned char *p = data; #define xklistinit(lvar, ltype, var, freeFunc) do { \ (lvar) = (ltype) OPENSSL_malloc(sizeof(*(lvar))); \ @@ -1422,7 +1478,7 @@ if (!m) { if ((m = (dane_mtype_list) list_alloc(sizeof(*m->value))) == 0) { - list_free(d, CRYPTO_free); + list_free(d, ossl_free); xkfreeret(0); } m->value->data = 0; @@ -1479,7 +1535,6 @@ int DANESSL_init(SSL *ssl, const char *sni_domain, const char **hostnames) { ssl_dane *dane; -int i; DEBUG(D_tls) debug_printf("Dane ssl_init\n"); if (dane_idx < 0) @@ -1518,7 +1573,7 @@ dane->multi = 0; /* Future SSL control interface */ dane->count = 0; dane->hosts = 0; -for (i = 0; i <= DANESSL_USAGE_LAST; ++i) +for (int i = 0; i <= DANESSL_USAGE_LAST; ++i) dane->selectors[i] = 0; if (hostnames && (dane->hosts = host_list_init(hostnames)) == 0) @@ -1563,31 +1618,6 @@ DANEerr(DANESSL_F_CTX_INIT, DANESSL_R_LIBRARY_INIT); return -1; } -static int -init_once(volatile int *value, int (*init)(void), void (*postinit)(void)) -{ -int wlock = 0; - -CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); -if (*value < 0) - { - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); - CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); - wlock = 1; - if (*value < 0) - { - *value = init(); - if (postinit) - postinit(); - } - } -if (wlock) - CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); -else - CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); -return *value; -} - static void dane_init(void) { @@ -1595,10 +1625,15 @@ dane_init(void) * Store library id in zeroth function slot, used to locate the library * name. This must be done before we load the error strings. */ +err_lib_dane = ERR_get_next_error_library(); + #ifndef OPENSSL_NO_ERR -dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0); -ERR_load_strings(err_lib_dane, dane_str_functs); -ERR_load_strings(err_lib_dane, dane_str_reasons); +if (err_lib_dane > 0) + { + dane_str_functs[0].error |= ERR_PACK(err_lib_dane, 0, 0); + ERR_load_strings(err_lib_dane, dane_str_functs); + ERR_load_strings(err_lib_dane, dane_str_reasons); + } #endif /* @@ -1623,6 +1658,32 @@ dane_idx = SSL_get_ex_new_index(0, 0, 0, 0, 0); } +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) +static void +run_once(volatile int * once, void (*init)(void)) +{ +int wlock = 0; + +CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX); +if (!*once) + { + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); + CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX); + wlock = 1; + if (!*once) + { + *once = 1; + init(); + } + } +if (wlock) + CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX); +else + CRYPTO_r_unlock(CRYPTO_LOCK_SSL_CTX); +} +#endif + + /* @@ -1639,9 +1700,10 @@ Return int DANESSL_library_init(void) { +static CRYPTO_ONCE once = CRYPTO_ONCE_STATIC_INIT; + DEBUG(D_tls) debug_printf("Dane lib-init\n"); -if (err_lib_dane < 0) - init_once(&err_lib_dane, ERR_get_next_error_library, dane_init); +(void) CRYPTO_THREAD_run_once(&once, dane_init); #if defined(LN_sha256) /* No DANE without SHA256 support */ @@ -1653,6 +1715,5 @@ return 0; } -#endif /* OPENSSL_VERSION_NUMBER */ /* vi: aw ai sw=2 */