@@ -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+ }
0 commit comments