Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -12,7 +12,13 @@ internal static partial class Interop
internal static partial class Crypto
{
[DllImport(Libraries.CryptoNative)]
private static extern ulong ErrGetError([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);
internal static extern ulong ErrGetError();

[DllImport(Libraries.CryptoNative)]
private static extern ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);

[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr ErrReasonErrorString(ulong error);

[DllImport(Libraries.CryptoNative, CharSet = CharSet.Ansi)]
private static extern void ErrErrorStringN(ulong e, [Out] StringBuilder buf, int len);
Expand Down Expand Up @@ -41,7 +47,7 @@ internal static Exception CreateOpenSslCryptographicException()
// whenever an Exception is desired, and report the exception
// related to the last value in the queue.
bool isAllocFailure;
ulong error = ErrGetError(out isAllocFailure);
ulong error = ErrGetErrorAlloc(out isAllocFailure);
ulong lastRead = error;
bool lastIsAllocFailure = isAllocFailure;

Expand All @@ -52,7 +58,7 @@ internal static Exception CreateOpenSslCryptographicException()
error = lastRead;
isAllocFailure = lastIsAllocFailure;

lastRead = ErrGetError(out lastIsAllocFailure);
lastRead = ErrGetErrorAlloc(out lastIsAllocFailure);
}

// If we're in an error flow which results in an Exception, but
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,195 @@ internal static partial class Interop
{
internal static partial class Ssl
{
[DllImport(Interop.Libraries.CryptoNative)]
[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr SslV2_3Method();

[DllImport(Interop.Libraries.CryptoNative)]
[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr SslV3Method();

[DllImport(Interop.Libraries.CryptoNative)]
[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr TlsV1Method();

[DllImport(Interop.Libraries.CryptoNative)]
[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr TlsV1_1Method();

[DllImport(Interop.Libraries.CryptoNative)]
[DllImport(Libraries.CryptoNative)]
internal static extern IntPtr TlsV1_2Method();

[DllImport(Interop.Libraries.CryptoNative)]
internal static extern libssl.SafeSslContextHandle SslCtxCreate(IntPtr method);
[DllImport(Libraries.CryptoNative)]
internal static extern SafeSslContextHandle SslCtxCreate(IntPtr method);

[DllImport(Libraries.CryptoNative)]
internal static extern long SslCtxCtrl(SafeSslContextHandle ctx, int cmd, long larg, IntPtr parg);

[DllImport(Libraries.CryptoNative)]
internal static extern SafeSslHandle SslCreate(SafeSslContextHandle ctx);

[DllImport(Interop.Libraries.CryptoNative)]
internal static unsafe extern int SslWrite(libssl.SafeSslHandle ssl, byte* buf, int num);
[DllImport(Libraries.CryptoNative)]
internal static extern libssl.SslErrorCode SslGetError(SafeSslHandle ssl, int ret);

[DllImport(Interop.Libraries.CryptoNative)]
internal static extern int SslRead(libssl.SafeSslHandle ssl, byte[] buf, int num);
[DllImport(Libraries.CryptoNative)]
internal static extern void SslDestroy(IntPtr ssl);

[DllImport(Libraries.CryptoNative)]
internal static extern void SslCtxDestroy(IntPtr ctx);

[DllImport(Libraries.CryptoNative)]
private static extern IntPtr SslGetVersion(SafeSslHandle ssl);

internal static string GetProtocolVersion(SafeSslHandle ssl)
{
return Marshal.PtrToStringAnsi(SslGetVersion(ssl));
}

[DllImport(Libraries.CryptoNative)]
internal static extern bool GetSslConnectionInfo(
SafeSslHandle ssl,
out int dataCipherAlg,
out int keyExchangeAlg,
out int dataHashAlg,
out int dataKeySize);

[DllImport(Libraries.CryptoNative)]
internal static unsafe extern int SslWrite(SafeSslHandle ssl, byte* buf, int num);

[DllImport(Libraries.CryptoNative)]
internal static extern int SslRead(SafeSslHandle ssl, byte[] buf, int num);

// NOTE: this is just an (unsafe) overload to the BioWrite method from Interop.Bio.cs.
[DllImport(Libraries.CryptoNative)]
internal static unsafe extern int BioWrite(SafeBioHandle b, byte* data, int len);
}
}

namespace Microsoft.Win32.SafeHandles
{
internal sealed class SafeSslContextHandle : SafeHandle
{
private SafeSslContextHandle()
: base(IntPtr.Zero, true)
{
}

public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}

protected override bool ReleaseHandle()
{
Interop.Ssl.SslCtxDestroy(handle);
SetHandle(IntPtr.Zero);
return true;
}
}

internal sealed class SafeSslHandle : SafeHandle
{
private SafeBioHandle _readBio;
private SafeBioHandle _writeBio;
private bool _isServer;

public bool IsServer
{
get { return _isServer; }
}

public SafeBioHandle InputBio
{
get
{
return _readBio;
}
}

public SafeBioHandle OutputBio
{
get
{
return _writeBio;
}
}

public static SafeSslHandle Create(SafeSslContextHandle context, bool isServer)
{
SafeBioHandle readBio = Interop.Crypto.CreateMemoryBio();
if (readBio.IsInvalid)
{
return new SafeSslHandle();
}

SafeBioHandle writeBio = Interop.Crypto.CreateMemoryBio();
if (writeBio.IsInvalid)
{
readBio.Dispose();
return new SafeSslHandle();
}

SafeSslHandle handle = Interop.Ssl.SslCreate(context);
if (handle.IsInvalid)
{
readBio.Dispose();
writeBio.Dispose();
return handle;
}
handle._isServer = isServer;

// After SSL_set_bio, the BIO handles are owned by SSL pointer
// and are automatically freed by SSL_free. To prevent a double
// free, we need to keep the ref counts bumped up till SSL_free
bool gotRef = false;
readBio.DangerousAddRef(ref gotRef);
try
{
bool ignore = false;
writeBio.DangerousAddRef(ref ignore);
}
catch
{
if (gotRef)
{
readBio.DangerousRelease();
}
throw;
}

Interop.libssl.SSL_set_bio(handle, readBio, writeBio);
handle._readBio = readBio;
handle._writeBio = writeBio;

if (isServer)
{
Interop.libssl.SSL_set_accept_state(handle);
}
else
{
Interop.libssl.SSL_set_connect_state(handle);
}
return handle;
}

public override bool IsInvalid
{
get { return handle == IntPtr.Zero; }
}

protected override bool ReleaseHandle()
{
Interop.Ssl.SslDestroy(handle);
if (_readBio != null)
{
_readBio.SetHandleAsInvalid(); // BIO got freed in SslDestroy
}
if (_writeBio != null)
{
_writeBio.SetHandleAsInvalid(); // BIO got freed in SslDestroy
}
return true;
}

private SafeSslHandle() : base(IntPtr.Zero, true)
{
}
}
}
40 changes: 12 additions & 28 deletions src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;

using SafeSslHandle = Interop.libssl.SafeSslHandle;

internal static partial class Interop
{
internal static class OpenSsl
Expand All @@ -25,14 +23,14 @@ internal static SafeSslHandle AllocateSslContext(long options, SafeX509Handle ce

IntPtr method = GetSslMethod(isServer, options);

using (libssl.SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method))
using (SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method))
{
if (innerContext.IsInvalid)
{
throw CreateSslException(SR.net_allocate_ssl_context_failed);
}

libssl.SSL_CTX_ctrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero);
Ssl.SslCtxCtrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero);

libssl.SSL_CTX_set_quiet_shutdown(innerContext, 1);

Expand Down Expand Up @@ -212,20 +210,6 @@ internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle
return libssl.SSL_get_peer_cert_chain(context);
}

internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle sslHandle, out string protocolVersion)
{
IntPtr cipherPtr = libssl.SSL_get_current_cipher(sslHandle);
var cipher = new libssl.SSL_CIPHER();
if (IntPtr.Zero != cipherPtr)
{
cipher = Marshal.PtrToStructure<libssl.SSL_CIPHER>(cipherPtr);
}

IntPtr versionPtr = libssl.SSL_get_version(sslHandle);
protocolVersion = Marshal.PtrToStringAnsi(versionPtr);
return cipher;
}

internal static void FreeSslContext(SafeSslHandle context)
{
Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext");
Expand Down Expand Up @@ -317,7 +301,7 @@ private static int VerifyClientCertificate(int preverify_ok, IntPtr x509_ctx_ptr
}
}

private static void UpdateCAListFromRootStore(libssl.SafeSslContextHandle context)
private static void UpdateCAListFromRootStore(SafeSslContextHandle context)
{
using (SafeX509NameStackHandle nameStack = Crypto.NewX509NameStack())
{
Expand Down Expand Up @@ -375,8 +359,8 @@ private static void Disconnect(SafeSslHandle context)
int retVal = libssl.SSL_shutdown(context);
if (retVal < 0)
{
//TODO (Issue #3362) check this error
libssl.SSL_get_error(context, retVal);
//TODO (Issue #4031) check this error
Ssl.SslGetError(context, retVal);
}
}

Expand Down Expand Up @@ -421,15 +405,15 @@ private static int BioWrite(SafeBioHandle bio, byte[] buffer, int offset, int co

private static libssl.SslErrorCode GetSslError(SafeSslHandle context, int result)
{
libssl.SslErrorCode retVal = libssl.SSL_get_error(context, result);
libssl.SslErrorCode retVal = Ssl.SslGetError(context, result);
if (retVal == libssl.SslErrorCode.SSL_ERROR_SYSCALL)
{
retVal = (libssl.SslErrorCode)libssl.ERR_get_error();
retVal = (libssl.SslErrorCode)Crypto.ErrGetError();
}
return retVal;
}

private static void SetSslCertificate(libssl.SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr)
private static void SetSslCertificate(SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr)
{
Debug.Assert(certPtr != null && !certPtr.IsInvalid, "certPtr != null && !certPtr.IsInvalid");
Debug.Assert(keyPtr != null && !keyPtr.IsInvalid, "keyPtr != null && !keyPtr.IsInvalid");
Expand Down Expand Up @@ -457,10 +441,10 @@ private static void SetSslCertificate(libssl.SafeSslContextHandle contextPtr, Sa
}
}

private static SslException CreateSslException(string message)
internal static SslException CreateSslException(string message)
{
ulong errorVal = libssl.ERR_get_error();
string msg = SR.Format(message, Marshal.PtrToStringAnsi(libssl.ERR_reason_error_string(errorVal)));
ulong errorVal = Crypto.ErrGetError();
string msg = SR.Format(message, Marshal.PtrToStringAnsi(Crypto.ErrReasonErrorString(errorVal)));
return new SslException(msg, (int)errorVal);
}

Expand All @@ -483,7 +467,7 @@ private static SslException CreateSslException(string message, libssl.SslErrorCo

private static SslException CreateSslException(SafeSslHandle context, string message, int error)
{
return CreateSslException(message, libssl.SSL_get_error(context, error));
return CreateSslException(message, Ssl.SslGetError(context, error));
}

#endregion
Expand Down
Loading