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

Tls resume PoC (server stateless) #57079

Merged
merged 15 commits into from
Sep 3, 2021

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Authentication;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Ssl
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetProtocolOptions")]
internal static extern void SetProtocolOptions(IntPtr ctx, SslProtocols protocols);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetProtocolOptions")]
internal static extern void SslCtxSetProtocolOptions(IntPtr ctx, SslProtocols protocols);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetProtocolOptions")]
internal static extern void SslCtxSetProtocolOptions(SafeSslContextHandle ctx, SslProtocols protocols);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Security;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -44,6 +45,9 @@ internal static partial class Ssl
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAcceptState")]
internal static extern void SslSetAcceptState(SafeSslHandle ssl);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAlpnProtos")]
internal static extern int SslSetAlpnProtos(SafeSslHandle ssl, IntPtr protos, int len);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetVersion")]
internal static extern IntPtr SslGetVersion(SafeSslHandle ssl);

Expand Down Expand Up @@ -120,9 +124,6 @@ internal static partial class Ssl
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool SslSessionReused(SafeSslHandle ssl);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslAddExtraChainCert")]
internal static extern bool SslAddExtraChainCert(SafeSslHandle ssl, SafeX509Handle x509);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetClientCAList")]
private static extern SafeSharedX509NameStackHandle SslGetClientCAList_private(SafeSslHandle ssl);

Expand All @@ -133,6 +134,55 @@ internal static partial class Ssl
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOpenSslCipherSuiteName")]
private static extern IntPtr GetOpenSslCipherSuiteName(SafeSslHandle ssl, int cipherSuite, out int isTls12OrLower);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetCiphers")]
internal static extern unsafe bool SslSetCiphers(SafeSslHandle ssl, byte* cipherList, byte* cipherSuites);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetVerifyPeer")]
internal static extern void SslSetVerifyPeer(SafeSslHandle ssl);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetData")]
internal static extern IntPtr SslGetData(IntPtr ssl);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetData")]
internal static extern int SslSetData(SafeSslHandle ssl, IntPtr data);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetData")]
internal static extern int SslSetData(IntPtr ssl, IntPtr data);

internal static unsafe int SslSetAlpnProtos(SafeSslHandle ssl, List<SslApplicationProtocol> protocols)
{
byte[] buffer = ConvertAlpnProtocolListToByteArray(protocols);
wfurt marked this conversation as resolved.
Show resolved Hide resolved
fixed (byte* b = buffer)
{
return SslSetAlpnProtos(ssl, (IntPtr)b, buffer.Length);
}
}

internal static byte[] ConvertAlpnProtocolListToByteArray(List<SslApplicationProtocol> applicationProtocols)
{
int protocolSize = 0;
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 + 1;
}

byte[] buffer = new byte[protocolSize];
var offset = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
buffer[offset++] = (byte)(protocol.Protocol.Length);
protocol.Protocol.Span.CopyTo(buffer.AsSpan(offset));
offset += protocol.Protocol.Length;
}

return buffer;
}

internal static string? GetOpenSslCipherSuiteName(SafeSslHandle ssl, TlsCipherSuite cipherSuite, out bool isTls12OrLower)
{
string? ret = Marshal.PtrToStringAnsi(GetOpenSslCipherSuiteName(ssl, (int)cipherSuite, out int isTls12OrLowerInt));
Expand All @@ -159,58 +209,6 @@ internal static SafeSharedX509NameStackHandle SslGetClientCAList(SafeSslHandle s
return handle;
}

internal static bool AddExtraChainCertificates(SafeSslHandle sslContext, X509Chain chain)
{
Debug.Assert(chain != null, "X509Chain should not be null");
Debug.Assert(chain.ChainElements.Count > 0, "chain.Build should have already been called");

// If the last certificate is a root certificate, don't send it. PartialChain means the last cert wasn't a root.
int stop = chain.ChainElements.Count - 1;
foreach (X509ChainStatus s in chain.ChainStatus)
{
if ((s.Status & X509ChainStatusFlags.PartialChain) != 0)
{
stop++;
break;
}
}

// Don't include the first item (the cert whose private key we have)
for (int i = 1; i < stop; i++)
{
SafeX509Handle dupCertHandle = Crypto.X509UpRef(chain.ChainElements[i].Certificate!.Handle);
Crypto.CheckValidOpenSslHandle(dupCertHandle);
if (!SslAddExtraChainCert(sslContext, dupCertHandle))
{
Crypto.ErrClearError();
dupCertHandle.Dispose(); // we still own the safe handle; clean it up
return false;
}
dupCertHandle.SetHandleAsInvalid(); // ownership has been transferred to sslHandle; do not free via this safe handle
}

return true;
}

internal static bool AddExtraChainCertificates(SafeSslHandle sslContext, X509Certificate2[] chain)
{
// send pre-computed list of intermediates.
for (int i = 0; i < chain.Length; i++)
{
SafeX509Handle dupCertHandle = Crypto.X509UpRef(chain[i].Handle);
Crypto.CheckValidOpenSslHandle(dupCertHandle);
if (!SslAddExtraChainCert(sslContext, dupCertHandle))
{
Crypto.ErrClearError();
dupCertHandle.Dispose(); // we still own the safe handle; clean it up
return false;
}
dupCertHandle.SetHandleAsInvalid(); // ownership has been transferred to sslHandle; do not free via this safe handle
}

return true;
}

internal static class SslMethods
{
internal static readonly IntPtr SSLv23_method = SslV2_3Method();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Net.Security;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Microsoft.Win32.SafeHandles;

Expand All @@ -18,44 +19,26 @@ internal static partial class Ssl
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxDestroy")]
internal static extern void SslCtxDestroy(IntPtr ctx);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetAlpnProtos")]
internal static extern int SslCtxSetAlpnProtos(SafeSslContextHandle ctx, IntPtr protos, int len);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetAlpnSelectCb")]
internal static extern unsafe void SslCtxSetAlpnSelectCb(SafeSslContextHandle ctx, delegate* unmanaged<IntPtr, byte**, byte*, byte*, uint, IntPtr, int> callback, IntPtr arg);

internal static unsafe int SslCtxSetAlpnProtos(SafeSslContextHandle ctx, List<SslApplicationProtocol> protocols)
{
byte[] buffer = ConvertAlpnProtocolListToByteArray(protocols);
fixed (byte* b = buffer)
{
return SslCtxSetAlpnProtos(ctx, (IntPtr)b, buffer.Length);
}
}

internal static byte[] ConvertAlpnProtocolListToByteArray(List<SslApplicationProtocol> applicationProtocols)
internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, X509Certificate2[] chain)
{
int protocolSize = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
// send pre-computed list of intermediates.
for (int i = 0; i < chain.Length; i++)
{
if (protocol.Protocol.Length == 0 || protocol.Protocol.Length > byte.MaxValue)
SafeX509Handle dupCertHandle = Crypto.X509UpRef(chain[i].Handle);
Crypto.CheckValidOpenSslHandle(dupCertHandle);
if (!SslCtxAddExtraChainCert(ctx, dupCertHandle))
{
throw new ArgumentException(SR.net_ssl_app_protocols_invalid, nameof(applicationProtocols));
Crypto.ErrClearError();
dupCertHandle.Dispose(); // we still own the safe handle; clean it up
return false;
}

protocolSize += protocol.Protocol.Length + 1;
dupCertHandle.SetHandleAsInvalid(); // ownership has been transferred to sslHandle; do not free via this safe handle
}

byte[] buffer = new byte[protocolSize];
var offset = 0;
foreach (SslApplicationProtocol protocol in applicationProtocols)
{
buffer[offset++] = (byte)(protocol.Protocol.Length);
protocol.Protocol.Span.CopyTo(buffer.AsSpan(offset));
offset += protocol.Protocol.Length;
}

return buffer;
return true;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ internal static partial class Interop
{
internal static partial class Ssl
{
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxAddExtraChainCert")]
internal static extern bool SslCtxAddExtraChainCert(SafeSslContextHandle ctx, SafeX509Handle x509);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxUseCertificate")]
internal static extern int SslCtxUseCertificate(SafeSslContextHandle ctx, SafeX509Handle certPtr);

Expand All @@ -26,10 +29,10 @@ internal static partial class Ssl
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetVerify")]
internal static extern unsafe void SslCtxSetVerify(SafeSslContextHandle ctx, delegate* unmanaged<int, IntPtr, int> callback);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetCiphers")]
internal static extern unsafe bool SetCiphers(SafeSslContextHandle ctx, byte* cipherList, byte* cipherSuites);
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCiphers")]
internal static extern unsafe bool SslCtxSetCiphers(SafeSslContextHandle ctx, byte* cipherList, byte* cipherSuites);

[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetEncryptionPolicy")]
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetEncryptionPolicy")]
internal static extern bool SetEncryptionPolicy(SafeSslContextHandle ctx, EncryptionPolicy policy);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthentication

try
{
_sslContext = Interop.OpenSsl.AllocateSslContext(
credential.Protocols,
credential.CertHandle,
credential.CertKeyHandle,
credential.Policy,
sslAuthenticationOptions);
_sslContext = Interop.OpenSsl.AllocateSslHandle(credential, sslAuthenticationOptions);
}
catch (Exception ex)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ internal sealed class SafeFreeSslCredentials : SafeFreeCredentials
private SslProtocols _protocols = SslProtocols.None;
private EncryptionPolicy _policy;
private bool _isInvalid;
private SslStreamCertificateContext? _context;

internal SafeX509Handle? CertHandle
{
Expand All @@ -42,14 +43,15 @@ internal EncryptionPolicy Policy
get { return _policy; }
}

public SafeFreeSslCredentials(X509Certificate? certificate, SslProtocols protocols, EncryptionPolicy policy)
public SafeFreeSslCredentials(SslStreamCertificateContext? context, SslProtocols protocols, EncryptionPolicy policy, bool isServer)
: base(IntPtr.Zero, true)
{

Debug.Assert(
certificate == null || certificate is X509Certificate2,
context == null || context.Certificate is X509Certificate2,
"Only X509Certificate2 certificates are supported at this time");

X509Certificate2? cert = (X509Certificate2?)certificate;
X509Certificate2? cert = context?.Certificate;

if (cert != null)
{
Expand Down Expand Up @@ -87,6 +89,7 @@ public SafeFreeSslCredentials(X509Certificate? certificate, SslProtocols protoco

_protocols = protocols;
_policy = policy;
_context = context;
}

public override bool IsInvalid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,12 @@ void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level)
(void)level;
}

void local_SSL_set_security_level(SSL* ssl, int32_t level)
{
(void)ssl;
(void)level;
}

int local_BIO_up_ref(BIO *bio)
{
if (!bio)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ int32_t local_SSL_CTX_config(SSL_CTX* ctx, const char* name);
unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options);
unsigned long local_SSL_set_options(SSL* ssl, unsigned long options);
void local_SSL_CTX_set_security_level(SSL_CTX* ctx, int32_t level);
void local_SSL_set_security_level(SSL* ssl, int32_t level);
int local_SSL_session_reused(SSL* ssl);
int32_t local_X509_check_host(X509* x509, const char* name, size_t namelen, unsigned int flags, char** peername);
const ASN1_TIME* local_X509_CRL_get0_nextUpdate(const X509_CRL* crl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,16 @@ static const Entry s_cryptoNative[] =
DllImportEntry(CryptoNative_SslRenegotiate)
DllImportEntry(CryptoNative_IsSslRenegotiatePending)
DllImportEntry(CryptoNative_IsSslStateOK)
DllImportEntry(CryptoNative_SslCtxAddExtraChainCert)
DllImportEntry(CryptoNative_SslCtxSetCiphers)
DllImportEntry(CryptoNative_SslCtxSetEncryptionPolicy)
DllImportEntry(CryptoNative_SetCiphers)
DllImportEntry(CryptoNative_SetEncryptionPolicy)
DllImportEntry(CryptoNative_SetProtocolOptions)
DllImportEntry(CryptoNative_SslAddExtraChainCert)
DllImportEntry(CryptoNative_SslCreate)
DllImportEntry(CryptoNative_SslCtxCheckPrivateKey)
DllImportEntry(CryptoNative_SslCtxCreate)
DllImportEntry(CryptoNative_SslCtxDestroy)
DllImportEntry(CryptoNative_SslCtxSetAlpnProtos)
DllImportEntry(CryptoNative_SslCtxSetAlpnSelectCb)
DllImportEntry(CryptoNative_SslCtxSetProtocolOptions)
DllImportEntry(CryptoNative_SslCtxSetQuietShutdown)
DllImportEntry(CryptoNative_SslCtxSetVerify)
DllImportEntry(CryptoNative_SslCtxUseCertificate)
Expand All @@ -305,6 +305,7 @@ static const Entry s_cryptoNative[] =
DllImportEntry(CryptoNative_SslDoHandshake)
DllImportEntry(CryptoNative_SslGetClientCAList)
DllImportEntry(CryptoNative_SslGetCurrentCipherId)
DllImportEntry(CryptoNative_SslGetData)
DllImportEntry(CryptoNative_SslGetError)
DllImportEntry(CryptoNative_SslGetFinished)
DllImportEntry(CryptoNative_SslGetPeerCertChain)
Expand All @@ -314,10 +315,13 @@ static const Entry s_cryptoNative[] =
DllImportEntry(CryptoNative_SslRead)
DllImportEntry(CryptoNative_SslSessionReused)
DllImportEntry(CryptoNative_SslSetAcceptState)
DllImportEntry(CryptoNative_SslSetAlpnProtos)
DllImportEntry(CryptoNative_SslSetBio)
DllImportEntry(CryptoNative_SslSetConnectState)
DllImportEntry(CryptoNative_SslSetData)
DllImportEntry(CryptoNative_SslSetQuietShutdown)
DllImportEntry(CryptoNative_SslSetTlsExtHostName)
DllImportEntry(CryptoNative_SslSetVerifyPeer)
DllImportEntry(CryptoNative_SslShutdown)
DllImportEntry(CryptoNative_SslV2_3Method)
DllImportEntry(CryptoNative_SslWrite)
Expand Down
Loading