Implement a replacement for SSL_set_tmp_dh()

The old function took a DH as a parameter. In the new version we pass
an EVP_PKEY instead. Similarly for the SSL_CTX version of this function.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/13368)
This commit is contained in:
Matt Caswell 2020-10-15 16:45:54 +01:00
parent 9912be1b33
commit 163f6dc1f7
7 changed files with 102 additions and 88 deletions

View File

@ -21,6 +21,7 @@
#include <openssl/e_os2.h>
#include <openssl/async.h>
#include <openssl/ssl.h>
#include <openssl/decoder.h>
#ifndef OPENSSL_NO_SOCK
@ -71,9 +72,6 @@ static int generate_session_id(SSL *ssl, unsigned char *id,
unsigned int *id_len);
static void init_session_cache_ctx(SSL_CTX *sctx);
static void free_sessions(void);
#ifndef OPENSSL_NO_DH
static DH *load_dh_param(const char *dhfile);
#endif
static void print_connection_info(SSL *con);
static const int bufsize = 16 * 1024;
@ -2030,62 +2028,67 @@ int s_server_main(int argc, char *argv[])
if (alpn_ctx.data)
SSL_CTX_set_alpn_select_cb(ctx, alpn_cb, &alpn_ctx);
#ifndef OPENSSL_NO_DH
if (!no_dhe) {
DH *dh = NULL;
EVP_PKEY *dhpkey = NULL;
if (dhfile != NULL)
dh = load_dh_param(dhfile);
dhpkey = load_keyparams(dhfile, 0, "DH", "DH parameters");
else if (s_cert_file != NULL)
dh = load_dh_param(s_cert_file);
dhpkey = load_keyparams(s_cert_file, 0, "DH", "DH parameters");
if (dh != NULL) {
if (dhpkey != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
} else {
BIO_printf(bio_s_out, "Using default temp DH parameters\n");
}
(void)BIO_flush(bio_s_out);
if (dh == NULL) {
if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx, 1);
} else {
/*
* We need 2 references: one for use by ctx and one for use by
* ctx2
*/
if (!EVP_PKEY_up_ref(dhpkey)) {
EVP_PKEY_free(dhpkey);
goto end;
}
if (!SSL_CTX_set0_tmp_dh_pkey(ctx, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
/* Free 2 references */
EVP_PKEY_free(dhpkey);
EVP_PKEY_free(dhpkey);
goto end;
}
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
/* TODO(3.0): We need a 3.0 friendly way of doing this */
else if (!SSL_CTX_set_tmp_dh(ctx, dh)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
DH_free(dh);
goto end;
}
# endif
if (ctx2 != NULL) {
if (!dhfile) {
DH *dh2 = load_dh_param(s_cert_file2);
if (dh2 != NULL) {
if (dhfile != NULL) {
EVP_PKEY *dhpkey2 = load_keyparams(s_cert_file2, 0, "DH",
"DH parameters");
if (dhpkey2 != NULL) {
BIO_printf(bio_s_out, "Setting temp DH parameters\n");
(void)BIO_flush(bio_s_out);
DH_free(dh);
dh = dh2;
EVP_PKEY_free(dhpkey);
dhpkey = dhpkey2;
}
}
if (dh == NULL) {
if (dhpkey == NULL) {
SSL_CTX_set_dh_auto(ctx2, 1);
}
# ifndef OPENSSL_NO_DEPRECATED_3_0
/* TODO(3.0): We need a 3.0 friendly way of doing this */
else if (!SSL_CTX_set_tmp_dh(ctx2, dh)) {
} else if (!SSL_CTX_set0_tmp_dh_pkey(ctx2, dhpkey)) {
BIO_puts(bio_err, "Error setting temp DH parameters\n");
ERR_print_errors(bio_err);
DH_free(dh);
EVP_PKEY_free(dhpkey);
goto end;
}
# endif
dhpkey = NULL;
}
DH_free(dh);
EVP_PKEY_free(dhpkey);
}
#endif
if (!set_cert_key_stuff(ctx, s_cert, s_key, s_chain, build_chain))
goto end;
@ -3011,26 +3014,6 @@ static void print_connection_info(SSL *con)
(void)BIO_flush(bio_s_out);
}
#ifndef OPENSSL_NO_DH
static DH *load_dh_param(const char *dhfile)
{
# ifndef OPENSSL_NO_DEPRECATED_3_0
/* TODO(3.0): Use a decoder for this */
DH *ret = NULL;
BIO *bio;
if ((bio = BIO_new_file(dhfile, "r")) == NULL)
goto err;
ret = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
err:
BIO_free(bio);
return ret;
# else
return NULL;
# endif
}
#endif
static int www_body(int s, int stype, int prot, unsigned char *context)
{
char *buf = NULL;

View File

@ -1505,6 +1505,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_get_server_tmp_key(s, pk) \
SSL_get_peer_tmp_key(s, pk)
int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey);
int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey);
/*
* The following symbol names are old and obsolete. They are kept
* for compatibility reasons only and should not be used anymore.

View File

@ -3465,15 +3465,7 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(pkdh);
return 0;
}
EVP_PKEY_free(s->cert->dh_tmp);
s->cert->dh_tmp = pkdh;
return 1;
return SSL_set0_tmp_dh_pkey(s, pkdh);
}
break;
case SSL_CTRL_SET_TMP_DH_CB:
@ -3816,15 +3808,7 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
ERR_raise(ERR_LIB_SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(pkdh), 0, pkdh)) {
ERR_raise(ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(pkdh);
return 0;
}
EVP_PKEY_free(ctx->cert->dh_tmp);
ctx->cert->dh_tmp = pkdh;
return 1;
return SSL_CTX_set0_tmp_dh_pkey(ctx, pkdh);
}
case SSL_CTRL_SET_TMP_DH_CB:
{

View File

@ -11,7 +11,8 @@
#include "ssl_local.h"
#include <openssl/conf.h>
#include <openssl/objects.h>
#include <openssl/dh.h>
#include <openssl/decoder.h>
#include <openssl/core_dispatch.h>
#include "internal/nelem.h"
/*
@ -574,34 +575,51 @@ static int cmd_ClientCAStore(SSL_CONF_CTX *cctx, const char *value)
return cmd_RequestCAStore(cctx, value);
}
#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
/* TODO(3.0): We need a 3.0 friendly way of doing this */
static int cmd_DHParameters(SSL_CONF_CTX *cctx, const char *value)
{
int rv = 0;
DH *dh = NULL;
EVP_PKEY *dhpkey = NULL;
BIO *in = NULL;
if (cctx->ctx || cctx->ssl) {
SSL_CTX *sslctx = (cctx->ssl != NULL) ? cctx->ssl->ctx : cctx->ctx;
OSSL_DECODER_CTX *decoderctx = NULL;
if (cctx->ctx != NULL || cctx->ssl != NULL) {
in = BIO_new(BIO_s_file());
if (in == NULL)
goto end;
if (BIO_read_filename(in, value) <= 0)
goto end;
dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
if (dh == NULL)
decoderctx
= OSSL_DECODER_CTX_new_by_EVP_PKEY(&dhpkey, "PEM", NULL, "DH",
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
sslctx->libctx, sslctx->propq);
if (decoderctx == NULL
|| !OSSL_DECODER_from_bio(decoderctx, in)) {
OSSL_DECODER_CTX_free(decoderctx);
goto end;
} else
}
OSSL_DECODER_CTX_free(decoderctx);
if (dhpkey == NULL)
goto end;
} else {
return 1;
if (cctx->ctx)
rv = SSL_CTX_set_tmp_dh(cctx->ctx, dh);
if (cctx->ssl)
rv = SSL_set_tmp_dh(cctx->ssl, dh);
}
if (cctx->ctx != NULL) {
if ((rv = SSL_CTX_set0_tmp_dh_pkey(cctx->ctx, dhpkey)) > 0)
dhpkey = NULL;
}
if (cctx->ssl != NULL) {
if ((rv = SSL_set0_tmp_dh_pkey(cctx->ssl, dhpkey)) > 0)
dhpkey = NULL;
}
end:
DH_free(dh);
EVP_PKEY_free(dhpkey);
BIO_free(in);
return rv > 0;
}
#endif
static int cmd_RecordPadding(SSL_CONF_CTX *cctx, const char *value)
{
@ -727,11 +745,9 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD(ClientCAStore, NULL,
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_STORE),
#if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
SSL_CONF_CMD(DHParameters, "dhparam",
SSL_CONF_FLAG_SERVER | SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
#endif
SSL_CONF_CMD_STRING(RecordPadding, "record_padding", 0),
SSL_CONF_CMD_STRING(NumTickets, "num_tickets", SSL_CONF_FLAG_SERVER),
};

View File

@ -5955,3 +5955,29 @@ void ssl_evp_md_free(const EVP_MD *md)
EVP_MD_free((EVP_MD *)md);
}
}
int SSL_set0_tmp_dh_pkey(SSL *s, EVP_PKEY *dhpkey)
{
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(dhpkey), 0, dhpkey)) {
SSLerr(0, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(dhpkey);
return 0;
}
EVP_PKEY_free(s->cert->dh_tmp);
s->cert->dh_tmp = dhpkey;
return 1;
}
int SSL_CTX_set0_tmp_dh_pkey(SSL_CTX *ctx, EVP_PKEY *dhpkey)
{
if (!ssl_ctx_security(ctx, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(dhpkey), 0, dhpkey)) {
SSLerr(0, SSL_R_DH_KEY_TOO_SMALL);
EVP_PKEY_free(dhpkey);
return 0;
}
EVP_PKEY_free(ctx->cert->dh_tmp);
ctx->cert->dh_tmp = dhpkey;
return 1;
}

View File

@ -144,7 +144,7 @@ HMAC_CTX *ssl_hmac_get0_HMAC_CTX(SSL_HMAC *ctx)
}
/* Some deprecated public APIs pass DH objects */
#ifndef OPENSSL_NO_DH
# ifndef OPENSSL_NO_DH
EVP_PKEY *ssl_dh_to_pkey(DH *dh)
{
EVP_PKEY *ret;
@ -158,6 +158,6 @@ EVP_PKEY *ssl_dh_to_pkey(DH *dh)
}
return ret;
}
#endif
# endif
#endif

View File

@ -517,3 +517,5 @@ SSL_new_session_ticket ? 3_0_0 EXIST::FUNCTION:
SSL_get0_peer_certificate ? 3_0_0 EXIST::FUNCTION:
SSL_get1_peer_certificate ? 3_0_0 EXIST::FUNCTION:
SSL_load_client_CA_file_ex ? 3_0_0 EXIST::FUNCTION:
SSL_set0_tmp_dh_pkey ? 3_0_0 EXIST::FUNCTION:
SSL_CTX_set0_tmp_dh_pkey ? 3_0_0 EXIST::FUNCTION: