2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
26 #include "tlsCallbacks.h"
27 #include "sslContext.h"
28 #include "sslCrypto.h"
30 #include "sslMemory.h"
31 #include "appleSession.h"
32 #include <Security/SecCertificate.h>
33 #include <Security/SecCertificatePriv.h>
34 #include "utilities/SecCFRelease.h"
38 int tls_handshake_write_callback(tls_handshake_ctx_t ctx
, const SSLBuffer data
, uint8_t content_type
)
40 SSLContext
*myCtx
= (SSLContext
*)ctx
;
41 sslDebugLog("%p (rec.len=%zd, ct=%d, d[0]=%d)\n", myCtx
, data
.length
, content_type
, data
.data
[0]);
46 rec
.contentType
=content_type
;
48 return myCtx
->recFuncs
->write(myCtx
->recCtx
,rec
);
53 tls_handshake_message_callback(tls_handshake_ctx_t ctx
, tls_handshake_message_t event
)
55 SSLContext
*myCtx
= (SSLContext
*)ctx
;
56 const tls_buffer
*npn_data
;
57 const tls_buffer
*alpn_data
;
60 sslDebugLog("%p, message = %d\n", ctx
, event
);
63 case tls_handshake_message_certificate_request
:
64 assert(myCtx
->protocolSide
== kSSLClientSide
);
65 // Need to call this here, in case SetCertificate was already called.
66 myCtx
->clientCertState
= kSSLClientCertRequested
;
67 myCtx
->clientAuthTypes
= tls_handshake_get_peer_acceptable_client_auth_type(myCtx
->hdsk
, &myCtx
->numAuthTypes
);
68 SSLUpdateNegotiatedClientAuthType(myCtx
);
69 if (myCtx
->breakOnCertRequest
&& (myCtx
->localCert
==NULL
)) {
70 myCtx
->signalCertRequest
= true;
71 err
= errSSLClientCertRequested
;
74 case tls_handshake_message_client_hello
:
75 myCtx
->peerSigAlgs
= tls_handshake_get_peer_signature_algorithms(myCtx
->hdsk
, &myCtx
->numPeerSigAlgs
);
76 if (myCtx
->breakOnClientHello
) {
77 err
= errSSLClientHelloReceived
;
80 case tls_handshake_message_server_hello
:
81 myCtx
->serverHelloReceived
= true;
82 alpn_data
= tls_handshake_get_peer_alpn_data(myCtx
->hdsk
);
84 myCtx
->alpnFunc(myCtx
, myCtx
->alpnFuncInfo
, alpn_data
->data
, alpn_data
->length
);
86 npn_data
= tls_handshake_get_peer_npn_data(myCtx
->hdsk
);
88 myCtx
->npnFunc(myCtx
, myCtx
->npnFuncInfo
, npn_data
->data
, npn_data
->length
);
91 myCtx
->peerSigAlgs
= tls_handshake_get_peer_signature_algorithms(myCtx
->hdsk
, &myCtx
->numPeerSigAlgs
);
93 case tls_handshake_message_certificate
:
94 /* For clients, we only check the cert when we receive the ServerHelloDone message.
95 For servers, we check the client's cert right here. For both we set the public key */
96 err
= tls_set_peer_pubkey(myCtx
);
97 if(!err
&& (myCtx
->protocolSide
== kSSLServerSide
)) {
98 err
= tls_verify_peer_cert(myCtx
);
101 case tls_handshake_message_server_hello_done
:
102 err
= tls_verify_peer_cert(myCtx
);
104 case tls_handshake_message_NPN_encrypted_extension
:
105 npn_data
= tls_handshake_get_peer_npn_data(myCtx
->hdsk
);
107 myCtx
->npnFunc(myCtx
, myCtx
->npnFuncInfo
, npn_data
->data
, npn_data
->length
);
109 case tls_handshake_message_certificate_status
:
119 tls_handshake_ready_callback(tls_handshake_ctx_t ctx
, bool write
, bool ready
)
121 SSLContext
*myCtx
= (SSLContext
*)ctx
;
123 sslDebugLog("%p %s ready=%d\n", myCtx
, write
?"write":"read", ready
);
126 myCtx
->writeCipher_ready
=ready
?1:0;
128 myCtx
->readCipher_ready
=ready
?1:0;
130 SSLChangeHdskState(myCtx
, SSL_HdskStateReady
);
132 SSLChangeHdskState(myCtx
, SSL_HdskStatePending
);
138 tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx
, int attempt
)
140 SSLContext
*myCtx
= (SSLContext
*)ctx
;
142 sslDebugLog("%p attempt=%d\n", ctx
, attempt
);
145 myCtx
->timeout_deadline
= CFAbsoluteTimeGetCurrent()+((1<<(attempt
-1))*myCtx
->timeout_duration
);
147 myCtx
->timeout_deadline
= 0; // cancel the timeout
153 tls_handshake_init_pending_cipher_callback(tls_handshake_ctx_t ctx
,
154 uint16_t selectedCipher
,
158 sslDebugLog("%p, cipher=%04x, server=%d\n", ctx
, selectedCipher
, server
);
159 SSLContext
*myCtx
= (SSLContext
*)ctx
;
160 return myCtx
->recFuncs
->initPendingCiphers(myCtx
->recCtx
, selectedCipher
, server
, key
);
164 tls_handshake_advance_write_callback(tls_handshake_ctx_t ctx
)
166 SSLContext
*myCtx
= (SSLContext
*)ctx
;
167 sslDebugLog("%p\n", myCtx
);
168 //FIXME: need to filter on cipher too - require missing coretls ciphersuite header */
169 bool split
= (myCtx
->oneByteRecordEnable
&& (myCtx
->negProtocolVersion
<=TLS_Version_1_0
));
170 myCtx
->recFuncs
->setOption(myCtx
->recCtx
, kSSLRecordOptionSendOneByteRecord
, split
);
171 return myCtx
->recFuncs
->advanceWriteCipher(myCtx
->recCtx
);
175 int tls_handshake_rollback_write_callback(tls_handshake_ctx_t ctx
)
177 SSLContext
*myCtx
= (SSLContext
*)ctx
;
178 sslDebugLog("%p\n", myCtx
);
179 return myCtx
->recFuncs
->rollbackWriteCipher(myCtx
->recCtx
);
183 int tls_handshake_advance_read_cipher_callback(tls_handshake_ctx_t ctx
)
185 SSLContext
*myCtx
= (SSLContext
*)ctx
;
186 sslDebugLog("%p\n", myCtx
);
187 return myCtx
->recFuncs
->advanceReadCipher(myCtx
->recCtx
);
191 int tls_handshake_set_protocol_version_callback(tls_handshake_ctx_t ctx
,
192 tls_protocol_version protocolVersion
)
194 SSLContext
*myCtx
= (SSLContext
*)ctx
;
195 myCtx
->negProtocolVersion
= protocolVersion
;
196 return myCtx
->recFuncs
->setProtocolVersion(myCtx
->recCtx
, protocolVersion
);
200 tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
, SSLBuffer sessionData
)
202 SSLContext
*myCtx
= (SSLContext
*)ctx
;
203 sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__
, myCtx
, sessionKey
.length
, sessionKey
.data
[0], sessionData
.length
);
204 return sslAddSession(sessionKey
, sessionData
, myCtx
->sessionCacheTimeout
);
208 tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
, SSLBuffer
*sessionData
)
210 SSLContext
*myCtx
= (SSLContext
*)ctx
;
213 SSLFreeBuffer(&myCtx
->resumableSession
);
214 err
= sslCopySession(sessionKey
, &myCtx
->resumableSession
);
216 sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx
, sessionKey
.length
, sessionData
->length
, err
);
218 *sessionData
= myCtx
->resumableSession
;
224 tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
)
226 sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx
, sessionKey
.length
, sessionKey
.data
[0]);
227 return sslDeleteSession(sessionKey
);
231 tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx
)
233 sslDebugLog("%p\n", ctx
);
235 return sslCleanupSession();
238 tls_handshake_callbacks_t tls_handshake_callbacks
= {
239 .write
= tls_handshake_write_callback
,
240 .message
= tls_handshake_message_callback
,
241 .ready
= tls_handshake_ready_callback
,
242 .set_retransmit_timer
= tls_handshake_set_retransmit_timer_callback
,
243 .save_session_data
= tls_handshake_save_session_data_callback
,
244 .load_session_data
= tls_handshake_load_session_data_callback
,
245 .delete_session_data
= tls_handshake_delete_session_data_callback
,
246 .delete_all_sessions
= tls_handshake_delete_all_sessions_callback
,
247 .init_pending_cipher
= tls_handshake_init_pending_cipher_callback
,
248 .advance_write_cipher
= tls_handshake_advance_write_callback
,
249 .rollback_write_cipher
= tls_handshake_rollback_write_callback
,
250 .advance_read_cipher
= tls_handshake_advance_read_cipher_callback
,
251 .set_protocol_version
= tls_handshake_set_protocol_version_callback
,