diff options
author | Jeremy Harris <jgh146exb@wizmail.org> | 2021-12-01 18:52:21 +0000 |
---|---|---|
committer | Jeremy Harris <jgh146exb@wizmail.org> | 2021-12-03 19:08:37 +0000 |
commit | c6a290f4d8df3734b3cdc2232b4334ff8386c1da (patch) | |
tree | ac9e874f2a19ffcf7602bc516564cb181ac00cb6 /src | |
parent | a5d79c99f4948d9fd288a1bfaca3a44cf2caaa32 (diff) |
OpenSSL: tidy DH and ECDH param setup
Testsuite: expand DH testcase
Diffstat (limited to 'src')
-rw-r--r-- | src/src/tls-openssl.c | 97 |
1 files changed, 44 insertions, 53 deletions
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c index 692636498..4bc92bd05 100644 --- a/src/src/tls-openssl.c +++ b/src/src/tls-openssl.c @@ -549,18 +549,18 @@ EVP_add_digest(EVP_sha256()); *************************************************/ /* If dhparam is set, expand it, and load up the parameters for DH encryption. +Server only. Arguments: sctx The current SSL CTX (inbound or outbound) dhparam DH parameter file or fixed parameter identity string - host connected host, if client; NULL if server errstr error string pointer Returns: TRUE if OK (nothing to set up, or setup worked) */ static BOOL -init_dh(SSL_CTX * sctx, uschar * dhparam, const host_item * host, uschar ** errstr) +init_dh(SSL_CTX * sctx, uschar * dhparam, uschar ** errstr) { BIO * bio; #if OPENSSL_VERSION_NUMBER < 0x30000000L @@ -582,7 +582,7 @@ else if (dhexpanded[0] == '/') if (!(bio = BIO_new_file(CS dhexpanded, "r"))) { tls_error(string_sprintf("could not read dhparams file %s", dhexpanded), - host, US strerror(errno), errstr); + NULL, US strerror(errno), errstr); return FALSE; } } @@ -597,7 +597,7 @@ else if (!(pem = std_dh_prime_named(dhexpanded))) { tls_error(string_sprintf("Unknown standard DH prime \"%s\"", dhexpanded), - host, US strerror(errno), errstr); + NULL, US strerror(errno), errstr); return FALSE; } bio = BIO_new_mem_buf(CS pem, -1); @@ -613,7 +613,7 @@ if (!( { BIO_free(bio); tls_error(string_sprintf("Could not read tls_dhparams \"%s\"", dhexpanded), - host, NULL, errstr); + NULL, NULL, errstr); return FALSE; } @@ -636,7 +636,7 @@ dh_bitsize = EVP_PKEY_get_bits(pkey); /* Even if it is larger, we silently return success rather than cause things to fail out, so that a too-large DH will not knock out all TLS; it's a debatable -choice. */ +choice. Likewise for a failing attempt to set one. */ if (dh_bitsize <= tls_dh_max_bits) { @@ -646,28 +646,29 @@ if (dh_bitsize <= tls_dh_max_bits) #else SSL_CTX_set0_tmp_dh_pkey(sctx, pkey) #endif - == 0) + == 0) { - DEBUG(D_tls) debug_printf("failed to set D-H parameters\n"); -#if OPENSSL_VERSION_NUMBER < 0x30000000L - DH_free(dh); -#else - EVP_PKEY_free(pkey); + ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring)); + log_write(0, LOG_MAIN|LOG_PANIC, "TLS error (D-H param setting '%s'): %s", + dhexpanded ? dhexpanded : US"default", ssl_errstring); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /* EVP_PKEY_free(pkey); crashes */ #endif - return FALSE; } - DEBUG(D_tls) - debug_printf("Diffie-Hellman initialized from %s with %d-bit prime\n", - dhexpanded ? dhexpanded : US"default", dh_bitsize); + else + DEBUG(D_tls) + debug_printf("Diffie-Hellman initialized from %s with %d-bit prime\n", + dhexpanded ? dhexpanded : US"default", dh_bitsize); } else DEBUG(D_tls) - debug_printf("dhparams file %d bits, is > tls_dh_max_bits limit of %d\n", - dh_bitsize, tls_dh_max_bits); + debug_printf("dhparams '%s' %d bits, is > tls_dh_max_bits limit of %d\n", + dhexpanded ? dhexpanded : US"default", dh_bitsize, tls_dh_max_bits); #if OPENSSL_VERSION_NUMBER < 0x30000000L DH_free(dh); #endif +/* The EVP_PKEY ownership stays with the ctx; do not free it */ BIO_free(bio); return TRUE; @@ -680,7 +681,7 @@ return TRUE; * Initialize for ECDH * *************************************************/ -/* Load parameters for ECDH encryption. +/* Load parameters for ECDH encryption. Server only. For now, we stick to NIST P-256 because: it's simple and easy to configure; it avoids any patent issues that might bite redistributors; despite events in @@ -698,14 +699,13 @@ Patches welcome. Arguments: sctx The current SSL CTX (inbound or outbound) - host connected host, if client; NULL if server errstr error string pointer Returns: TRUE if OK (nothing to set up, or setup worked) */ static BOOL -init_ecdh(SSL_CTX * sctx, host_item * host, uschar ** errstr) +init_ecdh(SSL_CTX * sctx, uschar ** errstr) { #ifdef OPENSSL_NO_ECDH return TRUE; @@ -715,9 +715,6 @@ uschar * exp_curve; int nid; BOOL rv; -if (host) /* No ECDH setup for clients, only for servers */ - return TRUE; - # ifndef EXIM_HAVE_ECDH DEBUG(D_tls) debug_printf("No OpenSSL API to define ECDH parameters, skipping\n"); @@ -764,7 +761,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef ) { tls_error(string_sprintf("Unknown curve name tls_eccurve '%s'", exp_curve), - host, NULL, errstr); + NULL, NULL, errstr); return FALSE; } @@ -773,7 +770,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef EC_KEY * ecdh; if (!(ecdh = EC_KEY_new_by_curve_name(nid))) { - tls_error(US"Unable to create ec curve", host, NULL, errstr); + tls_error(US"Unable to create ec curve", NULL, NULL, errstr); return FALSE; } @@ -781,7 +778,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef not to the stability of the interface. */ if ((rv = SSL_CTX_set_tmp_ecdh(sctx, ecdh) == 0)) - tls_error(string_sprintf("Error enabling '%s' curve", exp_curve), host, NULL, errstr); + tls_error(string_sprintf("Error enabling '%s' curve", exp_curve), NULL, NULL, errstr); else DEBUG(D_tls) debug_printf("ECDH: enabled '%s' curve\n", exp_curve); EC_KEY_free(ecdh); @@ -790,7 +787,7 @@ if ( (nid = OBJ_sn2nid (CCS exp_curve)) == NID_undef #else /* v 3.0.0 + */ if ((rv = SSL_CTX_set1_groups(sctx, &nid, 1)) == 0) - tls_error(string_sprintf("Error enabling '%s' group", exp_curve), host, NULL, errstr); + tls_error(string_sprintf("Error enabling '%s' group", exp_curve), NULL, NULL, errstr); else DEBUG(D_tls) debug_printf("ECDH: enabled '%s' group\n", exp_curve); @@ -1704,15 +1701,19 @@ state_server.lib_state.lib_ctx = ctx; if (opt_unset_or_noexpand(tls_dhparam)) { DEBUG(D_tls) debug_printf("TLS: preloading DH params for server\n"); - if (init_dh(ctx, tls_dhparam, NULL, &dummy_errstr)) + if (init_dh(ctx, tls_dhparam, &dummy_errstr)) state_server.lib_state.dh = TRUE; } +else + DEBUG(D_tls) debug_printf("TLS: not preloading DH params for server\n"); if (opt_unset_or_noexpand(tls_eccurve)) { DEBUG(D_tls) debug_printf("TLS: preloading ECDH curve for server\n"); - if (init_ecdh(ctx, NULL, &dummy_errstr)) + if (init_ecdh(ctx, &dummy_errstr)) state_server.lib_state.ecdh = TRUE; } +else + DEBUG(D_tls) debug_printf("TLS: not preloading ECDH curve for server\n"); #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) /* If we can, preload the server-side cert, key and ocsp */ @@ -1824,19 +1825,6 @@ ob->tls_preload.lib_ctx = ctx; tpt_dummy_state.lib_state = ob->tls_preload; -if (opt_unset_or_noexpand(tls_dhparam)) - { - DEBUG(D_tls) debug_printf("TLS: preloading DH params for transport '%s'\n", t->name); - if (init_dh(ctx, tls_dhparam, NULL, &dummy_errstr)) - ob->tls_preload.dh = TRUE; - } -if (opt_unset_or_noexpand(tls_eccurve)) - { - DEBUG(D_tls) debug_printf("TLS: preloading ECDH curve for transport '%s'\n", t->name); - if (init_ecdh(ctx, NULL, &dummy_errstr)) - ob->tls_preload.ecdh = TRUE; - } - #if defined(EXIM_HAVE_INOTIFY) || defined(EXIM_HAVE_KEVENT) if ( opt_set_and_noexpand(ob->tls_certificate) && opt_unset_or_noexpand(ob->tls_privatekey)) @@ -2146,8 +2134,8 @@ already exists. Might even need this selfsame callback, for reneg? */ SSL_CTX_set_tlsext_servername_arg(server_sni, state); } -if ( !init_dh(server_sni, state->dhparam, NULL, &dummy_errstr) - || !init_ecdh(server_sni, NULL, &dummy_errstr) +if ( !init_dh(server_sni, state->dhparam, &dummy_errstr) + || !init_ecdh(server_sni, &dummy_errstr) ) goto bad; @@ -2652,15 +2640,18 @@ will never be used because we use a new context every time. */ /* Initialize with DH parameters if supplied */ /* Initialize ECDH temp key parameter selection */ -if (state->lib_state.dh) - { DEBUG(D_tls) debug_printf("TLS: DH params were preloaded\n"); } -else - if (!init_dh(ctx, state->dhparam, host, errstr)) return DEFER; +if (!host) + { + if (state->lib_state.dh) + { DEBUG(D_tls) debug_printf("TLS: DH params were preloaded\n"); } + else + if (!init_dh(ctx, state->dhparam, errstr)) return DEFER; -if (state->lib_state.ecdh) - { DEBUG(D_tls) debug_printf("TLS: ECDH curve was preloaded\n"); } -else - if (!init_ecdh(ctx, host, errstr)) return DEFER; + if (state->lib_state.ecdh) + { DEBUG(D_tls) debug_printf("TLS: ECDH curve was preloaded\n"); } + else + if (!init_ecdh(ctx, errstr)) return DEFER; + } /* Set up certificate and key (and perhaps OCSP info) */ |