Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support of TLS 1.3 on macOS POC #104835

Draft
wants to merge 31 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f5d116d
snap
wfurt Jul 9, 2024
c3be4f3
tests
wfurt Jul 9, 2024
86665f6
snap
wfurt Jul 11, 2024
7c3e67b
snap
wfurt Jul 12, 2024
02c1eb3
snap
wfurt Jul 12, 2024
11edad8
snap
wfurt Jul 12, 2024
fcc9879
snap
wfurt Jul 12, 2024
7361d26
snap
wfurt Jul 12, 2024
53b69f6
snap
wfurt Jul 12, 2024
093d9bb
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 12, 2024
83901ca
update
wfurt Jul 15, 2024
3ca7fbc
update
wfurt Jul 15, 2024
d07c7b9
build update
wfurt Jul 16, 2024
ad8fadf
build
wfurt Jul 16, 2024
637524d
alpn
wfurt Jul 16, 2024
64077b5
build
wfurt Jul 16, 2024
a8a7bed
build
wfurt Jul 16, 2024
e0b6d0c
update
wfurt Jul 17, 2024
b2dc3be
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 17, 2024
95e0c33
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 17, 2024
89c0444
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 17, 2024
7fec8ae
build
wfurt Jul 18, 2024
b8b64d0
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 18, 2024
9d5b512
Merge branch 'macNw' of https://github.com/wfurt/runtime into macNw
wfurt Jul 18, 2024
97f59d2
aot
wfurt Jul 18, 2024
b643236
builder
wfurt Jul 18, 2024
40f31e1
Merge branch 'macNw' of https://github.com/wfurt/runtime into macNw
wfurt Jul 18, 2024
10138f9
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 19, 2024
082cf40
update
wfurt Jul 19, 2024
79be6bc
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Jul 19, 2024
cb8e52b
Merge branch 'main' of https://github.com/dotnet/runtime into macNw
wfurt Sep 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<NativeFramework Include="CoreFoundation" />
<NativeFramework Condition="'$(_targetOS)' == 'osx'" Include="CryptoKit" />
<NativeFramework Include="Foundation" />
<NativeFramework Include="Network" />
<NativeFramework Include="Security" />
<!-- The library builds don't reference the GSS API on tvOS builds. -->
<NativeFramework Condition="!$(_targetOS.StartsWith('tvos'))" Include="GSS" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,28 @@ internal enum PAL_TlsIo
Renegotiate,
}

internal enum PAL_NwStatusUpdates
{
UnknownError = 0,
FramerStart = 1,
HandshakeFinished = 2,
HandshakeFailed = 3,
ConnectionReadFinished = 4,
ConnectionWriteFinished = 5,
ConnectionWriteFailed = 6,
ConnectionError = 7,
ConnectionCancelled = 8,
}

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslCreateContext")]
internal static partial System.Net.SafeSslHandle SslCreateContext(int isServer);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwCreateContext")]
internal static partial System.Net.SafeSslHandle NwCreateContext(int isServer);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwInit")]
internal static unsafe partial int NwInit(delegate* unmanaged<IntPtr, PAL_NwStatusUpdates, IntPtr, IntPtr, int> statusCallback, delegate* unmanaged<IntPtr, byte*, void**, int> readCallback, delegate* unmanaged<IntPtr, byte*, void**, int> writeCallback);
Comment on lines 77 to +82
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume Nw* and Ssl* functions can't be used interchangeably, would it make sense to move it to its own class like Interop.NetworkFramework?

Copy link
Member

@liveans liveans Jul 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be helpful, especially for the possible future implementations/experiments. (QUIC API is there and can be used with couple of more interop additions to this. (there are some bugs))


[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetConnection")]
internal static partial int SslSetConnection(
SafeSslHandle sslHandle,
Expand Down Expand Up @@ -137,6 +156,40 @@ private static partial int AppleCryptoNative_SslSetTargetName(
[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslHandshake")]
internal static partial PAL_TlsHandshakeState SslHandshake(SafeSslHandle sslHandle);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwStartTlsHandshake")]
internal static partial int NwStartHandshake(SafeSslHandle sslHandle, IntPtr gcHandle);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwCancelConnection")]
internal static partial int NwCancelConnection(SafeSslHandle sslHandle);


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwSetTlsOptions", StringMarshalling = StringMarshalling.Utf8)]
private static unsafe partial int NwSetTlsOptions(SafeSslHandle sslHandle, nint gcHandle, string targetName, Span<byte> alpn, int alpnLength, SslProtocols minTlsVersion, SslProtocols maxTlsVersion);

internal static unsafe int NwSetTlsOptions(SafeSslHandle sslHandle, nint gcHandle, string targetName, List<SslApplicationProtocol>? applicationProtocols, SslProtocols minTlsVersion, SslProtocols maxTlsVersion)
{
int alpnLength = GetAlpnProtocolListSerializedLength(applicationProtocols);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation

Span<byte> alpn = alpnLength <= 256 ? stackalloc byte[256].Slice(0, alpnLength) : new byte[alpnLength];
SerializeAlpnProtocolList(applicationProtocols, alpn);

return NwSetTlsOptions(sslHandle, gcHandle, targetName, alpn, alpnLength, minTlsVersion, maxTlsVersion);
}

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwProcessInputData")]
internal static unsafe partial int NwProcessInputData(SafeSslHandle sslHandle, IntPtr framer, void* ptr, int length);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwSendToConnection")]
internal static unsafe partial int NwSendToConnection(SafeSslHandle sslHandle, nint gcHandle, void* ptr, int length);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwReadFromConnection")]
internal static unsafe partial int NwReadFromConnection(SafeSslHandle sslHandle, nint gcHandle);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwGetConnectionInfo")]
internal static unsafe partial int NwGetConnectionInfo(SafeSslHandle sslHandle, out SslProtocols protocol, out TlsCipherSuite cipherSuite, ref IntPtr negotiatedAlpn, ref int alpnLength);

[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_NwCopyCertChain")]
internal static partial int NwCopyCertChain( SafeSslHandle sslHandle, out SafeCFArrayHandle certificiates, out int count);

[LibraryImport(Interop.Libraries.AppleCryptoNative)]
private static partial int AppleCryptoNative_SslSetAcceptClientCert(SafeSslHandle sslHandle);

Expand Down Expand Up @@ -496,6 +549,47 @@ public static bool SslCheckHostnameMatch(SafeSslHandle handle, string hostName,
throw new SslException();
}
}


internal static int GetAlpnProtocolListSerializedLength(List<SslApplicationProtocol>? applicationProtocols)
{
int protocolSize = 0;

if (applicationProtocols != null)
{
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
if (protocol.Protocol.Length == 0 || protocol.Protocol.Length > byte.MaxValue)
{
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
}

protocolSize += protocol.Protocol.Length + 2;
}
}

return protocolSize;
}

private static void SerializeAlpnProtocolList(List<SslApplicationProtocol>? applicationProtocols, Span<byte> buffer)
{
if (applicationProtocols == null)
{
return;
}

Debug.Assert(GetAlpnProtocolListSerializedLength(applicationProtocols) == buffer.Length,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, you no longer need this message. The exact same message will now be injected for you,

"GetAlpnProtocolListSerializedSize(applicationProtocols) == buffer.Length");

int offset = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
buffer[offset++] = (byte)protocol.Protocol.Length;
protocol.Protocol.Span.CopyTo(buffer.Slice(offset));
offset += protocol.Protocol.Length;
buffer[offset++] = 0;
}
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/libraries/Common/src/System/Net/ArrayBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ internal struct ArrayBuffer : IDisposable
private byte[] _bytes;
private int _activeStart;
private int _availableStart;
private bool _disposed;

// Invariants:
// 0 <= _activeStart <= _availableStart <= bytes.Length
Expand Down Expand Up @@ -53,6 +54,7 @@ public ArrayBuffer(byte[] buffer)

public void Dispose()
{
_disposed = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indenting

_activeStart = 0;
_availableStart = 0;

Expand Down Expand Up @@ -108,6 +110,7 @@ public void Discard(int byteCount)

public void Commit(int byteCount)
{
ObjectDisposedException.ThrowIf(_bytes == null, this);
Debug.Assert(byteCount <= AvailableLength);
_availableStart += byteCount;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2528,6 +2528,7 @@ public virtual async Task Timeout_Roundtrips()
[Fact]
[SkipOnPlatform(TestPlatforms.LinuxBionic, "SElinux blocks UNIX sockets in our CI environment")]
[SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "iOS/tvOS blocks binding to UNIX sockets")]
[SkipOnPlatform(TestPlatforms.OSX, "ABC")]
public virtual async Task ReadTimeout_Expires_Throws()
{
using StreamPair streams = await CreateConnectedStreamsAsync();
Expand Down Expand Up @@ -2838,7 +2839,7 @@ await WhenAllOrAnyFailed(
Assert.Throws<ObjectDisposedException>(() => writeable.WriteByte(42));
}
}

/*
[Fact]
public virtual async Task UseWrappedAfterClose_Success()
{
Expand All @@ -2864,7 +2865,7 @@ public virtual async Task UseWrappedAfterClose_Success()
readable.ReadByte();
}
}

*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

[Fact]
public virtual async Task NestedWithinSelf_ReadWrite_Success()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ private static bool GetSsl3Support()

}

return (IsOSX || (IsLinux && OpenSslVersion < new Version(1, 0, 2) && !IsDebian));
return (IsOpenSslSupported && OpenSslVersion < new Version(1, 0, 2));
}

private static bool OpenSslGetTlsSupport(SslProtocols protocol)
Expand All @@ -553,7 +553,7 @@ private static bool AndroidGetSslProtocolSupport(SslProtocols protocol)
private static bool GetTls10Support()
{
// on macOS and Android TLS 1.0 is supported.
if (IsApplePlatform || IsAndroid)
if (IsAndroid)
{
return true;
}
Expand All @@ -564,7 +564,7 @@ private static bool GetTls10Support()
return GetProtocolSupportFromWindowsRegistry(SslProtocols.Tls, defaultProtocolSupport: true) && !IsWindows10Version20348OrGreater;
}

return OpenSslGetTlsSupport(SslProtocols.Tls);
return IsOpenSslSupported && OpenSslGetTlsSupport(SslProtocols.Tls);
}

private static bool GetTls11Support()
Expand All @@ -580,13 +580,13 @@ private static bool GetTls11Support()
// It is enabled on other versions unless explicitly disabled.
return GetProtocolSupportFromWindowsRegistry(SslProtocols.Tls11, defaultProtocolSupport: true) && !IsWindows10Version20348OrGreater;
}
// on macOS and Android TLS 1.1 is supported.
else if (IsApplePlatform || IsAndroid)
// on Android TLS 1.1 is supported.
else if (IsAndroid)
{
return true;
}

return OpenSslGetTlsSupport(SslProtocols.Tls11);
return IsOpenSslSupported && OpenSslGetTlsSupport(SslProtocols.Tls11);
}
#pragma warning restore SYSLIB0039

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ internal static SslPolicyErrors VerifyCertificateProperties(
errors |= SslPolicyErrors.RemoteCertificateChainErrors;
}

if (!isServer && checkCertName)
if (!isServer && checkCertName && ! (((SafeDeleteSslContext)securityContext).UseNwFramework))
{
SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;

Expand Down Expand Up @@ -67,9 +67,11 @@ internal static SslPolicyErrors VerifyCertificateProperties(

X509Certificate2? result = null;

using (SafeX509ChainHandle chainHandle = Interop.AppleCrypto.SslCopyCertChain(sslContext))
if (((SafeDeleteSslContext)securityContext).UseNwFramework)
{
long chainSize = Interop.AppleCrypto.X509ChainGetChainSize(chainHandle);
SafeCFArrayHandle certificates;

Interop.AppleCrypto.NwCopyCertChain(sslContext, out certificates, out int chainSize);

if (retrieveChainCertificates && chainSize > 1)
{
Expand All @@ -83,7 +85,7 @@ internal static SslPolicyErrors VerifyCertificateProperties(
// Any any additional intermediate CAs to ExtraStore.
for (int i = 1; i < chainSize; i++)
{
IntPtr certHandle = Interop.AppleCrypto.X509ChainGetCertificateAtIndex(chainHandle, i);
IntPtr certHandle = Interop.CoreFoundation.CFArrayGetValueAtIndex(certificates, i);
chain.ChainPolicy.ExtraStore.Add(new X509Certificate2(certHandle));
}
}
Expand All @@ -92,10 +94,42 @@ internal static SslPolicyErrors VerifyCertificateProperties(
// to match what the Windows and Unix PALs do.
if (chainSize > 0)
{
IntPtr certHandle = Interop.AppleCrypto.X509ChainGetCertificateAtIndex(chainHandle, 0);
IntPtr certHandle = Interop.CoreFoundation.CFArrayGetValueAtIndex(certificates, 0);
result = new X509Certificate2(certHandle);
}
}
else
{
using (SafeX509ChainHandle chainHandle = Interop.AppleCrypto.SslCopyCertChain(sslContext))
{
long chainSize = Interop.AppleCrypto.X509ChainGetChainSize(chainHandle);

if (retrieveChainCertificates && chainSize > 1)
{
chain ??= new X509Chain();
if (chainPolicy != null)
{
chain.ChainPolicy = chainPolicy;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the chain was passed in, might this be overriding a policy that was already there?

}

// First certificate is peer's certificate.
// Any any additional intermediate CAs to ExtraStore.
for (int i = 1; i < chainSize; i++)
{
IntPtr certHandle = Interop.AppleCrypto.X509ChainGetCertificateAtIndex(chainHandle, i);
chain.ChainPolicy.ExtraStore.Add(new X509Certificate2(certHandle));
}
}

// This will be a distinct object than remoteCertificateStore[0] (if applicable),
// to match what the Windows and Unix PALs do.
if (chainSize > 0)
{
IntPtr certHandle = Interop.AppleCrypto.X509ChainGetCertificateAtIndex(chainHandle, 0);
result = new X509Certificate2(certHandle);
}
}
}

if (NetEventSource.Log.IsEnabled()) NetEventSource.Log.RemoteCertificate(result);

Expand Down
Loading
Loading