X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/e3555426308395ef260b0dae4548593ac114aed5..f627fcf379d9453326672016168e2e73f6c42916:/src/src/dane-openssl.c diff --git a/src/src/dane-openssl.c b/src/src/dane-openssl.c index 6c2b1dbde..79f136eae 100644 --- a/src/src/dane-openssl.c +++ b/src/src/dane-openssl.c @@ -2,7 +2,7 @@ * Author: Viktor Dukhovni * License: THIS CODE IS IN THE PUBLIC DOMAIN. * - * Copyright (c) The Exim Maintainers 2014 - 2016 + * Copyright (c) The Exim Maintainers 2014 - 2019 */ #include #include @@ -20,14 +20,23 @@ #if OPENSSL_VERSION_NUMBER < 0x1000000fL # error "OpenSSL 1.0.0 or higher required" -#else /* remainder of file */ +#endif #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 + +/* 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 @@ -39,6 +48,14 @@ # 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 @@ -57,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 @@ -75,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"}, @@ -92,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"}, @@ -242,12 +262,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; } @@ -293,13 +313,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 @@ -338,7 +359,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; @@ -349,8 +370,8 @@ 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 @@ -397,16 +418,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 @@ -488,10 +509,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)) @@ -519,7 +540,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) @@ -657,7 +678,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; @@ -719,11 +740,12 @@ if (matched > 0) STACK_OF(X509) * sk = sk_X509_new_null(); if (sk && sk_X509_push(sk, cert)) { - X509_STORE_CTX_set0_verified_chain(ctx, sk); 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; } @@ -780,10 +802,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 */ @@ -804,14 +826,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)); } @@ -835,12 +857,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 @@ -901,7 +923,8 @@ verify_chain(X509_STORE_CTX *ctx) { int (*cb)(int, X509_STORE_CTX *) = X509_STORE_CTX_get_verify_cb(ctx); X509 *cert = X509_STORE_CTX_get0_cert(ctx); -int chain_length = sk_X509_num(X509_STORE_CTX_get0_chain(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); @@ -911,6 +934,7 @@ int matched = 0; DEBUG(D_tls) debug_printf("Dane verify_chain\n"); +/* 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) @@ -934,17 +958,17 @@ 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(X509_STORE_CTX_get0_chain(ctx), 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) { X509_STORE_CTX_set_error_depth(ctx, dane->depth); @@ -955,7 +979,7 @@ if (dane->roots && sk_X509_num(dane->roots)) #endif /* Pop synthetic trust-anchor ancestors off the chain! */ while (--chain_length > dane->depth) - X509_free(sk_X509_pop(X509_STORE_CTX_get0_chain(ctx))); + X509_free(sk_X509_pop(chain)); } else { @@ -973,7 +997,7 @@ else if (!matched && issuer_rrs) for (n = chain_length-1; !matched && n >= 0; --n) { - xn = sk_X509_value(X509_STORE_CTX_get0_chain(ctx), n); + xn = sk_X509_value(chain, n); if (n > 0 || X509_check_issued(xn, xn) == X509_V_OK) matched = match(issuer_rrs, xn, n); } @@ -996,7 +1020,8 @@ else } } -return (X509_STORE_CTX_get_verify(ctx))(ctx); +/* Tail recurse into OpenSSL's internal_verify */ +return dane->verify(ctx); } static void @@ -1083,7 +1108,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(X509_STORE_CTX_get0_untrusted(ctx) == dane->chain); + OPENSSL_assert(dane->chain == X509_STORE_CTX_get0_untrusted(ctx)); } } @@ -1153,10 +1178,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); } @@ -1197,7 +1228,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); @@ -1218,7 +1249,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++); @@ -1259,28 +1290,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; + } +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_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); } @@ -1340,38 +1379,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))); \ @@ -1449,7 +1488,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; @@ -1590,31 +1629,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) { @@ -1622,10 +1636,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 /* @@ -1650,6 +1669,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 + + /* @@ -1666,9 +1711,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 */ @@ -1680,6 +1726,5 @@ return 0; } -#endif /* OPENSSL_VERSION_NUMBER */ /* vi: aw ai sw=2 */