-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
base: main
Are you sure you want to change the base?
Changes from all commits
f5d116d
c3be4f3
86665f6
7c3e67b
02c1eb3
11edad8
fcc9879
7361d26
53b69f6
093d9bb
83901ca
3ca7fbc
d07c7b9
ad8fadf
637524d
64077b5
a8a7bed
e0b6d0c
b2dc3be
95e0c33
89c0444
7fec8ae
b8b64d0
9d5b512
97f59d2
b643236
40f31e1
10138f9
082cf40
79be6bc
cb8e52b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -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); | ||||
|
||||
[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetConnection")] | ||||
internal static partial int SslSetConnection( | ||||
SafeSslHandle sslHandle, | ||||
|
@@ -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); | ||||
|
||||
|
||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||||
|
||||
|
@@ -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, | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
|
||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -53,6 +54,7 @@ public ArrayBuffer(byte[] buffer) | |
|
||
public void Dispose() | ||
{ | ||
_disposed = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: indenting |
||
_activeStart = 0; | ||
_availableStart = 0; | ||
|
||
|
@@ -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; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
|
@@ -2838,7 +2839,7 @@ await WhenAllOrAnyFailed( | |
Assert.Throws<ObjectDisposedException>(() => writeable.WriteByte(42)); | ||
} | ||
} | ||
|
||
/* | ||
[Fact] | ||
public virtual async Task UseWrappedAfterClose_Success() | ||
{ | ||
|
@@ -2864,7 +2865,7 @@ public virtual async Task UseWrappedAfterClose_Success() | |
readable.ReadByte(); | ||
} | ||
} | ||
|
||
*/ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? |
||
[Fact] | ||
public virtual async Task NestedWithinSelf_ReadWrite_Success() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,7 +30,7 @@ internal static SslPolicyErrors VerifyCertificateProperties( | |
errors |= SslPolicyErrors.RemoteCertificateChainErrors; | ||
} | ||
|
||
if (!isServer && checkCertName) | ||
if (!isServer && checkCertName && ! (((SafeDeleteSslContext)securityContext).UseNwFramework)) | ||
{ | ||
SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext; | ||
|
||
|
@@ -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) | ||
{ | ||
|
@@ -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)); | ||
} | ||
} | ||
|
@@ -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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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); | ||
|
||
|
There was a problem hiding this comment.
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
?There was a problem hiding this comment.
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))