From 42b67ff7218877934abed2a738e164c0dea171b0 Mon Sep 17 00:00:00 2001 From: "Ned T. Crigler" Date: Sun, 26 Feb 2023 17:42:29 -0800 Subject: [PATCH 1/2] Fix compilation on Ubuntu 22.04 Starting with glibc 2.34 "The symbols __dn_comp, __dn_expand, __dn_skipname, __res_dnok, __res_hnok, __res_mailok, __res_mkquery, __res_nmkquery, __res_nquery, __res_nquerydomain, __res_nsearch, __res_nsend, __res_ownok, __res_query, __res_querydomain, __res_search, __res_send formerly in libresolv have been renamed and no longer have a __ prefix. They are now available in libc." https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html The hex_to_string array in include/dh.h also conflicts with OpenSSL, which OpenSSL 3.0 now complains about. --- configure.in | 4 ++-- include/dh.h | 2 +- include/resolv.h | 6 +++++- src/dh.c | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/configure.in b/configure.in index e76dee88..11720419 100644 --- a/configure.in +++ b/configure.in @@ -374,8 +374,7 @@ AC_C_INLINE dnl Checks for libraries. dnl Replace `main' with a function in -lnsl: AC_CHECK_LIB(nsl, gethostbyname) -AC_CHECK_FUNC(res_mkquery,, AC_CHECK_LIB(resolv, res_mkquery)) -AC_CHECK_FUNC(__res_mkquery,, AC_CHECK_LIB(resolv, __res_mkquery)) +AC_SEARCH_LIBS([res_mkquery],[resolv],,AC_SEARCH_LIBS([__res_mkquery],[resolv])) AC_CHECK_LIB(socket, socket, zlib) AC_CHECK_FUNC(crypt,, AC_CHECK_LIB(descrypt, crypt,,AC_CHECK_LIB(crypt, crypt,,))) @@ -406,6 +405,7 @@ AC_CHECK_FUNCS([strcasecmp strchr strdup strerror strncasecmp strrchr strtol]) AC_CHECK_FUNCS([strtoul index strerror strtoken strtok inet_addr inet_netof]) AC_CHECK_FUNCS([inet_aton gettimeofday lrand48 sigaction bzero bcmp bcopy]) AC_CHECK_FUNCS([dn_skipname __dn_skipname getrusage times break]) +AC_CHECK_FUNCS([res_init __res_init res_mkquery __res_mkquery dn_expand __dn_expand]) dnl check for various OSes diff --git a/include/dh.h b/include/dh.h index 1ca6996a..1817ce1e 100644 --- a/include/dh.h +++ b/include/dh.h @@ -45,7 +45,7 @@ struct session_info static BIGNUM *ircd_prime; static BIGNUM *ircd_generator; -static char *hex_to_string[256] = +static char *dh_hex_to_string[256] = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", diff --git a/include/resolv.h b/include/resolv.h index b5a8aaa1..5b042d43 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -106,9 +106,13 @@ extern struct state _res; extern char *p_cdname(), *p_rr(), *p_type(), *p_class(), *p_time(); -#if ((__GNU_LIBRARY__ == 6) && (__GLIBC__ >=2) && (__GLIBC_MINOR__ >= 2)) +#if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT) #define res_init __res_init +#endif +#if !defined(HAVE_RES_MKQUERY) && defined(HAVE___RES_MKQUERY) #define res_mkquery __res_mkquery +#endif +#if !defined(HAVE_DN_EXPAND) && defined(HAVE___DN_EXPAND) #define dn_expand __dn_expand #endif diff --git a/src/dh.c b/src/dh.c index cb065a4f..4b5da282 100644 --- a/src/dh.c +++ b/src/dh.c @@ -223,7 +223,7 @@ static void create_prime() for(i = 0; i < PRIME_BYTES; i++) { - char *x = hex_to_string[dh_prime_1024[i]]; + char *x = dh_hex_to_string[dh_prime_1024[i]]; while(*x) buf[bufpos++] = *x++; } From 135ebbea4c30e23228d00af762fa7da7ca5016bd Mon Sep 17 00:00:00 2001 From: "Ned T. Crigler" Date: Mon, 22 May 2023 15:31:54 -0700 Subject: [PATCH 2/2] Update the dh code to work with OpenSSL 3.0 --- include/dh.h | 8 ++++ src/dh.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 123 insertions(+), 5 deletions(-) diff --git a/include/dh.h b/include/dh.h index 1817ce1e..705e6dee 100644 --- a/include/dh.h +++ b/include/dh.h @@ -22,7 +22,11 @@ extern void rc4_destroystate(void *a); struct session_info { +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH *dh; +#else + EVP_PKEY *dh; +#endif unsigned char *session_shared; size_t session_shared_length; }; @@ -45,6 +49,10 @@ struct session_info static BIGNUM *ircd_prime; static BIGNUM *ircd_generator; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static EVP_PKEY *ircd_prime_ossl3; +#endif + static char *dh_hex_to_string[256] = { "00", "01", "02", "03", "04", "05", "06", "07", diff --git a/src/dh.c b/src/dh.c index 4b5da282..f74d2d76 100644 --- a/src/dh.c +++ b/src/dh.c @@ -36,6 +36,11 @@ #include #include "libcrypto-compat.h" +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif + #include "memcount.h" #define DH_HEADER @@ -215,7 +220,7 @@ static int init_random() return 0; } -static void create_prime() +static int create_prime() { char buf[PRIME_BYTES_HEX]; int i; @@ -233,6 +238,34 @@ static void create_prime() BN_hex2bn(&ircd_prime, buf); ircd_generator = BN_new(); BN_set_word(ircd_generator, dh_gen_1024); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM_BLD *paramBuild = NULL; + OSSL_PARAM *param = NULL; + EVP_PKEY_CTX *primeCtx = NULL; + + if(!(paramBuild = OSSL_PARAM_BLD_new()) || + !OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_P, ircd_prime) || + !OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_G, ircd_generator) || + !(param = OSSL_PARAM_BLD_to_param(paramBuild)) || + !(primeCtx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL)) || + EVP_PKEY_fromdata_init(primeCtx) <= 0 || + EVP_PKEY_fromdata(primeCtx, &ircd_prime_ossl3, + EVP_PKEY_KEY_PARAMETERS, param) <= 0 || + 1) + { + if(primeCtx) + EVP_PKEY_CTX_free(primeCtx); + if(param) + OSSL_PARAM_free(param); + if(paramBuild) + OSSL_PARAM_BLD_free(paramBuild); + } + + if(!ircd_prime_ossl3) + return -1; +#endif + return 0; } int dh_init() @@ -241,8 +274,7 @@ int dh_init() ERR_load_crypto_strings(); #endif - create_prime(); - if(init_random() == -1) + if(create_prime() == -1 || init_random() == -1) return -1; return 0; } @@ -250,7 +282,7 @@ int dh_init() int dh_generate_shared(void *session, char *public_key) { BIGNUM *tmp; - int len; + size_t len; struct session_info *si = (struct session_info *) session; if(verify_is_hex(public_key) == 0 || !si || si->session_shared) @@ -261,13 +293,55 @@ int dh_generate_shared(void *session, char *public_key) if(!tmp) return 0; +#if OPENSSL_VERSION_NUMBER < 0x30000000L si->session_shared_length = DH_size(si->dh); si->session_shared = (unsigned char *) malloc(DH_size(si->dh)); len = DH_compute_key(si->session_shared, tmp, si->dh); +#else + OSSL_PARAM_BLD *paramBuild = NULL; + OSSL_PARAM *param = NULL; + EVP_PKEY_CTX *peerPubKeyCtx = NULL; + EVP_PKEY *peerPubKey = NULL; + EVP_PKEY_CTX *deriveCtx = NULL; + + len = -1; + if(!(paramBuild = OSSL_PARAM_BLD_new()) || + !OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_P, ircd_prime) || + !OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_FFC_G, ircd_generator) || + !OSSL_PARAM_BLD_push_BN(paramBuild, OSSL_PKEY_PARAM_PUB_KEY, tmp) || + !(param = OSSL_PARAM_BLD_to_param(paramBuild)) || + !(peerPubKeyCtx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL)) || + EVP_PKEY_fromdata_init(peerPubKeyCtx) <= 0 || + EVP_PKEY_fromdata(peerPubKeyCtx, &peerPubKey, + EVP_PKEY_PUBLIC_KEY, param) <= 0 || + !(deriveCtx = EVP_PKEY_CTX_new(si->dh, NULL)) || + EVP_PKEY_derive_init(deriveCtx) <= 0 || + EVP_PKEY_derive_set_peer(deriveCtx, peerPubKey) <= 0 || + EVP_PKEY_derive(deriveCtx, NULL, &len) <= 0 || + !(si->session_shared = malloc(len)) || + EVP_PKEY_derive(deriveCtx, si->session_shared, &len) <= 0 || + 1) + { + if(deriveCtx) + EVP_PKEY_CTX_free(deriveCtx); + if(peerPubKey) + EVP_PKEY_free(peerPubKey); + if(peerPubKeyCtx) + EVP_PKEY_CTX_free(peerPubKeyCtx); + if(param) + OSSL_PARAM_free(param); + if(paramBuild) + OSSL_PARAM_BLD_free(paramBuild); + } +#endif BN_free(tmp); - if(len < 0) + if(len == -1 || !si->session_shared) + { + if(si->session_shared) + free(si->session_shared); return 0; + } si->session_shared_length = len; @@ -284,6 +358,7 @@ void *dh_start_session() memset(si, 0, sizeof(struct session_info)); +#if OPENSSL_VERSION_NUMBER < 0x30000000L si->dh = DH_new(); if(si->dh == NULL) return NULL; @@ -304,7 +379,23 @@ void *dh_start_session() MyFree(si); return NULL; } +#else + EVP_PKEY_CTX *keyGenCtx = NULL; + if(!(keyGenCtx = EVP_PKEY_CTX_new_from_pkey(NULL, ircd_prime_ossl3, NULL)) || + EVP_PKEY_keygen_init(keyGenCtx) <= 0 || + EVP_PKEY_generate(keyGenCtx, &si->dh) <= 0 || + 1) + { + if(keyGenCtx) + EVP_PKEY_CTX_free(keyGenCtx); + } + if(!si->dh) + { + MyFree(si); + return NULL; + } +#endif return (void *) si; } @@ -312,6 +403,7 @@ void dh_end_session(void *session) { struct session_info *si = (struct session_info *) session; +#if OPENSSL_VERSION_NUMBER < 0x30000000L if(si->dh) { DH_free(si->dh); @@ -324,6 +416,13 @@ void dh_end_session(void *session) free(si->session_shared); si->session_shared = NULL; } +#else + if(si->dh) + { + EVP_PKEY_free(si->dh); + si->dh = NULL; + } +#endif MyFree(si); } @@ -333,6 +432,7 @@ char *dh_get_s_public(char *buf, size_t maxlen, void *session) struct session_info *si = (struct session_info *) session; char *tmp; +#if OPENSSL_VERSION_NUMBER < 0x30000000L if(!si || !si->dh) return NULL; @@ -343,6 +443,16 @@ char *dh_get_s_public(char *buf, size_t maxlen, void *session) return NULL; tmp = BN_bn2hex(pub_key); +#else + BIGNUM *pub_key = NULL; + + if(!si || !si->dh) + return NULL; + if(!EVP_PKEY_get_bn_param(si->dh, OSSL_PKEY_PARAM_PUB_KEY, &pub_key)) + return NULL; + tmp = BN_bn2hex(pub_key); + BN_free(pub_key); +#endif if(!tmp) return NULL;