From: W.C.A. Wijngaards Date: Mon, 2 Aug 2021 12:43:51 +0000 (+0200) Subject: - Move RSA and DSA to use OpenSSL 3.0.0 API. X-Git-Tag: release-1.13.2rc1~16^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d242bfb73b90bdb1f34c1072dfab49f21729ccb6;p=thirdparty%2Funbound.git - Move RSA and DSA to use OpenSSL 3.0.0 API. --- diff --git a/config.h.in b/config.h.in index 3d45a0953..8fdf83e74 100644 --- a/config.h.in +++ b/config.h.in @@ -429,6 +429,9 @@ /* Define to 1 if you have the `OPENSSL_init_ssl' function. */ #undef HAVE_OPENSSL_INIT_SSL +/* Define to 1 if you have the header file. */ +#undef HAVE_OPENSSL_PARAM_BUILD_H + /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_RAND_H @@ -438,6 +441,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_SSL_H +/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */ +#undef HAVE_OSSL_PARAM_BLD_NEW + /* Define if you have POSIX threads libraries and header files. */ #undef HAVE_PTHREAD diff --git a/configure b/configure index ede92e732..84c97357f 100755 --- a/configure +++ b/configure @@ -18411,7 +18411,7 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h +for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default @@ -18425,7 +18425,7 @@ fi done -for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params +for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 933529690..2ec11b970 100644 --- a/configure.ac +++ b/configure.ac @@ -859,8 +859,8 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/ else AC_MSG_RESULT([no]) fi -AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params]) +AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h],,, [AC_INCLUDES_DEFAULT]) +AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new]) # these check_funcs need -lssl BAKLIBS="$LIBS" diff --git a/doc/Changelog b/doc/Changelog index 8557baf18..686203b8e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,6 +1,7 @@ 2 August 2021: Wouter - Prepare for OpenSSL 3.0.0 provider API usage, move the sldns keyraw functions to produce EVP_PKEY results. + - Move RSA and DSA to use OpenSSL 3.0.0 API. 30 July 2021: Wouter - Fix #515: Compilation against openssl 3.0.0 beta2 is failing to diff --git a/sldns/keyraw.c b/sldns/keyraw.c index 34cf94332..ce94dd74e 100644 --- a/sldns/keyraw.c +++ b/sldns/keyraw.c @@ -26,11 +26,15 @@ #ifdef HAVE_OPENSSL_BN_H #include #endif -#ifdef HAVE_OPENSSL_RSA_H -#include -#endif -#ifdef HAVE_OPENSSL_DSA_H -#include +#ifdef HAVE_OPENSSL_PARAM_BUILD_H +# include +#else +# ifdef HAVE_OPENSSL_RSA_H +# include +# endif +# ifdef HAVE_OPENSSL_DSA_H +# include +# endif #endif #endif /* HAVE_SSL */ @@ -191,45 +195,59 @@ void sldns_key_EVP_unload_gost(void) } #endif /* USE_GOST */ -DSA * -sldns_key_buf2dsa_raw(unsigned char* key, size_t len) +/* Retrieve params as BIGNUM from raw buffer */ +static int +sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p, + BIGNUM** q, BIGNUM** g, BIGNUM** y) { uint8_t T; uint16_t length; uint16_t offset; - DSA *dsa; - BIGNUM *Q; BIGNUM *P; - BIGNUM *G; BIGNUM *Y; if(len == 0) - return NULL; + return 0; T = (uint8_t)key[0]; length = (64 + T * 8); offset = 1; if (T > 8) { - return NULL; + return 0; } if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) - return NULL; + return 0; - Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); + *q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); offset += SHA_DIGEST_LENGTH; - P = BN_bin2bn(key+offset, (int)length, NULL); + *p = BN_bin2bn(key+offset, (int)length, NULL); offset += length; - G = BN_bin2bn(key+offset, (int)length, NULL); + *g = BN_bin2bn(key+offset, (int)length, NULL); offset += length; - Y = BN_bin2bn(key+offset, (int)length, NULL); + *y = BN_bin2bn(key+offset, (int)length, NULL); + if(!*q || !*p || !*g || !*y) { + BN_free(*q); + BN_free(*p); + BN_free(*g); + BN_free(*y); + return 0; + } + return 1; +} + +#ifndef HAVE_OSSL_PARAM_BLD_NEW +DSA * +sldns_key_buf2dsa_raw(unsigned char* key, size_t len) +{ + DSA *dsa; + BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL; + if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) { + return NULL; + } /* create the key and set its properties */ - if(!Q || !P || !G || !Y || !(dsa = DSA_new())) { - BN_free(Q); - BN_free(P); - BN_free(G); - BN_free(Y); + if(!(dsa = DSA_new())) { return NULL; } #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL) @@ -261,42 +279,110 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len) return dsa; } +#endif /* HAVE_OSSL_PARAM_BLD_NEW */ EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len) { +#ifdef HAVE_OSSL_PARAM_BLD_NEW + EVP_PKEY* evp_key = NULL; + EVP_PKEY_CTX* ctx; + BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL; + OSSL_PARAM_BLD* param_bld; + OSSL_PARAM* params = NULL; + if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) { + return NULL; + } + + param_bld = OSSL_PARAM_BLD_new(); + if(!param_bld) { + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return NULL; + } + if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) || + !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) || + !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) || + !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) { + OSSL_PARAM_BLD_free(param_bld); + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return NULL; + } + params = OSSL_PARAM_BLD_to_param(param_bld); + OSSL_PARAM_BLD_free(param_bld); + + ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL); + if(!ctx) { + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return NULL; + } + if(EVP_PKEY_fromdata_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return NULL; + } + if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return NULL; + } + + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(y); + return evp_key; +#else DSA* dsa; EVP_PKEY* evp_key = EVP_PKEY_new(); if(!evp_key) { - return 0; + return NULL; } dsa = sldns_key_buf2dsa_raw(key, len); if(!dsa) { EVP_PKEY_free(evp_key); - return 0; + return NULL; } if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) { DSA_free(dsa); EVP_PKEY_free(evp_key); - return 0; + return NULL; } return evp_key; +#endif } -RSA * -sldns_key_buf2rsa_raw(unsigned char* key, size_t len) +/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */ +static int +sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n, + BIGNUM** e) { uint16_t offset; uint16_t exp; uint16_t int16; - RSA *rsa; - BIGNUM *modulus; - BIGNUM *exponent; if (len == 0) - return NULL; + return 0; if (key[0] == 0) { if(len < 3) - return NULL; + return 0; memmove(&int16, key+1, 2); exp = ntohs(int16); offset = 3; @@ -307,23 +393,34 @@ sldns_key_buf2rsa_raw(unsigned char* key, size_t len) /* key length at least one */ if(len < (size_t)offset + exp + 1) - return NULL; + return 0; /* Exponent */ - exponent = BN_new(); - if(!exponent) return NULL; - (void) BN_bin2bn(key+offset, (int)exp, exponent); + *e = BN_new(); + if(!*e) return 0; + (void) BN_bin2bn(key+offset, (int)exp, *e); offset += exp; /* Modulus */ - modulus = BN_new(); - if(!modulus) { - BN_free(exponent); - return NULL; + *n = BN_new(); + if(!*n) { + BN_free(*e); + return 0; } /* length of the buffer must match the key length! */ - (void) BN_bin2bn(key+offset, (int)(len - offset), modulus); + (void) BN_bin2bn(key+offset, (int)(len - offset), *n); + return 1; +} +#ifndef HAVE_OSSL_PARAM_BLD_NEW +RSA * +sldns_key_buf2rsa_raw(unsigned char* key, size_t len) +{ + BIGNUM* modulus = NULL; + BIGNUM* exponent = NULL; + RSA *rsa; + if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent)) + return NULL; rsa = RSA_new(); if(!rsa) { BN_free(exponent); @@ -347,25 +444,86 @@ sldns_key_buf2rsa_raw(unsigned char* key, size_t len) return rsa; } +#endif /* HAVE_OSSL_PARAM_BLD_NEW */ EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len) { +#ifdef HAVE_OSSL_PARAM_BLD_NEW + EVP_PKEY* evp_key = NULL; + EVP_PKEY_CTX* ctx; + BIGNUM *n=NULL, *e=NULL; + OSSL_PARAM_BLD* param_bld; + OSSL_PARAM* params = NULL; + + if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) { + return NULL; + } + + param_bld = OSSL_PARAM_BLD_new(); + if(!param_bld) { + BN_free(n); + BN_free(e); + return NULL; + } + if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) { + OSSL_PARAM_BLD_free(param_bld); + BN_free(n); + BN_free(e); + return NULL; + } + if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) { + OSSL_PARAM_BLD_free(param_bld); + BN_free(n); + BN_free(e); + return NULL; + } + params = OSSL_PARAM_BLD_to_param(param_bld); + OSSL_PARAM_BLD_free(param_bld); + + ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); + if(!ctx) { + BN_free(n); + BN_free(e); + return NULL; + } + if(EVP_PKEY_fromdata_init(ctx) <= 0) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(n); + BN_free(e); + return NULL; + } + if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(n); + BN_free(e); + return NULL; + } + + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_free(params); + BN_free(n); + BN_free(e); + return evp_key; +#else RSA* rsa; EVP_PKEY *evp_key = EVP_PKEY_new(); if(!evp_key) { - return 0; + return NULL; } rsa = sldns_key_buf2rsa_raw(key, len); if(!rsa) { EVP_PKEY_free(evp_key); - return 0; + return NULL; } if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) { RSA_free(rsa); EVP_PKEY_free(evp_key); - return 0; + return NULL; } return evp_key; +#endif } #ifdef USE_GOST diff --git a/sldns/keyraw.h b/sldns/keyraw.h index 0166129b3..b1f19740c 100644 --- a/sldns/keyraw.h +++ b/sldns/keyraw.h @@ -57,6 +57,7 @@ int sldns_key_EVP_load_gost_id(void); /** Release the engine reference held for the GOST engine. */ void sldns_key_EVP_unload_gost(void); +#ifndef HAVE_OSSL_PARAM_BLD_NEW /** * Like sldns_key_buf2dsa, but uses raw buffer. * \param[in] key the uncompressed wireformat of the key. @@ -64,6 +65,7 @@ void sldns_key_EVP_unload_gost(void); * \return a DSA * structure with the key material */ DSA *sldns_key_buf2dsa_raw(unsigned char* key, size_t len); +#endif /** * Converts a holding buffer with DSA key material to EVP PKEY in openssl. @@ -92,6 +94,7 @@ EVP_PKEY* sldns_gost2pkey_raw(unsigned char* key, size_t keylen); */ EVP_PKEY* sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); +#ifndef HAVE_OSSL_PARAM_BLD_NEW /** * Like sldns_key_buf2rsa, but uses raw buffer. * \param[in] key the uncompressed wireformat of the key. @@ -99,6 +102,7 @@ EVP_PKEY* sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo); * \return a RSA * structure with the key material */ RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len); +#endif /** * Converts a holding buffer with RSA key material to EVP PKEY in openssl.