gdi32: Use get_object_type for GetObjectType implementation.
[wine.git] / dlls / secur32 / schannel_macosx.c
blobd7453a4481667f53475b5c9863fa1a263d580049
1 /*
2 * Mac OS X Secure Transport implementation of the schannel (SSL/TLS) provider.
4 * Copyright 2005 Juan Lang
5 * Copyright 2008 Henri Verbeet
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #if 0
23 #pragma makedep unix
24 #endif
26 #include "config.h"
27 #include "wine/port.h"
29 #include <stdarg.h>
30 #include <pthread.h>
31 #ifdef HAVE_SECURITY_SECURITY_H
32 #include <Security/Security.h>
33 #define GetCurrentThread GetCurrentThread_Mac
34 #define LoadResource LoadResource_Mac
35 #include <CoreServices/CoreServices.h>
36 #undef GetCurrentThread
37 #undef LoadResource
38 #endif
40 #include "ntstatus.h"
41 #define WIN32_NO_STATUS
42 #include "windef.h"
43 #include "winbase.h"
44 #include "sspi.h"
45 #include "schannel.h"
46 #include "winternl.h"
47 #include "secur32_priv.h"
48 #include "wine/debug.h"
50 #if defined(HAVE_SECURITY_SECURITY_H) && !defined(SONAME_LIBGNUTLS)
52 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
54 static const struct schan_callbacks *callbacks;
56 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
57 /* Defined in <Security/CipherSuite.h> in the 10.6 SDK or later. */
58 enum {
59 TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
60 TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
61 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
62 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
63 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
64 TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
65 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
66 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
67 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
68 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
69 TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
70 TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
71 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
72 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
73 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
74 TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
75 TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
76 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
77 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
78 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
79 TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
80 TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
81 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
82 TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
83 TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
85 #endif
87 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
88 /* Defined in <Security/CipherSuite.h> in the 10.8 SDK or later. */
89 enum {
90 TLS_NULL_WITH_NULL_NULL = 0x0000,
91 TLS_RSA_WITH_NULL_MD5 = 0x0001,
92 TLS_RSA_WITH_NULL_SHA = 0x0002,
93 TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
94 TLS_RSA_WITH_RC4_128_SHA = 0x0005,
95 TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
96 TLS_RSA_WITH_NULL_SHA256 = 0x003B,
97 TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
98 TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
99 TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
100 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
101 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
102 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
103 TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
104 TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
105 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
106 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
107 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
108 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
109 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
110 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
111 TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
112 TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
113 TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
114 TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
115 TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
116 TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
117 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
118 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
119 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
120 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
121 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
122 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
123 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
124 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
125 TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
126 TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
127 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
128 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
129 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
130 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
131 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
132 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
133 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
134 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
135 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
136 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
137 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
138 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
139 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
140 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
141 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
142 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
143 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
146 /* Defined in <Security/SecureTransport.h> in the 10.8 SDK or later. */
147 enum {
148 kTLSProtocol11 = 7, /* TLS 1.1 */
149 kTLSProtocol12 = 8, /* TLS 1.2 */
151 #endif
153 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
154 /* Defined in <Security/CipherSuite.h> in the 10.9 SDK or later. */
155 enum {
156 TLS_PSK_WITH_RC4_128_SHA = 0x008A,
157 TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
158 TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
159 TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
160 TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
161 TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
162 TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
163 TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
164 TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
165 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
166 TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
167 TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
168 TLS_PSK_WITH_NULL_SHA = 0x002C,
169 TLS_DHE_PSK_WITH_NULL_SHA = 0x002D,
170 TLS_RSA_PSK_WITH_NULL_SHA = 0x002E,
171 TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8,
172 TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9,
173 TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA,
174 TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB,
175 TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC,
176 TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD,
177 TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
178 TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF,
179 TLS_PSK_WITH_NULL_SHA256 = 0x00B0,
180 TLS_PSK_WITH_NULL_SHA384 = 0x00B1,
181 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2,
182 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3,
183 TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4,
184 TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5,
185 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6,
186 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7,
187 TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8,
188 TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9,
190 #endif
192 enum schan_mode {
193 schan_mode_NONE,
194 schan_mode_READ,
195 schan_mode_WRITE,
196 schan_mode_HANDSHAKE,
199 struct mac_session {
200 SSLContextRef context;
201 struct schan_transport *transport;
202 enum schan_mode mode;
203 pthread_mutex_t mutex;
206 enum {
207 schan_proto_SSL,
208 schan_proto_TLS,
211 enum {
212 schan_kx_DH_anon_EXPORT,
213 schan_kx_DH_anon,
214 schan_kx_DH_DSS_EXPORT,
215 schan_kx_DH_DSS,
216 schan_kx_DH_RSA_EXPORT,
217 schan_kx_DH_RSA,
218 schan_kx_DHE_DSS_EXPORT,
219 schan_kx_DHE_DSS,
220 schan_kx_DHE_PSK,
221 schan_kx_DHE_RSA_EXPORT,
222 schan_kx_DHE_RSA,
223 schan_kx_ECDH_anon,
224 schan_kx_ECDH_ECDSA,
225 schan_kx_ECDH_RSA,
226 schan_kx_ECDHE_ECDSA,
227 schan_kx_ECDHE_RSA,
228 schan_kx_FORTEZZA_DMS,
229 schan_kx_NULL,
230 schan_kx_PSK,
231 schan_kx_RSA_EXPORT,
232 schan_kx_RSA_PSK,
233 schan_kx_RSA,
236 enum {
237 schan_enc_3DES_EDE_CBC,
238 schan_enc_AES_128_CBC,
239 schan_enc_AES_128_GCM,
240 schan_enc_AES_256_CBC,
241 schan_enc_AES_256_GCM,
242 schan_enc_DES_CBC,
243 schan_enc_DES40_CBC,
244 schan_enc_FORTEZZA_CBC,
245 schan_enc_IDEA_CBC,
246 schan_enc_NULL,
247 schan_enc_RC2_CBC,
248 schan_enc_RC2_CBC_40,
249 schan_enc_RC4_128,
250 schan_enc_RC4_40,
253 enum {
254 schan_mac_MD5,
255 schan_mac_NULL,
256 schan_mac_SHA,
257 schan_mac_SHA256,
258 schan_mac_SHA384,
262 struct cipher_suite {
263 SSLCipherSuite suite;
264 int protocol;
265 int kx_alg;
266 int enc_alg;
267 int mac_alg;
270 /* This table corresponds to the enum in <Security/CipherSuite.h>. */
271 static const struct cipher_suite cipher_suites[] = {
272 #define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
273 schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
274 CIPHER_SUITE(SSL, RSA, NULL, MD5),
275 CIPHER_SUITE(SSL, RSA, NULL, MD5),
276 CIPHER_SUITE(SSL, RSA, NULL, SHA),
277 CIPHER_SUITE(SSL, RSA_EXPORT, RC4_40, MD5),
278 CIPHER_SUITE(SSL, RSA, RC4_128, MD5),
279 CIPHER_SUITE(SSL, RSA, RC4_128, SHA),
280 CIPHER_SUITE(SSL, RSA_EXPORT, RC2_CBC_40, MD5),
281 CIPHER_SUITE(SSL, RSA, IDEA_CBC, SHA),
282 CIPHER_SUITE(SSL, RSA_EXPORT, DES40_CBC, SHA),
283 CIPHER_SUITE(SSL, RSA, DES_CBC, SHA),
284 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, SHA),
285 CIPHER_SUITE(SSL, DH_DSS_EXPORT, DES40_CBC, SHA),
286 CIPHER_SUITE(SSL, DH_DSS, DES_CBC, SHA),
287 CIPHER_SUITE(SSL, DH_DSS, 3DES_EDE_CBC, SHA),
288 CIPHER_SUITE(SSL, DH_RSA_EXPORT, DES40_CBC, SHA),
289 CIPHER_SUITE(SSL, DH_RSA, DES_CBC, SHA),
290 CIPHER_SUITE(SSL, DH_RSA, 3DES_EDE_CBC, SHA),
291 CIPHER_SUITE(SSL, DHE_DSS_EXPORT, DES40_CBC, SHA),
292 CIPHER_SUITE(SSL, DHE_DSS, DES_CBC, SHA),
293 CIPHER_SUITE(SSL, DHE_DSS, 3DES_EDE_CBC, SHA),
294 CIPHER_SUITE(SSL, DHE_RSA_EXPORT, DES40_CBC, SHA),
295 CIPHER_SUITE(SSL, DHE_RSA, DES_CBC, SHA),
296 CIPHER_SUITE(SSL, DHE_RSA, 3DES_EDE_CBC, SHA),
297 CIPHER_SUITE(SSL, DH_anon_EXPORT, RC4_40, MD5),
298 CIPHER_SUITE(SSL, DH_anon, RC4_128, MD5),
299 CIPHER_SUITE(SSL, DH_anon_EXPORT, DES40_CBC, SHA),
300 CIPHER_SUITE(SSL, DH_anon, DES_CBC, SHA),
301 CIPHER_SUITE(SSL, DH_anon, 3DES_EDE_CBC, SHA),
302 CIPHER_SUITE(SSL, FORTEZZA_DMS, NULL, SHA),
303 CIPHER_SUITE(SSL, FORTEZZA_DMS, FORTEZZA_CBC, SHA),
305 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA),
306 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA),
307 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA),
308 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA),
309 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA),
310 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA),
311 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA),
312 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA),
313 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA),
314 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA),
315 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA),
316 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA),
318 CIPHER_SUITE(TLS, ECDH_ECDSA, NULL, SHA),
319 CIPHER_SUITE(TLS, ECDH_ECDSA, RC4_128, SHA),
320 CIPHER_SUITE(TLS, ECDH_ECDSA, 3DES_EDE_CBC, SHA),
321 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA),
322 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA),
323 CIPHER_SUITE(TLS, ECDHE_ECDSA, NULL, SHA),
324 CIPHER_SUITE(TLS, ECDHE_ECDSA, RC4_128, SHA),
325 CIPHER_SUITE(TLS, ECDHE_ECDSA, 3DES_EDE_CBC, SHA),
326 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA),
327 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA),
328 CIPHER_SUITE(TLS, ECDH_RSA, NULL, SHA),
329 CIPHER_SUITE(TLS, ECDH_RSA, RC4_128, SHA),
330 CIPHER_SUITE(TLS, ECDH_RSA, 3DES_EDE_CBC, SHA),
331 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA),
332 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA),
333 CIPHER_SUITE(TLS, ECDHE_RSA, NULL, SHA),
334 CIPHER_SUITE(TLS, ECDHE_RSA, RC4_128, SHA),
335 CIPHER_SUITE(TLS, ECDHE_RSA, 3DES_EDE_CBC, SHA),
336 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA),
337 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA),
338 CIPHER_SUITE(TLS, ECDH_anon, NULL, SHA),
339 CIPHER_SUITE(TLS, ECDH_anon, RC4_128, SHA),
340 CIPHER_SUITE(TLS, ECDH_anon, 3DES_EDE_CBC, SHA),
341 CIPHER_SUITE(TLS, ECDH_anon, AES_128_CBC, SHA),
342 CIPHER_SUITE(TLS, ECDH_anon, AES_256_CBC, SHA),
344 CIPHER_SUITE(TLS, NULL, NULL, NULL),
345 CIPHER_SUITE(TLS, RSA, NULL, MD5),
346 CIPHER_SUITE(TLS, RSA, NULL, SHA),
347 CIPHER_SUITE(TLS, RSA, RC4_128, MD5),
348 CIPHER_SUITE(TLS, RSA, RC4_128, SHA),
349 CIPHER_SUITE(TLS, RSA, 3DES_EDE_CBC, SHA),
350 CIPHER_SUITE(TLS, RSA, NULL, SHA256),
351 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA256),
352 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA256),
353 CIPHER_SUITE(TLS, DH_DSS, 3DES_EDE_CBC, SHA),
354 CIPHER_SUITE(TLS, DH_RSA, 3DES_EDE_CBC, SHA),
355 CIPHER_SUITE(TLS, DHE_DSS, 3DES_EDE_CBC, SHA),
356 CIPHER_SUITE(TLS, DHE_RSA, 3DES_EDE_CBC, SHA),
357 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA256),
358 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA256),
359 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA256),
360 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA256),
361 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA256),
362 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA256),
363 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA256),
364 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA256),
365 CIPHER_SUITE(TLS, DH_anon, RC4_128, MD5),
366 CIPHER_SUITE(TLS, DH_anon, 3DES_EDE_CBC, SHA),
367 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA256),
368 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA256),
370 CIPHER_SUITE(TLS, PSK, RC4_128, SHA),
371 CIPHER_SUITE(TLS, PSK, 3DES_EDE_CBC, SHA),
372 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA),
373 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA),
374 CIPHER_SUITE(TLS, DHE_PSK, RC4_128, SHA),
375 CIPHER_SUITE(TLS, DHE_PSK, 3DES_EDE_CBC, SHA),
376 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA),
377 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA),
378 CIPHER_SUITE(TLS, RSA_PSK, RC4_128, SHA),
379 CIPHER_SUITE(TLS, RSA_PSK, 3DES_EDE_CBC, SHA),
380 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA),
381 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA),
382 CIPHER_SUITE(TLS, PSK, NULL, SHA),
383 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA),
384 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA),
386 CIPHER_SUITE(TLS, RSA, AES_128_GCM, SHA256),
387 CIPHER_SUITE(TLS, RSA, AES_256_GCM, SHA384),
388 CIPHER_SUITE(TLS, DHE_RSA, AES_128_GCM, SHA256),
389 CIPHER_SUITE(TLS, DHE_RSA, AES_256_GCM, SHA384),
390 CIPHER_SUITE(TLS, DH_RSA, AES_128_GCM, SHA256),
391 CIPHER_SUITE(TLS, DH_RSA, AES_256_GCM, SHA384),
392 CIPHER_SUITE(TLS, DHE_DSS, AES_128_GCM, SHA256),
393 CIPHER_SUITE(TLS, DHE_DSS, AES_256_GCM, SHA384),
394 CIPHER_SUITE(TLS, DH_DSS, AES_128_GCM, SHA256),
395 CIPHER_SUITE(TLS, DH_DSS, AES_256_GCM, SHA384),
396 CIPHER_SUITE(TLS, DH_anon, AES_128_GCM, SHA256),
397 CIPHER_SUITE(TLS, DH_anon, AES_256_GCM, SHA384),
399 CIPHER_SUITE(TLS, PSK, AES_128_GCM, SHA256),
400 CIPHER_SUITE(TLS, PSK, AES_256_GCM, SHA384),
401 CIPHER_SUITE(TLS, DHE_PSK, AES_128_GCM, SHA256),
402 CIPHER_SUITE(TLS, DHE_PSK, AES_256_GCM, SHA384),
403 CIPHER_SUITE(TLS, RSA_PSK, AES_128_GCM, SHA256),
404 CIPHER_SUITE(TLS, RSA_PSK, AES_256_GCM, SHA384),
405 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA256),
406 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA384),
407 CIPHER_SUITE(TLS, PSK, NULL, SHA256),
408 CIPHER_SUITE(TLS, PSK, NULL, SHA384),
409 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA256),
410 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA384),
411 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA256),
412 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA384),
413 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA256),
414 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA384),
415 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA256),
416 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA384),
418 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA256),
419 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA384),
420 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA256),
421 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA384),
422 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA256),
423 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA384),
424 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA256),
425 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA384),
426 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_GCM, SHA256),
427 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_GCM, SHA384),
428 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_GCM, SHA256),
429 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_GCM, SHA384),
430 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_GCM, SHA256),
431 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_GCM, SHA384),
432 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_GCM, SHA256),
433 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_GCM, SHA384),
435 CIPHER_SUITE(SSL, RSA, RC2_CBC, MD5),
436 CIPHER_SUITE(SSL, RSA, IDEA_CBC, MD5),
437 CIPHER_SUITE(SSL, RSA, DES_CBC, MD5),
438 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, MD5),
439 #undef CIPHER_SUITE
443 static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
445 int i;
446 for (i = 0; i < ARRAY_SIZE(cipher_suites); i++)
448 if (cipher_suites[i].suite == cipher_suite)
449 return &cipher_suites[i];
452 return NULL;
456 static DWORD get_session_protocol(struct mac_session* s)
458 SSLProtocol protocol;
459 int status;
461 TRACE("(%p/%p)\n", s, s->context);
463 status = SSLGetNegotiatedProtocolVersion(s->context, &protocol);
464 if (status != noErr)
466 ERR("Failed to get session protocol: %d\n", status);
467 return 0;
470 TRACE("protocol %d\n", protocol);
472 switch (protocol)
474 case kSSLProtocol2: return SP_PROT_SSL2_CLIENT;
475 case kSSLProtocol3: return SP_PROT_SSL3_CLIENT;
476 case kTLSProtocol1: return SP_PROT_TLS1_CLIENT;
477 case kTLSProtocol11: return SP_PROT_TLS1_1_CLIENT;
478 case kTLSProtocol12: return SP_PROT_TLS1_2_CLIENT;
479 default:
480 FIXME("unknown protocol %d\n", protocol);
481 return 0;
485 static ALG_ID get_cipher_algid(const struct cipher_suite* c)
487 TRACE("(%#x)\n", (unsigned int)c->suite);
489 switch (c->enc_alg)
491 case schan_enc_3DES_EDE_CBC: return CALG_3DES;
492 case schan_enc_AES_128_CBC: return CALG_AES_128;
493 case schan_enc_AES_256_CBC: return CALG_AES_256;
494 case schan_enc_DES_CBC: return CALG_DES;
495 case schan_enc_DES40_CBC: return CALG_DES;
496 case schan_enc_NULL: return 0;
497 case schan_enc_RC2_CBC_40: return CALG_RC2;
498 case schan_enc_RC2_CBC: return CALG_RC2;
499 case schan_enc_RC4_128: return CALG_RC4;
500 case schan_enc_RC4_40: return CALG_RC4;
502 case schan_enc_AES_128_GCM:
503 case schan_enc_AES_256_GCM:
504 case schan_enc_FORTEZZA_CBC:
505 case schan_enc_IDEA_CBC:
506 FIXME("Don't know CALG for encryption algorithm %d, returning 0\n", c->enc_alg);
507 return 0;
509 default:
510 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
511 return 0;
515 static unsigned int get_cipher_key_size(const struct cipher_suite* c)
517 TRACE("(%#x)\n", (unsigned int)c->suite);
519 switch (c->enc_alg)
521 case schan_enc_3DES_EDE_CBC: return 168;
522 case schan_enc_AES_128_CBC: return 128;
523 case schan_enc_AES_128_GCM: return 128;
524 case schan_enc_AES_256_CBC: return 256;
525 case schan_enc_AES_256_GCM: return 256;
526 case schan_enc_DES_CBC: return 56;
527 case schan_enc_DES40_CBC: return 40;
528 case schan_enc_NULL: return 0;
529 case schan_enc_RC2_CBC_40: return 40;
530 case schan_enc_RC2_CBC: return 128;
531 case schan_enc_RC4_128: return 128;
532 case schan_enc_RC4_40: return 40;
534 case schan_enc_FORTEZZA_CBC:
535 case schan_enc_IDEA_CBC:
536 FIXME("Don't know key size for encryption algorithm %d, returning 0\n", c->enc_alg);
537 return 0;
539 default:
540 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
541 return 0;
545 static ALG_ID get_mac_algid(const struct cipher_suite* c)
547 TRACE("(%#x)\n", (unsigned int)c->suite);
549 switch (c->mac_alg)
551 case schan_mac_MD5: return CALG_MD5;
552 case schan_mac_NULL: return 0;
553 case schan_mac_SHA: return CALG_SHA;
554 case schan_mac_SHA256: return CALG_SHA_256;
555 case schan_mac_SHA384: return CALG_SHA_384;
557 default:
558 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
559 return 0;
563 static unsigned int get_mac_key_size(const struct cipher_suite* c)
565 TRACE("(%#x)\n", (unsigned int)c->suite);
567 switch (c->mac_alg)
569 case schan_mac_MD5: return 128;
570 case schan_mac_NULL: return 0;
571 case schan_mac_SHA: return 160;
572 case schan_mac_SHA256: return 256;
573 case schan_mac_SHA384: return 384;
575 default:
576 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
577 return 0;
581 static ALG_ID get_kx_algid(const struct cipher_suite* c)
583 TRACE("(%#x)\n", (unsigned int)c->suite);
585 switch (c->kx_alg)
587 case schan_kx_DHE_DSS_EXPORT:
588 case schan_kx_DHE_DSS:
589 case schan_kx_DHE_PSK:
590 case schan_kx_DHE_RSA_EXPORT:
591 case schan_kx_DHE_RSA: return CALG_DH_EPHEM;
592 case schan_kx_ECDH_anon:
593 case schan_kx_ECDH_ECDSA:
594 case schan_kx_ECDH_RSA: return CALG_ECDH;
595 case schan_kx_ECDHE_ECDSA:
596 case schan_kx_ECDHE_RSA: return CALG_ECDH_EPHEM;
597 case schan_kx_NULL: return 0;
598 case schan_kx_RSA:
599 case schan_kx_RSA_EXPORT:
600 case schan_kx_RSA_PSK: return CALG_RSA_KEYX;
602 case schan_kx_DH_anon_EXPORT:
603 case schan_kx_DH_anon:
604 case schan_kx_DH_DSS_EXPORT:
605 case schan_kx_DH_DSS:
606 case schan_kx_DH_RSA_EXPORT:
607 case schan_kx_DH_RSA:
608 case schan_kx_FORTEZZA_DMS:
609 case schan_kx_PSK:
610 FIXME("Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
611 return 0;
613 default:
614 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
615 return 0;
620 /* pull_adapter
621 * Callback registered with SSLSetIOFuncs as the read function for a
622 * session. Reads data from the session connection. Conforms to the
623 * SSLReadFunc type.
625 * transport - The session connection
626 * buff - The buffer into which to store the read data. Must be at least
627 * *buff_len bytes in length.
628 * *buff_len - On input, the desired length to read. On successful return,
629 * the number of bytes actually read.
631 * Returns:
632 * noErr on complete success meaning the requested length was successfully
633 * read.
634 * errSSLWouldBlock when the requested length could not be read without
635 * blocking. *buff_len indicates how much was actually read. The
636 * caller should try again if/when they want to read more.
637 * errSSLClosedGraceful when the connection has closed and there's no
638 * more data to be read.
639 * other error code for failure.
641 static OSStatus pull_adapter(SSLConnectionRef transport, void *buff, SIZE_T *buff_len)
643 struct mac_session *s = (struct mac_session*)transport;
644 size_t requested = *buff_len;
645 int status;
646 OSStatus ret;
648 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
650 if (s->mode != schan_mode_READ && s->mode != schan_mode_HANDSHAKE)
652 WARN("called in mode %u\n", s->mode);
653 return noErr;
656 status = callbacks->pull(s->transport, buff, buff_len);
657 if (status == 0)
659 if (*buff_len == 0)
661 TRACE("Connection closed\n");
662 ret = errSSLClosedGraceful;
664 else if (*buff_len < requested)
666 TRACE("Pulled %lu bytes before would block\n", *buff_len);
667 ret = errSSLWouldBlock;
669 else
671 TRACE("Pulled %lu bytes\n", *buff_len);
672 ret = noErr;
675 else if (status == -1)
677 TRACE("Would block before being able to pull anything\n");
678 ret = errSSLWouldBlock;
680 else
682 FIXME("Unknown status code from schan_pull: %d\n", status);
683 ret = ioErr;
686 return ret;
689 /* push_adapter
690 * Callback registered with SSLSetIOFuncs as the write function for a
691 * session. Writes data to the session connection. Conforms to the
692 * SSLWriteFunc type.
694 * transport - The session connection
695 * buff - The buffer of data to write. Must be at least *buff_len bytes in length.
696 * *buff_len - On input, the desired length to write. On successful return,
697 * the number of bytes actually written.
699 * Returns:
700 * noErr on complete or partial success; *buff_len indicates how much data
701 * was actually written, which may be less than requested.
702 * errSSLWouldBlock when no data could be written without blocking. The
703 * caller should try again.
704 * other error code for failure.
706 static OSStatus push_adapter(SSLConnectionRef transport, const void *buff, SIZE_T *buff_len)
708 struct mac_session *s = (struct mac_session*)transport;
709 int status;
710 OSStatus ret;
712 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
714 if (s->mode != schan_mode_WRITE && s->mode != schan_mode_HANDSHAKE)
716 WARN("called in mode %u\n", s->mode);
717 return noErr;
720 status = callbacks->push(s->transport, buff, buff_len);
721 if (status == 0)
723 TRACE("Pushed %lu bytes\n", *buff_len);
724 ret = noErr;
726 else if (status == -1)
728 TRACE("Would block before being able to push anything\n");
729 ret = errSSLWouldBlock;
731 else
733 FIXME("Unknown status code from schan_push: %d\n", status);
734 ret = ioErr;
737 return ret;
740 static const struct {
741 DWORD enable_flag;
742 SSLProtocol mac_version;
743 } protocol_priority_flags[] = {
744 {SP_PROT_TLS1_2_CLIENT, kTLSProtocol12},
745 {SP_PROT_TLS1_1_CLIENT, kTLSProtocol11},
746 {SP_PROT_TLS1_0_CLIENT, kTLSProtocol1},
747 {SP_PROT_SSL3_CLIENT, kSSLProtocol3},
748 {SP_PROT_SSL2_CLIENT, kSSLProtocol2}
751 static DWORD supported_protocols;
753 static DWORD CDECL schan_get_enabled_protocols(void)
755 return supported_protocols;
758 static BOOL CDECL schan_create_session(schan_session *session, schan_credentials *cred)
760 struct mac_session *s;
761 unsigned i;
762 int status;
764 TRACE("(%p)\n", session);
766 if (!(s = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*s)))) return FALSE;
768 pthread_mutex_init(&s->mutex, NULL);
770 status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
771 if (status != noErr)
773 ERR("Failed to create session context: %d\n", status);
774 goto fail;
777 status = SSLSetConnection(s->context, s);
778 if (status != noErr)
780 ERR("Failed to set session connection: %d\n", status);
781 goto fail;
784 status = SSLSetEnableCertVerify(s->context, FALSE);
785 if (status != noErr)
787 ERR("Failed to disable certificate verification: %d\n", status);
788 goto fail;
791 for(i = 0; i < ARRAY_SIZE(protocol_priority_flags); i++) {
792 if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
793 continue;
795 status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
796 (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
797 if (status != noErr)
799 ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status);
800 goto fail;
804 status = SSLSetIOFuncs(s->context, pull_adapter, push_adapter);
805 if (status != noErr)
807 ERR("Failed to set session I/O funcs: %d\n", status);
808 goto fail;
811 s->mode = schan_mode_NONE;
813 TRACE(" -> %p/%p\n", s, s->context);
815 *session = (schan_session)s;
816 return TRUE;
818 fail:
819 RtlFreeHeap(GetProcessHeap(), 0, s);
820 return FALSE;
823 static void CDECL schan_dispose_session(schan_session session)
825 struct mac_session *s = (struct mac_session*)session;
826 int status;
828 TRACE("(%p/%p)\n", s, s->context);
830 status = SSLDisposeContext(s->context);
831 if (status != noErr)
832 ERR("Failed to dispose of session context: %d\n", status);
833 pthread_mutex_destroy(&s->mutex);
834 RtlFreeHeap(GetProcessHeap(), 0, s);
837 static void CDECL schan_set_session_transport(schan_session session, struct schan_transport *t)
839 struct mac_session *s = (struct mac_session*)session;
841 TRACE("(%p/%p, %p)\n", s, s->context, t);
843 s->transport = t;
846 static void CDECL schan_set_session_target(schan_session session, const char *target)
848 struct mac_session *s = (struct mac_session*)session;
850 TRACE("(%p/%p, %s)\n", s, s->context, debugstr_a(target));
852 SSLSetPeerDomainName( s->context, target, strlen(target) );
855 static SECURITY_STATUS CDECL schan_handshake(schan_session session)
857 struct mac_session *s = (struct mac_session*)session;
858 int status;
860 TRACE("(%p/%p)\n", s, s->context);
862 s->mode = schan_mode_HANDSHAKE;
863 status = SSLHandshake(s->context);
864 s->mode = schan_mode_NONE;
866 if (status == noErr)
868 TRACE("Handshake completed\n");
869 return SEC_E_OK;
871 else if (status == errSSLWouldBlock)
873 TRACE("Continue...\n");
874 return SEC_I_CONTINUE_NEEDED;
876 else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
878 ERR("Handshake failed: %s\n", strerror(status));
879 return SEC_E_INTERNAL_ERROR;
881 else
883 ERR("Handshake failed: %d\n", status);
884 cssmPerror("SSLHandshake", status);
885 return SEC_E_INTERNAL_ERROR;
888 /* Never reached */
889 return SEC_E_OK;
892 static unsigned int CDECL schan_get_session_cipher_block_size(schan_session session)
894 struct mac_session* s = (struct mac_session*)session;
895 SSLCipherSuite cipherSuite;
896 const struct cipher_suite* c;
897 int status;
899 TRACE("(%p/%p)\n", s, s->context);
901 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
902 if (status != noErr)
904 ERR("Failed to get session cipher suite: %d\n", status);
905 return 0;
908 c = get_cipher_suite(cipherSuite);
909 if (!c)
911 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
912 return 0;
915 switch (c->enc_alg)
917 case schan_enc_3DES_EDE_CBC: return 64;
918 case schan_enc_AES_128_CBC: return 128;
919 case schan_enc_AES_128_GCM: return 128;
920 case schan_enc_AES_256_CBC: return 128;
921 case schan_enc_AES_256_GCM: return 128;
922 case schan_enc_DES_CBC: return 64;
923 case schan_enc_DES40_CBC: return 64;
924 case schan_enc_NULL: return 0;
925 case schan_enc_RC2_CBC_40: return 64;
926 case schan_enc_RC2_CBC: return 64;
927 case schan_enc_RC4_128: return 0;
928 case schan_enc_RC4_40: return 0;
930 case schan_enc_FORTEZZA_CBC:
931 case schan_enc_IDEA_CBC:
932 FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
933 return 0;
935 default:
936 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
937 return 0;
941 static unsigned int CDECL schan_get_max_message_size(schan_session session)
943 FIXME("Returning 1 << 14.\n");
944 return 1 << 14;
947 static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session)
949 struct mac_session* s = (struct mac_session*)session;
950 SSLCipherSuite cipherSuite;
951 const struct cipher_suite* c;
952 int status;
954 TRACE("(%p/%p)\n", s, s->context);
956 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
957 if (status != noErr)
959 ERR("Failed to get session cipher suite: %d\n", status);
960 return 0;
963 c = get_cipher_suite(cipherSuite);
964 if (!c)
966 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
967 return 0;
970 switch (c->kx_alg)
972 case schan_kx_DH_DSS_EXPORT:
973 case schan_kx_DH_DSS:
974 case schan_kx_DHE_DSS_EXPORT:
975 case schan_kx_DHE_DSS:
976 return CALG_DSS_SIGN;
978 case schan_kx_DH_RSA_EXPORT:
979 case schan_kx_DH_RSA:
980 case schan_kx_DHE_RSA_EXPORT:
981 case schan_kx_DHE_RSA:
982 case schan_kx_ECDH_RSA:
983 case schan_kx_ECDHE_RSA:
984 case schan_kx_RSA_EXPORT:
985 case schan_kx_RSA:
986 return CALG_RSA_SIGN;
988 case schan_kx_ECDH_ECDSA:
989 case schan_kx_ECDHE_ECDSA:
990 return CALG_ECDSA;
992 case schan_kx_DH_anon_EXPORT:
993 case schan_kx_DH_anon:
994 case schan_kx_DHE_PSK:
995 case schan_kx_ECDH_anon:
996 case schan_kx_FORTEZZA_DMS:
997 case schan_kx_NULL:
998 case schan_kx_PSK:
999 case schan_kx_RSA_PSK:
1000 FIXME("Don't know key signature algorithm for key exchange algorithm %d, returning 0\n", c->kx_alg);
1001 return 0;
1003 default:
1004 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned int)c->suite);
1005 return 0;
1009 static SECURITY_STATUS CDECL schan_get_connection_info(schan_session session, SecPkgContext_ConnectionInfo *info)
1011 struct mac_session* s = (struct mac_session*)session;
1012 SSLCipherSuite cipherSuite;
1013 const struct cipher_suite* c;
1014 int status;
1016 TRACE("(%p/%p, %p)\n", s, s->context, info);
1018 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
1019 if (status != noErr)
1021 ERR("Failed to get session cipher suite: %d\n", status);
1022 return SEC_E_INTERNAL_ERROR;
1025 c = get_cipher_suite(cipherSuite);
1026 if (!c)
1028 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
1029 return SEC_E_INTERNAL_ERROR;
1032 info->dwProtocol = get_session_protocol(s);
1033 info->aiCipher = get_cipher_algid(c);
1034 info->dwCipherStrength = get_cipher_key_size(c);
1035 info->aiHash = get_mac_algid(c);
1036 info->dwHashStrength = get_mac_key_size(c);
1037 info->aiExch = get_kx_algid(c);
1038 /* FIXME: info->dwExchStrength? */
1039 info->dwExchStrength = 0;
1041 return SEC_E_OK;
1044 static SECURITY_STATUS CDECL schan_get_unique_channel_binding(schan_session session, SecPkgContext_Bindings *bindings)
1046 FIXME("SECPKG_ATTR_UNIQUE_BINDINGS is unsupported on MacOS\n");
1047 return SEC_E_UNSUPPORTED_FUNCTION;
1050 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1051 static void cf_release(const void *arg, void *ctx)
1053 CFRelease(arg);
1055 #endif
1057 static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, struct schan_cert_list *list)
1059 struct mac_session *s = (struct mac_session *)session;
1060 SECURITY_STATUS ret = SEC_E_OK;
1061 SecCertificateRef cert;
1062 CFArrayRef cert_array;
1063 int status;
1064 unsigned int size;
1065 CFIndex i;
1066 CFDataRef data;
1067 BYTE *ptr;
1069 TRACE("(%p/%p, %p)\n", s, s->context, list);
1071 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
1072 status = SSLCopyPeerCertificates(s->context, &cert_array);
1073 #else
1074 status = SSLGetPeerCertificates(s->context, &cert_array);
1075 #endif
1076 if (status != noErr || !cert_array)
1078 WARN("SSLCopyPeerCertificates failed: %d\n", status);
1079 return SEC_E_INTERNAL_ERROR;
1082 list->count = CFArrayGetCount(cert_array);
1083 size = list->count * sizeof(list->certs[0]);
1085 for (i = 0; i < list->count; i++)
1087 if (!(cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
1088 (SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
1090 WARN("Couldn't extract certificate data\n");
1091 ret = SEC_E_INTERNAL_ERROR;
1092 goto done;
1094 size += CFDataGetLength(data);
1095 CFRelease(data);
1098 if (!(list->certs = RtlAllocateHeap(GetProcessHeap(), 0, size)))
1100 ret = SEC_E_INSUFFICIENT_MEMORY;
1101 goto done;
1104 ptr = (BYTE *)&list->certs[list->count];
1105 for (i = 0; i < list->count; i++)
1107 if (!(cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
1108 (SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
1110 WARN("Couldn't extract certificate data\n");
1111 ret = SEC_E_INTERNAL_ERROR;
1112 goto done;
1114 list->certs[i].cbData = CFDataGetLength(data);
1115 list->certs[i].pbData = ptr;
1116 memcpy(list->certs[i].pbData, CFDataGetBytePtr(data), CFDataGetLength(data));
1117 ptr += CFDataGetLength(data);
1118 CFRelease(data);
1121 done:
1122 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1123 /* This is why SSLGetPeerCertificates was deprecated */
1124 CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)), cf_release, NULL);
1125 #endif
1126 CFRelease(cert_array);
1127 return ret;
1130 static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffer, SIZE_T *length)
1132 struct mac_session* s = (struct mac_session*)session;
1133 int status;
1135 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1137 pthread_mutex_lock(&s->mutex);
1138 s->mode = schan_mode_WRITE;
1140 status = SSLWrite(s->context, buffer, *length, length);
1142 s->mode = schan_mode_NONE;
1143 pthread_mutex_unlock(&s->mutex);
1145 if (status == noErr)
1146 TRACE("Wrote %lu bytes\n", *length);
1147 else if (status == errSSLWouldBlock)
1149 if (!*length)
1151 TRACE("Would block before being able to write anything\n");
1152 return SEC_I_CONTINUE_NEEDED;
1154 else
1155 TRACE("Wrote %lu bytes before would block\n", *length);
1157 else
1159 WARN("SSLWrite failed: %d\n", status);
1160 return SEC_E_INTERNAL_ERROR;
1163 return SEC_E_OK;
1166 static SECURITY_STATUS CDECL schan_recv(schan_session session, void *buffer, SIZE_T *length)
1168 struct mac_session* s = (struct mac_session*)session;
1169 int status;
1171 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1173 pthread_mutex_lock(&s->mutex);
1174 s->mode = schan_mode_READ;
1176 status = SSLRead(s->context, buffer, *length, length);
1178 s->mode = schan_mode_NONE;
1179 pthread_mutex_unlock(&s->mutex);
1181 if (status == noErr || status == errSSLClosedGraceful)
1182 TRACE("Read %lu bytes\n", *length);
1183 else if (status == errSSLWouldBlock)
1185 if (!*length)
1187 TRACE("Would block before being able to read anything\n");
1188 return SEC_I_CONTINUE_NEEDED;
1190 else
1191 TRACE("Read %lu bytes before would block\n", *length);
1193 else
1195 WARN("SSLRead failed: %d\n", status);
1196 return SEC_E_INTERNAL_ERROR;
1199 return SEC_E_OK;
1202 static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *cert,
1203 const DATA_BLOB *key_blob)
1205 if (cert) FIXME("no support for certificate credentials on this platform\n");
1206 c->credentials = NULL;
1207 return TRUE;
1210 static void CDECL schan_free_certificate_credentials(schan_credentials *c)
1214 static void CDECL schan_set_application_protocols(schan_session session, unsigned char *buffer, unsigned int buflen)
1216 FIXME("no support for application protocols on this platform\n");
1219 static SECURITY_STATUS CDECL schan_get_application_protocol(schan_session session,
1220 SecPkgContext_ApplicationProtocol *protocol)
1222 FIXME("no support for application protocols on this platform\n");
1223 return SEC_E_UNSUPPORTED_FUNCTION;
1226 static SECURITY_STATUS CDECL schan_set_dtls_mtu(schan_session session, unsigned int mtu)
1228 FIXME("no support for setting dtls mtu on this platform\n");
1229 return SEC_E_UNSUPPORTED_FUNCTION;
1232 static void ssl_init(void)
1234 TRACE("()\n");
1236 supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
1238 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1239 if(&SSLGetProtocolVersionMax != NULL) {
1240 SSLProtocol max_protocol;
1241 SSLContextRef ctx;
1242 OSStatus status;
1244 status = SSLNewContext(FALSE, &ctx);
1245 if(status == noErr) {
1246 status = SSLGetProtocolVersionMax(ctx, &max_protocol);
1247 if(status == noErr) {
1248 if(max_protocol >= kTLSProtocol11)
1249 supported_protocols |= SP_PROT_TLS1_1_CLIENT;
1250 if(max_protocol >= kTLSProtocol12)
1251 supported_protocols |= SP_PROT_TLS1_2_CLIENT;
1253 SSLDisposeContext(ctx);
1254 }else {
1255 WARN("SSLNewContext failed\n");
1258 #endif
1261 static const struct schan_funcs funcs =
1263 schan_allocate_certificate_credentials,
1264 schan_create_session,
1265 schan_dispose_session,
1266 schan_free_certificate_credentials,
1267 schan_get_application_protocol,
1268 schan_get_connection_info,
1269 schan_get_enabled_protocols,
1270 schan_get_key_signature_algorithm,
1271 schan_get_max_message_size,
1272 schan_get_session_cipher_block_size,
1273 schan_get_session_peer_certificate,
1274 schan_get_unique_channel_binding,
1275 schan_handshake,
1276 schan_recv,
1277 schan_send,
1278 schan_set_application_protocols,
1279 schan_set_dtls_mtu,
1280 schan_set_session_target,
1281 schan_set_session_transport,
1284 NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
1286 if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
1287 ssl_init();
1288 callbacks = ptr_in;
1289 *(const struct schan_funcs **)ptr_out = &funcs;
1290 return STATUS_SUCCESS;
1293 #endif /* HAVE_SECURITY_SECURITY_H && !SONAME_LIBGNUTLS */