2 * Mac OS X Secure Transport implementation of the schannel (SSL/TLS) provider.
4 * Copyright 2005 Juan Lang
5 * Copyright 2008 Henri Verbeet
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
26 #ifdef HAVE_SECURITY_SECURITY_H
27 #include <Security/Security.h>
28 #define GetCurrentThread GetCurrentThread_Mac
29 #define LoadResource LoadResource_Mac
30 #include <CoreServices/CoreServices.h>
31 #undef GetCurrentThread
40 #include "secur32_priv.h"
41 #include "wine/debug.h"
42 #include "wine/library.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(secur32
);
46 #ifdef HAVE_SECURITY_SECURITY_H
49 SSLContextRef context
;
50 struct schan_transport
*transport
;
60 schan_kx_DH_anon_EXPORT
,
62 schan_kx_DH_DSS_EXPORT
,
64 schan_kx_DH_RSA_EXPORT
,
66 schan_kx_DHE_DSS_EXPORT
,
68 schan_kx_DHE_RSA_EXPORT
,
75 schan_kx_FORTEZZA_DMS
,
82 schan_enc_3DES_EDE_CBC
,
83 schan_enc_AES_128_CBC
,
84 schan_enc_AES_256_CBC
,
87 schan_enc_FORTEZZA_CBC
,
103 struct cipher_suite
{
104 SSLCipherSuite suite
;
111 /* This table corresponds to the enum in <Security/CipherSuite.h>. */
112 static const struct cipher_suite cipher_suites
[] = {
113 #define CIPHER_SUITE(p, kx, enc, mac) { p##_##kx##_WITH_##enc##_##mac, schan_proto_##p, \
114 schan_kx_##kx, schan_enc_##enc, schan_mac_##mac }
115 CIPHER_SUITE(SSL
, RSA
, NULL
, MD5
),
116 CIPHER_SUITE(SSL
, RSA
, NULL
, MD5
),
117 CIPHER_SUITE(SSL
, RSA
, NULL
, SHA
),
118 CIPHER_SUITE(SSL
, RSA_EXPORT
, RC4_40
, MD5
),
119 CIPHER_SUITE(SSL
, RSA
, RC4_128
, MD5
),
120 CIPHER_SUITE(SSL
, RSA
, RC4_128
, SHA
),
121 CIPHER_SUITE(SSL
, RSA_EXPORT
, RC2_CBC_40
, MD5
),
122 CIPHER_SUITE(SSL
, RSA
, IDEA_CBC
, SHA
),
123 CIPHER_SUITE(SSL
, RSA_EXPORT
, DES40_CBC
, SHA
),
124 CIPHER_SUITE(SSL
, RSA
, DES_CBC
, SHA
),
125 CIPHER_SUITE(SSL
, RSA
, 3DES_EDE_CBC
, SHA
),
126 CIPHER_SUITE(SSL
, DH_DSS_EXPORT
, DES40_CBC
, SHA
),
127 CIPHER_SUITE(SSL
, DH_DSS
, DES_CBC
, SHA
),
128 CIPHER_SUITE(SSL
, DH_DSS
, 3DES_EDE_CBC
, SHA
),
129 CIPHER_SUITE(SSL
, DH_RSA_EXPORT
, DES40_CBC
, SHA
),
130 CIPHER_SUITE(SSL
, DH_RSA
, DES_CBC
, SHA
),
131 CIPHER_SUITE(SSL
, DH_RSA
, 3DES_EDE_CBC
, SHA
),
132 CIPHER_SUITE(SSL
, DHE_DSS_EXPORT
, DES40_CBC
, SHA
),
133 CIPHER_SUITE(SSL
, DHE_DSS
, DES_CBC
, SHA
),
134 CIPHER_SUITE(SSL
, DHE_DSS
, 3DES_EDE_CBC
, SHA
),
135 CIPHER_SUITE(SSL
, DHE_RSA_EXPORT
, DES40_CBC
, SHA
),
136 CIPHER_SUITE(SSL
, DHE_RSA
, DES_CBC
, SHA
),
137 CIPHER_SUITE(SSL
, DHE_RSA
, 3DES_EDE_CBC
, SHA
),
138 CIPHER_SUITE(SSL
, DH_anon_EXPORT
, RC4_40
, MD5
),
139 CIPHER_SUITE(SSL
, DH_anon
, RC4_128
, MD5
),
140 CIPHER_SUITE(SSL
, DH_anon_EXPORT
, DES40_CBC
, SHA
),
141 CIPHER_SUITE(SSL
, DH_anon
, DES_CBC
, SHA
),
142 CIPHER_SUITE(SSL
, DH_anon
, 3DES_EDE_CBC
, SHA
),
143 CIPHER_SUITE(SSL
, FORTEZZA_DMS
, NULL
, SHA
),
144 CIPHER_SUITE(SSL
, FORTEZZA_DMS
, FORTEZZA_CBC
, SHA
),
146 CIPHER_SUITE(TLS
, RSA
, AES_128_CBC
, SHA
),
147 CIPHER_SUITE(TLS
, DH_DSS
, AES_128_CBC
, SHA
),
148 CIPHER_SUITE(TLS
, DH_RSA
, AES_128_CBC
, SHA
),
149 CIPHER_SUITE(TLS
, DHE_DSS
, AES_128_CBC
, SHA
),
150 CIPHER_SUITE(TLS
, DHE_RSA
, AES_128_CBC
, SHA
),
151 CIPHER_SUITE(TLS
, DH_anon
, AES_128_CBC
, SHA
),
152 CIPHER_SUITE(TLS
, RSA
, AES_256_CBC
, SHA
),
153 CIPHER_SUITE(TLS
, DH_DSS
, AES_256_CBC
, SHA
),
154 CIPHER_SUITE(TLS
, DH_RSA
, AES_256_CBC
, SHA
),
155 CIPHER_SUITE(TLS
, DHE_DSS
, AES_256_CBC
, SHA
),
156 CIPHER_SUITE(TLS
, DHE_RSA
, AES_256_CBC
, SHA
),
157 CIPHER_SUITE(TLS
, DH_anon
, AES_256_CBC
, SHA
),
159 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
160 CIPHER_SUITE(TLS
, ECDH_ECDSA
, NULL
, SHA
),
161 CIPHER_SUITE(TLS
, ECDH_ECDSA
, RC4_128
, SHA
),
162 CIPHER_SUITE(TLS
, ECDH_ECDSA
, 3DES_EDE_CBC
, SHA
),
163 CIPHER_SUITE(TLS
, ECDH_ECDSA
, AES_128_CBC
, SHA
),
164 CIPHER_SUITE(TLS
, ECDH_ECDSA
, AES_256_CBC
, SHA
),
165 CIPHER_SUITE(TLS
, ECDHE_ECDSA
, NULL
, SHA
),
166 CIPHER_SUITE(TLS
, ECDHE_ECDSA
, RC4_128
, SHA
),
167 CIPHER_SUITE(TLS
, ECDHE_ECDSA
, 3DES_EDE_CBC
, SHA
),
168 CIPHER_SUITE(TLS
, ECDHE_ECDSA
, AES_128_CBC
, SHA
),
169 CIPHER_SUITE(TLS
, ECDHE_ECDSA
, AES_256_CBC
, SHA
),
170 CIPHER_SUITE(TLS
, ECDH_RSA
, NULL
, SHA
),
171 CIPHER_SUITE(TLS
, ECDH_RSA
, RC4_128
, SHA
),
172 CIPHER_SUITE(TLS
, ECDH_RSA
, 3DES_EDE_CBC
, SHA
),
173 CIPHER_SUITE(TLS
, ECDH_RSA
, AES_128_CBC
, SHA
),
174 CIPHER_SUITE(TLS
, ECDH_RSA
, AES_256_CBC
, SHA
),
175 CIPHER_SUITE(TLS
, ECDHE_RSA
, NULL
, SHA
),
176 CIPHER_SUITE(TLS
, ECDHE_RSA
, RC4_128
, SHA
),
177 CIPHER_SUITE(TLS
, ECDHE_RSA
, 3DES_EDE_CBC
, SHA
),
178 CIPHER_SUITE(TLS
, ECDHE_RSA
, AES_128_CBC
, SHA
),
179 CIPHER_SUITE(TLS
, ECDHE_RSA
, AES_256_CBC
, SHA
),
180 CIPHER_SUITE(TLS
, ECDH_anon
, NULL
, SHA
),
181 CIPHER_SUITE(TLS
, ECDH_anon
, RC4_128
, SHA
),
182 CIPHER_SUITE(TLS
, ECDH_anon
, 3DES_EDE_CBC
, SHA
),
183 CIPHER_SUITE(TLS
, ECDH_anon
, AES_128_CBC
, SHA
),
184 CIPHER_SUITE(TLS
, ECDH_anon
, AES_256_CBC
, SHA
),
187 CIPHER_SUITE(SSL
, RSA
, RC2_CBC
, MD5
),
188 CIPHER_SUITE(SSL
, RSA
, IDEA_CBC
, MD5
),
189 CIPHER_SUITE(SSL
, RSA
, DES_CBC
, MD5
),
190 CIPHER_SUITE(SSL
, RSA
, 3DES_EDE_CBC
, MD5
),
195 static const struct cipher_suite
* get_cipher_suite(SSLCipherSuite cipher_suite
)
198 for (i
= 0; i
< sizeof(cipher_suites
)/sizeof(cipher_suites
[0]); i
++)
200 if (cipher_suites
[i
].suite
== cipher_suite
)
201 return &cipher_suites
[i
];
208 static DWORD
schan_get_session_protocol(struct mac_session
* s
)
210 SSLProtocol protocol
;
213 TRACE("(%p/%p)\n", s
, s
->context
);
215 status
= SSLGetNegotiatedProtocolVersion(s
->context
, &protocol
);
218 ERR("Failed to get session protocol: %ld\n", status
);
222 TRACE("protocol %d\n", protocol
);
226 case kSSLProtocol2
: return SP_PROT_SSL2_CLIENT
;
227 case kSSLProtocol3
: return SP_PROT_SSL3_CLIENT
;
228 case kTLSProtocol1
: return SP_PROT_TLS1_CLIENT
;
230 FIXME("unknown protocol %d\n", protocol
);
235 static ALG_ID
schan_get_cipher_algid(const struct cipher_suite
* c
)
237 TRACE("(%#x)\n", (unsigned int)c
->suite
);
241 case schan_enc_3DES_EDE_CBC
: return CALG_3DES
;
242 case schan_enc_AES_128_CBC
: return CALG_AES_128
;
243 case schan_enc_AES_256_CBC
: return CALG_AES_256
;
244 case schan_enc_DES_CBC
: return CALG_DES
;
245 case schan_enc_DES40_CBC
: return CALG_DES
;
246 case schan_enc_NULL
: return 0;
247 case schan_enc_RC2_CBC_40
: return CALG_RC2
;
248 case schan_enc_RC2_CBC
: return CALG_RC2
;
249 case schan_enc_RC4_128
: return CALG_RC4
;
250 case schan_enc_RC4_40
: return CALG_RC4
;
252 case schan_enc_FORTEZZA_CBC
:
253 case schan_enc_IDEA_CBC
:
254 FIXME("Don't know CALG for encryption algorithm %d, returning 0\n", c
->enc_alg
);
258 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
263 static unsigned int schan_get_cipher_key_size(const struct cipher_suite
* c
)
265 TRACE("(%#x)\n", (unsigned int)c
->suite
);
269 case schan_enc_3DES_EDE_CBC
: return 168;
270 case schan_enc_AES_128_CBC
: return 128;
271 case schan_enc_AES_256_CBC
: return 256;
272 case schan_enc_DES_CBC
: return 56;
273 case schan_enc_DES40_CBC
: return 40;
274 case schan_enc_NULL
: return 0;
275 case schan_enc_RC2_CBC_40
: return 40;
276 case schan_enc_RC2_CBC
: return 128;
277 case schan_enc_RC4_128
: return 128;
278 case schan_enc_RC4_40
: return 40;
280 case schan_enc_FORTEZZA_CBC
:
281 case schan_enc_IDEA_CBC
:
282 FIXME("Don't know key size for encryption algorithm %d, returning 0\n", c
->enc_alg
);
286 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
291 static ALG_ID
schan_get_mac_algid(const struct cipher_suite
* c
)
293 TRACE("(%#x)\n", (unsigned int)c
->suite
);
297 case schan_mac_MD5
: return CALG_MD5
;
298 case schan_mac_NULL
: return 0;
299 case schan_mac_SHA
: return CALG_SHA
;
302 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c
->mac_alg
, (unsigned)c
->suite
);
307 static unsigned int schan_get_mac_key_size(const struct cipher_suite
* c
)
309 TRACE("(%#x)\n", (unsigned int)c
->suite
);
313 case schan_mac_MD5
: return 128;
314 case schan_mac_NULL
: return 0;
315 case schan_mac_SHA
: return 160;
318 FIXME("Unknown hashing algorithm %d for cipher suite %#x, returning 0\n", c
->mac_alg
, (unsigned)c
->suite
);
323 static ALG_ID
schan_get_kx_algid(const struct cipher_suite
* c
)
325 TRACE("(%#x)\n", (unsigned int)c
->suite
);
329 case schan_kx_DHE_DSS_EXPORT
:
330 case schan_kx_DHE_DSS
:
331 case schan_kx_DHE_RSA_EXPORT
:
332 case schan_kx_DHE_RSA
: return CALG_DH_EPHEM
;
333 case schan_kx_NULL
: return 0;
334 case schan_kx_RSA
: return CALG_RSA_KEYX
;
336 case schan_kx_DH_anon_EXPORT
:
337 case schan_kx_DH_anon
:
338 case schan_kx_DH_DSS_EXPORT
:
339 case schan_kx_DH_DSS
:
340 case schan_kx_DH_RSA_EXPORT
:
341 case schan_kx_DH_RSA
:
342 case schan_kx_ECDH_anon
:
343 case schan_kx_ECDH_ECDSA
:
344 case schan_kx_ECDH_RSA
:
345 case schan_kx_ECDHE_ECDSA
:
346 case schan_kx_ECDHE_RSA
:
347 case schan_kx_FORTEZZA_DMS
:
348 case schan_kx_RSA_EXPORT
:
349 FIXME("Don't know CALG for key exchange algorithm %d for cipher suite %#x, returning 0\n", c
->kx_alg
, (unsigned)c
->suite
);
353 FIXME("Unknown key exchange algorithm %d for cipher suite %#x, returning 0\n", c
->kx_alg
, (unsigned)c
->suite
);
359 /* schan_pull_adapter
360 * Callback registered with SSLSetIOFuncs as the read function for a
361 * session. Reads data from the session connection. Conforms to the
364 * transport - The session connection
365 * buff - The buffer into which to store the read data. Must be at least
366 * *buff_len bytes in length.
367 * *buff_len - On input, the desired length to read. On successful return,
368 * the number of bytes actually read.
371 * noErr on complete success meaning the requested length was successfully
373 * errSSLWouldBlock when the requested length could not be read without
374 * blocking. *buff_len indicates how much was actually read. The
375 * caller should try again if/when they want to read more.
376 * errSSLClosedGraceful when the connection has closed and there's no
377 * more data to be read.
378 * other error code for failure.
380 static OSStatus
schan_pull_adapter(SSLConnectionRef transport
, void *buff
,
383 struct mac_session
*s
= (struct mac_session
*)transport
;
384 size_t requested
= *buff_len
;
388 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->transport
, buff
, buff_len
, *buff_len
);
390 status
= schan_pull(s
->transport
, buff
, buff_len
);
395 TRACE("Connection closed\n");
396 ret
= errSSLClosedGraceful
;
398 else if (*buff_len
< requested
)
400 TRACE("Pulled %lu bytes before would block\n", *buff_len
);
401 ret
= errSSLWouldBlock
;
405 TRACE("Pulled %lu bytes\n", *buff_len
);
409 else if (status
== EAGAIN
)
411 TRACE("Would block before being able to pull anything\n");
412 ret
= errSSLWouldBlock
;
416 FIXME("Unknown status code from schan_pull: %d\n", status
);
423 /* schan_push_adapter
424 * Callback registered with SSLSetIOFuncs as the write function for a
425 * session. Writes data to the session connection. Conforms to the
428 * transport - The session connection
429 * buff - The buffer of data to write. Must be at least *buff_len bytes in length.
430 * *buff_len - On input, the desired length to write. On successful return,
431 * the number of bytes actually written.
434 * noErr on complete or partial success; *buff_len indicates how much data
435 * was actually written, which may be less than requrested.
436 * errSSLWouldBlock when no data could be written without blocking. The
437 * caller should try again.
438 * other error code for failure.
440 static OSStatus
schan_push_adapter(SSLConnectionRef transport
, const void *buff
,
443 struct mac_session
*s
= (struct mac_session
*)transport
;
447 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->transport
, buff
, buff_len
, *buff_len
);
449 status
= schan_push(s
->transport
, buff
, buff_len
);
452 TRACE("Pushed %lu bytes\n", *buff_len
);
455 else if (status
== EAGAIN
)
457 TRACE("Would block before being able to push anything\n");
458 ret
= errSSLWouldBlock
;
462 FIXME("Unknown status code from schan_push: %d\n", status
);
470 BOOL
schan_imp_create_session(schan_imp_session
*session
, BOOL is_server
,
471 schan_imp_certificate_credentials cred
)
473 struct mac_session
*s
;
476 TRACE("(%p, %d)\n", session
, is_server
);
478 s
= HeapAlloc(GetProcessHeap(), 0, sizeof(*s
));
482 status
= SSLNewContext(is_server
, &s
->context
);
485 ERR("Failed to create session context: %ld\n", (long)status
);
489 status
= SSLSetConnection(s
->context
, s
);
492 ERR("Failed to set session connection: %ld\n", (long)status
);
496 status
= SSLSetEnableCertVerify(s
->context
, FALSE
);
499 ERR("Failed to disable certificate verification: %ld\n", (long)status
);
503 status
= SSLSetProtocolVersionEnabled(s
->context
, kSSLProtocol2
, FALSE
);
506 ERR("Failed to disable SSL version 2: %ld\n", (long)status
);
510 status
= SSLSetIOFuncs(s
->context
, schan_pull_adapter
, schan_push_adapter
);
513 ERR("Failed to set session I/O funcs: %ld\n", (long)status
);
517 TRACE(" -> %p/%p\n", s
, s
->context
);
519 *session
= (schan_imp_session
)s
;
523 HeapFree(GetProcessHeap(), 0, s
);
527 void schan_imp_dispose_session(schan_imp_session session
)
529 struct mac_session
*s
= (struct mac_session
*)session
;
532 TRACE("(%p/%p)\n", s
, s
->context
);
534 status
= SSLDisposeContext(s
->context
);
536 ERR("Failed to dispose of session context: %ld\n", status
);
537 HeapFree(GetProcessHeap(), 0, s
);
540 void schan_imp_set_session_transport(schan_imp_session session
,
541 struct schan_transport
*t
)
543 struct mac_session
*s
= (struct mac_session
*)session
;
545 TRACE("(%p/%p, %p)\n", s
, s
->context
, t
);
550 SECURITY_STATUS
schan_imp_handshake(schan_imp_session session
)
552 struct mac_session
*s
= (struct mac_session
*)session
;
555 TRACE("(%p/%p)\n", s
, s
->context
);
557 status
= SSLHandshake(s
->context
);
560 TRACE("Handshake completed\n");
563 else if (status
== errSSLWouldBlock
)
565 TRACE("Continue...\n");
566 return SEC_I_CONTINUE_NEEDED
;
568 else if (errSecErrnoBase
<= status
&& status
<= errSecErrnoLimit
)
570 ERR("Handshake failed: %s\n", strerror(status
));
571 return SEC_E_INTERNAL_ERROR
;
575 ERR("Handshake failed: %ld\n", (long)status
);
576 cssmPerror("SSLHandshake", status
);
577 return SEC_E_INTERNAL_ERROR
;
584 unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session
)
586 struct mac_session
* s
= (struct mac_session
*)session
;
587 SSLCipherSuite cipherSuite
;
588 const struct cipher_suite
* c
;
591 TRACE("(%p/%p)\n", s
, s
->context
);
593 status
= SSLGetNegotiatedCipher(s
->context
, &cipherSuite
);
596 ERR("Failed to get session cipher suite: %ld\n", status
);
600 c
= get_cipher_suite(cipherSuite
);
603 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite
);
609 case schan_enc_3DES_EDE_CBC
: return 64;
610 case schan_enc_AES_128_CBC
: return 128;
611 case schan_enc_AES_256_CBC
: return 128;
612 case schan_enc_DES_CBC
: return 64;
613 case schan_enc_DES40_CBC
: return 64;
614 case schan_enc_NULL
: return 0;
615 case schan_enc_RC2_CBC_40
: return 64;
616 case schan_enc_RC2_CBC
: return 64;
617 case schan_enc_RC4_128
: return 0;
618 case schan_enc_RC4_40
: return 0;
620 case schan_enc_FORTEZZA_CBC
:
621 case schan_enc_IDEA_CBC
:
622 FIXME("Don't know block size for encryption algorithm %d, returning 0\n", c
->enc_alg
);
626 FIXME("Unknown encryption algorithm %d for cipher suite %#x, returning 0\n", c
->enc_alg
, (unsigned int)c
->suite
);
631 unsigned int schan_imp_get_max_message_size(schan_imp_session session
)
633 FIXME("Returning 1 << 14.\n");
637 SECURITY_STATUS
schan_imp_get_connection_info(schan_imp_session session
,
638 SecPkgContext_ConnectionInfo
*info
)
640 struct mac_session
* s
= (struct mac_session
*)session
;
641 SSLCipherSuite cipherSuite
;
642 const struct cipher_suite
* c
;
645 TRACE("(%p/%p, %p)\n", s
, s
->context
, info
);
647 status
= SSLGetNegotiatedCipher(s
->context
, &cipherSuite
);
650 ERR("Failed to get session cipher suite: %ld\n", status
);
651 return SEC_E_INTERNAL_ERROR
;
654 c
= get_cipher_suite(cipherSuite
);
657 ERR("Unknown session cipher suite: %#x\n", (unsigned int)cipherSuite
);
658 return SEC_E_INTERNAL_ERROR
;
661 info
->dwProtocol
= schan_get_session_protocol(s
);
662 info
->aiCipher
= schan_get_cipher_algid(c
);
663 info
->dwCipherStrength
= schan_get_cipher_key_size(c
);
664 info
->aiHash
= schan_get_mac_algid(c
);
665 info
->dwHashStrength
= schan_get_mac_key_size(c
);
666 info
->aiExch
= schan_get_kx_algid(c
);
667 /* FIXME: info->dwExchStrength? */
668 info
->dwExchStrength
= 0;
673 SECURITY_STATUS
schan_imp_get_session_peer_certificate(schan_imp_session session
,
674 PCCERT_CONTEXT
*cert
)
676 struct mac_session
* s
= (struct mac_session
*)session
;
677 SECURITY_STATUS ret
= SEC_E_INTERNAL_ERROR
;
681 TRACE("(%p/%p, %p)\n", s
, s
->context
, cert
);
683 status
= SSLCopyPeerCertificates(s
->context
, &certs
);
684 if (status
== noErr
&& certs
)
686 SecCertificateRef mac_cert
;
688 if (CFArrayGetCount(certs
) &&
689 (mac_cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(certs
, 0)) &&
690 (SecKeychainItemExport(mac_cert
, kSecFormatX509Cert
, 0, NULL
, &data
) == noErr
))
692 *cert
= CertCreateCertificateContext(X509_ASN_ENCODING
,
693 CFDataGetBytePtr(data
), CFDataGetLength(data
));
698 ret
= GetLastError();
699 WARN("CertCreateCertificateContext failed: %x\n", ret
);
704 WARN("Couldn't extract certificate data\n");
708 WARN("SSLCopyPeerCertificates failed: %ld\n", (long)status
);
713 SECURITY_STATUS
schan_imp_send(schan_imp_session session
, const void *buffer
,
716 struct mac_session
* s
= (struct mac_session
*)session
;
719 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->context
, buffer
, length
, *length
);
721 status
= SSLWrite(s
->context
, buffer
, *length
, length
);
723 TRACE("Wrote %lu bytes\n", *length
);
724 else if (status
== errSSLWouldBlock
)
728 TRACE("Would block before being able to write anything\n");
729 return SEC_I_CONTINUE_NEEDED
;
732 TRACE("Wrote %lu bytes before would block\n", *length
);
736 WARN("SSLWrite failed: %ld\n", (long)status
);
737 return SEC_E_INTERNAL_ERROR
;
743 SECURITY_STATUS
schan_imp_recv(schan_imp_session session
, void *buffer
,
746 struct mac_session
* s
= (struct mac_session
*)session
;
749 TRACE("(%p/%p, %p, %p/%lu)\n", s
, s
->context
, buffer
, length
, *length
);
751 status
= SSLRead(s
->context
, buffer
, *length
, length
);
753 TRACE("Read %lu bytes\n", *length
);
754 else if (status
== errSSLWouldBlock
)
758 TRACE("Would block before being able to read anything\n");
759 return SEC_I_CONTINUE_NEEDED
;
762 TRACE("Read %lu bytes before would block\n", *length
);
766 WARN("SSLRead failed: %ld\n", (long)status
);
767 return SEC_E_INTERNAL_ERROR
;
773 BOOL
schan_imp_allocate_certificate_credentials(schan_imp_certificate_credentials
*c
)
775 /* The certificate is never really used for anything. */
780 void schan_imp_free_certificate_credentials(schan_imp_certificate_credentials c
)
784 BOOL
schan_imp_init(void)
790 void schan_imp_deinit(void)
795 #endif /* HAVE_SECURITY_SECURITY_H */