diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 828af2acfac0ee..dddf46e8a34703 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -78,7 +78,9 @@ private static bool DisableTlsResume // This is helper function to adjust requested protocols based on CipherSuitePolicy and system capability. private static SslProtocols CalculateEffectiveProtocols(SslAuthenticationOptions sslAuthenticationOptions) { - SslProtocols protocols = sslAuthenticationOptions.EnabledSslProtocols; + // make sure low bit is not set since we use it in context dictionary to distinguish use with ALPN + Debug.Assert(((int)sslAuthenticationOptions.EnabledSslProtocols & 1) == 0); + SslProtocols protocols = sslAuthenticationOptions.EnabledSslProtocols & ~((SslProtocols)1); if (!Interop.Ssl.Tls13Supported) { @@ -122,7 +124,7 @@ private static SslProtocols CalculateEffectiveProtocols(SslAuthenticationOptions } // This essentially wraps SSL_CTX* aka SSL_CTX_new + setting - internal static SafeSslContextHandle AllocateSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions, SslProtocols protocols) + internal static SafeSslContextHandle AllocateSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions, SslProtocols protocols, bool enableResume) { SafeX509Handle? certHandle = credential.CertHandle; SafeEvpPKeyHandle? certKeyHandle = credential.CertKeyHandle; @@ -181,6 +183,8 @@ internal static SafeSslContextHandle AllocateSslContext(SafeFreeSslCredentials c // https://www.openssl.org/docs/manmaster/ssl/SSL_shutdown.html Ssl.SslCtxSetQuietShutdown(sslCtx); + Ssl.SslCtxSetCaching(sslCtx, enableResume ? 1 : 0); + if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0) { unsafe @@ -222,24 +226,24 @@ internal static SafeSslHandle AllocateSslHandle(SafeFreeSslCredentials credentia SafeSslContextHandle? sslCtxHandle = null; SafeSslContextHandle? newCtxHandle = null; SslProtocols protocols = CalculateEffectiveProtocols(sslAuthenticationOptions); + bool hasAlpn = sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0; bool cacheSslContext = !DisableTlsResume && sslAuthenticationOptions.EncryptionPolicy == EncryptionPolicy.RequireEncryption && + sslAuthenticationOptions.IsServer && sslAuthenticationOptions.CertificateContext != null && sslAuthenticationOptions.CertificateContext.SslContexts != null && - sslAuthenticationOptions.CipherSuitesPolicy == null && - (!sslAuthenticationOptions.IsServer || - (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)); + sslAuthenticationOptions.CipherSuitesPolicy == null; if (cacheSslContext) { - sslAuthenticationOptions.CertificateContext!.SslContexts!.TryGetValue(protocols, out sslCtxHandle); + sslAuthenticationOptions.CertificateContext!.SslContexts!.TryGetValue(protocols | (SslProtocols)(hasAlpn ? 1 : 0), out sslCtxHandle); } if (sslCtxHandle == null) { // We did not get SslContext from cache - sslCtxHandle = newCtxHandle = AllocateSslContext(credential, sslAuthenticationOptions, protocols); + sslCtxHandle = newCtxHandle = AllocateSslContext(credential, sslAuthenticationOptions, protocols, cacheSslContext); - if (cacheSslContext && sslAuthenticationOptions.CertificateContext!.SslContexts!.TryAdd(protocols, newCtxHandle)) + if (cacheSslContext && sslAuthenticationOptions.CertificateContext!.SslContexts!.TryAdd(protocols | (SslProtocols)(hasAlpn ? 1 : 0), newCtxHandle)) { newCtxHandle = null; } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs index 2406f48d2484d0..7401389a394f9e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtx.cs @@ -22,6 +22,9 @@ internal static partial class Ssl [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetAlpnSelectCb")] internal static unsafe partial void SslCtxSetAlpnSelectCb(SafeSslContextHandle ctx, delegate* unmanaged callback, IntPtr arg); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCaching")] + internal static unsafe partial void SslCtxSetCaching(SafeSslContextHandle ctx, int mode); + internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, X509Certificate2[] chain) { // send pre-computed list of intermediates. diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index 4a95b97756a32e..58900164894997 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -287,6 +287,7 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_IsSslRenegotiatePending) DllImportEntry(CryptoNative_IsSslStateOK) DllImportEntry(CryptoNative_SslCtxAddExtraChainCert) + DllImportEntry(CryptoNative_SslCtxSetCaching) DllImportEntry(CryptoNative_SslCtxSetCiphers) DllImportEntry(CryptoNative_SslCtxSetEncryptionPolicy) DllImportEntry(CryptoNative_SetCiphers) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index 2b4eb271b022a2..a76aebfa176416 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -475,6 +475,16 @@ void CryptoNative_SslSetVerifyPeer(SSL* ssl) SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_callback); } +void CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode) +{ + // We never reuse same CTX for both client and server + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_SESS_CACHE_MODE, mode ? SSL_SESS_CACHE_BOTH : SSL_SESS_CACHE_OFF, NULL); + if (mode == 0) + { + SSL_CTX_set_options(ctx, SSL_OP_NO_TICKET); + } +} + int32_t CryptoNative_SslCtxSetEncryptionPolicy(SSL_CTX* ctx, EncryptionPolicy policy) { switch (policy) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 0a18f7a764c17f..7b0925fa2cf6bf 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -144,6 +144,11 @@ Sets the specified protocols in the SSL_CTX options. */ PALEXPORT void CryptoNative_SslCtxSetProtocolOptions(SSL_CTX* ctx, SslProtocols protocols); +/* +Sets session caching. 0 is disabled. +*/ +PALEXPORT void CryptoNative_SslCtxSetCaching(SSL_CTX* ctx, int mode); + /* Shims the SSL_new method.