From 3e5f0c1a62be4f6aa315443d208b1640799a9deb Mon Sep 17 00:00:00 2001 From: Radek Zikmund <32671551+rzikm@users.noreply.github.com> Date: Mon, 18 Jul 2022 15:59:11 +0200 Subject: [PATCH] Support OpenSSL-based MsQuic on Windows (#72262) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial OpenSSL MsQuic support * Don't check Windows version when OpenSSL is used * Update src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> Co-authored-by: Marie Píchová <11718369+ManickaP@users.noreply.github.com> --- .../src/System/Net/Quic/Internal/MsQuicApi.cs | 51 +++++++++++-------- .../Net/Quic/Internal/MsQuicConfiguration.cs | 6 +-- .../QuicConnection.SslConnectionOptions.cs | 2 +- .../tests/FunctionalTests/TestHelper.cs | 2 +- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs index c4b1e00ada347..20807cc2598d0 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicApi.cs @@ -51,27 +51,13 @@ private MsQuicApi(QUIC_API_TABLE* apiTable) internal static bool IsQuicSupported { get; } + internal static bool UsesSChannelBackend { get; } + internal static bool Tls13ServerMayBeDisabled { get; } internal static bool Tls13ClientMayBeDisabled { get; } static MsQuicApi() { - if (OperatingSystem.IsWindows()) - { - if (!IsWindowsVersionSupported()) - { - if (NetEventSource.Log.IsEnabled()) - { - NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); - } - - return; - } - - Tls13ServerMayBeDisabled = IsTls13Disabled(true); - Tls13ClientMayBeDisabled = IsTls13Disabled(false); - } - IntPtr msQuicHandle; if (NativeLibrary.TryLoad($"{Interop.Libraries.MsQuic}.{MsQuicVersion.Major}", typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle) || NativeLibrary.TryLoad(Interop.Libraries.MsQuic, typeof(MsQuicApi).Assembly, DllImportSearchPath.AssemblyDirectory, out msQuicHandle)) @@ -90,18 +76,39 @@ static MsQuicApi() if (StatusSucceeded(apiTable->GetParam(null, QUIC_PARAM_GLOBAL_LIBRARY_VERSION, &size, libVersion))) { var version = new Version((int)libVersion[0], (int)libVersion[1], (int)libVersion[2], (int)libVersion[3]); - if (version >= MsQuicVersion) - { - Api = new MsQuicApi(apiTable); - IsQuicSupported = true; - } - else + if (version < MsQuicVersion) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(null, $"Incompatible MsQuic library version '{version}', expecting '{MsQuicVersion}'"); } + return; + } + + // Assume SChanel is being used on windows and query for the actual provider from the library + QUIC_TLS_PROVIDER provider = OperatingSystem.IsWindows() ? QUIC_TLS_PROVIDER.SCHANNEL : QUIC_TLS_PROVIDER.OPENSSL; + size = sizeof(QUIC_TLS_PROVIDER); + apiTable->GetParam(null, QUIC_PARAM_GLOBAL_TLS_PROVIDER, &size, &provider); + UsesSChannelBackend = provider == QUIC_TLS_PROVIDER.SCHANNEL; + + if (UsesSChannelBackend) + { + if (!IsWindowsVersionSupported()) + { + if (NetEventSource.Log.IsEnabled()) + { + NetEventSource.Info(null, $"Current Windows version ({Environment.OSVersion}) is not supported by QUIC. Minimal supported version is {MinWindowsVersion}"); + } + + return; + } + + Tls13ServerMayBeDisabled = IsTls13Disabled(isServer: true); + Tls13ClientMayBeDisabled = IsTls13Disabled(isServer: false); } + + Api = new MsQuicApi(apiTable); + IsQuicSupported = true; } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs index 67a72e453ab72..50c00ae379e3c 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Internal/MsQuicConfiguration.cs @@ -23,7 +23,7 @@ public static MsQuicSafeHandle Create(QuicClientConnectionOptions options) flags |= QUIC_CREDENTIAL_FLAGS.CLIENT; flags |= QUIC_CREDENTIAL_FLAGS.INDICATE_CERTIFICATE_RECEIVED; flags |= QUIC_CREDENTIAL_FLAGS.NO_CERTIFICATE_VALIDATION; - if (OperatingSystem.IsWindows()) + if (MsQuicApi.UsesSChannelBackend) { flags |= QUIC_CREDENTIAL_FLAGS.USE_SUPPLIED_CREDENTIALS; } @@ -131,7 +131,7 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI try { QUIC_CREDENTIAL_CONFIG config = new QUIC_CREDENTIAL_CONFIG { Flags = flags }; - config.Flags |= (OperatingSystem.IsWindows() ? QUIC_CREDENTIAL_FLAGS.NONE : QUIC_CREDENTIAL_FLAGS.USE_PORTABLE_CERTIFICATES); + config.Flags |= (MsQuicApi.UsesSChannelBackend ? QUIC_CREDENTIAL_FLAGS.NONE : QUIC_CREDENTIAL_FLAGS.USE_PORTABLE_CERTIFICATES); if (cipherSuitesPolicy != null) { @@ -145,7 +145,7 @@ private static unsafe MsQuicSafeHandle Create(QuicConnectionOptions options, QUI config.Type = QUIC_CREDENTIAL_TYPE.NONE; status = MsQuicApi.Api.ApiTable->ConfigurationLoadCredential(configurationHandle.QuicHandle, &config); } - else if (OperatingSystem.IsWindows()) + else if (MsQuicApi.UsesSChannelBackend) { config.Type = QUIC_CREDENTIAL_TYPE.CERTIFICATE_CONTEXT; config.CertificateContext = (void*)certificate.Handle; diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.SslConnectionOptions.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.SslConnectionOptions.cs index 8255938b0e326..56aa8f2a9a16a 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.SslConnectionOptions.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/QuicConnection.SslConnectionOptions.cs @@ -69,7 +69,7 @@ public unsafe int ValidateCertificate(QUIC_BUFFER* certificatePtr, QUIC_BUFFER* chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot; chain.ChainPolicy.ApplicationPolicy.Add(_isClient ? s_serverAuthOid : s_clientAuthOid); - if (OperatingSystem.IsWindows()) + if (MsQuicApi.UsesSChannelBackend) { result = new X509Certificate2((IntPtr)certificatePtr); } diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs index 47e6b40c3dc4e..a8b4fba179d6a 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/TestHelper.cs @@ -206,7 +206,7 @@ internal static (X509Certificate2 certificate, X509Certificate2Collection) Gener if (PlatformDetection.IsWindows) { X509Certificate2 ephemeral = endEntity; - endEntity = new X509Certificate2(endEntity.Export(X509ContentType.Pfx)); + endEntity = new X509Certificate2(endEntity.Export(X509ContentType.Pfx), (string?)null, X509KeyStorageFlags.Exportable); ephemeral.Dispose(); }