From: Tobias Brunner Date: Fri, 4 Mar 2022 09:49:04 +0000 (+0100) Subject: openssl: Fixes for HMAC with OpenSSL 3.0 X-Git-Tag: 5.9.6rc1~1^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=db0c53c20788e7375d755501b93aae382f3337cc;p=thirdparty%2Fstrongswan.git openssl: Fixes for HMAC with OpenSSL 3.0 --- diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index d186134e20..e4fe7fa768 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hmac.c +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -42,6 +42,10 @@ #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif + #include "openssl_hmac.h" #include @@ -60,6 +64,19 @@ struct private_mac_t { */ mac_t public; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /** + * HMAC context + */ + EVP_MAC_CTX *hmac; + + /** + * Base context because EVP_MAC_init() does not reset the internal state if + * no key is passed, so the above is a copy that's replaced with every + * reset that does not change the key + */ + EVP_MAC_CTX *hmac_base; +#else /** * Hasher to use */ @@ -69,6 +86,7 @@ struct private_mac_t { * Current HMAC context */ HMAC_CTX *hmac; +#endif #if OPENSSL_VERSION_NUMBER < 0x10100000L /** @@ -84,16 +102,20 @@ struct private_mac_t { */ static bool reset(private_mac_t *this, chunk_t key) { -#if OPENSSL_VERSION_NUMBER >= 0x10000000L +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (!key.len || EVP_MAC_init(this->hmac_base, key.ptr, key.len, NULL)) + { + EVP_MAC_CTX_free(this->hmac); + this->hmac = EVP_MAC_CTX_dup(this->hmac_base); + return TRUE; + } +#else if (HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL)) { return TRUE; } - return FALSE; -#else /* OPENSSL_VERSION_NUMBER < 1.0 */ - HMAC_Init_ex(this->hmac, key.ptr, key.len, this->hasher, NULL); - return TRUE; #endif + return FALSE; } METHOD(mac_t, set_key, bool, @@ -104,46 +126,62 @@ METHOD(mac_t, set_key, bool, * use a lengthy string in case there is a limit in FIPS-mode */ key = chunk_from_str("00000000000000000000000000000000"); } - return reset(this, key); + if (!reset(this, key)) + { + return FALSE; + } + return TRUE; +} + +METHOD(mac_t, get_mac_size, size_t, + private_mac_t *this) +{ +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + return EVP_MAC_CTX_get_mac_size(this->hmac); +#else + return EVP_MD_size(this->hasher); +#endif } METHOD(mac_t, get_mac, bool, private_mac_t *this, chunk_t data, uint8_t *out) { -#if OPENSSL_VERSION_NUMBER >= 0x10000000L +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (!EVP_MAC_update(this->hmac, data.ptr, data.len)) + { + return FALSE; + } +#else if (!HMAC_Update(this->hmac, data.ptr, data.len)) { return FALSE; } - if (out == NULL) +#endif + if (!out) { return TRUE; } - if (!HMAC_Final(this->hmac, out, NULL)) +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (!EVP_MAC_final(this->hmac, out, NULL, get_mac_size(this))) { return FALSE; } -#else /* OPENSSL_VERSION_NUMBER < 1.0 */ - HMAC_Update(this->hmac, data.ptr, data.len); - if (out == NULL) +#else + if (!HMAC_Final(this->hmac, out, NULL)) { - return TRUE; + return FALSE; } - HMAC_Final(this->hmac, out, NULL); #endif return reset(this, chunk_empty); } -METHOD(mac_t, get_mac_size, size_t, - private_mac_t *this) -{ - return EVP_MD_size(this->hasher); -} - METHOD(mac_t, destroy, void, private_mac_t *this) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_CTX_free(this->hmac_base); + EVP_MAC_CTX_free(this->hmac); +#elif OPENSSL_VERSION_NUMBER >= 0x10100000L HMAC_CTX_free(this->hmac); #else HMAC_CTX_cleanup(&this->hmac_ctx); @@ -172,21 +210,41 @@ static mac_t *hmac_create(hash_algorithm_t algo) .set_key = _set_key, .destroy = _destroy, }, - .hasher = EVP_get_digestbyname(name), ); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + OSSL_PARAM params[] = { + OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_DIGEST, name, 0), + OSSL_PARAM_END, + }; + EVP_MAC *mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + + if (!mac) + { + free(this); + return NULL; + } + this->hmac_base = EVP_MAC_CTX_new(mac); + EVP_MAC_free(mac); + if (!this->hmac_base || !EVP_MAC_CTX_set_params(this->hmac_base, params)) + { + free(this); + return NULL; + } +#else /* OPENSSL_VERSION_NUMBER */ + this->hasher = EVP_get_digestbyname(name); if (!this->hasher) { free(this); return NULL; } - #if OPENSSL_VERSION_NUMBER >= 0x10100000L this->hmac = HMAC_CTX_new(); #else HMAC_CTX_init(&this->hmac_ctx); this->hmac = &this->hmac_ctx; #endif +#endif /* OPENSSL_VERSION_NUMBER */ /* make sure the underlying hash algorithm is supported */ if (!set_key(this, chunk_empty))