ServerAuthCompleted,
ClientAuthCompleted,
ClientCertRequested,
+ ClientHelloReceived,
}
internal enum PAL_TlsIo
out int pOSStatus);
[LibraryImport(Interop.Libraries.AppleCryptoNative)]
+ private static partial int AppleCryptoNative_SslSetBreakOnClientHello(
+ SafeSslHandle sslHandle,
+ int setBreak,
+ out int pOSStatus);
+
+ [LibraryImport(Interop.Libraries.AppleCryptoNative)]
private static partial int AppleCryptoNative_SslSetBreakOnCertRequested(
SafeSslHandle sslHandle,
int setBreak,
[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SSLSetALPNProtocols")]
internal static partial int SSLSetALPNProtocols(SafeSslHandle ctx, SafeCreateHandle cfProtocolsRefs, out int osStatus);
+ [LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SSLSetALPNProtocol")]
+ internal static unsafe partial int SSLSetALPNProtocol(SafeSslHandle ctx, void* protocol, int length, out int osStatus);
+
[LibraryImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetAlpnSelected")]
internal static partial int SslGetAlpnSelected(SafeSslHandle ssl, out SafeCFDataHandle protocol);
throw new SslException();
}
+ internal static void SslBreakOnClientHello(SafeSslHandle sslHandle, bool setBreak)
+ {
+ int osStatus;
+ int result = AppleCryptoNative_SslSetBreakOnClientHello(sslHandle, setBreak ? 1 : 0, out osStatus);
+
+ if (result == 1)
+ {
+ return;
+ }
+
+ if (result == 0)
+ {
+ throw CreateExceptionForOSStatus(osStatus);
+ }
+
+ Debug.Fail($"AppleCryptoNative_SslSetBreakOnClientHello returned {result}");
+ throw new SslException();
+ }
+
internal static void SslBreakOnCertRequested(SafeSslHandle sslHandle, bool setBreak)
{
int osStatus;
}
}
+ internal static unsafe bool SslCtxSetAlpnProtocol(SafeSslHandle ctx, SslApplicationProtocol protocol)
+ {
+ int osStatus;
+
+ fixed (void* ptr = &MemoryMarshal.GetReference(protocol.Protocol.Span))
+ {
+ int result = SSLSetALPNProtocol(ctx, ptr, protocol.Protocol.Length, out osStatus);
+ if (result != 1)
+ {
+ throw CreateExceptionForOSStatus(osStatus);
+ }
+ }
+
+ return osStatus == 0;
+ }
+
internal static byte[]? SslGetAlpnSelected(SafeSslHandle ssl)
{
SafeCFDataHandle protocol;
CredentialsNeeded,
Renegotiate,
TryAgain,
+ HandshakeStarted,
// Errors
OutOfMemory,
// Windows - Schannel supports alpn from win8.1/2012 R2 and higher.
// Linux - OpenSsl supports alpn from openssl 1.0.2 and higher.
- // OSX - SecureTransport doesn't expose alpn APIs. TODO https://github.com/dotnet/runtime/issues/27727
// Android - Platform supports alpn from API level 29 and higher
private static readonly Lazy<bool> s_supportsAlpn = new Lazy<bool>(GetAlpnSupport);
private static bool GetAlpnSupport()
return Interop.AndroidCrypto.SSLSupportsApplicationProtocolsConfiguration();
}
+ if (IsOSX)
+ {
+ return true;
+ }
+
return false;
}
private ArrayBuffer _outputBuffer = new ArrayBuffer(InitialBufferSize);
public SafeSslHandle SslContext => _sslContext;
+ public SslApplicationProtocol SelectedApplicationProtocol;
+ public bool IsServer;
public SafeDeleteSslContext(SslAuthenticationOptions sslAuthenticationOptions)
: base(IntPtr.Zero)
if (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)
{
- // On OSX coretls supports only client side. For server, we will silently ignore the option.
- if (!sslAuthenticationOptions.IsServer)
+ if (sslAuthenticationOptions.IsClient)
{
+ // On macOS coreTls supports only client side.
Interop.AppleCrypto.SslCtxSetAlpnProtos(_sslContext, sslAuthenticationOptions.ApplicationProtocols);
}
+ else
+ {
+ // For Server, we do the selection in SslStream and we set it later
+ Interop.AppleCrypto.SslBreakOnClientHello(_sslContext, true);
+ }
}
}
catch (Exception ex)
if (sslAuthenticationOptions.IsServer)
{
+ IsServer = true;
+
if (sslAuthenticationOptions.RemoteCertRequired)
{
Interop.AppleCrypto.SslSetAcceptClientCert(_sslContext);
{
internal partial struct SslConnectionInfo
{
- public void UpdateSslConnectionInfo(SafeSslHandle sslContext)
+ public void UpdateSslConnectionInfo(SafeDeleteSslContext context)
{
+ SafeSslHandle sslContext = context.SslContext;
SslProtocols protocol;
TlsCipherSuite cipherSuite;
Protocol = (int)protocol;
TlsCipherSuite = cipherSuite;
- ApplicationProtocol = Interop.AppleCrypto.SslGetAlpnSelected(sslContext);
+ if (context.IsServer)
+ {
+ if (context.SelectedApplicationProtocol.Protocol.Length > 0)
+ {
+ if (context.SelectedApplicationProtocol.Equals(SslApplicationProtocol.Http11.Protocol))
+ {
+ ApplicationProtocol = s_http1;
+ }
+ else if (context.SelectedApplicationProtocol.Equals(SslApplicationProtocol.Http2.Protocol))
+ {
+ ApplicationProtocol = s_http2;
+ }
+ else if (context.SelectedApplicationProtocol.Equals(SslApplicationProtocol.Http3.Protocol))
+ {
+ ApplicationProtocol = s_http3;
+ }
+ else
+ {
+ ApplicationProtocol = context.SelectedApplicationProtocol.Protocol.ToArray();
+ }
+ }
+ }
+ else
+ {
+ ApplicationProtocol = Interop.AppleCrypto.SslGetAlpnSelected(sslContext);
+ }
MapCipherSuite(cipherSuite);
}
TlsFrameHelper.ProcessingOptions options = NetEventSource.Log.IsEnabled() ?
TlsFrameHelper.ProcessingOptions.All :
TlsFrameHelper.ProcessingOptions.ServerName;
+ if (OperatingSystem.IsMacOS() && _sslAuthenticationOptions.IsServer)
+ {
+ // macOS cannot process ALPN on server at the momennt.
+ // We fallback to our own process similar to SNI bellow.
+ options |= TlsFrameHelper.ProcessingOptions.RawApplicationProtocol;
+ }
// Process SNI from Client Hello message
if (!TlsFrameHelper.TryGetFrameInfo(_buffer.EncryptedReadOnlySpan, ref _lastFrame, options))
inputBuffer,
ref result,
_sslAuthenticationOptions);
+ if (status.ErrorCode == SecurityStatusPalErrorCode.HandshakeStarted)
+ {
+ status = SslStreamPal.SelectApplicationProtocol(
+ _credentialsHandle!,
+ _securityContext!,
+ _sslAuthenticationOptions,
+ _lastFrame.RawApplicationProtocols);
+
+ if (status.ErrorCode == SecurityStatusPalErrorCode.OK)
+ {
+ status = SslStreamPal.AcceptSecurityContext(
+ ref _credentialsHandle!,
+ ref _securityContext,
+ ReadOnlySpan<byte>.Empty,
+ ref result,
+ _sslAuthenticationOptions);
+ }
+ }
}
else
{
{
}
+ public static SecurityStatusPal SelectApplicationProtocol(
+ SafeFreeCredentials? credentialsHandle,
+ SafeDeleteSslContext? context,
+ SslAuthenticationOptions sslAuthenticationOptions,
+ ReadOnlySpan<byte> clientProtocols)
+ {
+ throw new PlatformNotSupportedException(nameof(SelectApplicationProtocol));
+ }
+
public static SecurityStatusPal AcceptSecurityContext(
ref SafeFreeCredentials credential,
ref SafeDeleteSslContext? context,
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
+using System.Net.Security;
using System.Security.Authentication;
using System.Security.Authentication.ExtendedProtection;
using System.Security.Cryptography.X509Certificates;
{
}
+ public static SecurityStatusPal SelectApplicationProtocol(
+ SafeFreeCredentials? _,
+ SafeDeleteSslContext context,
+ SslAuthenticationOptions sslAuthenticationOptions,
+ ReadOnlySpan<byte> clientProtocols)
+ {
+ // Client did not provide ALPN or APLN is not needed
+ if (clientProtocols.Length == 0 ||
+ sslAuthenticationOptions.ApplicationProtocols == null || sslAuthenticationOptions.ApplicationProtocols.Count == 0)
+ {
+ return new SecurityStatusPal(SecurityStatusPalErrorCode.OK);
+ }
+
+ // We do server side ALPN e.g. walk the intersect in server order
+ foreach (SslApplicationProtocol applicationProtcol in sslAuthenticationOptions.ApplicationProtocols)
+ {
+ ReadOnlySpan<byte> protocols = clientProtocols;
+
+ while (protocols.Length > 0)
+ {
+ byte length = protocols[0];
+ if (protocols.Length < length + 1)
+ {
+ break;
+ }
+ ReadOnlySpan<byte> protocol = protocols.Slice(1, length);
+ if (protocol.SequenceCompareTo<byte>(applicationProtcol.Protocol.Span) == 0)
+ {
+ if (Interop.AppleCrypto.SslCtxSetAlpnProtocol(context.SslContext, applicationProtcol))
+ {
+ context.SelectedApplicationProtocol = applicationProtcol;
+ }
+
+ // We ignore failure and we will move on with ALPN
+ return new SecurityStatusPal(SecurityStatusPalErrorCode.OK);
+ }
+
+ protocols = protocols.Slice(protocol.Length + 1);
+ }
+ }
+
+ return new SecurityStatusPal(SecurityStatusPalErrorCode.ApplicationProtocolMismatch);
+ }
+
#pragma warning disable IDE0060
public static SecurityStatusPal AcceptSecurityContext(
ref SafeFreeCredentials credential,
SafeDeleteSslContext securityContext,
ref SslConnectionInfo connectionInfo)
{
- connectionInfo.UpdateSslConnectionInfo(securityContext.SslContext);
+ connectionInfo.UpdateSslConnectionInfo(securityContext);
}
private static SecurityStatusPal HandshakeInternal(
SafeSslHandle sslHandle = sslContext!.SslContext;
SecurityStatusPal status = PerformHandshake(sslHandle);
+
if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded && clientCertificateSelectionCallback != null)
{
X509Certificate2? clientCertificate = clientCertificateSelectionCallback(out bool _);
break;
case PAL_TlsHandshakeState.ClientCertRequested:
return new SecurityStatusPal(SecurityStatusPalErrorCode.CredentialsNeeded);
+ case PAL_TlsHandshakeState.ClientHelloReceived:
+ return new SecurityStatusPal(SecurityStatusPalErrorCode.HandshakeStarted);
default:
return new SecurityStatusPal(
SecurityStatusPalErrorCode.InternalError,
{
}
+ public static SecurityStatusPal SelectApplicationProtocol(
+ SafeFreeCredentials? credentialsHandle,
+ SafeDeleteSslContext? context,
+ SslAuthenticationOptions sslAuthenticationOptions,
+ ReadOnlySpan<byte> clientProtocols)
+ {
+ throw new PlatformNotSupportedException(nameof(SelectApplicationProtocol));
+ }
+
#pragma warning disable IDE0060
public static SecurityStatusPal AcceptSecurityContext(
ref SafeFreeCredentials? credential,
}
}
+ public static SecurityStatusPal SelectApplicationProtocol(
+ SafeFreeCredentials? credentialsHandle,
+ SafeDeleteSslContext? context,
+ SslAuthenticationOptions sslAuthenticationOptions,
+ ReadOnlySpan<byte> clientProtocols)
+ {
+ throw new PlatformNotSupportedException(nameof(SelectApplicationProtocol));
+ }
+
public static unsafe SecurityStatusPal AcceptSecurityContext(
ref SafeFreeCredentials? credentialsHandle,
ref SafeDeleteSslContext? context,
ServerName = 0x1,
ApplicationProtocol = 0x2,
Versions = 0x4,
+ RawApplicationProtocol = 0x8,
}
[Flags]
public string TargetName;
public ApplicationProtocolInfo ApplicationProtocols;
public TlsAlertDescription AlertDescription;
+ public byte[]? RawApplicationProtocols;
public override string ToString()
{
info.SupportedVersions |= versions;
}
else if (extensionType == ExtensionType.ApplicationProtocols && (options == ProcessingOptions.All ||
- (options & ProcessingOptions.ApplicationProtocol) == ProcessingOptions.ApplicationProtocol))
+ (options.HasFlag(ProcessingOptions.ApplicationProtocol) || options.HasFlag(ProcessingOptions.RawApplicationProtocol))))
{
if (!TryGetApplicationProtocolsFromExtension(extensionData, out ApplicationProtocolInfo alpn))
{
}
info.ApplicationProtocols |= alpn;
+
+ // Process RAW options only if explicitly set since that will allocate....
+ if (options.HasFlag(ProcessingOptions.RawApplicationProtocol))
+ {
+ // Skip ALPN extension Length. We have that in span.
+ info.RawApplicationProtocols = extensionData.Slice(sizeof(short)).ToArray();
+ }
}
callback?.Invoke(ref info, extensionType, extensionData);
using System.Collections.Generic;
using System.IO;
-using System.Linq;
using System.Net.Sockets;
using System.Net.Test.Common;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
-using System.Text;
-using System.Threading;
using System.Threading.Tasks;
using Xunit;
public static IEnumerable<object[]> Alpn_TestData()
{
- if (OperatingSystem.IsMacOS())
- {
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 }, null };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null };
- yield return new object[] { null, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol>(), null };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null, null };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 }, null };
- yield return new object[] { new List<SslApplicationProtocol>(), new List<SslApplicationProtocol>(), null };
- yield return new object[] { null, new List<SslApplicationProtocol>(), null };
- yield return new object[] { new List<SslApplicationProtocol>(), null, null };
- yield return new object[] { null, null, null };
- }
- else
- {
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http2 : default };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http11 : default };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http11 : default };
- yield return new object[] { null, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, default(SslApplicationProtocol) };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
- yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null, default(SslApplicationProtocol) };
- yield return new object[] { new List<SslApplicationProtocol>(), new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
- yield return new object[] { null, new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
- yield return new object[] { new List<SslApplicationProtocol>(), null, default(SslApplicationProtocol) };
- yield return new object[] { null, null, default(SslApplicationProtocol) };
- }
+ yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http2 : default };
+ yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http11 : default };
+ yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, BackendSupportsAlpn ? SslApplicationProtocol.Http11 : default };
+ yield return new object[] { null, new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, default(SslApplicationProtocol) };
+ yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
+ yield return new object[] { new List<SslApplicationProtocol> { SslApplicationProtocol.Http11, SslApplicationProtocol.Http2 }, null, default(SslApplicationProtocol) };
+ yield return new object[] { new List<SslApplicationProtocol>(), new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
+ yield return new object[] { null, new List<SslApplicationProtocol>(), default(SslApplicationProtocol) };
+ yield return new object[] { new List<SslApplicationProtocol>(), null, default(SslApplicationProtocol) };
+ yield return new object[] { null, null, default(SslApplicationProtocol) };
}
}
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+// Definitions of structures from coreTLS
+// https://github.com/apple-oss-distributions/coreTLS/
+
+typedef struct
+{ size_t length;
+ uint8_t *data;
+} tls_buffer;
+
+struct _tls_handshake_s
+{
+ uint8_t _ignore0[968];
+ /* ALPN */
+ bool alpn_enabled; /* Client: alpn is enabled */
+ bool alpn_announced; /* Client: alpn extension was sent, Server: alpn extension was received */
+ bool alpn_confirmed; /* Client: alpn extension was received, Server: alpn extension was sent */
+ bool alpn_received; /* Server: alpn message was received */
+ tls_buffer alpnOwnData; /* Client: supported protocols sent, Server: selected protocol sent */
+ tls_buffer alpnPeerData; /* Client: select protocol received, Server: list of supported protocol received */
+};
+
+typedef struct _tls_handshake_s *tls_handshake_t;
+
+struct SSLContext
+{
+ uint8_t _ignored0[56];
+ tls_handshake_t hdsk;
+};
+
DllImportEntry(AppleCryptoNative_SslRead)
DllImportEntry(AppleCryptoNative_SslSetBreakOnCertRequested)
DllImportEntry(AppleCryptoNative_SslSetBreakOnClientAuth)
+ DllImportEntry(AppleCryptoNative_SslSetBreakOnClientHello)
DllImportEntry(AppleCryptoNative_SslSetBreakOnServerAuth)
DllImportEntry(AppleCryptoNative_SslSetIoCallbacks)
DllImportEntry(AppleCryptoNative_SslWrite)
DllImportEntry(AppleCryptoNative_SslSetCertificate)
DllImportEntry(AppleCryptoNative_SslSetCertificateAuthorities)
DllImportEntry(AppleCryptoNative_SslSetTargetName)
+ DllImportEntry(AppleCryptoNative_SSLSetALPNProtocol)
DllImportEntry(AppleCryptoNative_SSLSetALPNProtocols)
DllImportEntry(AppleCryptoNative_SslGetAlpnSelected)
DllImportEntry(AppleCryptoNative_SslHandshake)
#include "pal_ssl.h"
#include <dlfcn.h>
+#include "coretls_structs.h"
+
// 10.13.4 introduced public API but linking would fail on all prior versions.
// For that reason we use function pointers instead of direct call.
// This can be revisited after we drop support for 10.12 and iOS 10
#pragma clang diagnostic pop
}
+int32_t AppleCryptoNative_SslSetBreakOnClientHello(SSLContextRef sslContext, int32_t setBreak, int32_t* pOSStatus)
+{
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ return SslSetSessionOption(sslContext, kSSLSessionOptionBreakOnClientHello, setBreak, pOSStatus);
+#pragma clang diagnostic pop
+}
+
int32_t AppleCryptoNative_SslSetCertificate(SSLContextRef sslContext, CFArrayRef certRefs)
{
#pragma clang diagnostic push
return *pOSStatus == noErr;
}
+int32_t AppleCryptoNative_SSLSetALPNProtocol(SSLContextRef sslContext, void* protocol, int length, int32_t* pOSStatus)
+{
+ if (sslContext == NULL || protocol == NULL || length <= 0 || pOSStatus == NULL)
+ return -1;
+
+ if (!SSLSetALPNProtocolsPtr)
+ {
+ // not available.
+ *pOSStatus = errSecNotAvailable;
+ return 1;
+ }
+
+ CFStringRef value = CFStringCreateWithBytes(NULL, protocol, length, kCFStringEncodingASCII, 0);
+ if (!value)
+ {
+ *pOSStatus = errSecMemoryError;
+ return -2;
+ }
+
+ CFArrayRef protocolList = CFArrayCreate(kCFAllocatorDefault, (const void **)&value, 1, &kCFTypeArrayCallBacks);
+ if (!protocolList)
+ {
+ CFRelease(value);
+ *pOSStatus = errSecMemoryError;
+ return -2;
+ }
+
+
+ *pOSStatus = (*SSLSetALPNProtocolsPtr)(sslContext, protocolList);
+ if (*pOSStatus == 0)
+ {
+ struct SSLContext* ctx = (struct SSLContext*)sslContext;
+ tls_handshake_t tls = ctx->hdsk;
+
+ // This is extra consistency check to verify that the ALPN data appeared where we expect them
+ // before dereferencing sslContext
+ if (tls != NULL && tls->alpnOwnData.length == length + 1)
+ {
+ tls->alpn_announced = 1;
+ tls->alpn_received = 1 ;
+ }
+ else
+ {
+ *pOSStatus = errSecNotAvailable;
+ }
+ }
+
+ CFRelease(value);
+ CFRelease(protocolList);
+ return 1;
+}
+
int32_t AppleCryptoNative_SslGetAlpnSelected(SSLContextRef sslContext, CFDataRef* protocol)
{
if (sslContext == NULL || protocol == NULL)
return PAL_TlsHandshakeState_ServerAuthCompleted;
case errSSLClientCertRequested:
return PAL_TlsHandshakeState_ClientCertRequested;
+ case errSSLClientHelloReceived:
+ return PAL_TlsHandshakeState_ClientHelloReceived;
default:
return osStatus;
}
PAL_TlsHandshakeState_ServerAuthCompleted = 3,
PAL_TlsHandshakeState_ClientAuthCompleted = 4,
PAL_TlsHandshakeState_ClientCertRequested = 5,
+ PAL_TlsHandshakeState_ClientHelloReceived = 6,
};
typedef int32_t PAL_TlsHandshakeState;
AppleCryptoNative_SslSetBreakOnClientAuth(SSLContextRef sslContext, int32_t setBreak, int32_t* pOSStatus);
/*
+Sets the policy of whether or not to break when server receives ClientHello.
+
+Returns 1 on success, 0 on failure, other values on invalid state.
+
+Output:
+pOSStatus: Receives the value returned by SSLSetSessionOption
+*/
+PALEXPORT int32_t
+AppleCryptoNative_SslSetBreakOnClientHello(SSLContextRef sslContext, int32_t setBreak, int32_t* pOSStatus);
+
+/*
Set the certificate chain for the ServerHello or ClientHello message.
certRefs should be an array of [ SecIdentityRef, SecCertificateRef* ], the 0 element being the
PALEXPORT int32_t AppleCryptoNative_SSLSetALPNProtocols(SSLContextRef sslContext, CFArrayRef protocols, int32_t* pOSStatus);
/*
+Set selected protocol on server side.
+
+Returns 1 on success, 0 on failure, other values for invalid state.
+
+Output:
+pOSStatus: Receives the value from SSLSetALPNData()
+*/
+PALEXPORT int32_t AppleCryptoNative_SSLSetALPNProtocol(SSLContextRef sslContext, void* protocol, int length, int32_t* pOSStatus);
+
+/*
Get negotiated protocol value from ServerHello.
*/
PALEXPORT int32_t AppleCryptoNative_SslGetAlpnSelected(SSLContextRef sslContext, CFDataRef *protocol);