Release 1.5.29.
[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 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}
642 };
643
644 static DWORD supported_protocols;
645
646 DWORD schan_imp_enabled_protocols(void)
647 {
648     return supported_protocols;
649 }
650
651 BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
652 {
653     struct mac_session *s;
654     unsigned i;
655     OSStatus status;
656
657     TRACE("(%p)\n", session);
658
659     s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
660     if (!s)
661         return FALSE;
662
663     status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
664     if (status != noErr)
665     {
666         ERR("Failed to create session context: %ld\n", (long)status);
667         goto fail;
668     }
669
670     status = SSLSetConnection(s->context, s);
671     if (status != noErr)
672     {
673         ERR("Failed to set session connection: %ld\n", (long)status);
674         goto fail;
675     }
676
677     status = SSLSetEnableCertVerify(s->context, FALSE);
678     if (status != noErr)
679     {
680         ERR("Failed to disable certificate verification: %ld\n", (long)status);
681         goto fail;
682     }
683
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;
687
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)
691         {
692             ERR("Failed to set SSL version %d: %ld\n", protocol_priority_flags[i].mac_version, (long)status);
693             goto fail;
694         }
695     }
696
697     status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
698     if (status != noErr)
699     {
700         ERR("Failed to set session I/O funcs: %ld\n", (long)status);
701         goto fail;
702     }
703
704     TRACE("    -> %p/%p\n", s, s->context);
705
706     *session = (schan_imp_session)s;
707     return TRUE;
708
709 fail:
710     HeapFree(GetProcessHeap(), 0, s);
711     return FALSE;
712 }
713
714 void schan_imp_dispose_session(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 = SSLDisposeContext(s->context);
722     if (status != noErr)
723         ERR("Failed to dispose of session context: %ld\n", status);
724     HeapFree(GetProcessHeap(), 0, s);
725 }
726
727 void schan_imp_set_session_transport(schan_imp_session session,
728                                      struct schan_transport *t)
729 {
730     struct mac_session *s = (struct mac_session*)session;
731
732     TRACE("(%p/%p, %p)\n", s, s->context, t);
733
734     s->transport = t;
735 }
736
737 SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
738 {
739     struct mac_session *s = (struct mac_session*)session;
740     OSStatus status;
741
742     TRACE("(%p/%p)\n", s, s->context);
743
744     status = SSLHandshake(s->context);
745     if (status == noErr)
746     {
747         TRACE("Handshake completed\n");
748         return SEC_E_OK;
749     }
750     else if (status == errSSLWouldBlock)
751     {
752         TRACE("Continue...\n");
753         return SEC_I_CONTINUE_NEEDED;
754     }
755     else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
756     {
757         ERR("Handshake failed: %s\n", strerror(status));
758         return SEC_E_INTERNAL_ERROR;
759     }
760     else
761     {
762         ERR("Handshake failed: %ld\n", (long)status);
763         cssmPerror("SSLHandshake", status);
764         return SEC_E_INTERNAL_ERROR;
765     }
766
767     /* Never reached */
768     return SEC_E_OK;
769 }
770
771 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
772 {
773     struct mac_session* s = (struct mac_session*)session;
774     SSLCipherSuite cipherSuite;
775     const struct cipher_suite* c;
776     OSStatus status;
777
778     TRACE("(%p/%p)\n", s, s->context);
779
780     status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
781     if (status != noErr)
782     {
783         ERR("Failed to get session cipher suite: %ld\n", status);
784         return 0;
785     }
786
787     c = get_cipher_suite(cipherSuite);
788     if (!c)
789     {
790         ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
791         return 0;
792     }
793
794     switch (c->enc_alg)
795     {
796     case schan_enc_3DES_EDE_CBC:    return 64;
797     case schan_enc_AES_128_CBC:     return 128;
798     case schan_enc_AES_128_GCM:     return 128;
799     case schan_enc_AES_256_CBC:     return 128;
800     case schan_enc_AES_256_GCM:     return 128;
801     case schan_enc_DES_CBC:         return 64;
802     case schan_enc_DES40_CBC:       return 64;
803     case schan_enc_NULL:            return 0;
804     case schan_enc_RC2_CBC_40:      return 64;
805     case schan_enc_RC2_CBC:         return 64;
806     case schan_enc_RC4_128:         return 0;
807     case schan_enc_RC4_40:          return 0;
808
809     case schan_enc_FORTEZZA_CBC:
810     case schan_enc_IDEA_CBC:
811         FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
812         return 0;
813
814     default:
815         FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
816         return 0;
817     }
818 }
819
820 unsigned int schan_imp_get_max_message_size(schan_imp_session session)
821 {
822     FIXME("Returning 1 << 14.\n");
823     return 1 << 14;
824 }
825
826 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
827                                               SecPkgContext_ConnectionInfo *info)
828 {
829     struct mac_session* s = (struct mac_session*)session;
830     SSLCipherSuite cipherSuite;
831     const struct cipher_suite* c;
832     OSStatus status;
833
834     TRACE("(%p/%p, %p)\n", s, s->context, info);
835
836     status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
837     if (status != noErr)
838     {
839         ERR("Failed to get session cipher suite: %ld\n", status);
840         return SEC_E_INTERNAL_ERROR;
841     }
842
843     c = get_cipher_suite(cipherSuite);
844     if (!c)
845     {
846         ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
847         return SEC_E_INTERNAL_ERROR;
848     }
849
850     info->dwProtocol = schan_get_session_protocol(s);
851     info->aiCipher = schan_get_cipher_algid(c);
852     info->dwCipherStrength = schan_get_cipher_key_size(c);
853     info->aiHash = schan_get_mac_algid(c);
854     info->dwHashStrength = schan_get_mac_key_size(c);
855     info->aiExch = schan_get_kx_algid(c);
856     /* FIXME: info->dwExchStrength? */
857     info->dwExchStrength = 0;
858
859     return SEC_E_OK;
860 }
861
862 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
863 static void schan_imp_cf_release(const void *arg, void *ctx)
864 {
865     CFRelease(arg);
866 }
867 #endif
868
869 SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
870                                                        PCCERT_CONTEXT *ret_cert)
871 {
872     struct mac_session* s = (struct mac_session*)session;
873     SECURITY_STATUS ret = SEC_E_OK;
874     PCCERT_CONTEXT cert = NULL;
875     SecCertificateRef mac_cert;
876     CFArrayRef cert_array;
877     OSStatus status;
878     CFIndex cnt, i;
879     CFDataRef data;
880     BOOL res;
881
882     TRACE("(%p/%p, %p)\n", s, s->context, cert);
883
884 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
885     status = SSLCopyPeerCertificates(s->context, &cert_array);
886 #else
887     status = SSLGetPeerCertificates(s->context, &cert_array);
888 #endif
889     if (status != noErr || !cert_array)
890     {
891         WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status);
892         return SEC_E_INTERNAL_ERROR;
893     }
894
895     cnt = CFArrayGetCount(cert_array);
896     for (i=0; i < cnt; i++) {
897         if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
898             (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
899         {
900             WARN("Couldn't extract certificate data\n");
901             ret = SEC_E_INTERNAL_ERROR;
902             break;
903         }
904
905         res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
906                                                CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
907         CFRelease(data);
908         if (!res)
909         {
910             ret = GetLastError();
911             WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
912             break;
913         }
914     }
915
916 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
917     /* This is why SSLGetPeerCertificates was deprecated */
918     CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
919                          schan_imp_cf_release, NULL);
920 #endif
921     CFRelease(cert_array);
922     if (ret != SEC_E_OK) {
923         if(cert)
924             CertFreeCertificateContext(cert);
925         return ret;
926     }
927
928     *ret_cert = cert;
929     return SEC_E_OK;
930 }
931
932 SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
933                                SIZE_T *length)
934 {
935     struct mac_session* s = (struct mac_session*)session;
936     OSStatus status;
937
938     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
939
940     status = SSLWrite(s->context, buffer, *length, length);
941     if (status == noErr)
942         TRACE("Wrote %lu bytes\n", *length);
943     else if (status == errSSLWouldBlock)
944     {
945         if (!*length)
946         {
947             TRACE("Would block before being able to write anything\n");
948             return SEC_I_CONTINUE_NEEDED;
949         }
950         else
951             TRACE("Wrote %lu bytes before would block\n", *length);
952     }
953     else
954     {
955         WARN("SSLWrite failed: %ld\n", (long)status);
956         return SEC_E_INTERNAL_ERROR;
957     }
958
959     return SEC_E_OK;
960 }
961
962 SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
963                                SIZE_T *length)
964 {
965     struct mac_session* s = (struct mac_session*)session;
966     OSStatus status;
967
968     TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
969
970     status = SSLRead(s->context, buffer, *length, length);
971     if (status == noErr)
972         TRACE("Read %lu bytes\n", *length);
973     else if (status == errSSLWouldBlock)
974     {
975         if (!*length)
976         {
977             TRACE("Would block before being able to read anything\n");
978             return SEC_I_CONTINUE_NEEDED;
979         }
980         else
981             TRACE("Read %lu bytes before would block\n", *length);
982     }
983     else
984     {
985         WARN("SSLRead failed: %ld\n", (long)status);
986         return SEC_E_INTERNAL_ERROR;
987     }
988
989     return SEC_E_OK;
990 }
991
992 BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c)
993 {
994     /* The certificate is never really used for anything. */
995     c->credentials = NULL;
996     return TRUE;
997 }
998
999 void schan_imp_free_certificate_credentials(schan_credentials *c)
1000 {
1001 }
1002
1003 BOOL schan_imp_init(void)
1004 {
1005     TRACE("()\n");
1006
1007     supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
1008
1009 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1010     if(SSLGetProtocolVersionMax != NULL) {
1011         SSLProtocol max_protocol;
1012         SSLContextRef ctx;
1013         OSStatus status;
1014
1015         status = SSLNewContext(FALSE, &ctx);
1016         if(status == noErr) {
1017             status = SSLGetProtocolVersionMax(ctx, &max_protocol);
1018             if(status == noErr) {
1019                 if(max_protocol >= kTLSProtocol11)
1020                     supported_protocols |= SP_PROT_TLS1_1_CLIENT;
1021                 if(max_protocol >= kTLSProtocol12)
1022                     supported_protocols |= SP_PROT_TLS1_2_CLIENT;
1023             }
1024             SSLDisposeContext(ctx);
1025         }else {
1026             WARN("SSLNewContext failed\n");
1027         }
1028     }
1029 #endif
1030
1031     return TRUE;
1032 }
1033
1034 void schan_imp_deinit(void)
1035 {
1036     TRACE("()\n");
1037 }
1038
1039 #endif /* HAVE_SECURITY_SECURITY_H */