msvcrt/tests: Remove strcmp_space helper.
[wine.git] / dlls / secur32 / schannel_macosx.c
blobab97615014d97fbd0483f7bd355c2786729e7538
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 #endif
35 #include "windef.h"
36 #include "winbase.h"
37 #include "sspi.h"
38 #include "schannel.h"
39 #include "secur32_priv.h"
40 #include "wine/debug.h"
42 #ifdef HAVE_SECURITY_SECURITY_H
44 WINE_DEFAULT_DEBUG_CHANNEL(secur32);
46 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
47 /* Defined in <Security/CipherSuite.h> in the 10.6 SDK or later. */
48 enum {
49 TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001,
50 TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002,
51 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003,
52 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004,
53 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005,
54 TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006,
55 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007,
56 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008,
57 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009,
58 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A,
59 TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B,
60 TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C,
61 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D,
62 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E,
63 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F,
64 TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010,
65 TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011,
66 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012,
67 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013,
68 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014,
69 TLS_ECDH_anon_WITH_NULL_SHA = 0xC015,
70 TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016,
71 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017,
72 TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018,
73 TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019,
75 #endif
77 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1080
78 /* Defined in <Security/CipherSuite.h> in the 10.8 SDK or later. */
79 enum {
80 TLS_NULL_WITH_NULL_NULL = 0x0000,
81 TLS_RSA_WITH_NULL_MD5 = 0x0001,
82 TLS_RSA_WITH_NULL_SHA = 0x0002,
83 TLS_RSA_WITH_RC4_128_MD5 = 0x0004,
84 TLS_RSA_WITH_RC4_128_SHA = 0x0005,
85 TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A,
86 TLS_RSA_WITH_NULL_SHA256 = 0x003B,
87 TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C,
88 TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D,
89 TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D,
90 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010,
91 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013,
92 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016,
93 TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E,
94 TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F,
95 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040,
96 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067,
97 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068,
98 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069,
99 TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A,
100 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B,
101 TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018,
102 TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B,
103 TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C,
104 TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D,
105 TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C,
106 TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D,
107 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E,
108 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F,
109 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0,
110 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1,
111 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2,
112 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3,
113 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4,
114 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5,
115 TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6,
116 TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7,
117 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023,
118 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024,
119 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025,
120 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026,
121 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027,
122 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028,
123 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029,
124 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A,
125 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,
126 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C,
127 TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D,
128 TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E,
129 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F,
130 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030,
131 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031,
132 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032,
133 TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF,
136 /* Defined in <Security/SecureTransport.h> in the 10.8 SDK or later. */
137 enum {
138 kTLSProtocol11 = 7, /* TLS 1.1 */
139 kTLSProtocol12 = 8, /* TLS 1.2 */
141 #endif
143 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1090
144 /* Defined in <Security/CipherSuite.h> in the 10.9 SDK or later. */
145 enum {
146 TLS_PSK_WITH_RC4_128_SHA = 0x008A,
147 TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B,
148 TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C,
149 TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D,
150 TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E,
151 TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F,
152 TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090,
153 TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091,
154 TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092,
155 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093,
156 TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094,
157 TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095,
158 TLS_PSK_WITH_NULL_SHA = 0x002C,
159 TLS_DHE_PSK_WITH_NULL_SHA = 0x002D,
160 TLS_RSA_PSK_WITH_NULL_SHA = 0x002E,
161 TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8,
162 TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9,
163 TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA,
164 TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB,
165 TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC,
166 TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD,
167 TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE,
168 TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF,
169 TLS_PSK_WITH_NULL_SHA256 = 0x00B0,
170 TLS_PSK_WITH_NULL_SHA384 = 0x00B1,
171 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2,
172 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3,
173 TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4,
174 TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5,
175 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6,
176 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7,
177 TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8,
178 TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9,
180 #endif
182 enum schan_mode {
183 schan_mode_NONE,
184 schan_mode_READ,
185 schan_mode_WRITE,
186 schan_mode_HANDSHAKE,
189 struct mac_session {
190 SSLContextRef context;
191 struct schan_transport *transport;
192 enum schan_mode mode;
193 CRITICAL_SECTION cs;
197 enum {
198 schan_proto_SSL,
199 schan_proto_TLS,
202 enum {
203 schan_kx_DH_anon_EXPORT,
204 schan_kx_DH_anon,
205 schan_kx_DH_DSS_EXPORT,
206 schan_kx_DH_DSS,
207 schan_kx_DH_RSA_EXPORT,
208 schan_kx_DH_RSA,
209 schan_kx_DHE_DSS_EXPORT,
210 schan_kx_DHE_DSS,
211 schan_kx_DHE_PSK,
212 schan_kx_DHE_RSA_EXPORT,
213 schan_kx_DHE_RSA,
214 schan_kx_ECDH_anon,
215 schan_kx_ECDH_ECDSA,
216 schan_kx_ECDH_RSA,
217 schan_kx_ECDHE_ECDSA,
218 schan_kx_ECDHE_RSA,
219 schan_kx_FORTEZZA_DMS,
220 schan_kx_NULL,
221 schan_kx_PSK,
222 schan_kx_RSA_EXPORT,
223 schan_kx_RSA_PSK,
224 schan_kx_RSA,
227 enum {
228 schan_enc_3DES_EDE_CBC,
229 schan_enc_AES_128_CBC,
230 schan_enc_AES_128_GCM,
231 schan_enc_AES_256_CBC,
232 schan_enc_AES_256_GCM,
233 schan_enc_DES_CBC,
234 schan_enc_DES40_CBC,
235 schan_enc_FORTEZZA_CBC,
236 schan_enc_IDEA_CBC,
237 schan_enc_NULL,
238 schan_enc_RC2_CBC,
239 schan_enc_RC2_CBC_40,
240 schan_enc_RC4_128,
241 schan_enc_RC4_40,
244 enum {
245 schan_mac_MD5,
246 schan_mac_NULL,
247 schan_mac_SHA,
248 schan_mac_SHA256,
249 schan_mac_SHA384,
253 struct cipher_suite {
254 SSLCipherSuite suite;
255 int protocol;
256 int kx_alg;
257 int enc_alg;
258 int mac_alg;
261 /* This table corresponds to the enum in <Security/CipherSuite.h>. */
262 static const struct cipher_suite cipher_suites[] = {
263 #define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
264 schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
265 CIPHER_SUITE(SSL, RSA, NULL, MD5),
266 CIPHER_SUITE(SSL, RSA, NULL, MD5),
267 CIPHER_SUITE(SSL, RSA, NULL, SHA),
268 CIPHER_SUITE(SSL, RSA_EXPORT, RC4_40, MD5),
269 CIPHER_SUITE(SSL, RSA, RC4_128, MD5),
270 CIPHER_SUITE(SSL, RSA, RC4_128, SHA),
271 CIPHER_SUITE(SSL, RSA_EXPORT, RC2_CBC_40, MD5),
272 CIPHER_SUITE(SSL, RSA, IDEA_CBC, SHA),
273 CIPHER_SUITE(SSL, RSA_EXPORT, DES40_CBC, SHA),
274 CIPHER_SUITE(SSL, RSA, DES_CBC, SHA),
275 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, SHA),
276 CIPHER_SUITE(SSL, DH_DSS_EXPORT, DES40_CBC, SHA),
277 CIPHER_SUITE(SSL, DH_DSS, DES_CBC, SHA),
278 CIPHER_SUITE(SSL, DH_DSS, 3DES_EDE_CBC, SHA),
279 CIPHER_SUITE(SSL, DH_RSA_EXPORT, DES40_CBC, SHA),
280 CIPHER_SUITE(SSL, DH_RSA, DES_CBC, SHA),
281 CIPHER_SUITE(SSL, DH_RSA, 3DES_EDE_CBC, SHA),
282 CIPHER_SUITE(SSL, DHE_DSS_EXPORT, DES40_CBC, SHA),
283 CIPHER_SUITE(SSL, DHE_DSS, DES_CBC, SHA),
284 CIPHER_SUITE(SSL, DHE_DSS, 3DES_EDE_CBC, SHA),
285 CIPHER_SUITE(SSL, DHE_RSA_EXPORT, DES40_CBC, SHA),
286 CIPHER_SUITE(SSL, DHE_RSA, DES_CBC, SHA),
287 CIPHER_SUITE(SSL, DHE_RSA, 3DES_EDE_CBC, SHA),
288 CIPHER_SUITE(SSL, DH_anon_EXPORT, RC4_40, MD5),
289 CIPHER_SUITE(SSL, DH_anon, RC4_128, MD5),
290 CIPHER_SUITE(SSL, DH_anon_EXPORT, DES40_CBC, SHA),
291 CIPHER_SUITE(SSL, DH_anon, DES_CBC, SHA),
292 CIPHER_SUITE(SSL, DH_anon, 3DES_EDE_CBC, SHA),
293 CIPHER_SUITE(SSL, FORTEZZA_DMS, NULL, SHA),
294 CIPHER_SUITE(SSL, FORTEZZA_DMS, FORTEZZA_CBC, SHA),
296 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA),
297 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA),
298 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA),
299 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA),
300 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA),
301 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA),
302 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA),
303 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA),
304 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA),
305 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA),
306 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA),
307 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA),
309 CIPHER_SUITE(TLS, ECDH_ECDSA, NULL, SHA),
310 CIPHER_SUITE(TLS, ECDH_ECDSA, RC4_128, SHA),
311 CIPHER_SUITE(TLS, ECDH_ECDSA, 3DES_EDE_CBC, SHA),
312 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA),
313 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA),
314 CIPHER_SUITE(TLS, ECDHE_ECDSA, NULL, SHA),
315 CIPHER_SUITE(TLS, ECDHE_ECDSA, RC4_128, SHA),
316 CIPHER_SUITE(TLS, ECDHE_ECDSA, 3DES_EDE_CBC, SHA),
317 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA),
318 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA),
319 CIPHER_SUITE(TLS, ECDH_RSA, NULL, SHA),
320 CIPHER_SUITE(TLS, ECDH_RSA, RC4_128, SHA),
321 CIPHER_SUITE(TLS, ECDH_RSA, 3DES_EDE_CBC, SHA),
322 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA),
323 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA),
324 CIPHER_SUITE(TLS, ECDHE_RSA, NULL, SHA),
325 CIPHER_SUITE(TLS, ECDHE_RSA, RC4_128, SHA),
326 CIPHER_SUITE(TLS, ECDHE_RSA, 3DES_EDE_CBC, SHA),
327 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA),
328 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA),
329 CIPHER_SUITE(TLS, ECDH_anon, NULL, SHA),
330 CIPHER_SUITE(TLS, ECDH_anon, RC4_128, SHA),
331 CIPHER_SUITE(TLS, ECDH_anon, 3DES_EDE_CBC, SHA),
332 CIPHER_SUITE(TLS, ECDH_anon, AES_128_CBC, SHA),
333 CIPHER_SUITE(TLS, ECDH_anon, AES_256_CBC, SHA),
335 CIPHER_SUITE(TLS, NULL, NULL, NULL),
336 CIPHER_SUITE(TLS, RSA, NULL, MD5),
337 CIPHER_SUITE(TLS, RSA, NULL, SHA),
338 CIPHER_SUITE(TLS, RSA, RC4_128, MD5),
339 CIPHER_SUITE(TLS, RSA, RC4_128, SHA),
340 CIPHER_SUITE(TLS, RSA, 3DES_EDE_CBC, SHA),
341 CIPHER_SUITE(TLS, RSA, NULL, SHA256),
342 CIPHER_SUITE(TLS, RSA, AES_128_CBC, SHA256),
343 CIPHER_SUITE(TLS, RSA, AES_256_CBC, SHA256),
344 CIPHER_SUITE(TLS, DH_DSS, 3DES_EDE_CBC, SHA),
345 CIPHER_SUITE(TLS, DH_RSA, 3DES_EDE_CBC, SHA),
346 CIPHER_SUITE(TLS, DHE_DSS, 3DES_EDE_CBC, SHA),
347 CIPHER_SUITE(TLS, DHE_RSA, 3DES_EDE_CBC, SHA),
348 CIPHER_SUITE(TLS, DH_DSS, AES_128_CBC, SHA256),
349 CIPHER_SUITE(TLS, DH_RSA, AES_128_CBC, SHA256),
350 CIPHER_SUITE(TLS, DHE_DSS, AES_128_CBC, SHA256),
351 CIPHER_SUITE(TLS, DHE_RSA, AES_128_CBC, SHA256),
352 CIPHER_SUITE(TLS, DH_DSS, AES_256_CBC, SHA256),
353 CIPHER_SUITE(TLS, DH_RSA, AES_256_CBC, SHA256),
354 CIPHER_SUITE(TLS, DHE_DSS, AES_256_CBC, SHA256),
355 CIPHER_SUITE(TLS, DHE_RSA, AES_256_CBC, SHA256),
356 CIPHER_SUITE(TLS, DH_anon, RC4_128, MD5),
357 CIPHER_SUITE(TLS, DH_anon, 3DES_EDE_CBC, SHA),
358 CIPHER_SUITE(TLS, DH_anon, AES_128_CBC, SHA256),
359 CIPHER_SUITE(TLS, DH_anon, AES_256_CBC, SHA256),
361 CIPHER_SUITE(TLS, PSK, RC4_128, SHA),
362 CIPHER_SUITE(TLS, PSK, 3DES_EDE_CBC, SHA),
363 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA),
364 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA),
365 CIPHER_SUITE(TLS, DHE_PSK, RC4_128, SHA),
366 CIPHER_SUITE(TLS, DHE_PSK, 3DES_EDE_CBC, SHA),
367 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA),
368 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA),
369 CIPHER_SUITE(TLS, RSA_PSK, RC4_128, SHA),
370 CIPHER_SUITE(TLS, RSA_PSK, 3DES_EDE_CBC, SHA),
371 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA),
372 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA),
373 CIPHER_SUITE(TLS, PSK, NULL, SHA),
374 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA),
375 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA),
377 CIPHER_SUITE(TLS, RSA, AES_128_GCM, SHA256),
378 CIPHER_SUITE(TLS, RSA, AES_256_GCM, SHA384),
379 CIPHER_SUITE(TLS, DHE_RSA, AES_128_GCM, SHA256),
380 CIPHER_SUITE(TLS, DHE_RSA, AES_256_GCM, SHA384),
381 CIPHER_SUITE(TLS, DH_RSA, AES_128_GCM, SHA256),
382 CIPHER_SUITE(TLS, DH_RSA, AES_256_GCM, SHA384),
383 CIPHER_SUITE(TLS, DHE_DSS, AES_128_GCM, SHA256),
384 CIPHER_SUITE(TLS, DHE_DSS, AES_256_GCM, SHA384),
385 CIPHER_SUITE(TLS, DH_DSS, AES_128_GCM, SHA256),
386 CIPHER_SUITE(TLS, DH_DSS, AES_256_GCM, SHA384),
387 CIPHER_SUITE(TLS, DH_anon, AES_128_GCM, SHA256),
388 CIPHER_SUITE(TLS, DH_anon, AES_256_GCM, SHA384),
390 CIPHER_SUITE(TLS, PSK, AES_128_GCM, SHA256),
391 CIPHER_SUITE(TLS, PSK, AES_256_GCM, SHA384),
392 CIPHER_SUITE(TLS, DHE_PSK, AES_128_GCM, SHA256),
393 CIPHER_SUITE(TLS, DHE_PSK, AES_256_GCM, SHA384),
394 CIPHER_SUITE(TLS, RSA_PSK, AES_128_GCM, SHA256),
395 CIPHER_SUITE(TLS, RSA_PSK, AES_256_GCM, SHA384),
396 CIPHER_SUITE(TLS, PSK, AES_128_CBC, SHA256),
397 CIPHER_SUITE(TLS, PSK, AES_256_CBC, SHA384),
398 CIPHER_SUITE(TLS, PSK, NULL, SHA256),
399 CIPHER_SUITE(TLS, PSK, NULL, SHA384),
400 CIPHER_SUITE(TLS, DHE_PSK, AES_128_CBC, SHA256),
401 CIPHER_SUITE(TLS, DHE_PSK, AES_256_CBC, SHA384),
402 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA256),
403 CIPHER_SUITE(TLS, DHE_PSK, NULL, SHA384),
404 CIPHER_SUITE(TLS, RSA_PSK, AES_128_CBC, SHA256),
405 CIPHER_SUITE(TLS, RSA_PSK, AES_256_CBC, SHA384),
406 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA256),
407 CIPHER_SUITE(TLS, RSA_PSK, NULL, SHA384),
409 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_CBC, SHA256),
410 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_CBC, SHA384),
411 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_CBC, SHA256),
412 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_CBC, SHA384),
413 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_CBC, SHA256),
414 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_CBC, SHA384),
415 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_CBC, SHA256),
416 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_CBC, SHA384),
417 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_128_GCM, SHA256),
418 CIPHER_SUITE(TLS, ECDHE_ECDSA, AES_256_GCM, SHA384),
419 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_128_GCM, SHA256),
420 CIPHER_SUITE(TLS, ECDH_ECDSA, AES_256_GCM, SHA384),
421 CIPHER_SUITE(TLS, ECDHE_RSA, AES_128_GCM, SHA256),
422 CIPHER_SUITE(TLS, ECDHE_RSA, AES_256_GCM, SHA384),
423 CIPHER_SUITE(TLS, ECDH_RSA, AES_128_GCM, SHA256),
424 CIPHER_SUITE(TLS, ECDH_RSA, AES_256_GCM, SHA384),
426 CIPHER_SUITE(SSL, RSA, RC2_CBC, MD5),
427 CIPHER_SUITE(SSL, RSA, IDEA_CBC, MD5),
428 CIPHER_SUITE(SSL, RSA, DES_CBC, MD5),
429 CIPHER_SUITE(SSL, RSA, 3DES_EDE_CBC, MD5),
430 #undef CIPHER_SUITE
434 static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
436 int i;
437 for (i = 0; i < ARRAY_SIZE(cipher_suites); i++)
439 if (cipher_suites[i].suite == cipher_suite)
440 return &cipher_suites[i];
443 return NULL;
447 static DWORD schan_get_session_protocol(struct mac_session* s)
449 SSLProtocol protocol;
450 int status;
452 TRACE("(%p/%p)\n", s, s->context);
454 status = SSLGetNegotiatedProtocolVersion(s->context, &protocol);
455 if (status != noErr)
457 ERR("Failed to get session protocol: %d\n", status);
458 return 0;
461 TRACE("protocol %d\n", protocol);
463 switch (protocol)
465 case kSSLProtocol2: return SP_PROT_SSL2_CLIENT;
466 case kSSLProtocol3: return SP_PROT_SSL3_CLIENT;
467 case kTLSProtocol1: return SP_PROT_TLS1_CLIENT;
468 case kTLSProtocol11: return SP_PROT_TLS1_1_CLIENT;
469 case kTLSProtocol12: return SP_PROT_TLS1_2_CLIENT;
470 default:
471 FIXME("unknown protocol %d\n", protocol);
472 return 0;
476 static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
478 TRACE("(%#x)\n", (unsigned int)c->suite);
480 switch (c->enc_alg)
482 case schan_enc_3DES_EDE_CBC: return CALG_3DES;
483 case schan_enc_AES_128_CBC: return CALG_AES_128;
484 case schan_enc_AES_256_CBC: return CALG_AES_256;
485 case schan_enc_DES_CBC: return CALG_DES;
486 case schan_enc_DES40_CBC: return CALG_DES;
487 case schan_enc_NULL: return 0;
488 case schan_enc_RC2_CBC_40: return CALG_RC2;
489 case schan_enc_RC2_CBC: return CALG_RC2;
490 case schan_enc_RC4_128: return CALG_RC4;
491 case schan_enc_RC4_40: return CALG_RC4;
493 case schan_enc_AES_128_GCM:
494 case schan_enc_AES_256_GCM:
495 case schan_enc_FORTEZZA_CBC:
496 case schan_enc_IDEA_CBC:
497 FIXME("Don't know CALG for encryption algorithm %d, returning 0\n", c->enc_alg);
498 return 0;
500 default:
501 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
502 return 0;
506 static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
508 TRACE("(%#x)\n", (unsigned int)c->suite);
510 switch (c->enc_alg)
512 case schan_enc_3DES_EDE_CBC: return 168;
513 case schan_enc_AES_128_CBC: return 128;
514 case schan_enc_AES_128_GCM: return 128;
515 case schan_enc_AES_256_CBC: return 256;
516 case schan_enc_AES_256_GCM: return 256;
517 case schan_enc_DES_CBC: return 56;
518 case schan_enc_DES40_CBC: return 40;
519 case schan_enc_NULL: return 0;
520 case schan_enc_RC2_CBC_40: return 40;
521 case schan_enc_RC2_CBC: return 128;
522 case schan_enc_RC4_128: return 128;
523 case schan_enc_RC4_40: return 40;
525 case schan_enc_FORTEZZA_CBC:
526 case schan_enc_IDEA_CBC:
527 FIXME("Don't know key size for encryption algorithm %d, returning 0\n", c->enc_alg);
528 return 0;
530 default:
531 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
532 return 0;
536 static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
538 TRACE("(%#x)\n", (unsigned int)c->suite);
540 switch (c->mac_alg)
542 case schan_mac_MD5: return CALG_MD5;
543 case schan_mac_NULL: return 0;
544 case schan_mac_SHA: return CALG_SHA;
545 case schan_mac_SHA256: return CALG_SHA_256;
546 case schan_mac_SHA384: return CALG_SHA_384;
548 default:
549 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
550 return 0;
554 static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
556 TRACE("(%#x)\n", (unsigned int)c->suite);
558 switch (c->mac_alg)
560 case schan_mac_MD5: return 128;
561 case schan_mac_NULL: return 0;
562 case schan_mac_SHA: return 160;
563 case schan_mac_SHA256: return 256;
564 case schan_mac_SHA384: return 384;
566 default:
567 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c->mac_alg, (unsigned)c->suite);
568 return 0;
572 static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
574 TRACE("(%#x)\n", (unsigned int)c->suite);
576 switch (c->kx_alg)
578 case schan_kx_DHE_DSS_EXPORT:
579 case schan_kx_DHE_DSS:
580 case schan_kx_DHE_PSK:
581 case schan_kx_DHE_RSA_EXPORT:
582 case schan_kx_DHE_RSA: return CALG_DH_EPHEM;
583 case schan_kx_ECDH_anon:
584 case schan_kx_ECDH_ECDSA:
585 case schan_kx_ECDH_RSA: return CALG_ECDH;
586 case schan_kx_ECDHE_ECDSA:
587 case schan_kx_ECDHE_RSA: return CALG_ECDH_EPHEM;
588 case schan_kx_NULL: return 0;
589 case schan_kx_RSA:
590 case schan_kx_RSA_EXPORT:
591 case schan_kx_RSA_PSK: return CALG_RSA_KEYX;
593 case schan_kx_DH_anon_EXPORT:
594 case schan_kx_DH_anon:
595 case schan_kx_DH_DSS_EXPORT:
596 case schan_kx_DH_DSS:
597 case schan_kx_DH_RSA_EXPORT:
598 case schan_kx_DH_RSA:
599 case schan_kx_FORTEZZA_DMS:
600 case schan_kx_PSK:
601 FIXME("Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
602 return 0;
604 default:
605 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned)c->suite);
606 return 0;
611 /* schan_pull_adapter
612 * Callback registered with SSLSetIOFuncs as the read function for a
613 * session. Reads data from the session connection. Conforms to the
614 * SSLReadFunc type.
616 * transport - The session connection
617 * buff - The buffer into which to store the read data. Must be at least
618 * *buff_len bytes in length.
619 * *buff_len - On input, the desired length to read. On successful return,
620 * the number of bytes actually read.
622 * Returns:
623 * noErr on complete success meaning the requested length was successfully
624 * read.
625 * errSSLWouldBlock when the requested length could not be read without
626 * blocking. *buff_len indicates how much was actually read. The
627 * caller should try again if/when they want to read more.
628 * errSSLClosedGraceful when the connection has closed and there's no
629 * more data to be read.
630 * other error code for failure.
632 static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
633 SIZE_T *buff_len)
635 struct mac_session *s = (struct mac_session*)transport;
636 size_t requested = *buff_len;
637 int status;
638 OSStatus ret;
640 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
642 if (s->mode != schan_mode_READ && s->mode != schan_mode_HANDSHAKE)
644 WARN("called in mode %u\n", s->mode);
645 return noErr;
648 status = schan_pull(s->transport, buff, buff_len);
649 if (status == 0)
651 if (*buff_len == 0)
653 TRACE("Connection closed\n");
654 ret = errSSLClosedGraceful;
656 else if (*buff_len < requested)
658 TRACE("Pulled %lu bytes before would block\n", *buff_len);
659 ret = errSSLWouldBlock;
661 else
663 TRACE("Pulled %lu bytes\n", *buff_len);
664 ret = noErr;
667 else if (status == EAGAIN)
669 TRACE("Would block before being able to pull anything\n");
670 ret = errSSLWouldBlock;
672 else
674 FIXME("Unknown status code from schan_pull: %d\n", status);
675 ret = ioErr;
678 return ret;
681 /* schan_push_adapter
682 * Callback registered with SSLSetIOFuncs as the write function for a
683 * session. Writes data to the session connection. Conforms to the
684 * SSLWriteFunc type.
686 * transport - The session connection
687 * buff - The buffer of data to write. Must be at least *buff_len bytes in length.
688 * *buff_len - On input, the desired length to write. On successful return,
689 * the number of bytes actually written.
691 * Returns:
692 * noErr on complete or partial success; *buff_len indicates how much data
693 * was actually written, which may be less than requested.
694 * errSSLWouldBlock when no data could be written without blocking. The
695 * caller should try again.
696 * other error code for failure.
698 static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
699 SIZE_T *buff_len)
701 struct mac_session *s = (struct mac_session*)transport;
702 int status;
703 OSStatus ret;
705 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->transport, buff, buff_len, *buff_len);
707 if (s->mode != schan_mode_WRITE && s->mode != schan_mode_HANDSHAKE)
709 WARN("called in mode %u\n", s->mode);
710 return noErr;
713 status = schan_push(s->transport, buff, buff_len);
714 if (status == 0)
716 TRACE("Pushed %lu bytes\n", *buff_len);
717 ret = noErr;
719 else if (status == EAGAIN)
721 TRACE("Would block before being able to push anything\n");
722 ret = errSSLWouldBlock;
724 else
726 FIXME("Unknown status code from schan_push: %d\n", status);
727 ret = ioErr;
730 return ret;
733 static const struct {
734 DWORD enable_flag;
735 SSLProtocol mac_version;
736 } protocol_priority_flags[] = {
737 {SP_PROT_TLS1_2_CLIENT, kTLSProtocol12},
738 {SP_PROT_TLS1_1_CLIENT, kTLSProtocol11},
739 {SP_PROT_TLS1_0_CLIENT, kTLSProtocol1},
740 {SP_PROT_SSL3_CLIENT, kSSLProtocol3},
741 {SP_PROT_SSL2_CLIENT, kSSLProtocol2}
744 static DWORD supported_protocols;
746 DWORD schan_imp_enabled_protocols(void)
748 return supported_protocols;
751 BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
753 struct mac_session *s;
754 unsigned i;
755 int status;
757 TRACE("(%p)\n", session);
759 s = heap_alloc(sizeof(*s));
760 if (!s)
761 return FALSE;
763 InitializeCriticalSection(&s->cs);
764 s->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": mac_session.cs");
766 status = SSLNewContext(cred->credential_use == SECPKG_CRED_INBOUND, &s->context);
767 if (status != noErr)
769 ERR("Failed to create session context: %d\n", status);
770 goto fail;
773 status = SSLSetConnection(s->context, s);
774 if (status != noErr)
776 ERR("Failed to set session connection: %d\n", status);
777 goto fail;
780 status = SSLSetEnableCertVerify(s->context, FALSE);
781 if (status != noErr)
783 ERR("Failed to disable certificate verification: %d\n", status);
784 goto fail;
787 for(i = 0; i < ARRAY_SIZE(protocol_priority_flags); i++) {
788 if(!(protocol_priority_flags[i].enable_flag & supported_protocols))
789 continue;
791 status = SSLSetProtocolVersionEnabled(s->context, protocol_priority_flags[i].mac_version,
792 (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) != 0);
793 if (status != noErr)
795 ERR("Failed to set SSL version %d: %d\n", protocol_priority_flags[i].mac_version, status);
796 goto fail;
800 status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
801 if (status != noErr)
803 ERR("Failed to set session I/O funcs: %d\n", status);
804 goto fail;
807 s->mode = schan_mode_NONE;
809 TRACE(" -> %p/%p\n", s, s->context);
811 *session = (schan_imp_session)s;
812 return TRUE;
814 fail:
815 heap_free(s);
816 return FALSE;
819 void schan_imp_dispose_session(schan_imp_session session)
821 struct mac_session *s = (struct mac_session*)session;
822 int status;
824 TRACE("(%p/%p)\n", s, s->context);
826 status = SSLDisposeContext(s->context);
827 if (status != noErr)
828 ERR("Failed to dispose of session context: %d\n", status);
829 DeleteCriticalSection(&s->cs);
830 heap_free(s);
833 void schan_imp_set_session_transport(schan_imp_session session,
834 struct schan_transport *t)
836 struct mac_session *s = (struct mac_session*)session;
838 TRACE("(%p/%p, %p)\n", s, s->context, t);
840 s->transport = t;
843 void schan_imp_set_session_target(schan_imp_session session, const char *target)
845 struct mac_session *s = (struct mac_session*)session;
847 TRACE("(%p/%p, %s)\n", s, s->context, debugstr_a(target));
849 SSLSetPeerDomainName( s->context, target, strlen(target) );
852 SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
854 struct mac_session *s = (struct mac_session*)session;
855 int status;
857 TRACE("(%p/%p)\n", s, s->context);
859 s->mode = schan_mode_HANDSHAKE;
860 status = SSLHandshake(s->context);
861 s->mode = schan_mode_NONE;
863 if (status == noErr)
865 TRACE("Handshake completed\n");
866 return SEC_E_OK;
868 else if (status == errSSLWouldBlock)
870 TRACE("Continue...\n");
871 return SEC_I_CONTINUE_NEEDED;
873 else if (errSecErrnoBase <= status && status <= errSecErrnoLimit)
875 ERR("Handshake failed: %s\n", strerror(status));
876 return SEC_E_INTERNAL_ERROR;
878 else
880 ERR("Handshake failed: %d\n", status);
881 cssmPerror("SSLHandshake", status);
882 return SEC_E_INTERNAL_ERROR;
885 /* Never reached */
886 return SEC_E_OK;
889 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
891 struct mac_session* s = (struct mac_session*)session;
892 SSLCipherSuite cipherSuite;
893 const struct cipher_suite* c;
894 int status;
896 TRACE("(%p/%p)\n", s, s->context);
898 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
899 if (status != noErr)
901 ERR("Failed to get session cipher suite: %d\n", status);
902 return 0;
905 c = get_cipher_suite(cipherSuite);
906 if (!c)
908 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
909 return 0;
912 switch (c->enc_alg)
914 case schan_enc_3DES_EDE_CBC: return 64;
915 case schan_enc_AES_128_CBC: return 128;
916 case schan_enc_AES_128_GCM: return 128;
917 case schan_enc_AES_256_CBC: return 128;
918 case schan_enc_AES_256_GCM: return 128;
919 case schan_enc_DES_CBC: return 64;
920 case schan_enc_DES40_CBC: return 64;
921 case schan_enc_NULL: return 0;
922 case schan_enc_RC2_CBC_40: return 64;
923 case schan_enc_RC2_CBC: return 64;
924 case schan_enc_RC4_128: return 0;
925 case schan_enc_RC4_40: return 0;
927 case schan_enc_FORTEZZA_CBC:
928 case schan_enc_IDEA_CBC:
929 FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c->enc_alg);
930 return 0;
932 default:
933 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c->enc_alg, (unsigned int)c->suite);
934 return 0;
938 unsigned int schan_imp_get_max_message_size(schan_imp_session session)
940 FIXME("Returning 1 << 14.\n");
941 return 1 << 14;
944 ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
946 struct mac_session* s = (struct mac_session*)session;
947 SSLCipherSuite cipherSuite;
948 const struct cipher_suite* c;
949 int status;
951 TRACE("(%p/%p)\n", s, s->context);
953 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
954 if (status != noErr)
956 ERR("Failed to get session cipher suite: %d\n", status);
957 return 0;
960 c = get_cipher_suite(cipherSuite);
961 if (!c)
963 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
964 return 0;
967 switch (c->kx_alg)
969 case schan_kx_DH_DSS_EXPORT:
970 case schan_kx_DH_DSS:
971 case schan_kx_DHE_DSS_EXPORT:
972 case schan_kx_DHE_DSS:
973 return CALG_DSS_SIGN;
975 case schan_kx_DH_RSA_EXPORT:
976 case schan_kx_DH_RSA:
977 case schan_kx_DHE_RSA_EXPORT:
978 case schan_kx_DHE_RSA:
979 case schan_kx_ECDH_RSA:
980 case schan_kx_ECDHE_RSA:
981 case schan_kx_RSA_EXPORT:
982 case schan_kx_RSA:
983 return CALG_RSA_SIGN;
985 case schan_kx_ECDH_ECDSA:
986 case schan_kx_ECDHE_ECDSA:
987 return CALG_ECDSA;
989 case schan_kx_DH_anon_EXPORT:
990 case schan_kx_DH_anon:
991 case schan_kx_DHE_PSK:
992 case schan_kx_ECDH_anon:
993 case schan_kx_FORTEZZA_DMS:
994 case schan_kx_NULL:
995 case schan_kx_PSK:
996 case schan_kx_RSA_PSK:
997 FIXME("Don't know key signature algorithm for key exchange algorithm %d, returning 0\n", c->kx_alg);
998 return 0;
1000 default:
1001 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c->kx_alg, (unsigned int)c->suite);
1002 return 0;
1006 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
1007 SecPkgContext_ConnectionInfo *info)
1009 struct mac_session* s = (struct mac_session*)session;
1010 SSLCipherSuite cipherSuite;
1011 const struct cipher_suite* c;
1012 int status;
1014 TRACE("(%p/%p, %p)\n", s, s->context, info);
1016 status = SSLGetNegotiatedCipher(s->context, &cipherSuite);
1017 if (status != noErr)
1019 ERR("Failed to get session cipher suite: %d\n", status);
1020 return SEC_E_INTERNAL_ERROR;
1023 c = get_cipher_suite(cipherSuite);
1024 if (!c)
1026 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite);
1027 return SEC_E_INTERNAL_ERROR;
1030 info->dwProtocol = schan_get_session_protocol(s);
1031 info->aiCipher = schan_get_cipher_algid(c);
1032 info->dwCipherStrength = schan_get_cipher_key_size(c);
1033 info->aiHash = schan_get_mac_algid(c);
1034 info->dwHashStrength = schan_get_mac_key_size(c);
1035 info->aiExch = schan_get_kx_algid(c);
1036 /* FIXME: info->dwExchStrength? */
1037 info->dwExchStrength = 0;
1039 return SEC_E_OK;
1042 SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
1043 SecPkgContext_Bindings *bindings)
1045 FIXME("SECPKG_ATTR_UNIQUE_BINDINGS is unsupported on MacOS\n");
1046 return SEC_E_UNSUPPORTED_FUNCTION;
1049 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1050 static void schan_imp_cf_release(const void *arg, void *ctx)
1052 CFRelease(arg);
1054 #endif
1056 SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
1057 PCCERT_CONTEXT *ret_cert)
1059 struct mac_session* s = (struct mac_session*)session;
1060 SECURITY_STATUS ret = SEC_E_OK;
1061 PCCERT_CONTEXT cert = NULL;
1062 SecCertificateRef mac_cert;
1063 CFArrayRef cert_array;
1064 int status;
1065 CFIndex cnt, i;
1066 CFDataRef data;
1067 BOOL res;
1069 TRACE("(%p/%p, %p)\n", s, s->context, cert);
1071 #ifdef HAVE_SSLCOPYPEERCERTIFICATES
1072 status = SSLCopyPeerCertificates(s->context, &cert_array);
1073 #else
1074 status = SSLGetPeerCertificates(s->context, &cert_array);
1075 #endif
1076 if (status != noErr || !cert_array)
1078 WARN("SSLCopyPeerCertificates failed: %d\n", status);
1079 return SEC_E_INTERNAL_ERROR;
1082 cnt = CFArrayGetCount(cert_array);
1083 for (i=0; i < cnt; i++) {
1084 if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
1085 (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
1087 WARN("Couldn't extract certificate data\n");
1088 ret = SEC_E_INTERNAL_ERROR;
1089 break;
1092 res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
1093 CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
1094 CFRelease(data);
1095 if (!res)
1097 ret = GetLastError();
1098 WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
1099 break;
1103 #ifndef HAVE_SSLCOPYPEERCERTIFICATES
1104 /* This is why SSLGetPeerCertificates was deprecated */
1105 CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
1106 schan_imp_cf_release, NULL);
1107 #endif
1108 CFRelease(cert_array);
1109 if (ret != SEC_E_OK) {
1110 if(cert)
1111 CertFreeCertificateContext(cert);
1112 return ret;
1115 *ret_cert = cert;
1116 return SEC_E_OK;
1119 SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
1120 SIZE_T *length)
1122 struct mac_session* s = (struct mac_session*)session;
1123 int status;
1125 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1127 EnterCriticalSection(&s->cs);
1128 s->mode = schan_mode_WRITE;
1130 status = SSLWrite(s->context, buffer, *length, length);
1132 s->mode = schan_mode_NONE;
1133 LeaveCriticalSection(&s->cs);
1135 if (status == noErr)
1136 TRACE("Wrote %lu bytes\n", *length);
1137 else if (status == errSSLWouldBlock)
1139 if (!*length)
1141 TRACE("Would block before being able to write anything\n");
1142 return SEC_I_CONTINUE_NEEDED;
1144 else
1145 TRACE("Wrote %lu bytes before would block\n", *length);
1147 else
1149 WARN("SSLWrite failed: %d\n", status);
1150 return SEC_E_INTERNAL_ERROR;
1153 return SEC_E_OK;
1156 SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
1157 SIZE_T *length)
1159 struct mac_session* s = (struct mac_session*)session;
1160 int status;
1162 TRACE("(%p/%p, %p, %p/%lu)\n", s, s->context, buffer, length, *length);
1164 EnterCriticalSection(&s->cs);
1165 s->mode = schan_mode_READ;
1167 status = SSLRead(s->context, buffer, *length, length);
1169 s->mode = schan_mode_NONE;
1170 LeaveCriticalSection(&s->cs);
1172 if (status == noErr || status == errSSLClosedGraceful)
1173 TRACE("Read %lu bytes\n", *length);
1174 else if (status == errSSLWouldBlock)
1176 if (!*length)
1178 TRACE("Would block before being able to read anything\n");
1179 return SEC_I_CONTINUE_NEEDED;
1181 else
1182 TRACE("Read %lu bytes before would block\n", *length);
1184 else
1186 WARN("SSLRead failed: %d\n", status);
1187 return SEC_E_INTERNAL_ERROR;
1190 return SEC_E_OK;
1193 BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *cert)
1195 if (cert) FIXME("no support for certificate credentials on this platform\n");
1196 c->credentials = NULL;
1197 return TRUE;
1200 void schan_imp_free_certificate_credentials(schan_credentials *c)
1204 void schan_imp_set_application_protocols(schan_imp_session session, unsigned char *buffer, unsigned int buflen)
1206 FIXME("no support for application protocols on this platform\n");
1209 SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session session,
1210 SecPkgContext_ApplicationProtocol *protocol)
1212 FIXME("no support for application protocols on this platform\n");
1213 return SEC_E_UNSUPPORTED_FUNCTION;
1216 SECURITY_STATUS schan_imp_set_dtls_mtu(schan_imp_session session, unsigned int mtu)
1218 FIXME("no support for setting dtls mtu on this platform\n");
1219 return SEC_E_UNSUPPORTED_FUNCTION;
1222 BOOL schan_imp_init(void)
1224 TRACE("()\n");
1226 supported_protocols = SP_PROT_SSL2_CLIENT | SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT;
1228 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
1229 if(&SSLGetProtocolVersionMax != NULL) {
1230 SSLProtocol max_protocol;
1231 SSLContextRef ctx;
1232 OSStatus status;
1234 status = SSLNewContext(FALSE, &ctx);
1235 if(status == noErr) {
1236 status = SSLGetProtocolVersionMax(ctx, &max_protocol);
1237 if(status == noErr) {
1238 if(max_protocol >= kTLSProtocol11)
1239 supported_protocols |= SP_PROT_TLS1_1_CLIENT;
1240 if(max_protocol >= kTLSProtocol12)
1241 supported_protocols |= SP_PROT_TLS1_2_CLIENT;
1243 SSLDisposeContext(ctx);
1244 }else {
1245 WARN("SSLNewContext failed\n");
1248 #endif
1250 return TRUE;
1253 void schan_imp_deinit(void)
1255 TRACE("()\n");
1258 #endif /* HAVE_SECURITY_SECURITY_H */