mshtml: Use lazy allocation for connection points.
[wine] / dlls / secur32 / schannel_macosx.c
1 /*
2  * Mac OS X Secure Transport implementation of the schannel (SSL/TLS) provider.
3  *
4  * Copyright 2005 Juan Lang
5  * Copyright 2008 Henri Verbeet
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
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
35
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"
43
44 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
45
46 #ifdef HAVE_SECURITY_SECURITY_H
47
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,
76 };
77 #endif
78
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,
136 };
137
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 */
142 };
143 #endif
144
145
146 struct mac_session {
147     SSLContextRef context;
148     struct schan_transport *transport;
149 };
150
151
152 enum {
153     schan_proto_SSL,
154     schan_proto_TLS,
155 };
156
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,
177 };
178
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,
194 };
195
196 enum {
197     schan_mac_MD5,
198     schan_mac_NULL,
199     schan_mac_SHA,
200     schan_mac_SHA256,
201     schan_mac_SHA384,
202 };
203
204
205 struct cipher_suite {
206     SSLCipherSuite suite;
207     int protocol;
208     int kx_alg;
209     int enc_alg;
210     int mac_alg;
211 };
212
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),
247
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),
260
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),
286
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),
340
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
346 };
347
348
349 static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
350 {
351     int i;
352     for (i = 0; i < sizeof(cipher_suites)/sizeof(cipher_suites[0]); i++)
353     {
354         if (cipher_suites[i].suite == cipher_suite)
355             return &cipher_suites[i];
356     }
357
358     return NULL;
359 }
360
361
362 static DWORD schan_get_session_protocol(struct mac_session* s)
363 {
364     SSLProtocol protocol;
365     OSStatus status;
366
367     TRACE("(%p/%p)\n", s, s->context);
368
369     status = SSLGetNegotiatedProtocolVersion(s->context, &protocol);
370     if (status != noErr)
371     {
372         ERR("Failed to get session protocol: %ld\n", status);
373         return 0;
374     }
375
376     TRACE("protocol %d\n", protocol);
377
378     switch (protocol)
379     {
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;
388     }
389 }
390
391 static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
392 {
393     TRACE("(%#x)\n", (unsigned int)c->suite);
394
395     switch (c->enc_alg)
396     {
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;
407
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;
414
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;
418     }
419 }
420
421 static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
422 {
423     TRACE("(%#x)\n", (unsigned int)c->suite);
424
425     switch (c->enc_alg)
426     {
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;
439
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;
444
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;
448     }
449 }
450
451 static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
452 {
453     TRACE("(%#x)\n", (unsigned int)c->suite);
454
455     switch (c->mac_alg)
456     {
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;
462
463     default:
464         FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
465         return 0;
466     }
467 }
468
469 static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
470 {
471     TRACE("(%#x)\n", (unsigned int)c->suite);
472
473     switch (c->mac_alg)
474     {
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;
480
481     default:
482         FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
483         return 0;
484     }
485 }
486
487 static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
488 {
489     TRACE("(%#x)\n", (unsigned int)c->suite);
490
491     switch (c->kx_alg)
492     {
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;
504
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;
515
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;
519     }
520 }
521
522
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.
527  *
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.
533  *
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.
543  */
544 static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
545                                    SIZE_T *buff_len)
546 {
547     struct mac_session *s = (struct mac_session*)transport;
548     size_t requested = *buff_len;
549     int status;
550     OSStatus ret;
551
552     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
553
554     status = schan_pull(s->transport, buff, buff_len);
555     if (status == 0)
556     {
557         if (*buff_len == 0)
558         {
559             TRACE("Connection closed\n");
560             ret = errSSLClosedGraceful;
561         }
562         else if (*buff_len < requested)
563         {
564             TRACE("Pulled %lu bytes before would block\n", *buff_len);
565             ret = errSSLWouldBlock;
566         }
567         else
568         {
569             TRACE("Pulled %lu bytes\n", *buff_len);
570             ret = noErr;
571         }
572     }
573     else if (status == EAGAIN)
574     {
575         TRACE("Would block before being able to pull anything\n");
576         ret = errSSLWouldBlock;
577     }
578     else
579     {
580         FIXME("Unknown status code from schan_pull: %d\n", status);
581         ret = ioErr;
582     }
583
584     return ret;
585 }
586
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.
591  *
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.
596  *
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.
603  */
604 static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
605                                        SIZE_T *buff_len)
606 {
607     struct mac_session *s = (struct mac_session*)transport;
608     int status;
609     OSStatus ret;
610
611     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
612
613     status = schan_push(s->transport, buff, buff_len);
614     if (status == 0)
615     {
616         TRACE("Pushed %lu bytes\n", *buff_len);
617         ret = noErr;
618     }
619     else if (status == EAGAIN)
620     {
621         TRACE("Would block before being able to push anything\n");
622         ret = errSSLWouldBlock;
623     }
624     else
625     {
626         FIXME("Unknown status code from schan_push: %d\n", status);
627         ret = ioErr;
628     }
629
630     return ret;
631 }
632
633
634 BOOL schan_imp_create_session(schan_imp_session *session, BOOL is_server,
635                               schan_imp_certificate_credentials cred)
636 {
637     struct mac_session *s;
638     OSStatus status;
639
640     TRACE("(%p, %d)\n", session, is_server);
641
642     s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
643     if (!s)
644         return FALSE;
645
646     status = SSLNewContext(is_server, &s->context);
647     if (status != noErr)
648     {
649         ERR("Failed to create session context: %ld\n", (long)status);
650         goto fail;
651     }
652
653     status = SSLSetConnection(s->context, s);
654     if (status != noErr)
655     {
656         ERR("Failed to set session connection: %ld\n", (long)status);
657         goto fail;
658     }
659
660     status = SSLSetEnableCertVerify(s->context, FALSE);
661     if (status != noErr)
662     {
663         ERR("Failed to disable certificate verification: %ld\n", (long)status);
664         goto fail;
665     }
666
667     status = SSLSetProtocolVersionEnabled(s->context, kSSLProtocol2, FALSE);
668     if (status != noErr)
669     {
670         ERR("Failed to disable SSL version 2: %ld\n", (long)status);
671         goto fail;
672     }
673
674     status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
675     if (status != noErr)
676     {
677         ERR("Failed to set session I/O funcs: %ld\n", (long)status);
678         goto fail;
679     }
680
681     TRACE("    -> %p/%p\n", s, s->context);
682
683     *session = (schan_imp_session)s;
684     return TRUE;
685
686 fail:
687     HeapFree(GetProcessHeap(), 0, s);
688     return FALSE;
689 }
690
691 void schan_imp_dispose_session(schan_imp_session session)
692 {
693     struct mac_session *s = (struct mac_session*)session;
694     OSStatus status;
695
696     TRACE("(%p/%p)\n", s, s->context);
697
698     status = SSLDisposeContext(s->context);
699     if (status != noErr)
700         ERR("Failed to dispose of session context: %ld\n", status);
701     HeapFree(GetProcessHeap(), 0, s);
702 }
703
704 void schan_imp_set_session_transport(schan_imp_session session,
705                                      struct schan_transport *t)
706 {
707     struct mac_session *s = (struct mac_session*)session;
708
709     TRACE("(%p/%p, %p)\n", s, s->context, t);
710
711     s->transport = t;
712 }
713
714 SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
715 {
716     struct mac_session *s = (struct mac_session*)session;
717     OSStatus status;
718
719     TRACE("(%p/%p)\n", s, s->context);
720
721     status = SSLHandshake(s->context);
722     if (status == noErr)
723     {
724         TRACE("Handshake completed\n");
725         return SEC_E_OK;
726     }
727     else if (status == errSSLWouldBlock)
728     {
729         TRACE("Continue...\n");
730         return SEC_I_CONTINUE_NEEDED;
731     }
732     else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
733     {
734         ERR("Handshake failed: %s\n", strerror(status));
735         return SEC_E_INTERNAL_ERROR;
736     }
737     else
738     {
739         ERR("Handshake failed: %ld\n", (long)status);
740         cssmPerror("SSLHandshake", status);
741         return SEC_E_INTERNAL_ERROR;
742     }
743
744     /* Never reached */
745     return SEC_E_OK;
746 }
747
748 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
749 {
750     struct mac_session* s = (struct mac_session*)session;
751     SSLCipherSuite cipherSuite;
752     const struct cipher_suite* c;
753     OSStatus status;
754
755     TRACE("(%p/%p)\n", s, s->context);
756
757     status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
758     if (status != noErr)
759     {
760         ERR("Failed to get session cipher suite: %ld\n", status);
761         return 0;
762     }
763
764     c = get_cipher_suite(cipherSuite);
765     if (!c)
766     {
767         ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
768         return 0;
769     }
770
771     switch (c->enc_alg)
772     {
773     case schan_enc_3DES_EDE_CBC:    return 64;
774     case schan_enc_AES_128_CBC:     return 128;
775     case schan_enc_AES_128_GCM:     return 128;
776     case schan_enc_AES_256_CBC:     return 128;
777     case schan_enc_AES_256_GCM:     return 128;
778     case schan_enc_DES_CBC:         return 64;
779     case schan_enc_DES40_CBC:       return 64;
780     case schan_enc_NULL:            return 0;
781     case schan_enc_RC2_CBC_40:      return 64;
782     case schan_enc_RC2_CBC:         return 64;
783     case schan_enc_RC4_128:         return 0;
784     case schan_enc_RC4_40:          return 0;
785
786     case schan_enc_FORTEZZA_CBC:
787     case schan_enc_IDEA_CBC:
788         FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
789         return 0;
790
791     default:
792         FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
793         return 0;
794     }
795 }
796
797 unsigned int schan_imp_get_max_message_size(schan_imp_session session)
798 {
799     FIXME("Returning 1 << 14.\n");
800     return 1 << 14;
801 }
802
803 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
804                                               SecPkgContext_ConnectionInfo *info)
805 {
806     struct mac_session* s = (struct mac_session*)session;
807     SSLCipherSuite cipherSuite;
808     const struct cipher_suite* c;
809     OSStatus status;
810
811     TRACE("(%p/%p, %p)\n", s, s->context, info);
812
813     status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
814     if (status != noErr)
815     {
816         ERR("Failed to get session cipher suite: %ld\n", status);
817         return SEC_E_INTERNAL_ERROR;
818     }
819
820     c = get_cipher_suite(cipherSuite);
821     if (!c)
822     {
823         ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
824         return SEC_E_INTERNAL_ERROR;
825     }
826
827     info->dwProtocol = schan_get_session_protocol(s);
828     info->aiCipher = schan_get_cipher_algid(c);
829     info->dwCipherStrength = schan_get_cipher_key_size(c);
830     info->aiHash = schan_get_mac_algid(c);
831     info->dwHashStrength = schan_get_mac_key_size(c);
832     info->aiExch = schan_get_kx_algid(c);
833     /* FIXME: info->dwExchStrength? */
834     info->dwExchStrength = 0;
835
836     return SEC_E_OK;
837 }
838
839 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
840 static void schan_imp_cf_release(const void *arg, void *ctx)
841 {
842     CFRelease(arg);
843 }
844 #endif
845
846 SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
847                                                        PCCERT_CONTEXT *ret_cert)
848 {
849     struct mac_session* s = (struct mac_session*)session;
850     SECURITY_STATUS ret = SEC_E_OK;
851     PCCERT_CONTEXT cert = NULL;
852     SecCertificateRef mac_cert;
853     CFArrayRef cert_array;
854     OSStatus status;
855     CFIndex cnt, i;
856     CFDataRef data;
857     BOOL res;
858
859     TRACE("(%p/%p, %p)\n", s, s->context, cert);
860
861 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
862     status = SSLCopyPeerCertificates(s->context, &cert_array);
863 #else
864     status = SSLGetPeerCertificates(s->context, &cert_array);
865 #endif
866     if (status != noErr || !cert_array)
867     {
868         WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status);
869         return SEC_E_INTERNAL_ERROR;
870     }
871
872     cnt = CFArrayGetCount(cert_array);
873     for (i=0; i < cnt; i++) {
874         if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
875             (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
876         {
877             WARN("Couldn't extract certificate data\n");
878             ret = SEC_E_INTERNAL_ERROR;
879             break;
880         }
881
882         res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
883                                                CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
884         CFRelease(data);
885         if (!res)
886         {
887             ret = GetLastError();
888             WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
889             break;
890         }
891     }
892
893 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
894     /* This is why SSLGetPeerCertificates was deprecated */
895     CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
896                          schan_imp_cf_release, NULL);
897 #endif
898     CFRelease(cert_array);
899     if (ret != SEC_E_OK) {
900         if(cert)
901             CertFreeCertificateContext(cert);
902         return ret;
903     }
904
905     *ret_cert = cert;
906     return SEC_E_OK;
907 }
908
909 SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
910                                SIZE_T *length)
911 {
912     struct mac_session* s = (struct mac_session*)session;
913     OSStatus status;
914
915     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
916
917     status = SSLWrite(s->context, buffer, *length, length);
918     if (status == noErr)
919         TRACE("Wrote %lu bytes\n", *length);
920     else if (status == errSSLWouldBlock)
921     {
922         if (!*length)
923         {
924             TRACE("Would block before being able to write anything\n");
925             return SEC_I_CONTINUE_NEEDED;
926         }
927         else
928             TRACE("Wrote %lu bytes before would block\n", *length);
929     }
930     else
931     {
932         WARN("SSLWrite failed: %ld\n", (long)status);
933         return SEC_E_INTERNAL_ERROR;
934     }
935
936     return SEC_E_OK;
937 }
938
939 SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
940                                SIZE_T *length)
941 {
942     struct mac_session* s = (struct mac_session*)session;
943     OSStatus status;
944
945     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
946
947     status = SSLRead(s->context, buffer, *length, length);
948     if (status == noErr)
949         TRACE("Read %lu bytes\n", *length);
950     else if (status == errSSLWouldBlock)
951     {
952         if (!*length)
953         {
954             TRACE("Would block before being able to read anything\n");
955             return SEC_I_CONTINUE_NEEDED;
956         }
957         else
958             TRACE("Read %lu bytes before would block\n", *length);
959     }
960     else
961     {
962         WARN("SSLRead failed: %ld\n", (long)status);
963         return SEC_E_INTERNAL_ERROR;
964     }
965
966     return SEC_E_OK;
967 }
968
969 BOOL schan_imp_allocate_certificate_credentials(schan_imp_certificate_credentials *c)
970 {
971     /* The certificate is never really used for anything. */
972     *c = NULL;
973     return TRUE;
974 }
975
976 void schan_imp_free_certificate_credentials(schan_imp_certificate_credentials c)
977 {
978 }
979
980 BOOL schan_imp_init(void)
981 {
982     TRACE("()\n");
983     return TRUE;
984 }
985
986 void schan_imp_deinit(void)
987 {
988     TRACE("()\n");
989 }
990
991 #endif /* HAVE_SECURITY_SECURITY_H */