From 963465b4fa2918059a38b94a1b5be3b5862f0321 Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 17 Nov 2023 09:45:40 -0500 Subject: [PATCH 1/3] Re-enable MD5 for FIPS with OpenSSL 3 --- .../opensslshim.h | 2 ++ .../pal_evp.c | 30 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index efb0a9378ae77c..4d68062a88a9f0 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -326,6 +326,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); REQUIRED_FUNCTION(EVP_MD_CTX_copy_ex) \ RENAMED_FUNCTION(EVP_MD_CTX_free, EVP_MD_CTX_destroy) \ RENAMED_FUNCTION(EVP_MD_CTX_new, EVP_MD_CTX_create) \ + LIGHTUP_FUNCTION(EVP_MD_fetch) \ RENAMED_FUNCTION(EVP_MD_get_size, EVP_MD_size) \ REQUIRED_FUNCTION(EVP_PKCS82PKEY) \ REQUIRED_FUNCTION(EVP_PKEY2PKCS8) \ @@ -805,6 +806,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_MD_CTX_copy_ex EVP_MD_CTX_copy_ex_ptr #define EVP_MD_CTX_free EVP_MD_CTX_free_ptr #define EVP_MD_CTX_new EVP_MD_CTX_new_ptr +#define EVP_MD_fetch EVP_MD_fetch_ptr #define EVP_MD_get_size EVP_MD_get_size_ptr #define EVP_PKCS82PKEY EVP_PKCS82PKEY_ptr #define EVP_PKEY2PKCS8 EVP_PKEY2PKCS8_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c index fcdd1aef74f551..4af6047a059b3d 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -7,6 +7,32 @@ #define SUCCESS 1 +static const EVP_MD* g_evpFetchMd5 = NULL; +static pthread_once_t g_evpFetch = PTHREAD_ONCE_INIT; + +static void EnsureFetchEvpMdAlgorithms(void) +{ + // This is called from a pthread_once - this method should not be called directly. + +#if NEED_OPENSSL_3_0 + if (API_EXISTS(EVP_MD_fetch)) + { + ERR_clear_error(); + + // Try to fetch an MD5 implementation that will work regardless if + // FIPS is enforced or not. + g_evpFetchMd5 = EVP_MD_fetch(NULL, "MD5", "-fips"); + } +#endif + + // No error queue impact. + // If EVP_MD_fetch is unavailable, use the implicit loader. If it failed, use the implicit loader as a last resort. + if (g_evpFetchMd5 == NULL) + { + g_evpFetchMd5 = EVP_md5(); + } +} + EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type) { ERR_clear_error(); @@ -147,8 +173,8 @@ int32_t CryptoNative_EvpMdSize(const EVP_MD* md) const EVP_MD* CryptoNative_EvpMd5() { - // No error queue impact. - return EVP_md5(); + pthread_once(&g_evpFetch, EnsureFetchEvpMdAlgorithms); + return g_evpFetchMd5; } const EVP_MD* CryptoNative_EvpSha1() From 8af7e73b5668c0d4766728198a5280c4dc0ed1fd Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 17 Nov 2023 13:30:27 -0500 Subject: [PATCH 2/3] Permit MD5 on OpenSSL 1.1.1 regardless of FIPS --- .../System.Security.Cryptography.Native/opensslshim.h | 2 ++ .../osslcompat_30.h | 1 + .../libs/System.Security.Cryptography.Native/pal_evp.c | 10 +++++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 4d68062a88a9f0..efc0d4706027bb 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -326,6 +326,7 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); REQUIRED_FUNCTION(EVP_MD_CTX_copy_ex) \ RENAMED_FUNCTION(EVP_MD_CTX_free, EVP_MD_CTX_destroy) \ RENAMED_FUNCTION(EVP_MD_CTX_new, EVP_MD_CTX_create) \ + REQUIRED_FUNCTION(EVP_MD_CTX_set_flags) \ LIGHTUP_FUNCTION(EVP_MD_fetch) \ RENAMED_FUNCTION(EVP_MD_get_size, EVP_MD_size) \ REQUIRED_FUNCTION(EVP_PKCS82PKEY) \ @@ -806,6 +807,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_MD_CTX_copy_ex EVP_MD_CTX_copy_ex_ptr #define EVP_MD_CTX_free EVP_MD_CTX_free_ptr #define EVP_MD_CTX_new EVP_MD_CTX_new_ptr +#define EVP_MD_CTX_set_flags EVP_MD_CTX_set_flags_ptr #define EVP_MD_fetch EVP_MD_fetch_ptr #define EVP_MD_get_size EVP_MD_get_size_ptr #define EVP_PKCS82PKEY EVP_PKCS82PKEY_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h index 095dd3176e7aa4..5167f2a0fbcd11 100644 --- a/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/osslcompat_30.h @@ -19,6 +19,7 @@ void ERR_new(void); void ERR_set_debug(const char *file, int line, const char *func); void ERR_set_error(int lib, int reason, const char *fmt, ...); int EVP_CIPHER_get_nid(const EVP_CIPHER *e); +EVP_MD* EVP_MD_fetch(OSSL_LIB_CTX *ctx, const char *algorithm, const char *properties); int EVP_MD_get_size(const EVP_MD* md); int EVP_PKEY_CTX_set_rsa_keygen_bits(EVP_PKEY_CTX* ctx, int bits); int EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c index 4af6047a059b3d..687eb6c23900fb 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include "openssl.h" #include "pal_evp.h" #include @@ -14,7 +15,7 @@ static void EnsureFetchEvpMdAlgorithms(void) { // This is called from a pthread_once - this method should not be called directly. -#if NEED_OPENSSL_3_0 +#ifdef NEED_OPENSSL_3_0 if (API_EXISTS(EVP_MD_fetch)) { ERR_clear_error(); @@ -48,6 +49,13 @@ EVP_MD_CTX* CryptoNative_EvpMdCtxCreate(const EVP_MD* type) return NULL; } + // For OpenSSL 1.x, set the non-FIPS allow flag for MD5. OpenSSL 3 does this differently with EVP_MD_fetch + // and no longer has this flag. + if (CryptoNative_OpenSslVersionNumber() < OPENSSL_VERSION_3_0_RTM && type == EVP_md5()) + { + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); + } + int ret = EVP_DigestInit_ex(ctx, type, NULL); if (!ret) { From fcae10e18361584d5e1e8751f79105503138249d Mon Sep 17 00:00:00 2001 From: Kevin Jones Date: Fri, 17 Nov 2023 14:04:08 -0500 Subject: [PATCH 3/3] Fix build --- src/native/libs/System.Security.Cryptography.Native/pal_evp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c index 687eb6c23900fb..aa9ec3344aee44 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -5,6 +5,7 @@ #include "pal_evp.h" #include +#include #define SUCCESS 1