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
23 #include "wine/port.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
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. */
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,
79 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
80 /* Defined in <Security/CipherSuite.h> in the 10.8 SDK or later. */
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. */
140 kTLSProtocol11
= 7, /* TLS 1.1 */
141 kTLSProtocol12
= 8, /* TLS 1.2 */
147 SSLContextRef context
;
148 struct schan_transport
*transport
;
158 schan_kx_DH_anon_EXPORT
,
160 schan_kx_DH_DSS_EXPORT
,
162 schan_kx_DH_RSA_EXPORT
,
164 schan_kx_DHE_DSS_EXPORT
,
166 schan_kx_DHE_RSA_EXPORT
,
171 schan_kx_ECDHE_ECDSA
,
173 schan_kx_FORTEZZA_DMS
,
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
,
187 schan_enc_FORTEZZA_CBC
,
191 schan_enc_RC2_CBC_40
,
205 struct cipher_suite
{
206 SSLCipherSuite suite
;
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
),
349 static const struct cipher_suite
* get_cipher_suite(SSLCipherSuite cipher_suite
)
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
];
362 static DWORD
schan_get_session_protocol(struct mac_session
* s
)
364 SSLProtocol protocol
;
367 TRACE("(%p/%p)\n", s
, s
->context
);
369 status
= SSLGetNegotiatedProtocolVersion(s
->context
, &protocol
);
372 ERR("Failed to get session protocol: %ld\n", status
);
376 TRACE("protocol %d\n", 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
;
386 FIXME("unknown protocol %d\n", protocol
);
391 static ALG_ID
schan_get_cipher_algid(const struct cipher_suite
* c
)
393 TRACE("(%#x)\n", (unsigned int)c
->suite
);
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
);
416 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
421 static unsigned int schan_get_cipher_key_size(const struct cipher_suite
* c
)
423 TRACE("(%#x)\n", (unsigned int)c
->suite
);
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
);
446 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
451 static ALG_ID
schan_get_mac_algid(const struct cipher_suite
* c
)
453 TRACE("(%#x)\n", (unsigned int)c
->suite
);
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
;
464 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c
->mac_alg
, (unsigned)c
->suite
);
469 static unsigned int schan_get_mac_key_size(const struct cipher_suite
* c
)
471 TRACE("(%#x)\n", (unsigned int)c
->suite
);
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;
482 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c
->mac_alg
, (unsigned)c
->suite
);
487 static ALG_ID
schan_get_kx_algid(const struct cipher_suite
* c
)
489 TRACE("(%#x)\n", (unsigned int)c
->suite
);
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
);
517 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c
->kx_alg
, (unsigned)c
->suite
);
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
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.
535 * noErr on complete success meaning the requested length was successfully
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
,
547 struct mac_session
*s
= (struct mac_session
*)transport
;
548 size_t requested
= *buff_len
;
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
);
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
;
569 TRACE("Pulled %lu bytes\n", *buff_len
);
573 else if (status
== EAGAIN
)
575 TRACE("Would block before being able to pull anything\n");
576 ret
= errSSLWouldBlock
;
580 FIXME("Unknown status code from schan_pull: %d\n", status
);
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
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.
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
,
607 struct mac_session
*s
= (struct mac_session
*)transport
;
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
);
616 TRACE("Pushed %lu bytes\n", *buff_len
);
619 else if (status
== EAGAIN
)
621 TRACE("Would block before being able to push anything\n");
622 ret
= errSSLWouldBlock
;
626 FIXME("Unknown status code from schan_push: %d\n", status
);
633 static const struct {
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
;
657 TRACE("(%p)\n", session
);
659 s
= HeapAlloc(GetProcessHeap(), 0, sizeof(*s
));
663 status
= SSLNewContext(cred
->credential_use
== SECPKG_CRED_INBOUND
, &s
->context
);
666 ERR("Failed to create session context: %ld\n", (long)status
);
670 status
= SSLSetConnection(s
->context
, s
);
673 ERR("Failed to set session connection: %ld\n", (long)status
);
677 status
= SSLSetEnableCertVerify(s
->context
, FALSE
);
680 ERR("Failed to disable certificate verification: %ld\n", (long)status
);
684 for(i
=0; i
< sizeof(protocol_priority_flags
)/sizeof(*protocol_priority_flags
); i
++) {
685 if(!(protocol_priority_flags
[i
].enable_flag
& supported_protocols
))
688 status
= SSLSetProtocolVersionEnabled(s
->context
, protocol_priority_flags
[i
].mac_version
,
689 (cred
->enabled_protocols
& protocol_priority_flags
[i
].enable_flag
) != 0);
692 ERR("Failed to set SSL version %d: %ld\n", protocol_priority_flags
[i
].mac_version
, (long)status
);
697 status
= SSLSetIOFuncs(s
->context
, schan_pull_adapter
, schan_push_adapter
);
700 ERR("Failed to set session I/O funcs: %ld\n", (long)status
);
704 TRACE(" -> %p/%p\n", s
, s
->context
);
706 *session
= (schan_imp_session
)s
;
710 HeapFree(GetProcessHeap(), 0, s
);
714 void schan_imp_dispose_session(schan_imp_session session
)
716 struct mac_session
*s
= (struct mac_session
*)session
;
719 TRACE("(%p/%p)\n", s
, s
->context
);
721 status
= SSLDisposeContext(s
->context
);
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
);
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
;
751 TRACE("(%p/%p)\n", s
, s
->context
);
753 status
= SSLHandshake(s
->context
);
756 TRACE("Handshake completed\n");
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
;
771 ERR("Handshake failed: %ld\n", (long)status
);
772 cssmPerror("SSLHandshake", status
);
773 return SEC_E_INTERNAL_ERROR
;
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
;
787 TRACE("(%p/%p)\n", s
, s
->context
);
789 status
= SSLGetNegotiatedCipher(s
->context
, &cipherSuite
);
792 ERR("Failed to get session cipher suite: %ld\n", status
);
796 c
= get_cipher_suite(cipherSuite
);
799 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite
);
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
);
824 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
829 unsigned int schan_imp_get_max_message_size(schan_imp_session session
)
831 FIXME("Returning 1 << 14.\n");
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
;
843 TRACE("(%p/%p, %p)\n", s
, s
->context
, info
);
845 status
= SSLGetNegotiatedCipher(s
->context
, &cipherSuite
);
848 ERR("Failed to get session cipher suite: %ld\n", status
);
849 return SEC_E_INTERNAL_ERROR
;
852 c
= get_cipher_suite(cipherSuite
);
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;
871 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
872 static void schan_imp_cf_release(const void *arg
, void *ctx
)
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
;
891 TRACE("(%p/%p, %p)\n", s
, s
->context
, cert
);
893 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
894 status
= SSLCopyPeerCertificates(s
->context
, &cert_array
);
896 status
= SSLGetPeerCertificates(s
->context
, &cert_array
);
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
;
914 res
= CertAddEncodedCertificateToStore(store
, X509_ASN_ENCODING
, CFDataGetBytePtr(data
), CFDataGetLength(data
),
915 CERT_STORE_ADD_REPLACE_EXISTING
, i
? NULL
: &cert
);
919 ret
= GetLastError();
920 WARN("CertAddEncodedCertificateToStore failed: %x\n", ret
);
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
);
930 CFRelease(cert_array
);
931 if (ret
!= SEC_E_OK
) {
933 CertFreeCertificateContext(cert
);
941 SECURITY_STATUS
schan_imp_send(schan_imp_session session
, const void *buffer
,
944 struct mac_session
* s
= (struct mac_session
*)session
;
947 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->context
, buffer
, length
, *length
);
949 status
= SSLWrite(s
->context
, buffer
, *length
, length
);
951 TRACE("Wrote %lu bytes\n", *length
);
952 else if (status
== errSSLWouldBlock
)
956 TRACE("Would block before being able to write anything\n");
957 return SEC_I_CONTINUE_NEEDED
;
960 TRACE("Wrote %lu bytes before would block\n", *length
);
964 WARN("SSLWrite failed: %ld\n", (long)status
);
965 return SEC_E_INTERNAL_ERROR
;
971 SECURITY_STATUS
schan_imp_recv(schan_imp_session session
, void *buffer
,
974 struct mac_session
* s
= (struct mac_session
*)session
;
977 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->context
, buffer
, length
, *length
);
979 status
= SSLRead(s
->context
, buffer
, *length
, length
);
981 TRACE("Read %lu bytes\n", *length
);
982 else if (status
== errSSLWouldBlock
)
986 TRACE("Would block before being able to read anything\n");
987 return SEC_I_CONTINUE_NEEDED
;
990 TRACE("Read %lu bytes before would block\n", *length
);
994 WARN("SSLRead failed: %ld\n", (long)status
);
995 return SEC_E_INTERNAL_ERROR
;
1001 BOOL
schan_imp_allocate_certificate_credentials(schan_credentials
*c
)
1003 /* The certificate is never really used for anything. */
1004 c
->credentials
= NULL
;
1008 void schan_imp_free_certificate_credentials(schan_credentials
*c
)
1012 BOOL
schan_imp_init(void)
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
;
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
);
1035 WARN("SSLNewContext failed\n");
1043 void schan_imp_deinit(void)
1048 #endif /* HAVE_SECURITY_SECURITY_H */