diff --git a/dotnet8.0.spec b/dotnet8.0.spec index 2be9dd9..c87496f 100644 --- a/dotnet8.0.spec +++ b/dotnet8.0.spec @@ -92,6 +92,8 @@ Patch2: vstest-intent-net8.0.patch Patch3: runtime-re-enable-implicit-rejection.patch # https://github.com/dotnet/msbuild/pull/9449 Patch4: msbuild-9449-exec-stop-setting-a-locale.patch +# https://github.com/dotnet/runtime/pull/104994 +Patch5: runtime-104994-openssl-engine.patch ExclusiveArch: aarch64 ppc64le s390x x86_64 diff --git a/runtime-104994-openssl-engine.patch b/runtime-104994-openssl-engine.patch new file mode 100644 index 0000000..488c93a --- /dev/null +++ b/runtime-104994-openssl-engine.patch @@ -0,0 +1,324 @@ +From 5eb7fd1d9909c3824caba0bc6a3f376557961aef Mon Sep 17 00:00:00 2001 +From: Kevin Jones +Date: Tue, 16 Jul 2024 16:56:59 -0400 +Subject: [PATCH 1/2] Light up support for OpenSSL ENGINEs only if they are + available. + +Some Linux distributions are phasing out support for OpenSSL 1.x ENGINEs. They are doing this by moving the header, `engine.h`, to a separate package or removing the header entirely. The actual OpenSSL shared libraries still contain the engine APIs. This makes the change an API, not ABI, break. + +We react to this by disabling OpenSSL engine support on non-portable builds that are missing the engine header. Portable builds will continue to probe the loaded OpenSSL library for support, and non-portable builds will only support ENGINEs if the header is present. +--- + .../Interop.EvpPkey.cs | 22 +++++-- + .../src/Resources/Strings.resx | 3 + + .../configure.cmake | 6 ++ + .../opensslshim.h | 36 ++++++++-- + .../pal_crypto_config.h.in | 1 + + .../pal_evp_pkey.c | 65 ++++++++++++++----- + .../pal_evp_pkey.h | 6 +- + 7 files changed, 109 insertions(+), 30 deletions(-) + +diff --git a/src/runtime/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/runtime/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +index 77b80634bd0ce..4e8659b5653b7 100644 +--- a/src/runtime/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs ++++ b/src/runtime/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +@@ -217,7 +217,8 @@ internal static ArraySegment RentEncodeSubjectPublicKeyInfo(SafeEvpPKeyHan + [LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)] + private static partial SafeEvpPKeyHandle CryptoNative_LoadPrivateKeyFromEngine( + string engineName, +- string keyName); ++ string keyName, ++ [MarshalAs(UnmanagedType.Bool)] out bool haveEngine); + + internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine( + string engineName, +@@ -226,7 +227,13 @@ internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine( + Debug.Assert(engineName is not null); + Debug.Assert(keyName is not null); + +- SafeEvpPKeyHandle pkey = CryptoNative_LoadPrivateKeyFromEngine(engineName, keyName); ++ SafeEvpPKeyHandle pkey = CryptoNative_LoadPrivateKeyFromEngine(engineName, keyName, out bool haveEngine); ++ ++ if (!haveEngine) ++ { ++ pkey.Dispose(); ++ throw new CryptographicException(SR.Cryptography_EnginesNotSupported); ++ } + + if (pkey.IsInvalid) + { +@@ -240,7 +247,8 @@ internal static SafeEvpPKeyHandle LoadPrivateKeyFromEngine( + [LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)] + private static partial SafeEvpPKeyHandle CryptoNative_LoadPublicKeyFromEngine( + string engineName, +- string keyName); ++ string keyName, ++ [MarshalAs(UnmanagedType.Bool)] out bool haveEngine); + + internal static SafeEvpPKeyHandle LoadPublicKeyFromEngine( + string engineName, +@@ -249,7 +257,13 @@ internal static SafeEvpPKeyHandle LoadPublicKeyFromEngine( + Debug.Assert(engineName is not null); + Debug.Assert(keyName is not null); + +- SafeEvpPKeyHandle pkey = CryptoNative_LoadPublicKeyFromEngine(engineName, keyName); ++ SafeEvpPKeyHandle pkey = CryptoNative_LoadPublicKeyFromEngine(engineName, keyName, out bool haveEngine); ++ ++ if (!haveEngine) ++ { ++ pkey.Dispose(); ++ throw new CryptographicException(SR.Cryptography_EnginesNotSupported); ++ } + + if (pkey.IsInvalid) + { +diff --git a/src/runtime/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx b/src/runtime/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +index 4bcfdcfd3454f..5cc5cce830a35 100644 +--- a/src/runtime/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx ++++ b/src/runtime/src/libraries/System.Security.Cryptography/src/Resources/Strings.resx +@@ -327,6 +327,9 @@ + + {0} unexpectedly produced a ciphertext with the incorrect length. + ++ ++ OpenSSL ENGINE is not available on this platform. ++ + + The total number of bytes extracted cannot exceed UInt32.MaxValue * hash length. + +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake +index 74ed49f5d1916..10a6b986268b0 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake +@@ -1,5 +1,6 @@ + include(CheckLibraryExists) + include(CheckFunctionExists) ++include(CheckSourceCompiles) + + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY}) +@@ -22,6 +23,11 @@ check_function_exists( + HAVE_OPENSSL_SHA3 + ) + ++check_source_compiles(C " ++#include ++int main(void) { ENGINE_init(NULL); return 1; }" ++HAVE_OPENSSL_ENGINE) ++ + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/pal_crypto_config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/pal_crypto_config.h) +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/runtime/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +index 57ba6a6809649..3d6d77895b64f 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/opensslshim.h ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +@@ -17,7 +17,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -46,6 +45,11 @@ + #include + #endif + ++#if HAVE_OPENSSL_ENGINE ++// Some Linux distributions build without engine support. ++#include ++#endif ++ + #if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_1_RTM + #define HAVE_OPENSSL_SET_CIPHERSUITES 1 + #else +@@ -168,6 +172,24 @@ const EVP_MD *EVP_shake256(void); + int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); + #endif + ++#if !HAVE_OPENSSL_ENGINE ++#undef HAVE_OPENSSL_ENGINE ++#define HAVE_OPENSSL_ENGINE 1 ++ ++ENGINE *ENGINE_by_id(const char *id); ++int ENGINE_init(ENGINE *e); ++int ENGINE_finish(ENGINE *e); ++ENGINE *ENGINE_new(void); ++int ENGINE_free(ENGINE *e); ++typedef EVP_PKEY *(*ENGINE_LOAD_KEY_PTR)(ENGINE *, const char *, ++ UI_METHOD *ui_method, ++ void *callback_data); ++EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, ++ UI_METHOD *ui_method, void *callback_data); ++EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id, ++ UI_METHOD *ui_method, void *callback_data); ++#endif ++ + #define API_EXISTS(fn) (fn != NULL) + + // List of all functions from the libssl that are used in the System.Security.Cryptography.Native. +@@ -298,12 +320,12 @@ int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len); + REQUIRED_FUNCTION(EC_POINT_mul) \ + REQUIRED_FUNCTION(EC_POINT_new) \ + REQUIRED_FUNCTION(EC_POINT_set_affine_coordinates_GFp) \ +- REQUIRED_FUNCTION(ENGINE_by_id) \ +- REQUIRED_FUNCTION(ENGINE_finish) \ +- REQUIRED_FUNCTION(ENGINE_free) \ +- REQUIRED_FUNCTION(ENGINE_init) \ +- REQUIRED_FUNCTION(ENGINE_load_public_key) \ +- REQUIRED_FUNCTION(ENGINE_load_private_key) \ ++ LIGHTUP_FUNCTION(ENGINE_by_id) \ ++ LIGHTUP_FUNCTION(ENGINE_finish) \ ++ LIGHTUP_FUNCTION(ENGINE_free) \ ++ LIGHTUP_FUNCTION(ENGINE_init) \ ++ LIGHTUP_FUNCTION(ENGINE_load_public_key) \ ++ LIGHTUP_FUNCTION(ENGINE_load_private_key) \ + REQUIRED_FUNCTION(ERR_clear_error) \ + REQUIRED_FUNCTION(ERR_error_string_n) \ + REQUIRED_FUNCTION(ERR_get_error) \ +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in +index d7aef5a7d1b67..30d1219eb98b0 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_crypto_config.h.in +@@ -4,3 +4,4 @@ + #cmakedefine01 HAVE_OPENSSL_ALPN + #cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305 + #cmakedefine01 HAVE_OPENSSL_SHA3 ++#cmakedefine01 HAVE_OPENSSL_ENGINE +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c +index 80183b97a77c9..dea4f277b8969 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.c +@@ -511,41 +511,72 @@ int32_t CryptoNative_EncodeSubjectPublicKeyInfo(EVP_PKEY* pkey, uint8_t* buf) + return i2d_PUBKEY(pkey, &buf); + } + ++#if HAVE_OPENSSL_ENGINE + static EVP_PKEY* LoadKeyFromEngine( + const char* engineName, + const char* keyName, +- ENGINE_LOAD_KEY_PTR load_func) ++ ENGINE_LOAD_KEY_PTR load_func, ++ int32_t* haveEngine) + { ++ assert(haveEngine); + ERR_clear_error(); + +- EVP_PKEY* ret = NULL; +- ENGINE* engine = NULL; ++ if (API_EXISTS(ENGINE_by_id) && API_EXISTS(ENGINE_init) && API_EXISTS(ENGINE_finish) && API_EXISTS(ENGINE_free)) ++ { ++ *haveEngine = 1; ++ EVP_PKEY* ret = NULL; ++ ENGINE* engine = NULL; + +- // Per https://github.com/openssl/openssl/discussions/21427 +- // using EVP_PKEY after freeing ENGINE is correct. +- engine = ENGINE_by_id(engineName); ++ // Per https://github.com/openssl/openssl/discussions/21427 ++ // using EVP_PKEY after freeing ENGINE is correct. ++ engine = ENGINE_by_id(engineName); + +- if (engine != NULL) +- { +- if (ENGINE_init(engine)) ++ if (engine != NULL) + { +- ret = load_func(engine, keyName, NULL, NULL); ++ if (ENGINE_init(engine)) ++ { ++ ret = load_func(engine, keyName, NULL, NULL); ++ ++ ENGINE_finish(engine); ++ } + +- ENGINE_finish(engine); ++ ENGINE_free(engine); + } + +- ENGINE_free(engine); ++ return ret; + } + +- return ret; ++ *haveEngine = 0; ++ return NULL; + } ++#endif + +-EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName) ++EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine) + { +- return LoadKeyFromEngine(engineName, keyName, ENGINE_load_private_key); ++#if HAVE_OPENSSL_ENGINE ++ if (API_EXISTS(ENGINE_load_private_key)) ++ { ++ return LoadKeyFromEngine(engineName, keyName, ENGINE_load_private_key, haveEngine); ++ } ++#endif ++ (void)engineName; ++ (void)keyName; ++ (void)haveEngine; ++ *haveEngine = 0; ++ return NULL; + } + +-EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName) ++EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine) + { +- return LoadKeyFromEngine(engineName, keyName, ENGINE_load_public_key); ++#if HAVE_OPENSSL_ENGINE ++ if (API_EXISTS(ENGINE_load_private_key)) ++ { ++ return LoadKeyFromEngine(engineName, keyName, ENGINE_load_public_key, haveEngine); ++ } ++#endif ++ (void)engineName; ++ (void)keyName; ++ (void)haveEngine; ++ *haveEngine = 0; ++ return NULL; + } +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h +index 64d289dc6f488..e4d5f85d4b9ec 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/pal_evp_pkey.h +@@ -93,12 +93,14 @@ PALEXPORT int32_t CryptoNative_EncodeSubjectPublicKeyInfo(EVP_PKEY* pkey, uint8_ + Load a named key, via ENGINE_load_private_key, from the named engine. + + Returns a valid EVP_PKEY* on success, NULL on failure. ++haveEngine is 1 if OpenSSL ENGINE's are supported, otherwise 0. + */ +-PALEXPORT EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName); ++PALEXPORT EVP_PKEY* CryptoNative_LoadPrivateKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine); + + /* + Load a named key, via ENGINE_load_public_key, from the named engine. + + Returns a valid EVP_PKEY* on success, NULL on failure. ++haveEngine is 1 if OpenSSL ENGINE's are supported, otherwise 0. + */ +-PALEXPORT EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName); ++PALEXPORT EVP_PKEY* CryptoNative_LoadPublicKeyFromEngine(const char* engineName, const char* keyName, int32_t* haveEngine); + +From c81f7a8f5000151edfac9f9d891121a01a64f1ba Mon Sep 17 00:00:00 2001 +From: Kevin Jones +Date: Wed, 17 Jul 2024 07:47:53 -0400 +Subject: [PATCH 2/2] Fix detection of ENGINE APIs with OpenSSL 3 + +--- + .../libs/System.Security.Cryptography.Native/configure.cmake | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake +index 10a6b986268b0..4a70e70899c5e 100644 +--- a/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake ++++ b/src/runtime/src/native/libs/System.Security.Cryptography.Native/configure.cmake +@@ -4,6 +4,7 @@ include(CheckSourceCompiles) + + set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) + set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY}) ++set(CMAKE_REQUIRED_DEFINITIONS -DOPENSSL_API_COMPAT=0x10100000L) + + check_function_exists( + EC_GF2m_simple_method