X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Fdane-openssl.c;h=bb3763a4866328f74849ded861f41043783800f3;hp=50a2e8aa5ebef706f016a3475f5b90fdd7f669ea;hb=4f5830fe24fb69e5f1cc11d5bf9d608c256a4c2a;hpb=f92c55222fcc678d28110ec58df998c16e98c84a diff --git a/src/src/dane-openssl.c b/src/src/dane-openssl.c index 50a2e8aa5..bb3763a48 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 - 2017 */ #include #include @@ -18,12 +20,36 @@ #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 +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) +# define EXIM_HAVE_ASN1_MACROS +# define EXIM_OPAQUE_X509 +#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" #define DANESSL_F_ADD_SKID 100 @@ -39,6 +65,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 +84,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 +102,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"}, @@ -190,6 +219,8 @@ typedef struct ssl_dane # define X509_V_ERR_HOSTNAME_MISMATCH X509_V_ERR_APPLICATION_VERIFICATION #endif + + static int match(dane_selector_list slist, X509 *cert, int depth) { @@ -222,12 +253,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; } @@ -273,13 +304,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 @@ -318,7 +350,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; @@ -329,13 +361,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) @@ -373,7 +409,7 @@ 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); @@ -382,7 +418,7 @@ X509_NAME *name = akid_issuer_name(akid); * must use that. */ return X509_set_issuer_name(cert, - name ? name : X509_get_subject_name(cert)); + name ? name : subj); } static int @@ -410,7 +446,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); @@ -460,10 +500,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)) @@ -491,7 +531,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) @@ -575,7 +615,7 @@ 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; @@ -629,7 +669,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; @@ -686,13 +726,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; } @@ -749,10 +793,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 */ @@ -773,14 +817,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)); } @@ -804,12 +848,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 @@ -840,6 +884,7 @@ if (gens) continue; if (!(dane->mhost = OPENSSL_strdup(certid))) matched = -1; + DEBUG(D_tls) debug_printf("Dane name_check: matched SAN %s\n", certid); break; } } @@ -850,14 +895,16 @@ if (gens) * XXX: Should the subjectName be skipped when *any* altnames are present, * or only when DNS altnames are present? */ -if (got_altname == 0) +if (!got_altname) { char *certid = parse_subject_name(cert); - if (certid != 0 && *certid - && (matched = match_name(certid, dane)) != 0) + if (certid != 0 && *certid && (matched = match_name(certid, dane)) != 0) + { + DEBUG(D_tls) debug_printf("Dane name_check: matched SN %s\n", certid); dane->mhost = OPENSSL_strdup(certid); - if (certid) - OPENSSL_free(certid); + } + if (certid) + OPENSSL_free(certid); } return matched; } @@ -865,21 +912,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"); +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) { @@ -889,41 +936,41 @@ 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; } matched = 0; - /* - * Satisfy at least one usage 0 or 1 constraint, unless we've already - * 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. - */ - if (dane->roots && sk_X509_num(dane->roots)) - { - X509 *top = sk_X509_value(ctx->chain, dane->depth); +/* + * Satisfy at least one usage 0 or 1 constraint, unless we've already + * matched a usage 2 trust anchor. + * + * XXX: internal_verify() doesn't callback with top certs that are not + * self-issued. This is fixed in OpenSSL 1.1.0. + */ +if (dane->roots && sk_X509_num(dane->roots)) + { + X509 *top = sk_X509_value(chain, dane->depth); - dane->mdpth = dane->depth; - dane->match = top; - X509_up_ref(top); + dane->mdpth = dane->depth; + dane->match = top; + X509_up_ref(top); -#ifndef NO_CALLBACK_WORKAROUND - if (X509_check_issued(top, top) != X509_V_OK) - { - ctx->error_depth = dane->depth; - ctx->current_cert = top; - if (!cb(1, ctx)) - return 0; - } +#if OPENSSL_VERSION_NUMBER < 0x10100000L + if (X509_check_issued(top, top) != X509_V_OK) + { + 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 { @@ -936,19 +983,22 @@ else */ if (leaf_rrs) matched = match(leaf_rrs, xn, 0); + if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched EE\n"); 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); } + if (matched) DEBUG(D_tls) debug_printf("Dane verify_chain: matched %s\n", + n>0 ? "CA" : "selfisssued EE"); 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; @@ -961,7 +1011,8 @@ else } } -return ctx->verify(ctx); +/* Tail recurse into OpenSSL's internal_verify */ +return dane->verify(ctx); } static void @@ -997,11 +1048,11 @@ 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"); +DEBUG(D_tls) debug_printf("Dane verify_cert\n"); if (ssl_idx < 0) ssl_idx = SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -1015,15 +1066,15 @@ ssl = X509_STORE_CTX_get_ex_data(ctx, ssl_idx); if (!(dane = SSL_get_ex_data(ssl, dane_idx)) || !cert) return X509_verify_cert(ctx); - /* Reset for verification of a new chain, perhaps a renegotiation. */ +/* Reset for verification of a new chain, perhaps a renegotiation. */ dane_reset(dane); 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) @@ -1048,7 +1099,7 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) */ X509_STORE_CTX_trusted_stack(ctx, dane->roots); X509_STORE_CTX_set_chain(ctx, dane->chain); - OPENSSL_assert(ctx->untrusted == dane->chain); + OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx)); } } @@ -1057,8 +1108,8 @@ if (dane->selectors[DANESSL_USAGE_DANE_EE]) * X509_verify_cert() builds the full chain and calls our verify_chain() * wrapper. */ - dane->verify = ctx->verify; - ctx->verify = verify_chain; + dane->verify = X509_STORE_CTX_get_verify(ctx); + X509_STORE_CTX_set_verify(ctx, verify_chain); if (X509_verify_cert(ctx)) return 1; @@ -1118,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); } @@ -1162,7 +1219,7 @@ if (dane_idx < 0 || !(dane = SSL_get_ex_data(ssl, dane_idx))) dane_reset(dane); if (dane->hosts) - list_free(dane->hosts, CRYPTO_free); + list_free(dane->hosts, ossl_free); for (u = 0; u <= DANESSL_USAGE_LAST; ++u) if (dane->selectors[u]) list_free(dane->selectors[u], dane_selector_free); @@ -1183,7 +1240,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++); @@ -1224,28 +1281,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); } @@ -1305,38 +1370,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))); \ @@ -1414,7 +1479,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; @@ -1555,31 +1620,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) { @@ -1587,10 +1627,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 /* @@ -1615,6 +1660,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 + + /* @@ -1631,9 +1702,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 */ @@ -1645,6 +1717,5 @@ return 0; } -#endif /* OPENSSL_VERSION_NUMBER */ /* vi: aw ai sw=2 */