OpenSSL: Convert DH/DSA parameter loading to new API

OpenSSL 3.0 has deprecated low-level DH/DSA functions. Convert this
loading of the dh_file parameter to use newer API.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2022-04-16 11:32:21 +03:00
parent 28c1c91d03
commit bcd299b326

View file

@ -24,12 +24,18 @@
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif /* OPENSSL_NO_ENGINE */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/core_names.h>
#include <openssl/decoder.h>
#include <openssl/param_build.h>
#else /* OpenSSL version >= 3.0 */
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
#endif
#endif /* OpenSSL version >= 3.0 */
#include "common.h"
#include "crypto.h"
@ -3940,6 +3946,45 @@ static int tls_global_private_key(struct tls_data *data,
}
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#ifndef OPENSSL_NO_DH
#ifndef OPENSSL_NO_DSA
/* This is needed to replace the deprecated DSA_dup_DH() function */
static EVP_PKEY * openssl_dsa_to_dh(EVP_PKEY *dsa)
{
OSSL_PARAM_BLD *bld = NULL;
OSSL_PARAM *params = NULL;
BIGNUM *p = NULL, *q = NULL, *g = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL;
if (!EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_P, &p) ||
!EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_Q, &q) ||
!EVP_PKEY_get_bn_param(dsa, OSSL_PKEY_PARAM_FFC_G, &g) ||
!(bld = OSSL_PARAM_BLD_new()) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q) ||
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g) ||
!(params = OSSL_PARAM_BLD_to_param(bld)) ||
!(ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL)) ||
EVP_PKEY_fromdata_init(ctx) != 1 ||
EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEY_PARAMETERS,
params) != 1)
wpa_printf(MSG_INFO,
"TLS: Failed to convert DSA parameters to DH parameters");
EVP_PKEY_CTX_free(ctx);
OSSL_PARAM_free(params);
OSSL_PARAM_BLD_free(bld);
BN_free(p);
BN_free(q);
BN_free(g);
return pkey;
}
#endif /* !OPENSSL_NO_DSA */
#endif /* OPENSSL_NO_DH */
#endif /* OpenSSL version >= 3.0 */
static int tls_global_dh(struct tls_data *data, const char *dh_file)
{
#ifdef OPENSSL_NO_DH
@ -3949,6 +3994,74 @@ static int tls_global_dh(struct tls_data *data, const char *dh_file)
"dh_file specified");
return -1;
#else /* OPENSSL_NO_DH */
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
SSL_CTX *ssl_ctx = data->ssl;
BIO *bio;
OSSL_DECODER_CTX *ctx = NULL;
EVP_PKEY *pkey = NULL, *tmpkey = NULL;
bool dsa = false;
if (!dh_file)
return 0;
if (!ssl_ctx)
return -1;
bio = BIO_new_file(dh_file, "r");
if (!bio) {
wpa_printf(MSG_INFO, "TLS: Failed to open DH file '%s': %s",
dh_file, ERR_error_string(ERR_get_error(), NULL));
return -1;
}
ctx = OSSL_DECODER_CTX_new_for_pkey(
&tmpkey, "PEM", NULL, NULL,
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, NULL, NULL);
if (!ctx ||
OSSL_DECODER_from_bio(ctx, bio) != 1) {
wpa_printf(MSG_INFO,
"TLS: Failed to decode domain parameters from '%s': %s",
dh_file, ERR_error_string(ERR_get_error(), NULL));
BIO_free(bio);
return -1;
}
BIO_free(bio);
if (!tmpkey) {
wpa_printf(MSG_INFO, "TLS: Failed to load domain parameters");
return -1;
}
#ifndef OPENSSL_NO_DSA
if (EVP_PKEY_is_a(tmpkey, "DSA")) {
pkey = openssl_dsa_to_dh(tmpkey);
EVP_PKEY_free(tmpkey);
if (!pkey)
return -1;
dsa = true;
}
#endif /* !OPENSSL_NO_DSA */
if (!dsa) {
if (EVP_PKEY_is_a(tmpkey, "DH") ||
EVP_PKEY_is_a(tmpkey, "DHX")) {
} else {
wpa_printf(MSG_INFO,
"TLS: No DH parameters found in %s",
dh_file);
EVP_PKEY_free(tmpkey);
return -1;
}
pkey = tmpkey;
tmpkey = NULL;
}
if (SSL_CTX_set0_tmp_dh_pkey(ssl_ctx, pkey) != 1) {
wpa_printf(MSG_INFO,
"TLS: Failed to set DH params from '%s': %s",
dh_file, ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY_free(pkey);
return -1;
}
return 0;
#else /* OpenSSL version >= 3.0 */
SSL_CTX *ssl_ctx = data->ssl;
DH *dh;
BIO *bio;
@ -4010,6 +4123,7 @@ static int tls_global_dh(struct tls_data *data, const char *dh_file)
}
DH_free(dh);
return 0;
#endif /* OpenSSL version >= 3.0 */
#endif /* OPENSSL_NO_DH */
}