Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libraries/System.Net.Quic/src/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@
<data name="net_quic_tls_version_notsupported" xml:space="preserve">
<value>Could not use a TLS version required by Quic. TLS 1.3 may have been disabled in the registry.</value>
</data>
<data name="net_auth_ephemeral" xml:space="preserve">
<value>Authentication failed because the platform does not support ephemeral keys.</value>
</data>
<data name="net_quic_empty_cipher_suite" xml:space="preserve">
<value>CipherSuitePolicy must specify at least one cipher supported by QUIC.</value>
</data>
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/System.Net.Quic/src/System.Net.Quic.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
<Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs" Link="Common\Interop\Windows\Interop.Libraries.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CERT_CONTEXT.cs" Link="Common\Interop\Windows\Crypt32\Interop.CERT_CONTEXT.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CertContextPropId.cs" Link="Common\Interop\Windows\Crypt32\Interop.CertContextPropId.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CertDuplicateCertificateContext.cs" Link="Common\Interop\Windows\Crypt32\Interop.CertDuplicateCertificateContext.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CertGetCertificateContextProperty_NO_NULLABLE.cs" Link="Common\Interop\Windows\Crypt32\Interop.CertGetCertificateContextProperty_NO_NULLABLE.cs" />
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeCrypt32Handle.cs" Link="Common\Microsoft\Win32\SafeHandles\SafeCrypt32Handle.cs" />
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeHandleCache.cs" Link="Common\Microsoft\Win32\SafeHandles\SafeHandleCache.cs" />
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeCertContextHandle.cs" Link="Common\Microsoft\Win32\SafeHandles\SafeCertContextHandle.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CERT_INFO.cs" Link="Common\Interop\Windows\Crypt32\Interop.CERT_INFO.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CERT_PUBLIC_KEY_INFO.cs" Link="Common\Interop\Windows\Crypt32\Interop.CERT_PUBLIC_KEY_INFO.cs" />
<Compile Include="$(CommonPath)Interop\Windows\Crypt32\Interop.CRYPT_ALGORITHM_IDENTIFIER.cs" Link="Common\Interop\Windows\Crypt32\Interop.Interop.CRYPT_ALGORITHM_IDENTIFIER.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using Microsoft.Quic;
using Microsoft.Win32.SafeHandles;
using static Microsoft.Quic.MsQuic;

namespace System.Net.Quic;
Expand Down Expand Up @@ -206,6 +208,16 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI
{
ThrowHelper.ThrowIfMsQuicError(status, SR.net_quic_tls_version_notsupported);
}

if ((status == QUIC_STATUS_CERT_NO_CERT || (Interop.SECURITY_STATUS)status == Interop.SECURITY_STATUS.UnknownCredentials) &&
certificate is not null && certificate.HasPrivateKey())
{
using SafeCertContextHandle safeCertContextHandle = Interop.Crypt32.CertDuplicateCertificateContext(certificate.Handle);
if (safeCertContextHandle.HasEphemeralPrivateKey)
{
throw new AuthenticationException(SR.net_auth_ephemeral);
}
Comment thread
rzikm marked this conversation as resolved.
}
#endif

ThrowHelper.ThrowIfMsQuicError(status, "ConfigurationLoadCredential failed");
Expand Down
39 changes: 39 additions & 0 deletions src/libraries/System.Net.Quic/tests/FunctionalTests/MsQuicTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1364,5 +1364,44 @@ private async Task SniTestCore(string hostname, bool shouldSendSni)
[InlineData("fe80::9c3a:b64d:6249:1de8%2")]
[InlineData("fe80::9c3a:b64d:6249:1de8")]
public Task DoesNotSendIPAsSni(string target) => SniTestCore(target, false);

[ConditionalFact]
[PlatformSpecific(TestPlatforms.Windows)]
public async Task Server_CertificateWithEphemeralKey_Throws()
{
using X509Certificate2 cert = System.Net.Test.Common.Configuration.Certificates.GetServerCertificate();
using ECDsa key = ECDsa.Create();
using X509Certificate2 ephemeralCert = cert.CopyWithPrivateKey(key);

QuicListenerOptions listenerOptions = CreateQuicListenerOptions();
listenerOptions.ConnectionOptionsCallback = (_, _, _) =>
{
QuicServerConnectionOptions serverOptions = CreateQuicServerOptions();
serverOptions.ServerAuthenticationOptions.ServerCertificate = ephemeralCert;
return ValueTask.FromResult(serverOptions);
};

await Assert.ThrowsAsync<AuthenticationException>(async () => await CreateQuicListener(listenerOptions));
}
Comment thread
rzikm marked this conversation as resolved.
Outdated

[ConditionalFact]
[PlatformSpecific(TestPlatforms.Windows)]
public async Task Client_CertificateWithEphemeralKey_Throws()
{
if (PlatformDetection.IsWindows10Version20348OrLower)
{
throw new SkipTestException("Client certificates are not supported on Windows Server 2022.");
}

using X509Certificate2 cert = System.Net.Test.Common.Configuration.Certificates.GetClientCertificate();
using ECDsa key = ECDsa.Create();
using X509Certificate2 ephemeralCert = cert.CopyWithPrivateKey(key);

await using QuicListener listener = await CreateQuicListener();
QuicClientConnectionOptions clientOptions = CreateQuicClientOptions(listener.LocalEndPoint);
clientOptions.ClientAuthenticationOptions.ClientCertificates = new X509CertificateCollection() { ephemeralCert };

await Assert.ThrowsAsync<AuthenticationException>(async () => await CreateQuicConnection(clientOptions));
}
}
}
Loading