From d3939b58a14ec991b5c27939f6003f263b1ae138 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 20 Oct 2015 16:32:06 -0500 Subject: [PATCH 1/3] Add shims for the next set of SSL interop methods. I also moved the SSL SafeHandle classes out of the Interop class to be better aligned with the rest of the SafeHandles. --- .../Interop.ERR.cs | 12 +- .../Interop.Ssl.cs | 37 +++-- .../Interop/Unix/libssl/Interop.OpenSsl.cs | 22 ++- .../Unix/libssl/Interop.SafeSslHandle.cs | 142 ------------------ .../src/Interop/Unix/libssl/Interop.libssl.cs | 21 --- .../Unix/libssl/SecuritySafeHandles.cs | 4 +- .../Win32/SafeHandles/SafeSslHandle.Unix.cs | 139 +++++++++++++++++ .../pal_err.cpp | 17 ++- .../pal_err.h | 14 +- .../pal_ssl.cpp | 31 ++++ .../pal_ssl.h | 43 ++++++ .../src/System.Net.Security.csproj | 6 +- .../src/System/Net/SslStreamPal.Unix.cs | 2 +- 13 files changed, 292 insertions(+), 198 deletions(-) delete mode 100644 src/Common/src/Interop/Unix/libssl/Interop.SafeSslHandle.cs create mode 100644 src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs index e34a81cb1b18..46bfd26eb901 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs @@ -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); @@ -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; @@ -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 diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index e0d1b7ca6497..72bcc9687608 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -9,29 +9,44 @@ 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)] + 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)] diff --git a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs index b16a638f79b7..11206f7615e8 100644 --- a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs +++ b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs @@ -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 @@ -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); + Crypto.SslCtxCtrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero); libssl.SSL_CTX_set_quiet_shutdown(innerContext, 1); @@ -317,7 +315,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()) { @@ -376,7 +374,7 @@ private static void Disconnect(SafeSslHandle context) if (retVal < 0) { //TODO (Issue #3362) check this error - libssl.SSL_get_error(context, retVal); + Crypto.SslGetError(context, retVal); } } @@ -421,15 +419,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 = Crypto.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"); @@ -459,8 +457,8 @@ private static void SetSslCertificate(libssl.SafeSslContextHandle contextPtr, Sa private 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); } @@ -483,7 +481,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, Crypto.SslGetError(context, error)); } #endregion diff --git a/src/Common/src/Interop/Unix/libssl/Interop.SafeSslHandle.cs b/src/Common/src/Interop/Unix/libssl/Interop.SafeSslHandle.cs deleted file mode 100644 index 97b7eba26954..000000000000 --- a/src/Common/src/Interop/Unix/libssl/Interop.SafeSslHandle.cs +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; - -internal static partial class Interop -{ - internal static partial class libssl - { - internal sealed class SafeSslContextHandle : SafeHandle - { - private SafeSslContextHandle() - : base(IntPtr.Zero, true) - { - } - - public override bool IsInvalid - { - get { return handle == IntPtr.Zero; } - } - - protected override bool ReleaseHandle() - { - SSL_CTX_free(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 = Crypto.CreateMemoryBio(); - if (readBio.IsInvalid) - { - return new SafeSslHandle(); - } - - SafeBioHandle writeBio = Crypto.CreateMemoryBio(); - if (writeBio.IsInvalid) - { - readBio.Dispose(); - return new SafeSslHandle(); - } - - SafeSslHandle handle = SSL_new(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; - } - - SSL_set_bio(handle, readBio, writeBio); - handle._readBio = readBio; - handle._writeBio = writeBio; - - if (isServer) - { - SSL_set_accept_state(handle); - } - else - { - SSL_set_connect_state(handle); - } - return handle; - } - - public override bool IsInvalid - { - get { return handle == IntPtr.Zero; } - } - - protected override bool ReleaseHandle() - { - SSL_free(handle); - if (_readBio != null) - { - _readBio.SetHandleAsInvalid(); // BIO got freed in SSL_free - } - if (_writeBio != null) - { - _writeBio.SetHandleAsInvalid(); // BIO got freed in SSL_free - } - return true; - } - - private SafeSslHandle() : base(IntPtr.Zero, true) - { - } - } - } -} diff --git a/src/Common/src/Interop/Unix/libssl/Interop.libssl.cs b/src/Common/src/Interop/Unix/libssl/Interop.libssl.cs index 54f43c7d3a69..ca69b20c8455 100644 --- a/src/Common/src/Interop/Unix/libssl/Interop.libssl.cs +++ b/src/Common/src/Interop/Unix/libssl/Interop.libssl.cs @@ -10,27 +10,6 @@ internal static partial class Interop { internal static partial class libssl { - [DllImport(Interop.Libraries.LibSsl)] - internal static extern long SSL_CTX_ctrl(SafeSslContextHandle ctx, int cmd, long larg, IntPtr parg); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern SafeSslHandle SSL_new(SafeSslContextHandle ctx); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern ulong ERR_get_error(); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern IntPtr ERR_reason_error_string(ulong error); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern SslErrorCode SSL_get_error(SafeSslHandle ssl, int ret); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern void SSL_free(IntPtr ssl); - - [DllImport(Interop.Libraries.LibSsl)] - internal static extern void SSL_CTX_free(IntPtr ctx); - [DllImport(Interop.Libraries.LibSsl)] internal static extern void SSL_set_connect_state(SafeSslHandle ssl); diff --git a/src/Common/src/Interop/Unix/libssl/SecuritySafeHandles.cs b/src/Common/src/Interop/Unix/libssl/SecuritySafeHandles.cs index d6d0957d42ac..6ed686f76ab1 100644 --- a/src/Common/src/Interop/Unix/libssl/SecuritySafeHandles.cs +++ b/src/Common/src/Interop/Unix/libssl/SecuritySafeHandles.cs @@ -213,9 +213,9 @@ internal sealed class SafeDeleteContext : SafeHandle { #endif private readonly SafeFreeCredentials _credential; - private readonly Interop.libssl.SafeSslHandle _sslContext; + private readonly SafeSslHandle _sslContext; - public Interop.libssl.SafeSslHandle SslContext + public SafeSslHandle SslContext { get { diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs new file mode 100644 index 000000000000..c657b6e9b1b5 --- /dev/null +++ b/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using Microsoft.Win32.SafeHandles; + +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.Crypto.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.Crypto.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.Crypto.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) + { + } + } +} \ No newline at end of file diff --git a/src/Native/System.Security.Cryptography.Native/pal_err.cpp b/src/Native/System.Security.Cryptography.Native/pal_err.cpp index e2939811ad4a..26dd70b7a96b 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_err.cpp +++ b/src/Native/System.Security.Cryptography.Native/pal_err.cpp @@ -6,15 +6,28 @@ #include -extern "C" uint64_t ErrGetError(int32_t* isAllocFailure) +extern "C" uint64_t ErrGetError() +{ + return ERR_get_error(); +} + +extern "C" uint64_t ErrGetErrorAlloc(int32_t* isAllocFailure) { unsigned long err = ERR_get_error(); - *isAllocFailure = ERR_GET_REASON(err) == ERR_R_MALLOC_FAILURE; + if (isAllocFailure) + { + *isAllocFailure = ERR_GET_REASON(err) == ERR_R_MALLOC_FAILURE; + } return err; } +extern "C" const char* ErrReasonErrorString(uint64_t error) +{ + return ERR_reason_error_string(error); +} + extern "C" void ErrErrorStringN(uint64_t e, char* buf, int32_t len) { ERR_error_string_n(e, buf, UnsignedCast(len)); diff --git a/src/Native/System.Security.Cryptography.Native/pal_err.h b/src/Native/System.Security.Cryptography.Native/pal_err.h index f16ba358719c..3feea84ff2f0 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_err.h +++ b/src/Native/System.Security.Cryptography.Native/pal_err.h @@ -3,11 +3,23 @@ #include +/* +Shims the ERR_get_error method. +*/ +extern "C" uint64_t ErrGetError(); + /* Shim to ERR_get_error which also returns whether the error was caused by an allocation failure. */ -extern "C" uint64_t ErrGetError(int32_t* isAllocFailure); +extern "C" uint64_t ErrGetErrorAlloc(int32_t* isAllocFailure); + +/* +Shims the ERR_reason_error_string method. + +Returns the string for the specified error. +*/ +extern "C" const char* ErrReasonErrorString(uint64_t error); /* Direct shim to ERR_error_string_n. diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp index 4818b46011b6..903b1669b82c 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp @@ -42,6 +42,37 @@ extern "C" SSL_CTX* SslCtxCreate(SSL_METHOD* method) return SSL_CTX_new(method); } +extern "C" int64_t SslCtxCtrl(SSL_CTX* ctx, int32_t cmd, int64_t larg, void* parg) +{ + return SSL_CTX_ctrl(ctx, cmd, larg, parg); +} + +extern "C" SSL* SslCreate(SSL_CTX* ctx) +{ + return SSL_new(ctx); +} + +extern "C" int32_t SslGetError(SSL* ssl, int32_t ret) +{ + return SSL_get_error(ssl, ret); +} + +extern "C" void SslDestroy(SSL* ssl) +{ + if (ssl) + { + SSL_free(ssl); + } +} + +extern "C" void SslCtxDestroy(SSL_CTX* ctx) +{ + if (ctx) + { + SSL_CTX_free(ctx); + } +} + extern "C" int32_t SslWrite(SSL* ssl, const void* buf, int32_t num) { return SSL_write(ssl, buf, num); diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.h b/src/Native/System.Security.Cryptography.Native/pal_ssl.h index fb9c65472635..06248526e18b 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.h @@ -47,6 +47,49 @@ Returns the new SSL_CTX instance. */ extern "C" SSL_CTX* SslCtxCreate(SSL_METHOD* method); +/* +Shims the SSL_CTX_ctrl method. + +The return value of the SSL_CTX_ctrl() function depends on the command supplied via the cmd parameter. +*/ +extern "C" int64_t SslCtxCtrl(SSL_CTX* ctx, int32_t cmd, int64_t larg, void* parg); + +/* +Shims the SSL_new method. + +Returns the new SSL instance. +*/ +extern "C" SSL* SslCreate(SSL_CTX* ctx); + +/* +Shims the SSL_get_error method. + +Returns the error code for the specified result. +*/ +extern "C" int32_t SslGetError(SSL* ssl, int32_t ret); + +/* +Cleans up and deletes an SSL instance. + +Implemented by calling SSL_free. + +No-op if ssl is null. +The given X509 SSL is invalid after this call. +Always succeeds. +*/ +extern "C" void SslDestroy(SSL* ssl); + +/* +Cleans up and deletes an SSL_CTX instance. + +Implemented by calling SSL_CTX_free. + +No-op if ctx is null. +The given X509 SSL_CTX is invalid after this call. +Always succeeds. +*/ +extern "C" void SslCtxDestroy(SSL_CTX* ctx); + /* Shims the SSL_write method. diff --git a/src/System.Net.Security/src/System.Net.Security.csproj b/src/System.Net.Security/src/System.Net.Security.csproj index 6e7c4de956c3..b976c4341ef6 100644 --- a/src/System.Net.Security/src/System.Net.Security.csproj +++ b/src/System.Net.Security/src/System.Net.Security.csproj @@ -209,9 +209,6 @@ Common\Interop\Unix\libssl\Interop.libssl_types.cs - - Common\Interop\Unix\libssl\Interop.SafeSslHandle.cs - Common\Interop\Unix\libssl\SecuritySafeHandles.cs @@ -272,6 +269,9 @@ Common\Microsoft\Win32\SafeHandles\Asn1SafeHandles.Unix.cs + + Common\Microsoft\Win32\SafeHandles\SafeSslHandle.Unix.cs + diff --git a/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs b/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs index 693b75b2f9fc..5d78ae49d3d5 100644 --- a/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs +++ b/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs @@ -193,7 +193,7 @@ private static SecurityStatusPal EncryptDecryptHelper(SafeDeleteContext security Interop.libssl.SslErrorCode errorCode = Interop.libssl.SslErrorCode.SSL_ERROR_NONE; - Interop.libssl.SafeSslHandle scHandle = securityContext.SslContext; + SafeSslHandle scHandle = securityContext.SslContext; resultSize = encrypt ? Interop.OpenSsl.Encrypt(scHandle, buffer, offset, size, out errorCode) : From 30c98cc053bcdd0f7aef556bbe203ada1b9f23a2 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Tue, 20 Oct 2015 22:56:05 -0500 Subject: [PATCH 2/3] Move SSL_CIPHER struct usage into native shim. Instead of having managed code duplicate the SSL_CIPHER struct, moving all the code that uses the cipher struct into a native shim method. That also pulled a lot of algorithm constants to be defined in native instead of managed. --- .../Interop.Ssl.cs | 16 ++ .../Interop/Unix/libssl/Interop.OpenSsl.cs | 16 +- .../Unix/libssl/Interop.libssl_types.cs | 68 ------ .../Interop/Unix/libssl/SslConnectionInfo.cs | 171 ++------------ .../CMakeLists.txt | 6 + .../pal_ssl.cpp | 221 ++++++++++++++++++ .../pal_ssl.h | 162 +++++++++++++ .../src/Resources/Strings.resx | 3 + .../src/System/Net/SslStreamPal.Unix.cs | 6 +- 9 files changed, 427 insertions(+), 242 deletions(-) diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index 72bcc9687608..0e5ef9bf6d08 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -42,6 +42,22 @@ internal static partial class 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); diff --git a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs index 11206f7615e8..7ec91a6c3be9 100644 --- a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs +++ b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs @@ -210,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(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"); @@ -455,7 +441,7 @@ private static void SetSslCertificate(SafeSslContextHandle contextPtr, SafeX509H } } - private static SslException CreateSslException(string message) + internal static SslException CreateSslException(string message) { ulong errorVal = Crypto.ErrGetError(); string msg = SR.Format(message, Marshal.PtrToStringAnsi(Crypto.ErrReasonErrorString(errorVal))); diff --git a/src/Common/src/Interop/Unix/libssl/Interop.libssl_types.cs b/src/Common/src/Interop/Unix/libssl/Interop.libssl_types.cs index 121803b09276..8fe153f6d5aa 100644 --- a/src/Common/src/Interop/Unix/libssl/Interop.libssl_types.cs +++ b/src/Common/src/Interop/Unix/libssl/Interop.libssl_types.cs @@ -19,23 +19,6 @@ internal static partial class libssl Options.SSL_OP_NO_TLSv1 | Options.SSL_OP_NO_TLSv1_1 | Options.SSL_OP_NO_TLSv1_2; - [StructLayout(LayoutKind.Sequential)] - internal struct SSL_CIPHER - { - internal int valid; - internal string name; - internal long id; - internal long algorithm_mkey; - internal long algorithm_auth; - internal long algorithm_enc; - internal long algorithm_mac; - internal long algorithm_ssl; - internal long algo_strength; - internal long algorithm2; - internal int strength_bits; - internal int alg_bits; - } - internal class Options { internal const long SSL_OP_NO_SSLv2 = 0x01000000; @@ -107,57 +90,6 @@ internal enum SslState SSL_ST_OK = 3 } - internal enum CipherAlgorithm - { - SSL_DES = 1, - SSL_3DES = 2, - SSL_RC4 = 4, - SSL_RC2 = 8, - SSL_IDEA = 16, - SSL_eNULL = 32, - SSL_AES128 = 64, - SSL_AES256 = 128, - SSL_CAMELLIA128 = 256, - SSL_CAMELLIA256 = 512, - SSL_eGOST2814789CNT = 1024, - SSL_SEED = 2048, - SSL_AES128GCM = 4096, - SSL_AES256GCM = 8192 - - } - - internal enum KeyExchangeAlgorithm - { - SSL_kRSA = 1, - /* DH cert, RSA CA cert */ - SSL_kDHr = 2, - /* DH cert, DSA CA cert */ - SSL_kDHd = 4, - /* tmp DH key no DH cert */ - SSL_kEDH = 8, - /* Kerberos5 key exchange */ - SSL_kKRB5 = 16, - /* ECDH cert, RSA CA cert */ - SSL_kECDHr = 32, - /* ECDH cert, ECDSA CA cert */ - SSL_kECDHe = 64, - SSL_kEECDH = 128, - SSL_kPSK = 256, - SSL_kGOST = 512, - SSL_kSRP = 1024, - } - - internal enum DataHashAlgorithm - { - SSL_MD5 = 1, - SSL_SHA1 = 2, - SSL_GOST94 = 4, - SSL_GOST89MAC = 8, - SSL_SHA256 = 16, - SSL_SHA384 = 32, - SSL_AEAD = 64 - } - [FlagsAttribute] internal enum ClientCertOption { diff --git a/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs b/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs index 732c55245f10..0b08811c2a55 100644 --- a/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs +++ b/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs @@ -2,50 +2,34 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Security.Authentication; +using Microsoft.Win32.SafeHandles; namespace System.Net { internal class SslConnectionInfo { - //Windows constants for algorithms without matching enums in SslStream - //Taken from wincrypt.h - internal const int SSL_SHA256 = 32780; - internal const int SSL_SHA384 = 32781; - internal const int SSL_ECDH = 43525; - internal const int SSL_ECDSA = 41475; - - //Algorithm constants which are not present in wincrypt.h(not supported in Windows) - //These constants values are not conflicting with existing constants in wincrypt.h - internal const int SSL_IDEA = 229380; - internal const int SSL_CAMELLIA128 = 229381; - internal const int SSL_CAMELLIA256 = 229382; - internal const int SSL_eGOST2814789CNT = 229383; - internal const int SSL_SEED = 229384; - - internal const int SSL_kPSK = 229390; - internal const int SSL_kGOST = 229391; - internal const int SSL_kSRP = 229392; - internal const int SSL_kKRB5 = 229393; - - internal const int SSL_GOST94 = 229410; - internal const int SSL_GOST89 = 229411; - internal const int SSL_AEAD = 229412; - - public readonly int Protocol; + public readonly SslProtocols Protocol; public readonly int DataCipherAlg; - public readonly int DataKeySize = 0; + public readonly int DataKeySize; public readonly int DataHashAlg; public readonly int DataHashKeySize = 0; public readonly int KeyExchangeAlg; public readonly int KeyExchKeySize = 0; - internal SslConnectionInfo(Interop.libssl.SSL_CIPHER cipher, string protocol) + internal SslConnectionInfo(SafeSslHandle sslContext) { - Protocol = (int) MapProtocolVersion(protocol); - DataCipherAlg = (int) MapCipherAlgorithmType((Interop.libssl.CipherAlgorithm) cipher.algorithm_enc); - KeyExchangeAlg = (int) MapExchangeAlgorithmType((Interop.libssl.KeyExchangeAlgorithm) cipher.algorithm_mkey); - DataHashAlg = (int) MapHashAlgorithmType((Interop.libssl.DataHashAlgorithm) cipher.algorithm_mac); - DataKeySize = cipher.alg_bits; + string protocolVersion = Interop.Crypto.GetProtocolVersion(sslContext); + Protocol = MapProtocolVersion(protocolVersion); + + if (!Interop.Crypto.GetSslConnectionInfo( + sslContext, + out DataCipherAlg, + out KeyExchangeAlg, + out DataHashAlg, + out DataKeySize)) + { + throw Interop.OpenSsl.CreateSslException(SR.net_ssl_get_connection_info_failed); + } // TODO (Issue #3362) map key sizes } @@ -67,128 +51,5 @@ private SslProtocols MapProtocolVersion(string protocolVersion) return SslProtocols.None; } } - - private static CipherAlgorithmType MapCipherAlgorithmType(Interop.libssl.CipherAlgorithm encryption) - { - switch (encryption) - { - case Interop.libssl.CipherAlgorithm.SSL_DES: - return CipherAlgorithmType.Des; - - case Interop.libssl.CipherAlgorithm.SSL_3DES: - return CipherAlgorithmType.TripleDes; - - case Interop.libssl.CipherAlgorithm.SSL_RC4: - return CipherAlgorithmType.Rc4; - - case Interop.libssl.CipherAlgorithm.SSL_RC2: - return CipherAlgorithmType.Rc2; - - case Interop.libssl.CipherAlgorithm.SSL_eNULL: - return CipherAlgorithmType.Null; - - case Interop.libssl.CipherAlgorithm.SSL_AES128: - return CipherAlgorithmType.Aes128; - - case Interop.libssl.CipherAlgorithm.SSL_AES256: - return CipherAlgorithmType.Aes256; - - case Interop.libssl.CipherAlgorithm.SSL_IDEA: - return (CipherAlgorithmType) SSL_IDEA; - - case Interop.libssl.CipherAlgorithm.SSL_CAMELLIA128: - return (CipherAlgorithmType) SSL_CAMELLIA128; - - case Interop.libssl.CipherAlgorithm.SSL_CAMELLIA256: - return (CipherAlgorithmType) SSL_CAMELLIA256; - - case Interop.libssl.CipherAlgorithm.SSL_eGOST2814789CNT: - return (CipherAlgorithmType) SSL_eGOST2814789CNT; - - case Interop.libssl.CipherAlgorithm.SSL_SEED: - return (CipherAlgorithmType) SSL_SEED; - - case Interop.libssl.CipherAlgorithm.SSL_AES128GCM: - return CipherAlgorithmType.Aes128; - - case Interop.libssl.CipherAlgorithm.SSL_AES256GCM: - return CipherAlgorithmType.Aes256; - - default: - return CipherAlgorithmType.None; - } - } - - private static ExchangeAlgorithmType MapExchangeAlgorithmType(Interop.libssl.KeyExchangeAlgorithm mkey) - { - switch (mkey) - { - case Interop.libssl.KeyExchangeAlgorithm.SSL_kRSA: - return ExchangeAlgorithmType.RsaKeyX; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kDHr: - return ExchangeAlgorithmType.DiffieHellman; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kDHd: - return ExchangeAlgorithmType.DiffieHellman; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kEDH: - return ExchangeAlgorithmType.DiffieHellman; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kKRB5: - return (ExchangeAlgorithmType) SSL_kKRB5; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kECDHr: - return (ExchangeAlgorithmType) SSL_ECDH; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kECDHe: - return (ExchangeAlgorithmType) SSL_ECDSA; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kEECDH: - return (ExchangeAlgorithmType) SSL_ECDSA; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kPSK: - return (ExchangeAlgorithmType) SSL_kPSK; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kGOST: - return (ExchangeAlgorithmType) SSL_kGOST; - - case Interop.libssl.KeyExchangeAlgorithm.SSL_kSRP: - return (ExchangeAlgorithmType) SSL_kSRP; - - default: - return ExchangeAlgorithmType.None; - } - } - - private static HashAlgorithmType MapHashAlgorithmType(Interop.libssl.DataHashAlgorithm mac) - { - switch (mac) - { - case Interop.libssl.DataHashAlgorithm.SSL_MD5: - return HashAlgorithmType.Md5; - - case Interop.libssl.DataHashAlgorithm.SSL_SHA1: - return HashAlgorithmType.Sha1; - - case Interop.libssl.DataHashAlgorithm.SSL_GOST94: - return (HashAlgorithmType) SSL_GOST94; - - case Interop.libssl.DataHashAlgorithm.SSL_GOST89MAC: - return (HashAlgorithmType) SSL_GOST89; - - case Interop.libssl.DataHashAlgorithm.SSL_SHA256: - return (HashAlgorithmType) SSL_SHA256; - - case Interop.libssl.DataHashAlgorithm.SSL_SHA384: - return (HashAlgorithmType) SSL_SHA384; - - case Interop.libssl.DataHashAlgorithm.SSL_AEAD: - return (HashAlgorithmType) SSL_AEAD; - - default: - return HashAlgorithmType.None; - } - } } } diff --git a/src/Native/System.Security.Cryptography.Native/CMakeLists.txt b/src/Native/System.Security.Cryptography.Native/CMakeLists.txt index bbf028d69ebb..06328a49f4e6 100644 --- a/src/Native/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/Native/System.Security.Cryptography.Native/CMakeLists.txt @@ -13,6 +13,12 @@ add_definitions(-DPIC=1) find_package(OpenSSL REQUIRED) +include(CheckStructHasMember) +check_struct_has_member ("SSL_CIPHER" algorithms openssl/ssl.h SSL_CIPHER_ALGORITHMS) +if (SSL_CIPHER_ALGORITHMS) + add_definitions(-DHAVE_SSL_CIPHER_ALGORITHMS=1) +endif() + set(NATIVECRYPTO_SOURCES openssl.c pal_asn1.cpp diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp index 903b1669b82c..cc3968da4f0a 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp @@ -4,6 +4,8 @@ #include "pal_ssl.h" #include "pal_crypto_config.h" +#include + extern "C" const SSL_METHOD* SslV2_3Method() { return SSLv23_method(); @@ -73,6 +75,225 @@ extern "C" void SslCtxDestroy(SSL_CTX* ctx) } } +extern "C" const char* SSLGetVersion(SSL* ssl) +{ + return SSL_get_version(ssl); +} + +static CipherAlgorithmType MapCipherAlgorithmType(const SSL_CIPHER* cipher) +{ + unsigned long enc; + +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + const unsigned long SSL_ENC_MASK = 0x1C3F8000L; + enc = cipher->algorithms & SSL_ENC_MASK; +#else + enc = cipher->algorithm_enc; +#endif + + SSL_CipherAlgorithm sslEnc = static_cast(enc); + switch (sslEnc) + { + case SSL_CipherAlgorithm::SSL_DES: + return CipherAlgorithmType::Des; + + case SSL_CipherAlgorithm::SSL_3DES: + return CipherAlgorithmType::TripleDes; + + case SSL_CipherAlgorithm::SSL_RC4: + return CipherAlgorithmType::Rc4; + + case SSL_CipherAlgorithm::SSL_RC2: + return CipherAlgorithmType::Rc2; + + case SSL_CipherAlgorithm::SSL_eNULL: + return CipherAlgorithmType::Null; + + case SSL_CipherAlgorithm::SSL_IDEA: + return CipherAlgorithmType::SSL_IDEA; + + case SSL_CipherAlgorithm::SSL_SEED: + return CipherAlgorithmType::SSL_SEED; + +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + case SSL_CipherAlgorithm::SSL_AES: + switch (cipher->alg_bits) + { + case 128: + return CipherAlgorithmType::Aes128; + case 256: + return CipherAlgorithmType::Aes256; + } + case SSL_CipherAlgorithm::SSL_CAMELLIA: + switch (cipher->alg_bits) + { + case 128: + return CipherAlgorithmType::SSL_CAMELLIA128; + case 256: + return CipherAlgorithmType::SSL_CAMELLIA256; + } +#else + case SSL_CipherAlgorithm::SSL_AES128: + return CipherAlgorithmType::Aes128; + + case SSL_CipherAlgorithm::SSL_AES256: + return CipherAlgorithmType::Aes256; + + case SSL_CipherAlgorithm::SSL_CAMELLIA128: + return CipherAlgorithmType::SSL_CAMELLIA128; + + case SSL_CipherAlgorithm::SSL_CAMELLIA256: + return CipherAlgorithmType::SSL_CAMELLIA256; + + case SSL_CipherAlgorithm::SSL_eGOST2814789CNT: + return CipherAlgorithmType::SSL_eGOST2814789CNT; + + case SSL_CipherAlgorithm::SSL_AES128GCM: + return CipherAlgorithmType::Aes128; + + case SSL_CipherAlgorithm::SSL_AES256GCM: + return CipherAlgorithmType::Aes256; +#endif + } + + return CipherAlgorithmType::None; +} + +static ExchangeAlgorithmType MapExchangeAlgorithmType(const SSL_CIPHER* cipher) +{ + unsigned long mkey; +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + const unsigned long SSL_MKEY_MASK = 0x000000FFL; + mkey = cipher->algorithms & SSL_MKEY_MASK; +#else + mkey = cipher->algorithm_mkey; +#endif + + SSL_KeyExchangeAlgorithm sslMkey = static_cast(mkey); + switch (sslMkey) + { + case SSL_KeyExchangeAlgorithm::SSL_kRSA: + return ExchangeAlgorithmType::RsaKeyX; + + case SSL_KeyExchangeAlgorithm::SSL_kDHr: + return ExchangeAlgorithmType::DiffieHellman; + + case SSL_KeyExchangeAlgorithm::SSL_kDHd: + return ExchangeAlgorithmType::DiffieHellman; + + case SSL_KeyExchangeAlgorithm::SSL_kEDH: + return ExchangeAlgorithmType::DiffieHellman; + + case SSL_KeyExchangeAlgorithm::SSL_kKRB5: + return ExchangeAlgorithmType::SSL_kKRB5; + +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + case SSL_KeyExchangeAlgorithm::SSL_kECDH: + return ExchangeAlgorithmType::SSL_ECDH; + + case SSL_KeyExchangeAlgorithm::SSL_kECDHE: + return ExchangeAlgorithmType::SSL_ECDSA; +#else + case SSL_KeyExchangeAlgorithm::SSL_kECDHr: + return ExchangeAlgorithmType::SSL_ECDH; + + case SSL_KeyExchangeAlgorithm::SSL_kECDHe: + return ExchangeAlgorithmType::SSL_ECDSA; + + case SSL_KeyExchangeAlgorithm::SSL_kEECDH: + return ExchangeAlgorithmType::SSL_ECDSA; + + case SSL_KeyExchangeAlgorithm::SSL_kPSK: + return ExchangeAlgorithmType::SSL_kPSK; + + case SSL_KeyExchangeAlgorithm::SSL_kGOST: + return ExchangeAlgorithmType::SSL_kGOST; + + case SSL_KeyExchangeAlgorithm::SSL_kSRP: + return ExchangeAlgorithmType::SSL_kSRP; +#endif + } + + return ExchangeAlgorithmType::None; +} + +static HashAlgorithmType MapHashAlgorithmType(const SSL_CIPHER* cipher) +{ + unsigned long mac; +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + const unsigned long SSL_MAC_MASK = 0x00c00000L; + mac = cipher->algorithms & SSL_MAC_MASK; +#else + mac = cipher->algorithm_mac; +#endif + + SSL_DataHashAlgorithm sslMac = static_cast(mac); + switch (sslMac) + { + case SSL_DataHashAlgorithm::SSL_MD5: + return HashAlgorithmType::Md5; + + case SSL_DataHashAlgorithm::SSL_SHA1: + return HashAlgorithmType::Sha1; + +#ifndef HAVE_SSL_CIPHER_ALGORITHMS + case SSL_DataHashAlgorithm::SSL_GOST94: + return HashAlgorithmType::SSL_GOST94; + + case SSL_DataHashAlgorithm::SSL_GOST89MAC: + return HashAlgorithmType::SSL_GOST89; + + case SSL_DataHashAlgorithm::SSL_SHA256: + return HashAlgorithmType::SSL_SHA256; + + case SSL_DataHashAlgorithm::SSL_SHA384: + return HashAlgorithmType::SSL_SHA384; + + case SSL_DataHashAlgorithm::SSL_AEAD: + return HashAlgorithmType::SSL_AEAD; +#endif + } + + return HashAlgorithmType::None; +} + +extern "C" int32_t GetSslConnectionInfo(SSL* ssl, CipherAlgorithmType* dataCipherAlg, ExchangeAlgorithmType* keyExchangeAlg, HashAlgorithmType* dataHashAlg, int32_t* dataKeySize) +{ + const SSL_CIPHER* cipher; + + if (!ssl || !dataCipherAlg || !keyExchangeAlg || !dataHashAlg || !dataKeySize) + { + goto err; + } + + cipher = SSL_get_current_cipher(ssl); + if (!cipher) + { + goto err; + } + + *dataCipherAlg = MapCipherAlgorithmType(cipher); + *keyExchangeAlg = MapExchangeAlgorithmType(cipher); + *dataHashAlg = MapHashAlgorithmType(cipher); + *dataKeySize = cipher->alg_bits; + + return 1; + +err: + assert(false); + + if (dataCipherAlg) + *dataCipherAlg = CipherAlgorithmType::None; + if (keyExchangeAlg) + *keyExchangeAlg = ExchangeAlgorithmType::None; + if (dataHashAlg) + *dataHashAlg = HashAlgorithmType::None; + if (dataKeySize) + *dataKeySize = 0; + + return 0; +} + extern "C" int32_t SslWrite(SSL* ssl, const void* buf, int32_t num) { return SSL_write(ssl, buf, num); diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.h b/src/Native/System.Security.Cryptography.Native/pal_ssl.h index 06248526e18b..4aa9e0395ab6 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.h @@ -5,6 +5,154 @@ #include +/* +These values should be kept in sync with System.Security.Authentication.CipherAlgorithmType. +*/ +enum class CipherAlgorithmType : int32_t +{ + None = 0, + Null = 24576, + Des = 26113, + Rc2 = 26114, + TripleDes = 26115, + Aes128 = 26126, + Aes192 = 26127, + Aes256 = 26128, + Aes = 26129, + Rc4 = 26625, + + //Algorithm constants which are not present in the managed CipherAlgorithmType enum. + SSL_IDEA = 229380, + SSL_CAMELLIA128 = 229381, + SSL_CAMELLIA256 = 229382, + SSL_eGOST2814789CNT = 229383, + SSL_SEED = 229384, +}; + +/* +The values used in OpenSSL for SSL_CIPHER algorithm_enc. +*/ +enum class SSL_CipherAlgorithm : int64_t +{ +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + SSL_DES = 0x00008000L, + SSL_3DES = 0x00010000L, + SSL_RC4 = 0x00020000L, + SSL_RC2 = 0x00040000L, + SSL_IDEA = 0x00080000L, + //SSL_eFZA = 0x00100000L, this value is defined in ssl_locl.h, but has no match + SSL_eNULL = 0x00200000L, + SSL_AES = 0x04000000L, + SSL_CAMELLIA = 0x08000000L, + SSL_SEED = 0x10000000L, +#else + SSL_DES = 1, + SSL_3DES = 2, + SSL_RC4 = 4, + SSL_RC2 = 8, + SSL_IDEA = 16, + SSL_eNULL = 32, + SSL_AES128 = 64, + SSL_AES256 = 128, + SSL_CAMELLIA128 = 256, + SSL_CAMELLIA256 = 512, + SSL_eGOST2814789CNT = 1024, + SSL_SEED = 2048, + SSL_AES128GCM = 4096, + SSL_AES256GCM = 8192 +#endif +}; + +/* +These values should be kept in sync with System.Security.Authentication.ExchangeAlgorithmType. +*/ +enum class ExchangeAlgorithmType : int32_t +{ + None, + RsaSign = 9216, + RsaKeyX = 41984, + DiffieHellman = 43522, + + //ExchangeAlgorithm constants which are not present in the managed ExchangeAlgorithmType enum. + SSL_ECDH = 43525, + SSL_ECDSA = 41475, + SSL_kPSK = 229390, + SSL_kGOST = 229391, + SSL_kSRP = 229392, + SSL_kKRB5 = 229393, +}; + +/* +The values used in OpenSSL for SSL_CIPHER algorithm_mkey. +*/ +enum class SSL_KeyExchangeAlgorithm : int64_t +{ +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + SSL_kRSA = 0x00000001L, + SSL_kDHr = 0x00000002L, + SSL_kDHd = 0x00000004L, + //SSL_kFZA = 0x00000008L, this value is defined in ssl_locl.h, but has no match + SSL_kEDH = 0x00000010L, + SSL_kKRB5 = 0x00000020L, + SSL_kECDH = 0x00000040L, + SSL_kECDHE = 0x00000080L, +#else + SSL_kRSA = 1, + /* DH cert, RSA CA cert */ + SSL_kDHr = 2, + /* DH cert, DSA CA cert */ + SSL_kDHd = 4, + /* tmp DH key no DH cert */ + SSL_kEDH = 8, + /* Kerberos5 key exchange */ + SSL_kKRB5 = 16, + /* ECDH cert, RSA CA cert */ + SSL_kECDHr = 32, + /* ECDH cert, ECDSA CA cert */ + SSL_kECDHe = 64, + SSL_kEECDH = 128, + SSL_kPSK = 256, + SSL_kGOST = 512, + SSL_kSRP = 1024, +#endif +}; + +/* +These values should be kept in sync with System.Security.Authentication.HashAlgorithmType. +*/ +enum class HashAlgorithmType : int32_t +{ + None = 0, + Md5 = 32771, + Sha1 = 32772, + + //HashAlgorithm constants which are not present in the managed HashAlgorithmType enum. + SSL_SHA256 = 32780, + SSL_SHA384 = 32781, + SSL_GOST94 = 229410, + SSL_GOST89 = 229411, + SSL_AEAD = 229412, +}; + +/* +The values used in OpenSSL for SSL_CIPHER algorithm_mac. +*/ +enum class SSL_DataHashAlgorithm : int64_t +{ +#ifdef HAVE_SSL_CIPHER_ALGORITHMS + SSL_MD5 = 0x00400000L, + SSL_SHA1 = 0x00800000L, +#else + SSL_MD5 = 1, + SSL_SHA1 = 2, + SSL_GOST94 = 4, + SSL_GOST89MAC = 8, + SSL_SHA256 = 16, + SSL_SHA384 = 32, + SSL_AEAD = 64 +#endif +}; + /* Shims the SSLv23_method method. @@ -90,6 +238,20 @@ Always succeeds. */ extern "C" void SslCtxDestroy(SSL_CTX* ctx); +/* +Shims the SSL_get_version method. + +Returns the protocol version string for the SSL instance. +*/ +extern "C" const char* SSLGetVersion(SSL* ssl); + +/* +Returns the connection information for the SSL instance. + +Returns 1 upon success, otherwise 0. +*/ +extern "C" int32_t GetSslConnectionInfo(SSL* ssl, CipherAlgorithmType* dataCipherAlg, ExchangeAlgorithmType* keyExchangeAlg, HashAlgorithmType* dataHashAlg, int32_t* dataKeySize); + /* Shims the SSL_write method. diff --git a/src/System.Net.Security/src/Resources/Strings.resx b/src/System.Net.Security/src/Resources/Strings.resx index d244a0504eca..36289cfcf4f8 100644 --- a/src/System.Net.Security/src/Resources/Strings.resx +++ b/src/System.Net.Security/src/Resources/Strings.resx @@ -366,4 +366,7 @@ Failed to push X509_NAME into stack. + + Getting SSL connection info failed with OpenSSL error - {0}. + diff --git a/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs b/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs index 5d78ae49d3d5..52fa6b9cbedb 100644 --- a/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs +++ b/src/System.Net.Security/src/System/Net/SslStreamPal.Unix.cs @@ -78,13 +78,11 @@ public static void QueryContextStreamSizes(SafeDeleteContext securityContext, ou public static int QueryContextConnectionInfo(SafeDeleteContext securityContext, out SslConnectionInfo connectionInfo) { - string protocolVersion; connectionInfo = null; try { - Interop.libssl.SSL_CIPHER cipher = Interop.OpenSsl.GetConnectionInfo(securityContext.SslContext, out protocolVersion); - connectionInfo = new SslConnectionInfo(cipher, protocolVersion); - + connectionInfo = new SslConnectionInfo(securityContext.SslContext); + return 0; } catch From dc637b76523eac289bfddd854adca3117ca349ef Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Wed, 21 Oct 2015 11:54:11 -0500 Subject: [PATCH 3/3] Rebase and respond to PR feedback. --- .../Interop.Ssl.cs | 136 ++++++++++++++- .../Interop/Unix/libssl/Interop.OpenSsl.cs | 10 +- .../Interop/Unix/libssl/SslConnectionInfo.cs | 8 +- .../Win32/SafeHandles/SafeSslHandle.Unix.cs | 139 --------------- .../CMakeLists.txt | 6 - .../configure.cmake | 3 + .../pal_crypto_config.h.in | 2 + .../pal_ssl.cpp | 161 ++++++++++++++---- .../pal_ssl.h | 90 +--------- .../src/System.Net.Security.csproj | 3 - 10 files changed, 273 insertions(+), 285 deletions(-) delete mode 100644 src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index 0e5ef9bf6d08..0d3816fb83a9 100644 --- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -43,11 +43,11 @@ internal static partial class Ssl internal static extern void SslCtxDestroy(IntPtr ctx); [DllImport(Libraries.CryptoNative)] - private static extern IntPtr SSLGetVersion(SafeSslHandle ssl); + private static extern IntPtr SslGetVersion(SafeSslHandle ssl); internal static string GetProtocolVersion(SafeSslHandle ssl) { - return Marshal.PtrToStringAnsi(SSLGetVersion(ssl)); + return Marshal.PtrToStringAnsi(SslGetVersion(ssl)); } [DllImport(Libraries.CryptoNative)] @@ -69,3 +69,135 @@ internal static extern bool GetSslConnectionInfo( 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) + { + } + } +} diff --git a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs index 7ec91a6c3be9..76ce32fdd77c 100644 --- a/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs +++ b/src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs @@ -30,7 +30,7 @@ internal static SafeSslHandle AllocateSslContext(long options, SafeX509Handle ce throw CreateSslException(SR.net_allocate_ssl_context_failed); } - Crypto.SslCtxCtrl(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); @@ -359,8 +359,8 @@ private static void Disconnect(SafeSslHandle context) int retVal = libssl.SSL_shutdown(context); if (retVal < 0) { - //TODO (Issue #3362) check this error - Crypto.SslGetError(context, retVal); + //TODO (Issue #4031) check this error + Ssl.SslGetError(context, retVal); } } @@ -405,7 +405,7 @@ private static int BioWrite(SafeBioHandle bio, byte[] buffer, int offset, int co private static libssl.SslErrorCode GetSslError(SafeSslHandle context, int result) { - libssl.SslErrorCode retVal = Crypto.SslGetError(context, result); + libssl.SslErrorCode retVal = Ssl.SslGetError(context, result); if (retVal == libssl.SslErrorCode.SSL_ERROR_SYSCALL) { retVal = (libssl.SslErrorCode)Crypto.ErrGetError(); @@ -467,7 +467,7 @@ private static SslException CreateSslException(string message, libssl.SslErrorCo private static SslException CreateSslException(SafeSslHandle context, string message, int error) { - return CreateSslException(message, Crypto.SslGetError(context, error)); + return CreateSslException(message, Ssl.SslGetError(context, error)); } #endregion diff --git a/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs b/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs index 0b08811c2a55..85ea9aeaf42a 100644 --- a/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs +++ b/src/Common/src/Interop/Unix/libssl/SslConnectionInfo.cs @@ -8,7 +8,7 @@ namespace System.Net { internal class SslConnectionInfo { - public readonly SslProtocols Protocol; + public readonly int Protocol; public readonly int DataCipherAlg; public readonly int DataKeySize; public readonly int DataHashAlg; @@ -18,10 +18,10 @@ internal class SslConnectionInfo internal SslConnectionInfo(SafeSslHandle sslContext) { - string protocolVersion = Interop.Crypto.GetProtocolVersion(sslContext); - Protocol = MapProtocolVersion(protocolVersion); + string protocolVersion = Interop.Ssl.GetProtocolVersion(sslContext); + Protocol = (int)MapProtocolVersion(protocolVersion); - if (!Interop.Crypto.GetSslConnectionInfo( + if (!Interop.Ssl.GetSslConnectionInfo( sslContext, out DataCipherAlg, out KeyExchangeAlg, diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs deleted file mode 100644 index c657b6e9b1b5..000000000000 --- a/src/Common/src/Microsoft/Win32/SafeHandles/SafeSslHandle.Unix.cs +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.Win32.SafeHandles; - -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.Crypto.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.Crypto.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.Crypto.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) - { - } - } -} \ No newline at end of file diff --git a/src/Native/System.Security.Cryptography.Native/CMakeLists.txt b/src/Native/System.Security.Cryptography.Native/CMakeLists.txt index 06328a49f4e6..bbf028d69ebb 100644 --- a/src/Native/System.Security.Cryptography.Native/CMakeLists.txt +++ b/src/Native/System.Security.Cryptography.Native/CMakeLists.txt @@ -13,12 +13,6 @@ add_definitions(-DPIC=1) find_package(OpenSSL REQUIRED) -include(CheckStructHasMember) -check_struct_has_member ("SSL_CIPHER" algorithms openssl/ssl.h SSL_CIPHER_ALGORITHMS) -if (SSL_CIPHER_ALGORITHMS) - add_definitions(-DHAVE_SSL_CIPHER_ALGORITHMS=1) -endif() - set(NATIVECRYPTO_SOURCES openssl.c pal_asn1.cpp diff --git a/src/Native/System.Security.Cryptography.Native/configure.cmake b/src/Native/System.Security.Cryptography.Native/configure.cmake index 43d421870a74..c8576403e272 100644 --- a/src/Native/System.Security.Cryptography.Native/configure.cmake +++ b/src/Native/System.Security.Cryptography.Native/configure.cmake @@ -1,9 +1,12 @@ include(CheckLibraryExists) +include(CheckStructHasMember) # Check which versions of TLS the OpenSSL/ssl library supports check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_1_method" "" HAVE_TLS_V1_1) check_library_exists(${OPENSSL_SSL_LIBRARY} "TLSv1_2_method" "" HAVE_TLS_V1_2) +check_struct_has_member ("SSL_CIPHER" algorithm_enc openssl/ssl.h HAVE_SSL_CIPHER_SPLIT_ALGORITHMS) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/pal_crypto_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/pal_crypto_config.h) diff --git a/src/Native/System.Security.Cryptography.Native/pal_crypto_config.h.in b/src/Native/System.Security.Cryptography.Native/pal_crypto_config.h.in index c2fe3b61986f..cae9fde2c92a 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_crypto_config.h.in +++ b/src/Native/System.Security.Cryptography.Native/pal_crypto_config.h.in @@ -2,3 +2,5 @@ #cmakedefine01 HAVE_TLS_V1_1 #cmakedefine01 HAVE_TLS_V1_2 + +#cmakedefine01 HAVE_SSL_CIPHER_SPLIT_ALGORITHMS diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp index cc3968da4f0a..0335c18f2810 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.cpp @@ -75,20 +75,53 @@ extern "C" void SslCtxDestroy(SSL_CTX* ctx) } } -extern "C" const char* SSLGetVersion(SSL* ssl) +extern "C" const char* SslGetVersion(SSL* ssl) { return SSL_get_version(ssl); } +/* +The values used in OpenSSL for SSL_CIPHER algorithm_enc. +*/ +enum class SSL_CipherAlgorithm : int64_t +{ +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + SSL_DES = 1, + SSL_3DES = 2, + SSL_RC4 = 4, + SSL_RC2 = 8, + SSL_IDEA = 16, + SSL_eNULL = 32, + SSL_AES128 = 64, + SSL_AES256 = 128, + SSL_CAMELLIA128 = 256, + SSL_CAMELLIA256 = 512, + SSL_eGOST2814789CNT = 1024, + SSL_SEED = 2048, + SSL_AES128GCM = 4096, + SSL_AES256GCM = 8192 +#else + SSL_DES = 0x00008000L, + SSL_3DES = 0x00010000L, + SSL_RC4 = 0x00020000L, + SSL_RC2 = 0x00040000L, + SSL_IDEA = 0x00080000L, + //SSL_eFZA = 0x00100000L, this value is defined in ssl_locl.h, but has no match + SSL_eNULL = 0x00200000L, + SSL_AES = 0x04000000L, + SSL_CAMELLIA = 0x08000000L, + SSL_SEED = 0x10000000L, +#endif +}; + static CipherAlgorithmType MapCipherAlgorithmType(const SSL_CIPHER* cipher) { unsigned long enc; - -#ifdef HAVE_SSL_CIPHER_ALGORITHMS +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + enc = cipher->algorithm_enc; +#else const unsigned long SSL_ENC_MASK = 0x1C3F8000L; enc = cipher->algorithms & SSL_ENC_MASK; -#else - enc = cipher->algorithm_enc; #endif SSL_CipherAlgorithm sslEnc = static_cast(enc); @@ -115,24 +148,7 @@ static CipherAlgorithmType MapCipherAlgorithmType(const SSL_CIPHER* cipher) case SSL_CipherAlgorithm::SSL_SEED: return CipherAlgorithmType::SSL_SEED; -#ifdef HAVE_SSL_CIPHER_ALGORITHMS - case SSL_CipherAlgorithm::SSL_AES: - switch (cipher->alg_bits) - { - case 128: - return CipherAlgorithmType::Aes128; - case 256: - return CipherAlgorithmType::Aes256; - } - case SSL_CipherAlgorithm::SSL_CAMELLIA: - switch (cipher->alg_bits) - { - case 128: - return CipherAlgorithmType::SSL_CAMELLIA128; - case 256: - return CipherAlgorithmType::SSL_CAMELLIA256; - } -#else +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS case SSL_CipherAlgorithm::SSL_AES128: return CipherAlgorithmType::Aes128; @@ -153,20 +169,72 @@ static CipherAlgorithmType MapCipherAlgorithmType(const SSL_CIPHER* cipher) case SSL_CipherAlgorithm::SSL_AES256GCM: return CipherAlgorithmType::Aes256; +#else + case SSL_CipherAlgorithm::SSL_AES: + switch (cipher->alg_bits) + { + case 128: + return CipherAlgorithmType::Aes128; + case 256: + return CipherAlgorithmType::Aes256; + } + case SSL_CipherAlgorithm::SSL_CAMELLIA: + switch (cipher->alg_bits) + { + case 128: + return CipherAlgorithmType::SSL_CAMELLIA128; + case 256: + return CipherAlgorithmType::SSL_CAMELLIA256; + } #endif } return CipherAlgorithmType::None; } +/* +The values used in OpenSSL for SSL_CIPHER algorithm_mkey. +*/ +enum class SSL_KeyExchangeAlgorithm : int64_t +{ +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + SSL_kRSA = 1, + /* DH cert, RSA CA cert */ + SSL_kDHr = 2, + /* DH cert, DSA CA cert */ + SSL_kDHd = 4, + /* tmp DH key no DH cert */ + SSL_kEDH = 8, + /* Kerberos5 key exchange */ + SSL_kKRB5 = 16, + /* ECDH cert, RSA CA cert */ + SSL_kECDHr = 32, + /* ECDH cert, ECDSA CA cert */ + SSL_kECDHe = 64, + SSL_kEECDH = 128, + SSL_kPSK = 256, + SSL_kGOST = 512, + SSL_kSRP = 1024, +#else + SSL_kRSA = 0x00000001L, + SSL_kDHr = 0x00000002L, + SSL_kDHd = 0x00000004L, + //SSL_kFZA = 0x00000008L, this value is defined in ssl_locl.h, but has no match + SSL_kEDH = 0x00000010L, + SSL_kKRB5 = 0x00000020L, + SSL_kECDH = 0x00000040L, + SSL_kECDHE = 0x00000080L, +#endif +}; + static ExchangeAlgorithmType MapExchangeAlgorithmType(const SSL_CIPHER* cipher) { unsigned long mkey; -#ifdef HAVE_SSL_CIPHER_ALGORITHMS +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + mkey = cipher->algorithm_mkey; +#else const unsigned long SSL_MKEY_MASK = 0x000000FFL; mkey = cipher->algorithms & SSL_MKEY_MASK; -#else - mkey = cipher->algorithm_mkey; #endif SSL_KeyExchangeAlgorithm sslMkey = static_cast(mkey); @@ -187,13 +255,7 @@ static ExchangeAlgorithmType MapExchangeAlgorithmType(const SSL_CIPHER* cipher) case SSL_KeyExchangeAlgorithm::SSL_kKRB5: return ExchangeAlgorithmType::SSL_kKRB5; -#ifdef HAVE_SSL_CIPHER_ALGORITHMS - case SSL_KeyExchangeAlgorithm::SSL_kECDH: - return ExchangeAlgorithmType::SSL_ECDH; - - case SSL_KeyExchangeAlgorithm::SSL_kECDHE: - return ExchangeAlgorithmType::SSL_ECDSA; -#else +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS case SSL_KeyExchangeAlgorithm::SSL_kECDHr: return ExchangeAlgorithmType::SSL_ECDH; @@ -211,20 +273,45 @@ static ExchangeAlgorithmType MapExchangeAlgorithmType(const SSL_CIPHER* cipher) case SSL_KeyExchangeAlgorithm::SSL_kSRP: return ExchangeAlgorithmType::SSL_kSRP; +#else + case SSL_KeyExchangeAlgorithm::SSL_kECDH: + return ExchangeAlgorithmType::SSL_ECDH; + + case SSL_KeyExchangeAlgorithm::SSL_kECDHE: + return ExchangeAlgorithmType::SSL_ECDSA; #endif } return ExchangeAlgorithmType::None; } +/* +The values used in OpenSSL for SSL_CIPHER algorithm_mac. +*/ +enum class SSL_DataHashAlgorithm : int64_t +{ +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + SSL_MD5 = 1, + SSL_SHA1 = 2, + SSL_GOST94 = 4, + SSL_GOST89MAC = 8, + SSL_SHA256 = 16, + SSL_SHA384 = 32, + SSL_AEAD = 64 +#else + SSL_MD5 = 0x00400000L, + SSL_SHA1 = 0x00800000L, +#endif +}; + static HashAlgorithmType MapHashAlgorithmType(const SSL_CIPHER* cipher) { unsigned long mac; -#ifdef HAVE_SSL_CIPHER_ALGORITHMS +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS + mac = cipher->algorithm_mac; +#else const unsigned long SSL_MAC_MASK = 0x00c00000L; mac = cipher->algorithms & SSL_MAC_MASK; -#else - mac = cipher->algorithm_mac; #endif SSL_DataHashAlgorithm sslMac = static_cast(mac); @@ -236,7 +323,7 @@ static HashAlgorithmType MapHashAlgorithmType(const SSL_CIPHER* cipher) case SSL_DataHashAlgorithm::SSL_SHA1: return HashAlgorithmType::Sha1; -#ifndef HAVE_SSL_CIPHER_ALGORITHMS +#if HAVE_SSL_CIPHER_SPLIT_ALGORITHMS case SSL_DataHashAlgorithm::SSL_GOST94: return HashAlgorithmType::SSL_GOST94; diff --git a/src/Native/System.Security.Cryptography.Native/pal_ssl.h b/src/Native/System.Security.Cryptography.Native/pal_ssl.h index 4aa9e0395ab6..8bedccc9923b 100644 --- a/src/Native/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/Native/System.Security.Cryptography.Native/pal_ssl.h @@ -29,40 +29,6 @@ enum class CipherAlgorithmType : int32_t SSL_SEED = 229384, }; -/* -The values used in OpenSSL for SSL_CIPHER algorithm_enc. -*/ -enum class SSL_CipherAlgorithm : int64_t -{ -#ifdef HAVE_SSL_CIPHER_ALGORITHMS - SSL_DES = 0x00008000L, - SSL_3DES = 0x00010000L, - SSL_RC4 = 0x00020000L, - SSL_RC2 = 0x00040000L, - SSL_IDEA = 0x00080000L, - //SSL_eFZA = 0x00100000L, this value is defined in ssl_locl.h, but has no match - SSL_eNULL = 0x00200000L, - SSL_AES = 0x04000000L, - SSL_CAMELLIA = 0x08000000L, - SSL_SEED = 0x10000000L, -#else - SSL_DES = 1, - SSL_3DES = 2, - SSL_RC4 = 4, - SSL_RC2 = 8, - SSL_IDEA = 16, - SSL_eNULL = 32, - SSL_AES128 = 64, - SSL_AES256 = 128, - SSL_CAMELLIA128 = 256, - SSL_CAMELLIA256 = 512, - SSL_eGOST2814789CNT = 1024, - SSL_SEED = 2048, - SSL_AES128GCM = 4096, - SSL_AES256GCM = 8192 -#endif -}; - /* These values should be kept in sync with System.Security.Authentication.ExchangeAlgorithmType. */ @@ -82,41 +48,6 @@ enum class ExchangeAlgorithmType : int32_t SSL_kKRB5 = 229393, }; -/* -The values used in OpenSSL for SSL_CIPHER algorithm_mkey. -*/ -enum class SSL_KeyExchangeAlgorithm : int64_t -{ -#ifdef HAVE_SSL_CIPHER_ALGORITHMS - SSL_kRSA = 0x00000001L, - SSL_kDHr = 0x00000002L, - SSL_kDHd = 0x00000004L, - //SSL_kFZA = 0x00000008L, this value is defined in ssl_locl.h, but has no match - SSL_kEDH = 0x00000010L, - SSL_kKRB5 = 0x00000020L, - SSL_kECDH = 0x00000040L, - SSL_kECDHE = 0x00000080L, -#else - SSL_kRSA = 1, - /* DH cert, RSA CA cert */ - SSL_kDHr = 2, - /* DH cert, DSA CA cert */ - SSL_kDHd = 4, - /* tmp DH key no DH cert */ - SSL_kEDH = 8, - /* Kerberos5 key exchange */ - SSL_kKRB5 = 16, - /* ECDH cert, RSA CA cert */ - SSL_kECDHr = 32, - /* ECDH cert, ECDSA CA cert */ - SSL_kECDHe = 64, - SSL_kEECDH = 128, - SSL_kPSK = 256, - SSL_kGOST = 512, - SSL_kSRP = 1024, -#endif -}; - /* These values should be kept in sync with System.Security.Authentication.HashAlgorithmType. */ @@ -134,25 +65,6 @@ enum class HashAlgorithmType : int32_t SSL_AEAD = 229412, }; -/* -The values used in OpenSSL for SSL_CIPHER algorithm_mac. -*/ -enum class SSL_DataHashAlgorithm : int64_t -{ -#ifdef HAVE_SSL_CIPHER_ALGORITHMS - SSL_MD5 = 0x00400000L, - SSL_SHA1 = 0x00800000L, -#else - SSL_MD5 = 1, - SSL_SHA1 = 2, - SSL_GOST94 = 4, - SSL_GOST89MAC = 8, - SSL_SHA256 = 16, - SSL_SHA384 = 32, - SSL_AEAD = 64 -#endif -}; - /* Shims the SSLv23_method method. @@ -243,7 +155,7 @@ Shims the SSL_get_version method. Returns the protocol version string for the SSL instance. */ -extern "C" const char* SSLGetVersion(SSL* ssl); +extern "C" const char* SslGetVersion(SSL* ssl); /* Returns the connection information for the SSL instance. diff --git a/src/System.Net.Security/src/System.Net.Security.csproj b/src/System.Net.Security/src/System.Net.Security.csproj index b976c4341ef6..3bc59e681905 100644 --- a/src/System.Net.Security/src/System.Net.Security.csproj +++ b/src/System.Net.Security/src/System.Net.Security.csproj @@ -269,9 +269,6 @@ Common\Microsoft\Win32\SafeHandles\Asn1SafeHandles.Unix.cs - - Common\Microsoft\Win32\SafeHandles\SafeSslHandle.Unix.cs -