gdiplus: Support GdipSetClipRegion in metafiles.
[wine.git] / dlls / secur32 / schannel_macosx.c
blob7f38133b4b4a2d18beadb3c796947c91cb3b8891
1 /*
2 * Mac OS X Secure Transport implementation of the schannel (SSL/TLS) provider.
4 * Copyright 2005 Juan Lang
5 * Copyright 2008 Henri Verbeet
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #ifdef HAVE_SECURITY_SECURITY_H
27 #include <Security/Security.h>
28 #define GetCurrentThread GetCurrentThread_Mac
29 #define LoadResource LoadResource_Mac
30 #include <CoreServices/CoreServices.h>
31 #undef GetCurrentThread
32 #undef LoadResource
33 #undef DPRINTF
34 #endif
36 #include "windef.h"
37 #include "winbase.h"
38 #include "sspi.h"
39 #include "schannel.h"
40 #include "secur32_priv.h"
41 #include "wine/debug.h"
42 #include "wine/library.h"
44 #ifdef HAVE_SECURITY_SECURITY_H
46 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
48 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
49 /* Defined in <Security/CipherSuite.h> in the 10.6 SDK or later. */
50 enum {
51 TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
52 TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
53 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
54 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
55 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
56 TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
57 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
58 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
59 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
60 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
61 TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
62 TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
63 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
64 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
65 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
66 TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
67 TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
68 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
69 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
70 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
71 TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
72 TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
73 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
74 TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
75 TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
77 #endif
79 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
80 /* Defined in <Security/CipherSuite.h> in the 10.8 SDK or later. */
81 enum {
82 TLS_NULL_WITH_NULL_NULL = 0x0000,
83 TLS_RSA_WITH_NULL_MD5 = 0x0001,
84 TLS_RSA_WITH_NULL_SHA = 0x0002,
85 TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
86 TLS_RSA_WITH_RC4_128_SHA = 0x0005,
87 TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
88 TLS_RSA_WITH_NULL_SHA256 = 0x003B,
89 TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
90 TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
91 TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
92 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
93 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
94 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
95 TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
96 TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
97 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
98 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
99 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
100 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
101 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
102 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
103 TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
104 TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
105 TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
106 TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
107 TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
108 TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
109 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
110 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
111 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
112 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
113 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
114 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
115 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
116 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
117 TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
118 TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
119 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
120 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
121 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
122 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
123 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
124 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
125 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
126 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
127 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
128 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
129 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
130 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
131 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
132 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
133 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
134 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
135 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
138 /* Defined in <Security/SecureTransport.h> in the 10.8 SDK or later. */
139 enum {
140 kTLSProtocol11 = 7, /* TLS 1.1 */
141 kTLSProtocol12 = 8, /* TLS 1.2 */
143 #endif
145 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
146 /* Defined in <Security/CipherSuite.h> in the 10.9 SDK or later. */
147 enum {
148 TLS_PSK_WITH_RC4_128_SHA = 0x008A,
149 TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
150 TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
151 TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
152 TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
153 TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
154 TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
155 TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
156 TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
157 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
158 TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
159 TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
160 TLS_PSK_WITH_NULL_SHA = 0x002C,
161 TLS_DHE_PSK_WITH_NULL_SHA = 0x002D,
162 TLS_RSA_PSK_WITH_NULL_SHA = 0x002E,
163 TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8,
164 TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9,
165 TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA,
166 TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB,
167 TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC,
168 TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD,
169 TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
170 TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF,
171 TLS_PSK_WITH_NULL_SHA256 = 0x00B0,
172 TLS_PSK_WITH_NULL_SHA384 = 0x00B1,
173 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2,
174 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3,
175 TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4,
176 TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5,
177 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6,
178 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7,
179 TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8,
180 TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9,
182 #endif
185 struct mac_session {
186 SSLContextRef context;
187 struct schan_transport *transport;
191 enum {
192 schan_proto_SSL,
193 schan_proto_TLS,
196 enum {
197 schan_kx_DH_anon_EXPORT,
198 schan_kx_DH_anon,
199 schan_kx_DH_DSS_EXPORT,
200 schan_kx_DH_DSS,
201 schan_kx_DH_RSA_EXPORT,
202 schan_kx_DH_RSA,
203 schan_kx_DHE_DSS_EXPORT,
204 schan_kx_DHE_DSS,
205 schan_kx_DHE_PSK,
206 schan_kx_DHE_RSA_EXPORT,
207 schan_kx_DHE_RSA,
208 schan_kx_ECDH_anon,
209 schan_kx_ECDH_ECDSA,
210 schan_kx_ECDH_RSA,
211 schan_kx_ECDHE_ECDSA,
212 schan_kx_ECDHE_RSA,
213 schan_kx_FORTEZZA_DMS,
214 schan_kx_NULL,
215 schan_kx_PSK,
216 schan_kx_RSA_EXPORT,
217 schan_kx_RSA_PSK,
218 schan_kx_RSA,
221 enum {
222 schan_enc_3DES_EDE_CBC,
223 schan_enc_AES_128_CBC,
224 schan_enc_AES_128_GCM,
225 schan_enc_AES_256_CBC,
226 schan_enc_AES_256_GCM,
227 schan_enc_DES_CBC,
228 schan_enc_DES40_CBC,
229 schan_enc_FORTEZZA_CBC,
230 schan_enc_IDEA_CBC,
231 schan_enc_NULL,
232 schan_enc_RC2_CBC,
233 schan_enc_RC2_CBC_40,
234 schan_enc_RC4_128,
235 schan_enc_RC4_40,
238 enum {
239 schan_mac_MD5,
240 schan_mac_NULL,
241 schan_mac_SHA,
242 schan_mac_SHA256,
243 schan_mac_SHA384,
247 struct cipher_suite {
248 SSLCipherSuite suite;
249 int protocol;
250 int kx_alg;
251 int enc_alg;
252 int mac_alg;
255 /* This table corresponds to the enum in <Security/CipherSuite.h>. */
256 static const struct cipher_suite cipher_suites[] = {
257 #define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
258 schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
259 CIPHER_SUITE(SSL, RSA, NULL, MD5),
260 CIPHER_SUITE(SSL, RSA, NULL, MD5),
261 CIPHER_SUITE(SSL, RSA, NULL, SHA),
262 CIPHER_SUITE(SSL, RSA_EXPORT, RC4_40, MD5),
263 CIPHER_SUITE(SSL, RSA, RC4_128, MD5),
264 CIPHER_SUITE(SSL, RSA, RC4_128, SHA),
265 CIPHER_SUITE(SSL, RSA_EXPORT, RC2_CBC_40, MD5),
266 CIPHER_SUITE(SSL, RSA, IDEA_CBC, SHA),
267 CIPHER_SUITE(SSL, RSA_EXPORT, DES40_CBC, SHA),
268 CIPHER_SUITE(SSL, RSA, DES_CBC, SHA),
269 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, SHA),
270 CIPHER_SUITE(SSL, DH_DSS_EXPORT, DES40_CBC, SHA),
271 CIPHER_SUITE(SSL, DH_DSS, DES_CBC, SHA),
272 CIPHER_SUITE(SSL, DH_DSS, 3DES_EDE_CBC, SHA),
273 CIPHER_SUITE(SSL, DH_RSA_EXPORT, DES40_CBC, SHA),
274 CIPHER_SUITE(SSL, DH_RSA, DES_CBC, SHA),
275 CIPHER_SUITE(SSL, DH_RSA, 3DES_EDE_CBC, SHA),
276 CIPHER_SUITE(SSL, DHE_DSS_EXPORT, DES40_CBC, SHA),
277 CIPHER_SUITE(SSL, DHE_DSS, DES_CBC, SHA),
278 CIPHER_SUITE(SSL, DHE_DSS, 3DES_EDE_CBC, SHA),
279 CIPHER_SUITE(SSL, DHE_RSA_EXPORT, DES40_CBC, SHA),
280 CIPHER_SUITE(SSL, DHE_RSA, DES_CBC, SHA),
281 CIPHER_SUITE(SSL, DHE_RSA, 3DES_EDE_CBC, SHA),
282 CIPHER_SUITE(SSL, DH_anon_EXPORT, RC4_40, MD5),
283 CIPHER_SUITE(SSL, DH_anon, RC4_128, MD5),
284 CIPHER_SUITE(SSL, DH_anon_EXPORT, DES40_CBC, SHA),
285 CIPHER_SUITE(SSL, DH_anon, DES_CBC, SHA),
286 CIPHER_SUITE(SSL, DH_anon, 3DES_EDE_CBC, SHA),
287 CIPHER_SUITE(SSL, FORTEZZA_DMS, NULL, SHA),
288 CIPHER_SUITE(SSL, FORTEZZA_DMS, FORTEZZA_CBC, SHA),
290 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA),
291 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA),
292 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA),
293 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA),
294 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA),
295 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA),
296 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA),
297 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA),
298 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA),
299 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA),
300 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA),
301 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA),
303 CIPHER_SUITE(TLS, ECDH_ECDSA, NULL, SHA),
304 CIPHER_SUITE(TLS, ECDH_ECDSA, RC4_128, SHA),
305 CIPHER_SUITE(TLS, ECDH_ECDSA, 3DES_EDE_CBC, SHA),
306 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA),
307 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA),
308 CIPHER_SUITE(TLS, ECDHE_ECDSA, NULL, SHA),
309 CIPHER_SUITE(TLS, ECDHE_ECDSA, RC4_128, SHA),
310 CIPHER_SUITE(TLS, ECDHE_ECDSA, 3DES_EDE_CBC, SHA),
311 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA),
312 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA),
313 CIPHER_SUITE(TLS, ECDH_RSA, NULL, SHA),
314 CIPHER_SUITE(TLS, ECDH_RSA, RC4_128, SHA),
315 CIPHER_SUITE(TLS, ECDH_RSA, 3DES_EDE_CBC, SHA),
316 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA),
317 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA),
318 CIPHER_SUITE(TLS, ECDHE_RSA, NULL, SHA),
319 CIPHER_SUITE(TLS, ECDHE_RSA, RC4_128, SHA),
320 CIPHER_SUITE(TLS, ECDHE_RSA, 3DES_EDE_CBC, SHA),
321 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA),
322 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA),
323 CIPHER_SUITE(TLS, ECDH_anon, NULL, SHA),
324 CIPHER_SUITE(TLS, ECDH_anon, RC4_128, SHA),
325 CIPHER_SUITE(TLS, ECDH_anon, 3DES_EDE_CBC, SHA),
326 CIPHER_SUITE(TLS, ECDH_anon, AES_128_CBC, SHA),
327 CIPHER_SUITE(TLS, ECDH_anon, AES_256_CBC, SHA),
329 CIPHER_SUITE(TLS, NULL, NULL, NULL),
330 CIPHER_SUITE(TLS, RSA, NULL, MD5),
331 CIPHER_SUITE(TLS, RSA, NULL, SHA),
332 CIPHER_SUITE(TLS, RSA, RC4_128, MD5),
333 CIPHER_SUITE(TLS, RSA, RC4_128, SHA),
334 CIPHER_SUITE(TLS, RSA, 3DES_EDE_CBC, SHA),
335 CIPHER_SUITE(TLS, RSA, NULL, SHA256),
336 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA256),
337 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA256),
338 CIPHER_SUITE(TLS, DH_DSS, 3DES_EDE_CBC, SHA),
339 CIPHER_SUITE(TLS, DH_RSA, 3DES_EDE_CBC, SHA),
340 CIPHER_SUITE(TLS, DHE_DSS, 3DES_EDE_CBC, SHA),
341 CIPHER_SUITE(TLS, DHE_RSA, 3DES_EDE_CBC, SHA),
342 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA256),
343 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA256),
344 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA256),
345 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA256),
346 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA256),
347 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA256),
348 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA256),
349 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA256),
350 CIPHER_SUITE(TLS, DH_anon, RC4_128, MD5),
351 CIPHER_SUITE(TLS, DH_anon, 3DES_EDE_CBC, SHA),
352 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA256),
353 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA256),
355 CIPHER_SUITE(TLS, PSK, RC4_128, SHA),
356 CIPHER_SUITE(TLS, PSK, 3DES_EDE_CBC, SHA),
357 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA),
358 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA),
359 CIPHER_SUITE(TLS, DHE_PSK, RC4_128, SHA),
360 CIPHER_SUITE(TLS, DHE_PSK, 3DES_EDE_CBC, SHA),
361 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA),
362 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA),
363 CIPHER_SUITE(TLS, RSA_PSK, RC4_128, SHA),
364 CIPHER_SUITE(TLS, RSA_PSK, 3DES_EDE_CBC, SHA),
365 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA),
366 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA),
367 CIPHER_SUITE(TLS, PSK, NULL, SHA),
368 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA),
369 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA),
371 CIPHER_SUITE(TLS, RSA, AES_128_GCM, SHA256),
372 CIPHER_SUITE(TLS, RSA, AES_256_GCM, SHA384),
373 CIPHER_SUITE(TLS, DHE_RSA, AES_128_GCM, SHA256),
374 CIPHER_SUITE(TLS, DHE_RSA, AES_256_GCM, SHA384),
375 CIPHER_SUITE(TLS, DH_RSA, AES_128_GCM, SHA256),
376 CIPHER_SUITE(TLS, DH_RSA, AES_256_GCM, SHA384),
377 CIPHER_SUITE(TLS, DHE_DSS, AES_128_GCM, SHA256),
378 CIPHER_SUITE(TLS, DHE_DSS, AES_256_GCM, SHA384),
379 CIPHER_SUITE(TLS, DH_DSS, AES_128_GCM, SHA256),
380 CIPHER_SUITE(TLS, DH_DSS, AES_256_GCM, SHA384),
381 CIPHER_SUITE(TLS, DH_anon, AES_128_GCM, SHA256),
382 CIPHER_SUITE(TLS, DH_anon, AES_256_GCM, SHA384),
384 CIPHER_SUITE(TLS, PSK, AES_128_GCM, SHA256),
385 CIPHER_SUITE(TLS, PSK, AES_256_GCM, SHA384),
386 CIPHER_SUITE(TLS, DHE_PSK, AES_128_GCM, SHA256),
387 CIPHER_SUITE(TLS, DHE_PSK, AES_256_GCM, SHA384),
388 CIPHER_SUITE(TLS, RSA_PSK, AES_128_GCM, SHA256),
389 CIPHER_SUITE(TLS, RSA_PSK, AES_256_GCM, SHA384),
390 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA256),
391 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA384),
392 CIPHER_SUITE(TLS, PSK, NULL, SHA256),
393 CIPHER_SUITE(TLS, PSK, NULL, SHA384),
394 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA256),
395 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA384),
396 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA256),
397 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA384),
398 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA256),
399 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA384),
400 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA256),
401 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA384),
403 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA256),
404 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA384),
405 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA256),
406 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA384),
407 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA256),
408 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA384),
409 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA256),
410 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA384),
411 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_GCM, SHA256),
412 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_GCM, SHA384),
413 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_GCM, SHA256),
414 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_GCM, SHA384),
415 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_GCM, SHA256),
416 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_GCM, SHA384),
417 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_GCM, SHA256),
418 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_GCM, SHA384),
420 CIPHER_SUITE(SSL, RSA, RC2_CBC, MD5),
421 CIPHER_SUITE(SSL, RSA, IDEA_CBC, MD5),
422 CIPHER_SUITE(SSL, RSA, DES_CBC, MD5),
423 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, MD5),
424 #undef CIPHER_SUITE
428 static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
430 int i;
431 for (i = 0; i < sizeof(cipher_suites)/sizeof(cipher_suites[0]); i++)
433 if (cipher_suites[i].suite == cipher_suite)
434 return &cipher_suites[i];
437 return NULL;
441 static DWORD schan_get_session_protocol(struct mac_session* s)
443 SSLProtocol protocol;
444 int status;
446 TRACE("(%p/%p)\n", s, s->context);
448 status = SSLGetNegotiatedProtocolVersion(s->context, &protocol);
449 if (status != noErr)
451 ERR("Failed to get session protocol: %d\n", status);
452 return 0;
455 TRACE("protocol %d\n", protocol);
457 switch (protocol)
459 case kSSLProtocol2: return SP_PROT_SSL2_CLIENT;
460 case kSSLProtocol3: return SP_PROT_SSL3_CLIENT;
461 case kTLSProtocol1: return SP_PROT_TLS1_CLIENT;
462 case kTLSProtocol11: return SP_PROT_TLS1_1_CLIENT;
463 case kTLSProtocol12: return SP_PROT_TLS1_2_CLIENT;
464 default:
465 FIXME("unknown protocol %d\n", protocol);
466 return 0;
470 static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
472 TRACE("(%#x)\n", (unsigned int)c->suite);
474 switch (c->enc_alg)
476 case schan_enc_3DES_EDE_CBC: return CALG_3DES;
477 case schan_enc_AES_128_CBC: return CALG_AES_128;
478 case schan_enc_AES_256_CBC: return CALG_AES_256;
479 case schan_enc_DES_CBC: return CALG_DES;
480 case schan_enc_DES40_CBC: return CALG_DES;
481 case schan_enc_NULL: return 0;
482 case schan_enc_RC2_CBC_40: return CALG_RC2;
483 case schan_enc_RC2_CBC: return CALG_RC2;
484 case schan_enc_RC4_128: return CALG_RC4;
485 case schan_enc_RC4_40: return CALG_RC4;
487 case schan_enc_AES_128_GCM:
488 case schan_enc_AES_256_GCM:
489 case schan_enc_FORTEZZA_CBC:
490 case schan_enc_IDEA_CBC:
491 FIXME("Don't know CALG for encryption algorithm %d, returning 0\n", c->enc_alg);
492 return 0;
494 default:
495 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
496 return 0;
500 static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
502 TRACE("(%#x)\n", (unsigned int)c->suite);
504 switch (c->enc_alg)
506 case schan_enc_3DES_EDE_CBC: return 168;
507 case schan_enc_AES_128_CBC: return 128;
508 case schan_enc_AES_128_GCM: return 128;
509 case schan_enc_AES_256_CBC: return 256;
510 case schan_enc_AES_256_GCM: return 256;
511 case schan_enc_DES_CBC: return 56;
512 case schan_enc_DES40_CBC: return 40;
513 case schan_enc_NULL: return 0;
514 case schan_enc_RC2_CBC_40: return 40;
515 case schan_enc_RC2_CBC: return 128;
516 case schan_enc_RC4_128: return 128;
517 case schan_enc_RC4_40: return 40;
519 case schan_enc_FORTEZZA_CBC:
520 case schan_enc_IDEA_CBC:
521 FIXME("Don't know key size for encryption algorithm %d, returning 0\n", c->enc_alg);
522 return 0;
524 default:
525 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
526 return 0;
530 static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
532 TRACE("(%#x)\n", (unsigned int)c->suite);
534 switch (c->mac_alg)
536 case schan_mac_MD5: return CALG_MD5;
537 case schan_mac_NULL: return 0;
538 case schan_mac_SHA: return CALG_SHA;
539 case schan_mac_SHA256: return CALG_SHA_256;
540 case schan_mac_SHA384: return CALG_SHA_384;
542 default:
543 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
544 return 0;
548 static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
550 TRACE("(%#x)\n", (unsigned int)c->suite);
552 switch (c->mac_alg)
554 case schan_mac_MD5: return 128;
555 case schan_mac_NULL: return 0;
556 case schan_mac_SHA: return 160;
557 case schan_mac_SHA256: return 256;
558 case schan_mac_SHA384: return 384;
560 default:
561 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
562 return 0;
566 static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
568 TRACE("(%#x)\n", (unsigned int)c->suite);
570 switch (c->kx_alg)
572 case schan_kx_DHE_DSS_EXPORT:
573 case schan_kx_DHE_DSS:
574 case schan_kx_DHE_PSK:
575 case schan_kx_DHE_RSA_EXPORT:
576 case schan_kx_DHE_RSA: return CALG_DH_EPHEM;
577 case schan_kx_ECDH_anon:
578 case schan_kx_ECDH_ECDSA:
579 case schan_kx_ECDH_RSA: return CALG_ECDH;
580 case schan_kx_ECDHE_ECDSA:
581 case schan_kx_ECDHE_RSA: return CALG_ECDH_EPHEM;
582 case schan_kx_NULL: return 0;
583 case schan_kx_RSA:
584 case schan_kx_RSA_EXPORT:
585 case schan_kx_RSA_PSK: return CALG_RSA_KEYX;
587 case schan_kx_DH_anon_EXPORT:
588 case schan_kx_DH_anon:
589 case schan_kx_DH_DSS_EXPORT:
590 case schan_kx_DH_DSS:
591 case schan_kx_DH_RSA_EXPORT:
592 case schan_kx_DH_RSA:
593 case schan_kx_FORTEZZA_DMS:
594 case schan_kx_PSK:
595 FIXME("Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
596 return 0;
598 default:
599 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
600 return 0;
605 /* schan_pull_adapter
606 * Callback registered with SSLSetIOFuncs as the read function for a
607 * session. Reads data from the session connection. Conforms to the
608 * SSLReadFunc type.
610 * transport - The session connection
611 * buff - The buffer into which to store the read data. Must be at least
612 * *buff_len bytes in length.
613 * *buff_len - On input, the desired length to read. On successful return,
614 * the number of bytes actually read.
616 * Returns:
617 * noErr on complete success meaning the requested length was successfully
618 * read.
619 * errSSLWouldBlock when the requested length could not be read without
620 * blocking. *buff_len indicates how much was actually read. The
621 * caller should try again if/when they want to read more.
622 * errSSLClosedGraceful when the connection has closed and there's no
623 * more data to be read.
624 * other error code for failure.
626 static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
627 SIZE_T *buff_len)
629 struct mac_session *s = (struct mac_session*)transport;
630 size_t requested = *buff_len;
631 int status;
632 OSStatus ret;
634 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
636 status = schan_pull(s->transport, buff, buff_len);
637 if (status == 0)
639 if (*buff_len == 0)
641 TRACE("Connection closed\n");
642 ret = errSSLClosedGraceful;
644 else if (*buff_len < requested)
646 TRACE("Pulled %lu bytes before would block\n", *buff_len);
647 ret = errSSLWouldBlock;
649 else
651 TRACE("Pulled %lu bytes\n", *buff_len);
652 ret = noErr;
655 else if (status == EAGAIN)
657 TRACE("Would block before being able to pull anything\n");
658 ret = errSSLWouldBlock;
660 else
662 FIXME("Unknown status code from schan_pull: %d\n", status);
663 ret = ioErr;
666 return ret;
669 /* schan_push_adapter
670 * Callback registered with SSLSetIOFuncs as the write function for a
671 * session. Writes data to the session connection. Conforms to the
672 * SSLWriteFunc type.
674 * transport - The session connection
675 * buff - The buffer of data to write. Must be at least *buff_len bytes in length.
676 * *buff_len - On input, the desired length to write. On successful return,
677 * the number of bytes actually written.
679 * Returns:
680 * noErr on complete or partial success; *buff_len indicates how much data
681 * was actually written, which may be less than requested.
682 * errSSLWouldBlock when no data could be written without blocking. The
683 * caller should try again.
684 * other error code for failure.
686 static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
687 SIZE_T *buff_len)
689 struct mac_session *s = (struct mac_session*)transport;
690 int status;
691 OSStatus ret;
693 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
695 status = schan_push(s->transport, buff, buff_len);
696 if (status == 0)
698 TRACE("Pushed %lu bytes\n", *buff_len);
699 ret = noErr;
701 else if (status == EAGAIN)
703 TRACE("Would block before being able to push anything\n");
704 ret = errSSLWouldBlock;
706 else
708 FIXME("Unknown status code from schan_push: %d\n", status);
709 ret = ioErr;
712 return ret;
715 static const struct {
716 DWORD enable_flag;
717 SSLProtocol mac_version;
718 } protocol_priority_flags[] = {
719 {SP_PROT_TLS1_2_CLIENT, kTLSProtocol12},
720 {SP_PROT_TLS1_1_CLIENT, kTLSProtocol11},
721 {SP_PROT_TLS1_0_CLIENT, kTLSProtocol1},
722 {SP_PROT_SSL3_CLIENT, kSSLProtocol3},
723 {SP_PROT_SSL2_CLIENT, kSSLProtocol2}
726 static DWORD supported_protocols;
728 DWORD schan_imp_enabled_protocols(void)
730 return supported_protocols;
733 BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
735 struct mac_session *s;
736 unsigned i;
737 int status;
739 TRACE("(%p)\n", session);
741 s = HeapAlloc(GetProcessHeap(), 0, sizeof(*s));
742 if (!s)
743 return FALSE;
745 status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
746 if (status != noErr)
748 ERR("Failed to create session context: %d\n", status);
749 goto fail;
752 status = SSLSetConnection(s->context, s);
753 if (status != noErr)
755 ERR("Failed to set session connection: %d\n", status);
756 goto fail;
759 status = SSLSetEnableCertVerify(s->context, FALSE);
760 if (status != noErr)
762 ERR("Failed to disable certificate verification: %d\n", status);
763 goto fail;
766 for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) {
767 if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
768 continue;
770 status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
771 (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
772 if (status != noErr)
774 ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status);
775 goto fail;
779 status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
780 if (status != noErr)
782 ERR("Failed to set session I/O funcs: %d\n", status);
783 goto fail;
786 TRACE(" -> %p/%p\n", s, s->context);
788 *session = (schan_imp_session)s;
789 return TRUE;
791 fail:
792 HeapFree(GetProcessHeap(), 0, s);
793 return FALSE;
796 void schan_imp_dispose_session(schan_imp_session session)
798 struct mac_session *s = (struct mac_session*)session;
799 int status;
801 TRACE("(%p/%p)\n", s, s->context);
803 status = SSLDisposeContext(s->context);
804 if (status != noErr)
805 ERR("Failed to dispose of session context: %d\n", status);
806 HeapFree(GetProcessHeap(), 0, s);
809 void schan_imp_set_session_transport(schan_imp_session session,
810 struct schan_transport *t)
812 struct mac_session *s = (struct mac_session*)session;
814 TRACE("(%p/%p, %p)\n", s, s->context, t);
816 s->transport = t;
819 void schan_imp_set_session_target(schan_imp_session session, const char *target)
821 struct mac_session *s = (struct mac_session*)session;
823 TRACE("(%p/%p, %s)\n", s, s->context, debugstr_a(target));
825 SSLSetPeerDomainName( s->context, target, strlen(target) );
828 SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
830 struct mac_session *s = (struct mac_session*)session;
831 int status;
833 TRACE("(%p/%p)\n", s, s->context);
835 status = SSLHandshake(s->context);
836 if (status == noErr)
838 TRACE("Handshake completed\n");
839 return SEC_E_OK;
841 else if (status == errSSLWouldBlock)
843 TRACE("Continue...\n");
844 return SEC_I_CONTINUE_NEEDED;
846 else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
848 ERR("Handshake failed: %s\n", strerror(status));
849 return SEC_E_INTERNAL_ERROR;
851 else
853 ERR("Handshake failed: %d\n", status);
854 cssmPerror("SSLHandshake", status);
855 return SEC_E_INTERNAL_ERROR;
858 /* Never reached */
859 return SEC_E_OK;
862 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
864 struct mac_session* s = (struct mac_session*)session;
865 SSLCipherSuite cipherSuite;
866 const struct cipher_suite* c;
867 int status;
869 TRACE("(%p/%p)\n", s, s->context);
871 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
872 if (status != noErr)
874 ERR("Failed to get session cipher suite: %d\n", status);
875 return 0;
878 c = get_cipher_suite(cipherSuite);
879 if (!c)
881 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
882 return 0;
885 switch (c->enc_alg)
887 case schan_enc_3DES_EDE_CBC: return 64;
888 case schan_enc_AES_128_CBC: return 128;
889 case schan_enc_AES_128_GCM: return 128;
890 case schan_enc_AES_256_CBC: return 128;
891 case schan_enc_AES_256_GCM: return 128;
892 case schan_enc_DES_CBC: return 64;
893 case schan_enc_DES40_CBC: return 64;
894 case schan_enc_NULL: return 0;
895 case schan_enc_RC2_CBC_40: return 64;
896 case schan_enc_RC2_CBC: return 64;
897 case schan_enc_RC4_128: return 0;
898 case schan_enc_RC4_40: return 0;
900 case schan_enc_FORTEZZA_CBC:
901 case schan_enc_IDEA_CBC:
902 FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
903 return 0;
905 default:
906 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
907 return 0;
911 unsigned int schan_imp_get_max_message_size(schan_imp_session session)
913 FIXME("Returning 1 << 14.\n");
914 return 1 << 14;
917 ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
919 struct mac_session* s = (struct mac_session*)session;
920 SSLCipherSuite cipherSuite;
921 const struct cipher_suite* c;
922 int status;
924 TRACE("(%p/%p)\n", s, s->context);
926 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
927 if (status != noErr)
929 ERR("Failed to get session cipher suite: %d\n", status);
930 return 0;
933 c = get_cipher_suite(cipherSuite);
934 if (!c)
936 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
937 return 0;
940 switch (c->kx_alg)
942 case schan_kx_DH_DSS_EXPORT:
943 case schan_kx_DH_DSS:
944 case schan_kx_DHE_DSS_EXPORT:
945 case schan_kx_DHE_DSS:
946 return CALG_DSS_SIGN;
948 case schan_kx_DH_RSA_EXPORT:
949 case schan_kx_DH_RSA:
950 case schan_kx_DHE_RSA_EXPORT:
951 case schan_kx_DHE_RSA:
952 case schan_kx_ECDH_RSA:
953 case schan_kx_ECDHE_RSA:
954 case schan_kx_RSA_EXPORT:
955 case schan_kx_RSA:
956 return CALG_RSA_SIGN;
958 case schan_kx_ECDH_ECDSA:
959 case schan_kx_ECDHE_ECDSA:
960 return CALG_ECDSA;
962 case schan_kx_DH_anon_EXPORT:
963 case schan_kx_DH_anon:
964 case schan_kx_DHE_PSK:
965 case schan_kx_ECDH_anon:
966 case schan_kx_FORTEZZA_DMS:
967 case schan_kx_NULL:
968 case schan_kx_PSK:
969 case schan_kx_RSA_PSK:
970 FIXME("Don't know key signature algorithm for key exchange algorithm %d, returning 0\n", c->kx_alg);
971 return 0;
973 default:
974 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned int)c->suite);
975 return 0;
979 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
980 SecPkgContext_ConnectionInfo *info)
982 struct mac_session* s = (struct mac_session*)session;
983 SSLCipherSuite cipherSuite;
984 const struct cipher_suite* c;
985 int status;
987 TRACE("(%p/%p, %p)\n", s, s->context, info);
989 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
990 if (status != noErr)
992 ERR("Failed to get session cipher suite: %d\n", status);
993 return SEC_E_INTERNAL_ERROR;
996 c = get_cipher_suite(cipherSuite);
997 if (!c)
999 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
1000 return SEC_E_INTERNAL_ERROR;
1003 info->dwProtocol = schan_get_session_protocol(s);
1004 info->aiCipher = schan_get_cipher_algid(c);
1005 info->dwCipherStrength = schan_get_cipher_key_size(c);
1006 info->aiHash = schan_get_mac_algid(c);
1007 info->dwHashStrength = schan_get_mac_key_size(c);
1008 info->aiExch = schan_get_kx_algid(c);
1009 /* FIXME: info->dwExchStrength? */
1010 info->dwExchStrength = 0;
1012 return SEC_E_OK;
1015 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1016 static void schan_imp_cf_release(const void *arg, void *ctx)
1018 CFRelease(arg);
1020 #endif
1022 SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
1023 PCCERT_CONTEXT *ret_cert)
1025 struct mac_session* s = (struct mac_session*)session;
1026 SECURITY_STATUS ret = SEC_E_OK;
1027 PCCERT_CONTEXT cert = NULL;
1028 SecCertificateRef mac_cert;
1029 CFArrayRef cert_array;
1030 int status;
1031 CFIndex cnt, i;
1032 CFDataRef data;
1033 BOOL res;
1035 TRACE("(%p/%p, %p)\n", s, s->context, cert);
1037 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
1038 status = SSLCopyPeerCertificates(s->context, &cert_array);
1039 #else
1040 status = SSLGetPeerCertificates(s->context, &cert_array);
1041 #endif
1042 if (status != noErr || !cert_array)
1044 WARN("SSLCopyPeerCertificates failed: %d\n", status);
1045 return SEC_E_INTERNAL_ERROR;
1048 cnt = CFArrayGetCount(cert_array);
1049 for (i=0; i < cnt; i++) {
1050 if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
1051 (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
1053 WARN("Couldn't extract certificate data\n");
1054 ret = SEC_E_INTERNAL_ERROR;
1055 break;
1058 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
1059 CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
1060 CFRelease(data);
1061 if (!res)
1063 ret = GetLastError();
1064 WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
1065 break;
1069 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1070 /* This is why SSLGetPeerCertificates was deprecated */
1071 CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
1072 schan_imp_cf_release, NULL);
1073 #endif
1074 CFRelease(cert_array);
1075 if (ret != SEC_E_OK) {
1076 if(cert)
1077 CertFreeCertificateContext(cert);
1078 return ret;
1081 *ret_cert = cert;
1082 return SEC_E_OK;
1085 SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
1086 SIZE_T *length)
1088 struct mac_session* s = (struct mac_session*)session;
1089 int status;
1091 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1093 status = SSLWrite(s->context, buffer, *length, length);
1094 if (status == noErr)
1095 TRACE("Wrote %lu bytes\n", *length);
1096 else if (status == errSSLWouldBlock)
1098 if (!*length)
1100 TRACE("Would block before being able to write anything\n");
1101 return SEC_I_CONTINUE_NEEDED;
1103 else
1104 TRACE("Wrote %lu bytes before would block\n", *length);
1106 else
1108 WARN("SSLWrite failed: %d\n", status);
1109 return SEC_E_INTERNAL_ERROR;
1112 return SEC_E_OK;
1115 SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
1116 SIZE_T *length)
1118 struct mac_session* s = (struct mac_session*)session;
1119 int status;
1121 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1123 status = SSLRead(s->context, buffer, *length, length);
1124 if (status == noErr || status == errSSLClosedGraceful)
1125 TRACE("Read %lu bytes\n", *length);
1126 else if (status == errSSLWouldBlock)
1128 if (!*length)
1130 TRACE("Would block before being able to read anything\n");
1131 return SEC_I_CONTINUE_NEEDED;
1133 else
1134 TRACE("Read %lu bytes before would block\n", *length);
1136 else
1138 WARN("SSLRead failed: %d\n", status);
1139 return SEC_E_INTERNAL_ERROR;
1142 return SEC_E_OK;
1145 BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c)
1147 /* The certificate is never really used for anything. */
1148 c->credentials = NULL;
1149 return TRUE;
1152 void schan_imp_free_certificate_credentials(schan_credentials *c)
1156 BOOL schan_imp_init(void)
1158 TRACE("()\n");
1160 supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
1162 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1163 if(SSLGetProtocolVersionMax != NULL) {
1164 SSLProtocol max_protocol;
1165 SSLContextRef ctx;
1166 OSStatus status;
1168 status = SSLNewContext(FALSE, &ctx);
1169 if(status == noErr) {
1170 status = SSLGetProtocolVersionMax(ctx, &max_protocol);
1171 if(status == noErr) {
1172 if(max_protocol >= kTLSProtocol11)
1173 supported_protocols |= SP_PROT_TLS1_1_CLIENT;
1174 if(max_protocol >= kTLSProtocol12)
1175 supported_protocols |= SP_PROT_TLS1_2_CLIENT;
1177 SSLDisposeContext(ctx);
1178 }else {
1179 WARN("SSLNewContext failed\n");
1182 #endif
1184 return TRUE;
1187 void schan_imp_deinit(void)
1189 TRACE("()\n");
1192 #endif /* HAVE_SECURITY_SECURITY_H */