quartz: Return increasing monitor GUID on VMR7 monitor enumeration.
[wine/multimedia.git] / dlls / secur32 / schannel_macosx.c
blob5d8822305e47dfd0188f3ee04da1a7a009980561
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 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #ifdef HAVE_SECURITY_SECURITY_H
27 #include <Security/Security.h>
28 #define GetCurrentThread GetCurrentThread_Mac
29 #define LoadResource LoadResource_Mac
30 #include <CoreServices/CoreServices.h>
31 #undef GetCurrentThread
32 #undef LoadResource
33 #undef DPRINTF
34 #endif
36 #include "windef.h"
37 #include "winbase.h"
38 #include "sspi.h"
39 #include "schannel.h"
40 #include "secur32_priv.h"
41 #include "wine/debug.h"
42 #include "wine/library.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
46 #ifdef HAVE_SECURITY_SECURITY_H
48 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
49 /* Defined in <Security/CipherSuite.h> in the 10.6 SDK or later. */
50 enum {
51 TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
52 TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
53 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
54 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
55 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
56 TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
57 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
58 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
59 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
60 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
61 TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
62 TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
63 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
64 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
65 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
66 TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
67 TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
68 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
69 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
70 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
71 TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
72 TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
73 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
74 TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
75 TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
77 #endif
79 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
80 /* Defined in <Security/CipherSuite.h> in the 10.8 SDK or later. */
81 enum {
82 TLS_NULL_WITH_NULL_NULL = 0x0000,
83 TLS_RSA_WITH_NULL_MD5 = 0x0001,
84 TLS_RSA_WITH_NULL_SHA = 0x0002,
85 TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
86 TLS_RSA_WITH_RC4_128_SHA = 0x0005,
87 TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
88 TLS_RSA_WITH_NULL_SHA256 = 0x003B,
89 TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
90 TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
91 TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
92 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
93 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
94 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
95 TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
96 TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
97 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
98 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
99 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
100 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
101 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
102 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
103 TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
104 TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
105 TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
106 TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
107 TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
108 TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
109 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
110 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
111 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
112 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
113 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
114 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
115 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
116 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
117 TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
118 TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
119 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
120 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
121 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
122 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
123 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
124 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
125 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
126 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
127 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
128 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
129 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
130 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
131 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
132 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
133 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
134 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
135 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
138 /* Defined in <Security/SecureTransport.h> in the 10.8 SDK or later. */
139 enum {
140 kTLSProtocol11 = 7, /* TLS 1.1 */
141 kTLSProtocol12 = 8, /* TLS 1.2 */
143 #endif
146 struct mac_session {
147 SSLContextRef context;
148 struct schan_transport *transport;
152 enum {
153 schan_proto_SSL,
154 schan_proto_TLS,
157 enum {
158 schan_kx_DH_anon_EXPORT,
159 schan_kx_DH_anon,
160 schan_kx_DH_DSS_EXPORT,
161 schan_kx_DH_DSS,
162 schan_kx_DH_RSA_EXPORT,
163 schan_kx_DH_RSA,
164 schan_kx_DHE_DSS_EXPORT,
165 schan_kx_DHE_DSS,
166 schan_kx_DHE_RSA_EXPORT,
167 schan_kx_DHE_RSA,
168 schan_kx_ECDH_anon,
169 schan_kx_ECDH_ECDSA,
170 schan_kx_ECDH_RSA,
171 schan_kx_ECDHE_ECDSA,
172 schan_kx_ECDHE_RSA,
173 schan_kx_FORTEZZA_DMS,
174 schan_kx_NULL,
175 schan_kx_RSA_EXPORT,
176 schan_kx_RSA,
179 enum {
180 schan_enc_3DES_EDE_CBC,
181 schan_enc_AES_128_CBC,
182 schan_enc_AES_128_GCM,
183 schan_enc_AES_256_CBC,
184 schan_enc_AES_256_GCM,
185 schan_enc_DES_CBC,
186 schan_enc_DES40_CBC,
187 schan_enc_FORTEZZA_CBC,
188 schan_enc_IDEA_CBC,
189 schan_enc_NULL,
190 schan_enc_RC2_CBC,
191 schan_enc_RC2_CBC_40,
192 schan_enc_RC4_128,
193 schan_enc_RC4_40,
196 enum {
197 schan_mac_MD5,
198 schan_mac_NULL,
199 schan_mac_SHA,
200 schan_mac_SHA256,
201 schan_mac_SHA384,
205 struct cipher_suite {
206 SSLCipherSuite suite;
207 int protocol;
208 int kx_alg;
209 int enc_alg;
210 int mac_alg;
213 /* This table corresponds to the enum in <Security/CipherSuite.h>. */
214 static const struct cipher_suite cipher_suites[] = {
215 #define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
216 schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
217 CIPHER_SUITE(SSL, RSA, NULL, MD5),
218 CIPHER_SUITE(SSL, RSA, NULL, MD5),
219 CIPHER_SUITE(SSL, RSA, NULL, SHA),
220 CIPHER_SUITE(SSL, RSA_EXPORT, RC4_40, MD5),
221 CIPHER_SUITE(SSL, RSA, RC4_128, MD5),
222 CIPHER_SUITE(SSL, RSA, RC4_128, SHA),
223 CIPHER_SUITE(SSL, RSA_EXPORT, RC2_CBC_40, MD5),
224 CIPHER_SUITE(SSL, RSA, IDEA_CBC, SHA),
225 CIPHER_SUITE(SSL, RSA_EXPORT, DES40_CBC, SHA),
226 CIPHER_SUITE(SSL, RSA, DES_CBC, SHA),
227 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, SHA),
228 CIPHER_SUITE(SSL, DH_DSS_EXPORT, DES40_CBC, SHA),
229 CIPHER_SUITE(SSL, DH_DSS, DES_CBC, SHA),
230 CIPHER_SUITE(SSL, DH_DSS, 3DES_EDE_CBC, SHA),
231 CIPHER_SUITE(SSL, DH_RSA_EXPORT, DES40_CBC, SHA),
232 CIPHER_SUITE(SSL, DH_RSA, DES_CBC, SHA),
233 CIPHER_SUITE(SSL, DH_RSA, 3DES_EDE_CBC, SHA),
234 CIPHER_SUITE(SSL, DHE_DSS_EXPORT, DES40_CBC, SHA),
235 CIPHER_SUITE(SSL, DHE_DSS, DES_CBC, SHA),
236 CIPHER_SUITE(SSL, DHE_DSS, 3DES_EDE_CBC, SHA),
237 CIPHER_SUITE(SSL, DHE_RSA_EXPORT, DES40_CBC, SHA),
238 CIPHER_SUITE(SSL, DHE_RSA, DES_CBC, SHA),
239 CIPHER_SUITE(SSL, DHE_RSA, 3DES_EDE_CBC, SHA),
240 CIPHER_SUITE(SSL, DH_anon_EXPORT, RC4_40, MD5),
241 CIPHER_SUITE(SSL, DH_anon, RC4_128, MD5),
242 CIPHER_SUITE(SSL, DH_anon_EXPORT, DES40_CBC, SHA),
243 CIPHER_SUITE(SSL, DH_anon, DES_CBC, SHA),
244 CIPHER_SUITE(SSL, DH_anon, 3DES_EDE_CBC, SHA),
245 CIPHER_SUITE(SSL, FORTEZZA_DMS, NULL, SHA),
246 CIPHER_SUITE(SSL, FORTEZZA_DMS, FORTEZZA_CBC, SHA),
248 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA),
249 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA),
250 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA),
251 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA),
252 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA),
253 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA),
254 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA),
255 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA),
256 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA),
257 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA),
258 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA),
259 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA),
261 CIPHER_SUITE(TLS, ECDH_ECDSA, NULL, SHA),
262 CIPHER_SUITE(TLS, ECDH_ECDSA, RC4_128, SHA),
263 CIPHER_SUITE(TLS, ECDH_ECDSA, 3DES_EDE_CBC, SHA),
264 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA),
265 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA),
266 CIPHER_SUITE(TLS, ECDHE_ECDSA, NULL, SHA),
267 CIPHER_SUITE(TLS, ECDHE_ECDSA, RC4_128, SHA),
268 CIPHER_SUITE(TLS, ECDHE_ECDSA, 3DES_EDE_CBC, SHA),
269 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA),
270 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA),
271 CIPHER_SUITE(TLS, ECDH_RSA, NULL, SHA),
272 CIPHER_SUITE(TLS, ECDH_RSA, RC4_128, SHA),
273 CIPHER_SUITE(TLS, ECDH_RSA, 3DES_EDE_CBC, SHA),
274 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA),
275 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA),
276 CIPHER_SUITE(TLS, ECDHE_RSA, NULL, SHA),
277 CIPHER_SUITE(TLS, ECDHE_RSA, RC4_128, SHA),
278 CIPHER_SUITE(TLS, ECDHE_RSA, 3DES_EDE_CBC, SHA),
279 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA),
280 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA),
281 CIPHER_SUITE(TLS, ECDH_anon, NULL, SHA),
282 CIPHER_SUITE(TLS, ECDH_anon, RC4_128, SHA),
283 CIPHER_SUITE(TLS, ECDH_anon, 3DES_EDE_CBC, SHA),
284 CIPHER_SUITE(TLS, ECDH_anon, AES_128_CBC, SHA),
285 CIPHER_SUITE(TLS, ECDH_anon, AES_256_CBC, SHA),
287 CIPHER_SUITE(TLS, NULL, NULL, NULL),
288 CIPHER_SUITE(TLS, RSA, NULL, MD5),
289 CIPHER_SUITE(TLS, RSA, NULL, SHA),
290 CIPHER_SUITE(TLS, RSA, RC4_128, MD5),
291 CIPHER_SUITE(TLS, RSA, RC4_128, SHA),
292 CIPHER_SUITE(TLS, RSA, 3DES_EDE_CBC, SHA),
293 CIPHER_SUITE(TLS, RSA, NULL, SHA256),
294 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA256),
295 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA256),
296 CIPHER_SUITE(TLS, DH_DSS, 3DES_EDE_CBC, SHA),
297 CIPHER_SUITE(TLS, DH_RSA, 3DES_EDE_CBC, SHA),
298 CIPHER_SUITE(TLS, DHE_DSS, 3DES_EDE_CBC, SHA),
299 CIPHER_SUITE(TLS, DHE_RSA, 3DES_EDE_CBC, SHA),
300 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA256),
301 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA256),
302 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA256),
303 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA256),
304 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA256),
305 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA256),
306 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA256),
307 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA256),
308 CIPHER_SUITE(TLS, DH_anon, RC4_128, MD5),
309 CIPHER_SUITE(TLS, DH_anon, 3DES_EDE_CBC, SHA),
310 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA256),
311 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA256),
312 CIPHER_SUITE(TLS, RSA, AES_128_GCM, SHA256),
313 CIPHER_SUITE(TLS, RSA, AES_256_GCM, SHA384),
314 CIPHER_SUITE(TLS, DHE_RSA, AES_128_GCM, SHA256),
315 CIPHER_SUITE(TLS, DHE_RSA, AES_256_GCM, SHA384),
316 CIPHER_SUITE(TLS, DH_RSA, AES_128_GCM, SHA256),
317 CIPHER_SUITE(TLS, DH_RSA, AES_256_GCM, SHA384),
318 CIPHER_SUITE(TLS, DHE_DSS, AES_128_GCM, SHA256),
319 CIPHER_SUITE(TLS, DHE_DSS, AES_256_GCM, SHA384),
320 CIPHER_SUITE(TLS, DH_DSS, AES_128_GCM, SHA256),
321 CIPHER_SUITE(TLS, DH_DSS, AES_256_GCM, SHA384),
322 CIPHER_SUITE(TLS, DH_anon, AES_128_GCM, SHA256),
323 CIPHER_SUITE(TLS, DH_anon, AES_256_GCM, SHA384),
324 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA256),
325 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA384),
326 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA256),
327 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA384),
328 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA256),
329 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA384),
330 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA256),
331 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA384),
332 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_GCM, SHA256),
333 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_GCM, SHA384),
334 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_GCM, SHA256),
335 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_GCM, SHA384),
336 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_GCM, SHA256),
337 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_GCM, SHA384),
338 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_GCM, SHA256),
339 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_GCM, SHA384),
341 CIPHER_SUITE(SSL, RSA, RC2_CBC, MD5),
342 CIPHER_SUITE(SSL, RSA, IDEA_CBC, MD5),
343 CIPHER_SUITE(SSL, RSA, DES_CBC, MD5),
344 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, MD5),
345 #undef CIPHER_SUITE
349 static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
351 int i;
352 for (i = 0; i < sizeof(cipher_suites)/sizeof(cipher_suites[0]); i++)
354 if (cipher_suites[i].suite == cipher_suite)
355 return &cipher_suites[i];
358 return NULL;
362 static DWORD schan_get_session_protocol(struct mac_session* s)
364 SSLProtocol protocol;
365 OSStatus status;
367 TRACE("(%p/%p)\n", s, s->context);
369 status = SSLGetNegotiatedProtocolVersion(s->context, &protocol);
370 if (status != noErr)
372 ERR("Failed to get session protocol: %ld\n", status);
373 return 0;
376 TRACE("protocol %d\n", protocol);
378 switch (protocol)
380 case kSSLProtocol2: return SP_PROT_SSL2_CLIENT;
381 case kSSLProtocol3: return SP_PROT_SSL3_CLIENT;
382 case kTLSProtocol1: return SP_PROT_TLS1_CLIENT;
383 case kTLSProtocol11: return SP_PROT_TLS1_1_CLIENT;
384 case kTLSProtocol12: return SP_PROT_TLS1_2_CLIENT;
385 default:
386 FIXME("unknown protocol %d\n", protocol);
387 return 0;
391 static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
393 TRACE("(%#x)\n", (unsigned int)c->suite);
395 switch (c->enc_alg)
397 case schan_enc_3DES_EDE_CBC: return CALG_3DES;
398 case schan_enc_AES_128_CBC: return CALG_AES_128;
399 case schan_enc_AES_256_CBC: return CALG_AES_256;
400 case schan_enc_DES_CBC: return CALG_DES;
401 case schan_enc_DES40_CBC: return CALG_DES;
402 case schan_enc_NULL: return 0;
403 case schan_enc_RC2_CBC_40: return CALG_RC2;
404 case schan_enc_RC2_CBC: return CALG_RC2;
405 case schan_enc_RC4_128: return CALG_RC4;
406 case schan_enc_RC4_40: return CALG_RC4;
408 case schan_enc_AES_128_GCM:
409 case schan_enc_AES_256_GCM:
410 case schan_enc_FORTEZZA_CBC:
411 case schan_enc_IDEA_CBC:
412 FIXME("Don't know CALG for encryption algorithm %d, returning 0\n", c->enc_alg);
413 return 0;
415 default:
416 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
417 return 0;
421 static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
423 TRACE("(%#x)\n", (unsigned int)c->suite);
425 switch (c->enc_alg)
427 case schan_enc_3DES_EDE_CBC: return 168;
428 case schan_enc_AES_128_CBC: return 128;
429 case schan_enc_AES_128_GCM: return 128;
430 case schan_enc_AES_256_CBC: return 256;
431 case schan_enc_AES_256_GCM: return 256;
432 case schan_enc_DES_CBC: return 56;
433 case schan_enc_DES40_CBC: return 40;
434 case schan_enc_NULL: return 0;
435 case schan_enc_RC2_CBC_40: return 40;
436 case schan_enc_RC2_CBC: return 128;
437 case schan_enc_RC4_128: return 128;
438 case schan_enc_RC4_40: return 40;
440 case schan_enc_FORTEZZA_CBC:
441 case schan_enc_IDEA_CBC:
442 FIXME("Don't know key size for encryption algorithm %d, returning 0\n", c->enc_alg);
443 return 0;
445 default:
446 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
447 return 0;
451 static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
453 TRACE("(%#x)\n", (unsigned int)c->suite);
455 switch (c->mac_alg)
457 case schan_mac_MD5: return CALG_MD5;
458 case schan_mac_NULL: return 0;
459 case schan_mac_SHA: return CALG_SHA;
460 case schan_mac_SHA256: return CALG_SHA_256;
461 case schan_mac_SHA384: return CALG_SHA_384;
463 default:
464 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
465 return 0;
469 static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
471 TRACE("(%#x)\n", (unsigned int)c->suite);
473 switch (c->mac_alg)
475 case schan_mac_MD5: return 128;
476 case schan_mac_NULL: return 0;
477 case schan_mac_SHA: return 160;
478 case schan_mac_SHA256: return 256;
479 case schan_mac_SHA384: return 384;
481 default:
482 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
483 return 0;
487 static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
489 TRACE("(%#x)\n", (unsigned int)c->suite);
491 switch (c->kx_alg)
493 case schan_kx_DHE_DSS_EXPORT:
494 case schan_kx_DHE_DSS:
495 case schan_kx_DHE_RSA_EXPORT:
496 case schan_kx_DHE_RSA: return CALG_DH_EPHEM;
497 case schan_kx_ECDH_anon:
498 case schan_kx_ECDH_ECDSA:
499 case schan_kx_ECDH_RSA:
500 case schan_kx_ECDHE_ECDSA:
501 case schan_kx_ECDHE_RSA: return CALG_ECDH;
502 case schan_kx_NULL: return 0;
503 case schan_kx_RSA: return CALG_RSA_KEYX;
505 case schan_kx_DH_anon_EXPORT:
506 case schan_kx_DH_anon:
507 case schan_kx_DH_DSS_EXPORT:
508 case schan_kx_DH_DSS:
509 case schan_kx_DH_RSA_EXPORT:
510 case schan_kx_DH_RSA:
511 case schan_kx_FORTEZZA_DMS:
512 case schan_kx_RSA_EXPORT:
513 FIXME("Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
514 return 0;
516 default:
517 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
518 return 0;
523 /* schan_pull_adapter
524 * Callback registered with SSLSetIOFuncs as the read function for a
525 * session. Reads data from the session connection. Conforms to the
526 * SSLReadFunc type.
528 * transport - The session connection
529 * buff - The buffer into which to store the read data. Must be at least
530 * *buff_len bytes in length.
531 * *buff_len - On input, the desired length to read. On successful return,
532 * the number of bytes actually read.
534 * Returns:
535 * noErr on complete success meaning the requested length was successfully
536 * read.
537 * errSSLWouldBlock when the requested length could not be read without
538 * blocking. *buff_len indicates how much was actually read. The
539 * caller should try again if/when they want to read more.
540 * errSSLClosedGraceful when the connection has closed and there's no
541 * more data to be read.
542 * other error code for failure.
544 static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
545 SIZE_T *buff_len)
547 struct mac_session *s = (struct mac_session*)transport;
548 size_t requested = *buff_len;
549 int status;
550 OSStatus ret;
552 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
554 status = schan_pull(s->transport, buff, buff_len);
555 if (status == 0)
557 if (*buff_len == 0)
559 TRACE("Connection closed\n");
560 ret = errSSLClosedGraceful;
562 else if (*buff_len < requested)
564 TRACE("Pulled %lu bytes before would block\n", *buff_len);
565 ret = errSSLWouldBlock;
567 else
569 TRACE("Pulled %lu bytes\n", *buff_len);
570 ret = noErr;
573 else if (status == EAGAIN)
575 TRACE("Would block before being able to pull anything\n");
576 ret = errSSLWouldBlock;
578 else
580 FIXME("Unknown status code from schan_pull: %d\n", status);
581 ret = ioErr;
584 return ret;
587 /* schan_push_adapter
588 * Callback registered with SSLSetIOFuncs as the write function for a
589 * session. Writes data to the session connection. Conforms to the
590 * SSLWriteFunc type.
592 * transport - The session connection
593 * buff - The buffer of data to write. Must be at least *buff_len bytes in length.
594 * *buff_len - On input, the desired length to write. On successful return,
595 * the number of bytes actually written.
597 * Returns:
598 * noErr on complete or partial success; *buff_len indicates how much data
599 * was actually written, which may be less than requrested.
600 * errSSLWouldBlock when no data could be written without blocking. The
601 * caller should try again.
602 * other error code for failure.
604 static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
605 SIZE_T *buff_len)
607 struct mac_session *s = (struct mac_session*)transport;
608 int status;
609 OSStatus ret;
611 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
613 status = schan_push(s->transport, buff, buff_len);
614 if (status == 0)
616 TRACE("Pushed %lu bytes\n", *buff_len);
617 ret = noErr;
619 else if (status == EAGAIN)
621 TRACE("Would block before being able to push anything\n");
622 ret = errSSLWouldBlock;
624 else
626 FIXME("Unknown status code from schan_push: %d\n", status);
627 ret = ioErr;
630 return ret;
633 static const struct {
634 DWORD enable_flag;
635 SSLProtocol mac_version;
636 } protocol_priority_flags[] = {
637 {SP_PROT_TLS1_2_CLIENT, kTLSProtocol12},
638 {SP_PROT_TLS1_1_CLIENT, kTLSProtocol11},
639 {SP_PROT_TLS1_0_CLIENT, kTLSProtocol1},
640 {SP_PROT_SSL3_CLIENT, kSSLProtocol3},
641 {SP_PROT_SSL2_CLIENT, kSSLProtocol2}
644 static DWORD supported_protocols;
646 DWORD schan_imp_enabled_protocols(void)
648 return supported_protocols;
651 BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
653 struct mac_session *s;
654 unsigned i;
655 OSStatus status;
657 TRACE("(%p)\n", session);
659 s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
660 if (!s)
661 return FALSE;
663 status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
664 if (status != noErr)
666 ERR("Failed to create session context: %ld\n", (long)status);
667 goto fail;
670 status = SSLSetConnection(s->context, s);
671 if (status != noErr)
673 ERR("Failed to set session connection: %ld\n", (long)status);
674 goto fail;
677 status = SSLSetEnableCertVerify(s->context, FALSE);
678 if (status != noErr)
680 ERR("Failed to disable certificate verification: %ld\n", (long)status);
681 goto fail;
684 for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) {
685 if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
686 continue;
688 status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
689 (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
690 if (status != noErr)
692 ERR("Failed to set SSL version %d: %ld\n", protocol_priority_flags[i].mac_version, (long)status);
693 goto fail;
697 status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
698 if (status != noErr)
700 ERR("Failed to set session I/O funcs: %ld\n", (long)status);
701 goto fail;
704 TRACE(" -> %p/%p\n", s, s->context);
706 *session = (schan_imp_session)s;
707 return TRUE;
709 fail:
710 HeapFree(GetProcessHeap(), 0, s);
711 return FALSE;
714 void schan_imp_dispose_session(schan_imp_session session)
716 struct mac_session *s = (struct mac_session*)session;
717 OSStatus status;
719 TRACE("(%p/%p)\n", s, s->context);
721 status = SSLDisposeContext(s->context);
722 if (status != noErr)
723 ERR("Failed to dispose of session context: %ld\n", status);
724 HeapFree(GetProcessHeap(), 0, s);
727 void schan_imp_set_session_transport(schan_imp_session session,
728 struct schan_transport *t)
730 struct mac_session *s = (struct mac_session*)session;
732 TRACE("(%p/%p, %p)\n", s, s->context, t);
734 s->transport = t;
737 void schan_imp_set_session_target(schan_imp_session session, const char *target)
739 struct mac_session *s = (struct mac_session*)session;
741 TRACE("(%p/%p, %s)\n", s, s->context, debugstr_a(target));
743 SSLSetPeerDomainName( s->context, target, strlen(target) );
746 SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
748 struct mac_session *s = (struct mac_session*)session;
749 OSStatus status;
751 TRACE("(%p/%p)\n", s, s->context);
753 status = SSLHandshake(s->context);
754 if (status == noErr)
756 TRACE("Handshake completed\n");
757 return SEC_E_OK;
759 else if (status == errSSLWouldBlock)
761 TRACE("Continue...\n");
762 return SEC_I_CONTINUE_NEEDED;
764 else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
766 ERR("Handshake failed: %s\n", strerror(status));
767 return SEC_E_INTERNAL_ERROR;
769 else
771 ERR("Handshake failed: %ld\n", (long)status);
772 cssmPerror("SSLHandshake", status);
773 return SEC_E_INTERNAL_ERROR;
776 /* Never reached */
777 return SEC_E_OK;
780 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
782 struct mac_session* s = (struct mac_session*)session;
783 SSLCipherSuite cipherSuite;
784 const struct cipher_suite* c;
785 OSStatus status;
787 TRACE("(%p/%p)\n", s, s->context);
789 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
790 if (status != noErr)
792 ERR("Failed to get session cipher suite: %ld\n", status);
793 return 0;
796 c = get_cipher_suite(cipherSuite);
797 if (!c)
799 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
800 return 0;
803 switch (c->enc_alg)
805 case schan_enc_3DES_EDE_CBC: return 64;
806 case schan_enc_AES_128_CBC: return 128;
807 case schan_enc_AES_128_GCM: return 128;
808 case schan_enc_AES_256_CBC: return 128;
809 case schan_enc_AES_256_GCM: return 128;
810 case schan_enc_DES_CBC: return 64;
811 case schan_enc_DES40_CBC: return 64;
812 case schan_enc_NULL: return 0;
813 case schan_enc_RC2_CBC_40: return 64;
814 case schan_enc_RC2_CBC: return 64;
815 case schan_enc_RC4_128: return 0;
816 case schan_enc_RC4_40: return 0;
818 case schan_enc_FORTEZZA_CBC:
819 case schan_enc_IDEA_CBC:
820 FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
821 return 0;
823 default:
824 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
825 return 0;
829 unsigned int schan_imp_get_max_message_size(schan_imp_session session)
831 FIXME("Returning 1 << 14.\n");
832 return 1 << 14;
835 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
836 SecPkgContext_ConnectionInfo *info)
838 struct mac_session* s = (struct mac_session*)session;
839 SSLCipherSuite cipherSuite;
840 const struct cipher_suite* c;
841 OSStatus status;
843 TRACE("(%p/%p, %p)\n", s, s->context, info);
845 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
846 if (status != noErr)
848 ERR("Failed to get session cipher suite: %ld\n", status);
849 return SEC_E_INTERNAL_ERROR;
852 c = get_cipher_suite(cipherSuite);
853 if (!c)
855 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
856 return SEC_E_INTERNAL_ERROR;
859 info->dwProtocol = schan_get_session_protocol(s);
860 info->aiCipher = schan_get_cipher_algid(c);
861 info->dwCipherStrength = schan_get_cipher_key_size(c);
862 info->aiHash = schan_get_mac_algid(c);
863 info->dwHashStrength = schan_get_mac_key_size(c);
864 info->aiExch = schan_get_kx_algid(c);
865 /* FIXME: info->dwExchStrength? */
866 info->dwExchStrength = 0;
868 return SEC_E_OK;
871 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
872 static void schan_imp_cf_release(const void *arg, void *ctx)
874 CFRelease(arg);
876 #endif
878 SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
879 PCCERT_CONTEXT *ret_cert)
881 struct mac_session* s = (struct mac_session*)session;
882 SECURITY_STATUS ret = SEC_E_OK;
883 PCCERT_CONTEXT cert = NULL;
884 SecCertificateRef mac_cert;
885 CFArrayRef cert_array;
886 OSStatus status;
887 CFIndex cnt, i;
888 CFDataRef data;
889 BOOL res;
891 TRACE("(%p/%p, %p)\n", s, s->context, cert);
893 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
894 status = SSLCopyPeerCertificates(s->context, &cert_array);
895 #else
896 status = SSLGetPeerCertificates(s->context, &cert_array);
897 #endif
898 if (status != noErr || !cert_array)
900 WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status);
901 return SEC_E_INTERNAL_ERROR;
904 cnt = CFArrayGetCount(cert_array);
905 for (i=0; i < cnt; i++) {
906 if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
907 (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
909 WARN("Couldn't extract certificate data\n");
910 ret = SEC_E_INTERNAL_ERROR;
911 break;
914 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
915 CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
916 CFRelease(data);
917 if (!res)
919 ret = GetLastError();
920 WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
921 break;
925 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
926 /* This is why SSLGetPeerCertificates was deprecated */
927 CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
928 schan_imp_cf_release, NULL);
929 #endif
930 CFRelease(cert_array);
931 if (ret != SEC_E_OK) {
932 if(cert)
933 CertFreeCertificateContext(cert);
934 return ret;
937 *ret_cert = cert;
938 return SEC_E_OK;
941 SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
942 SIZE_T *length)
944 struct mac_session* s = (struct mac_session*)session;
945 OSStatus status;
947 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
949 status = SSLWrite(s->context, buffer, *length, length);
950 if (status == noErr)
951 TRACE("Wrote %lu bytes\n", *length);
952 else if (status == errSSLWouldBlock)
954 if (!*length)
956 TRACE("Would block before being able to write anything\n");
957 return SEC_I_CONTINUE_NEEDED;
959 else
960 TRACE("Wrote %lu bytes before would block\n", *length);
962 else
964 WARN("SSLWrite failed: %ld\n", (long)status);
965 return SEC_E_INTERNAL_ERROR;
968 return SEC_E_OK;
971 SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
972 SIZE_T *length)
974 struct mac_session* s = (struct mac_session*)session;
975 OSStatus status;
977 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
979 status = SSLRead(s->context, buffer, *length, length);
980 if (status == noErr)
981 TRACE("Read %lu bytes\n", *length);
982 else if (status == errSSLWouldBlock)
984 if (!*length)
986 TRACE("Would block before being able to read anything\n");
987 return SEC_I_CONTINUE_NEEDED;
989 else
990 TRACE("Read %lu bytes before would block\n", *length);
992 else
994 WARN("SSLRead failed: %ld\n", (long)status);
995 return SEC_E_INTERNAL_ERROR;
998 return SEC_E_OK;
1001 BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c)
1003 /* The certificate is never really used for anything. */
1004 c->credentials = NULL;
1005 return TRUE;
1008 void schan_imp_free_certificate_credentials(schan_credentials *c)
1012 BOOL schan_imp_init(void)
1014 TRACE("()\n");
1016 supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
1018 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1019 if(SSLGetProtocolVersionMax != NULL) {
1020 SSLProtocol max_protocol;
1021 SSLContextRef ctx;
1022 OSStatus status;
1024 status = SSLNewContext(FALSE, &ctx);
1025 if(status == noErr) {
1026 status = SSLGetProtocolVersionMax(ctx, &max_protocol);
1027 if(status == noErr) {
1028 if(max_protocol >= kTLSProtocol11)
1029 supported_protocols |= SP_PROT_TLS1_1_CLIENT;
1030 if(max_protocol >= kTLSProtocol12)
1031 supported_protocols |= SP_PROT_TLS1_2_CLIENT;
1033 SSLDisposeContext(ctx);
1034 }else {
1035 WARN("SSLNewContext failed\n");
1038 #endif
1040 return TRUE;
1043 void schan_imp_deinit(void)
1045 TRACE("()\n");
1048 #endif /* HAVE_SECURITY_SECURITY_H */