Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 00f9ebc

Browse files
committed
Merge pull request #4026 from eerhardt/MoreLibSsl
Round #2 of LibSsl shim work
2 parents 7b43a8d + dc637b7 commit 00f9ebc

File tree

17 files changed

+707
-440
lines changed

17 files changed

+707
-440
lines changed

src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,13 @@ internal static partial class Interop
1212
internal static partial class Crypto
1313
{
1414
[DllImport(Libraries.CryptoNative)]
15-
private static extern ulong ErrGetError([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);
15+
internal static extern ulong ErrGetError();
16+
17+
[DllImport(Libraries.CryptoNative)]
18+
private static extern ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure);
19+
20+
[DllImport(Libraries.CryptoNative)]
21+
internal static extern IntPtr ErrReasonErrorString(ulong error);
1622

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

@@ -52,7 +58,7 @@ internal static Exception CreateOpenSslCryptographicException()
5258
error = lastRead;
5359
isAllocFailure = lastIsAllocFailure;
5460

55-
lastRead = ErrGetError(out lastIsAllocFailure);
61+
lastRead = ErrGetErrorAlloc(out lastIsAllocFailure);
5662
}
5763

5864
// If we're in an error flow which results in an Exception, but

src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs

Lines changed: 174 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,195 @@ internal static partial class Interop
99
{
1010
internal static partial class Ssl
1111
{
12-
[DllImport(Interop.Libraries.CryptoNative)]
12+
[DllImport(Libraries.CryptoNative)]
1313
internal static extern IntPtr SslV2_3Method();
1414

15-
[DllImport(Interop.Libraries.CryptoNative)]
15+
[DllImport(Libraries.CryptoNative)]
1616
internal static extern IntPtr SslV3Method();
1717

18-
[DllImport(Interop.Libraries.CryptoNative)]
18+
[DllImport(Libraries.CryptoNative)]
1919
internal static extern IntPtr TlsV1Method();
2020

21-
[DllImport(Interop.Libraries.CryptoNative)]
21+
[DllImport(Libraries.CryptoNative)]
2222
internal static extern IntPtr TlsV1_1Method();
2323

24-
[DllImport(Interop.Libraries.CryptoNative)]
24+
[DllImport(Libraries.CryptoNative)]
2525
internal static extern IntPtr TlsV1_2Method();
2626

27-
[DllImport(Interop.Libraries.CryptoNative)]
28-
internal static extern libssl.SafeSslContextHandle SslCtxCreate(IntPtr method);
27+
[DllImport(Libraries.CryptoNative)]
28+
internal static extern SafeSslContextHandle SslCtxCreate(IntPtr method);
29+
30+
[DllImport(Libraries.CryptoNative)]
31+
internal static extern long SslCtxCtrl(SafeSslContextHandle ctx, int cmd, long larg, IntPtr parg);
32+
33+
[DllImport(Libraries.CryptoNative)]
34+
internal static extern SafeSslHandle SslCreate(SafeSslContextHandle ctx);
2935

30-
[DllImport(Interop.Libraries.CryptoNative)]
31-
internal static unsafe extern int SslWrite(libssl.SafeSslHandle ssl, byte* buf, int num);
36+
[DllImport(Libraries.CryptoNative)]
37+
internal static extern libssl.SslErrorCode SslGetError(SafeSslHandle ssl, int ret);
3238

33-
[DllImport(Interop.Libraries.CryptoNative)]
34-
internal static extern int SslRead(libssl.SafeSslHandle ssl, byte[] buf, int num);
39+
[DllImport(Libraries.CryptoNative)]
40+
internal static extern void SslDestroy(IntPtr ssl);
41+
42+
[DllImport(Libraries.CryptoNative)]
43+
internal static extern void SslCtxDestroy(IntPtr ctx);
44+
45+
[DllImport(Libraries.CryptoNative)]
46+
private static extern IntPtr SslGetVersion(SafeSslHandle ssl);
47+
48+
internal static string GetProtocolVersion(SafeSslHandle ssl)
49+
{
50+
return Marshal.PtrToStringAnsi(SslGetVersion(ssl));
51+
}
52+
53+
[DllImport(Libraries.CryptoNative)]
54+
internal static extern bool GetSslConnectionInfo(
55+
SafeSslHandle ssl,
56+
out int dataCipherAlg,
57+
out int keyExchangeAlg,
58+
out int dataHashAlg,
59+
out int dataKeySize);
60+
61+
[DllImport(Libraries.CryptoNative)]
62+
internal static unsafe extern int SslWrite(SafeSslHandle ssl, byte* buf, int num);
63+
64+
[DllImport(Libraries.CryptoNative)]
65+
internal static extern int SslRead(SafeSslHandle ssl, byte[] buf, int num);
3566

3667
// NOTE: this is just an (unsafe) overload to the BioWrite method from Interop.Bio.cs.
3768
[DllImport(Libraries.CryptoNative)]
3869
internal static unsafe extern int BioWrite(SafeBioHandle b, byte* data, int len);
3970
}
4071
}
72+
73+
namespace Microsoft.Win32.SafeHandles
74+
{
75+
internal sealed class SafeSslContextHandle : SafeHandle
76+
{
77+
private SafeSslContextHandle()
78+
: base(IntPtr.Zero, true)
79+
{
80+
}
81+
82+
public override bool IsInvalid
83+
{
84+
get { return handle == IntPtr.Zero; }
85+
}
86+
87+
protected override bool ReleaseHandle()
88+
{
89+
Interop.Ssl.SslCtxDestroy(handle);
90+
SetHandle(IntPtr.Zero);
91+
return true;
92+
}
93+
}
94+
95+
internal sealed class SafeSslHandle : SafeHandle
96+
{
97+
private SafeBioHandle _readBio;
98+
private SafeBioHandle _writeBio;
99+
private bool _isServer;
100+
101+
public bool IsServer
102+
{
103+
get { return _isServer; }
104+
}
105+
106+
public SafeBioHandle InputBio
107+
{
108+
get
109+
{
110+
return _readBio;
111+
}
112+
}
113+
114+
public SafeBioHandle OutputBio
115+
{
116+
get
117+
{
118+
return _writeBio;
119+
}
120+
}
121+
122+
public static SafeSslHandle Create(SafeSslContextHandle context, bool isServer)
123+
{
124+
SafeBioHandle readBio = Interop.Crypto.CreateMemoryBio();
125+
if (readBio.IsInvalid)
126+
{
127+
return new SafeSslHandle();
128+
}
129+
130+
SafeBioHandle writeBio = Interop.Crypto.CreateMemoryBio();
131+
if (writeBio.IsInvalid)
132+
{
133+
readBio.Dispose();
134+
return new SafeSslHandle();
135+
}
136+
137+
SafeSslHandle handle = Interop.Ssl.SslCreate(context);
138+
if (handle.IsInvalid)
139+
{
140+
readBio.Dispose();
141+
writeBio.Dispose();
142+
return handle;
143+
}
144+
handle._isServer = isServer;
145+
146+
// After SSL_set_bio, the BIO handles are owned by SSL pointer
147+
// and are automatically freed by SSL_free. To prevent a double
148+
// free, we need to keep the ref counts bumped up till SSL_free
149+
bool gotRef = false;
150+
readBio.DangerousAddRef(ref gotRef);
151+
try
152+
{
153+
bool ignore = false;
154+
writeBio.DangerousAddRef(ref ignore);
155+
}
156+
catch
157+
{
158+
if (gotRef)
159+
{
160+
readBio.DangerousRelease();
161+
}
162+
throw;
163+
}
164+
165+
Interop.libssl.SSL_set_bio(handle, readBio, writeBio);
166+
handle._readBio = readBio;
167+
handle._writeBio = writeBio;
168+
169+
if (isServer)
170+
{
171+
Interop.libssl.SSL_set_accept_state(handle);
172+
}
173+
else
174+
{
175+
Interop.libssl.SSL_set_connect_state(handle);
176+
}
177+
return handle;
178+
}
179+
180+
public override bool IsInvalid
181+
{
182+
get { return handle == IntPtr.Zero; }
183+
}
184+
185+
protected override bool ReleaseHandle()
186+
{
187+
Interop.Ssl.SslDestroy(handle);
188+
if (_readBio != null)
189+
{
190+
_readBio.SetHandleAsInvalid(); // BIO got freed in SslDestroy
191+
}
192+
if (_writeBio != null)
193+
{
194+
_writeBio.SetHandleAsInvalid(); // BIO got freed in SslDestroy
195+
}
196+
return true;
197+
}
198+
199+
private SafeSslHandle() : base(IntPtr.Zero, true)
200+
{
201+
}
202+
}
203+
}

src/Common/src/Interop/Unix/libssl/Interop.OpenSsl.cs

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
using System.Security.Cryptography.X509Certificates;
1010
using Microsoft.Win32.SafeHandles;
1111

12-
using SafeSslHandle = Interop.libssl.SafeSslHandle;
13-
1412
internal static partial class Interop
1513
{
1614
internal static class OpenSsl
@@ -25,14 +23,14 @@ internal static SafeSslHandle AllocateSslContext(long options, SafeX509Handle ce
2523

2624
IntPtr method = GetSslMethod(isServer, options);
2725

28-
using (libssl.SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method))
26+
using (SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method))
2927
{
3028
if (innerContext.IsInvalid)
3129
{
3230
throw CreateSslException(SR.net_allocate_ssl_context_failed);
3331
}
3432

35-
libssl.SSL_CTX_ctrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero);
33+
Ssl.SslCtxCtrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero);
3634

3735
libssl.SSL_CTX_set_quiet_shutdown(innerContext, 1);
3836

@@ -212,20 +210,6 @@ internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle
212210
return libssl.SSL_get_peer_cert_chain(context);
213211
}
214212

215-
internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle sslHandle, out string protocolVersion)
216-
{
217-
IntPtr cipherPtr = libssl.SSL_get_current_cipher(sslHandle);
218-
var cipher = new libssl.SSL_CIPHER();
219-
if (IntPtr.Zero != cipherPtr)
220-
{
221-
cipher = Marshal.PtrToStructure<libssl.SSL_CIPHER>(cipherPtr);
222-
}
223-
224-
IntPtr versionPtr = libssl.SSL_get_version(sslHandle);
225-
protocolVersion = Marshal.PtrToStringAnsi(versionPtr);
226-
return cipher;
227-
}
228-
229213
internal static void FreeSslContext(SafeSslHandle context)
230214
{
231215
Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext");
@@ -317,7 +301,7 @@ private static int VerifyClientCertificate(int preverify_ok, IntPtr x509_ctx_ptr
317301
}
318302
}
319303

320-
private static void UpdateCAListFromRootStore(libssl.SafeSslContextHandle context)
304+
private static void UpdateCAListFromRootStore(SafeSslContextHandle context)
321305
{
322306
using (SafeX509NameStackHandle nameStack = Crypto.NewX509NameStack())
323307
{
@@ -375,8 +359,8 @@ private static void Disconnect(SafeSslHandle context)
375359
int retVal = libssl.SSL_shutdown(context);
376360
if (retVal < 0)
377361
{
378-
//TODO (Issue #3362) check this error
379-
libssl.SSL_get_error(context, retVal);
362+
//TODO (Issue #4031) check this error
363+
Ssl.SslGetError(context, retVal);
380364
}
381365
}
382366

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

422406
private static libssl.SslErrorCode GetSslError(SafeSslHandle context, int result)
423407
{
424-
libssl.SslErrorCode retVal = libssl.SSL_get_error(context, result);
408+
libssl.SslErrorCode retVal = Ssl.SslGetError(context, result);
425409
if (retVal == libssl.SslErrorCode.SSL_ERROR_SYSCALL)
426410
{
427-
retVal = (libssl.SslErrorCode)libssl.ERR_get_error();
411+
retVal = (libssl.SslErrorCode)Crypto.ErrGetError();
428412
}
429413
return retVal;
430414
}
431415

432-
private static void SetSslCertificate(libssl.SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr)
416+
private static void SetSslCertificate(SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr)
433417
{
434418
Debug.Assert(certPtr != null && !certPtr.IsInvalid, "certPtr != null && !certPtr.IsInvalid");
435419
Debug.Assert(keyPtr != null && !keyPtr.IsInvalid, "keyPtr != null && !keyPtr.IsInvalid");
@@ -457,10 +441,10 @@ private static void SetSslCertificate(libssl.SafeSslContextHandle contextPtr, Sa
457441
}
458442
}
459443

460-
private static SslException CreateSslException(string message)
444+
internal static SslException CreateSslException(string message)
461445
{
462-
ulong errorVal = libssl.ERR_get_error();
463-
string msg = SR.Format(message, Marshal.PtrToStringAnsi(libssl.ERR_reason_error_string(errorVal)));
446+
ulong errorVal = Crypto.ErrGetError();
447+
string msg = SR.Format(message, Marshal.PtrToStringAnsi(Crypto.ErrReasonErrorString(errorVal)));
464448
return new SslException(msg, (int)errorVal);
465449
}
466450

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

484468
private static SslException CreateSslException(SafeSslHandle context, string message, int error)
485469
{
486-
return CreateSslException(message, libssl.SSL_get_error(context, error));
470+
return CreateSslException(message, Ssl.SslGetError(context, error));
487471
}
488472

489473
#endregion

0 commit comments

Comments
 (0)