diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.PfxCertStoreFlags.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.PfxCertStoreFlags.cs index a345532a4eaf17..360b87d9b7d86d 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.PfxCertStoreFlags.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.PfxCertStoreFlags.cs @@ -18,6 +18,7 @@ internal enum PfxCertStoreFlags : int PKCS12_ALWAYS_CNG_KSP = 0x00000200, PKCS12_ALLOW_OVERWRITE_KEY = 0x00004000, PKCS12_NO_PERSIST_KEY = 0x00008000, + PKCS12_NAMED_NO_PERSIST_KEY = 0x00020000, PKCS12_INCLUDE_EXTENDED_PROPERTIES = 0x00000010, None = 0x00000000, } diff --git a/src/libraries/Common/tests/System/Net/Configuration.Certificates.Dynamic.cs b/src/libraries/Common/tests/System/Net/Configuration.Certificates.Dynamic.cs index fa20d1f374ce36..b2e89250c007d3 100644 --- a/src/libraries/Common/tests/System/Net/Configuration.Certificates.Dynamic.cs +++ b/src/libraries/Common/tests/System/Net/Configuration.Certificates.Dynamic.cs @@ -78,7 +78,8 @@ public static void CleanupCertificates([CallerMemberName] string? testName = nul } } } - catch { }; + catch { } + ; try { @@ -95,7 +96,8 @@ public static void CleanupCertificates([CallerMemberName] string? testName = nul } } } - catch { }; + catch { } + ; } internal static X509ExtensionCollection BuildTlsServerCertExtensions(string serverName) @@ -160,10 +162,10 @@ public static (X509Certificate2 certificate, X509Certificate2Collection) Generat responder.Dispose(); root.Dispose(); - if (!ephemeralKey && PlatformDetection.IsWindows) + if (PlatformDetection.IsWindows) { X509Certificate2 ephemeral = endEntity; - endEntity = X509CertificateLoader.LoadPkcs12(endEntity.Export(X509ContentType.Pfx), (string?)null, X509KeyStorageFlags.Exportable); + endEntity = X509CertificateLoader.LoadPkcs12(endEntity.Export(X509ContentType.Pfx), (string?)null, ephemeralKey ? X509KeyStorageFlags.EphemeralKeySet : X509KeyStorageFlags.Exportable); ephemeral.Dispose(); } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs index 7852a4c671f427..e5e40ef3da51eb 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/SslStreamNetworkStreamTest.cs @@ -938,7 +938,7 @@ public async Task SslStream_ClientCertificateContext_SendsChain(bool useTrust) TargetHost = "localhost", }; clientOptions.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; - clientOptions.ClientCertificateContext = SslStreamCertificateContext.Create(clientCertificate, useTrust ? null : clientChain, offline:true, trust); + clientOptions.ClientCertificateContext = SslStreamCertificateContext.Create(clientCertificate, useTrust ? null : clientChain, offline: true, trust); await SslStream_ClientSendsChain_Core(clientOptions, clientChain); @@ -952,10 +952,10 @@ public async Task SslStream_ClientCertificateContext_SendsChain(bool useTrust) [Fact] [PlatformSpecific(TestPlatforms.Windows)] - public async Task SslStream_EphemeralKey_Throws() + public async Task SslStream_EphemeralKey_DoesNotThrow() { - (X509Certificate2 serverCertificate, X509Certificate2Collection chain) = Configuration.Certificates.GenerateCertificates(nameof(SslStream_EphemeralKey_Throws), ephemeralKey: true); - TestHelper.CleanupCertificates(nameof(SslStream_EphemeralKey_Throws)); + (X509Certificate2 serverCertificate, X509Certificate2Collection chain) = Configuration.Certificates.GenerateCertificates(nameof(SslStream_EphemeralKey_DoesNotThrow), ephemeralKey: true); + TestHelper.CleanupCertificates(nameof(SslStream_EphemeralKey_DoesNotThrow)); var clientOptions = new SslClientAuthenticationOptions() { @@ -969,21 +969,25 @@ public async Task SslStream_EphemeralKey_Throws() }; (SslStream client, SslStream server) = TestHelper.GetConnectedSslStreams(); + try + { + using (client) + using (server) + { + Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); + Task t2 = server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); - Task t1 = client.AuthenticateAsClientAsync(clientOptions, CancellationToken.None); - Task t2 = server.AuthenticateAsServerAsync(serverOptions, CancellationToken.None); - - AuthenticationException e = await Assert.ThrowsAsync<AuthenticationException>(() => t2); - Assert.Contains("ephemeral", e.Message); - server.Dispose(); - await Assert.ThrowsAsync<IOException>(() => t1); - client.Dispose(); - - TestHelper.CleanupCertificates(nameof(SslStream_EphemeralKey_Throws)); - serverCertificate.Dispose(); - foreach (X509Certificate c in chain) + await TestConfiguration.WhenAllOrAnyFailedWithTimeout(t1, t2); + } + } + finally { - c.Dispose(); + TestHelper.CleanupCertificates(nameof(SslStream_EphemeralKey_DoesNotThrow)); + serverCertificate.Dispose(); + foreach (X509Certificate c in chain) + { + c.Dispose(); + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Windows.cs index 2e43dc78b56700..38f580edbfc5db 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/X509Certificates/X509CertificateLoader.Windows.cs @@ -300,7 +300,7 @@ private static Interop.Crypt32.PfxCertStoreFlags MapKeyStorageFlags(X509KeyStora if ((keyStorageFlags & X509KeyStorageFlags.EphemeralKeySet) == X509KeyStorageFlags.EphemeralKeySet) { pfxCertStoreFlags &= ~Interop.Crypt32.PfxCertStoreFlags.PKCS12_PREFER_CNG_KSP; - pfxCertStoreFlags |= Interop.Crypt32.PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | Interop.Crypt32.PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP; + pfxCertStoreFlags |= Interop.Crypt32.PfxCertStoreFlags.PKCS12_NAMED_NO_PERSIST_KEY | Interop.Crypt32.PfxCertStoreFlags.PKCS12_NO_PERSIST_KEY | Interop.Crypt32.PfxCertStoreFlags.PKCS12_ALWAYS_CNG_KSP; } // In .NET Framework loading a PFX then adding the key to the Windows Certificate Store would