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 <Security/SecCertificate.h>
32 #include <Security/SecCertificatePriv.h>
33 #include "utilities/SecCFRelease.h"
35 #include <tls_helpers.h>
36 #include <tls_cache.h>
38 #include "utilities/simulatecrash_assert.h"
41 int tls_handshake_write_callback(tls_handshake_ctx_t ctx
, const SSLBuffer data
, uint8_t content_type
)
43 SSLContext
*myCtx
= (SSLContext
*)ctx
;
44 sslDebugLog("%p (rec.len=%zd, ct=%d, d[0]=%d)\n", myCtx
, data
.length
, content_type
, data
.data
[0]);
49 rec
.contentType
=content_type
;
51 return myCtx
->recFuncs
->write(myCtx
->recCtx
,rec
);
56 tls_handshake_message_callback(tls_handshake_ctx_t ctx
, tls_handshake_message_t event
)
58 SSLContext
*myCtx
= (SSLContext
*)ctx
;
59 const tls_buffer
*npn_data
;
60 const tls_buffer
*alpn_data
;
63 sslDebugLog("%p, message = %d\n", ctx
, event
);
66 case tls_handshake_message_certificate_request
:
67 assert(myCtx
->protocolSide
== kSSLClientSide
);
68 // Need to call this here, in case SetCertificate was already called.
69 myCtx
->clientCertState
= kSSLClientCertRequested
;
70 myCtx
->clientAuthTypes
= tls_handshake_get_peer_acceptable_client_auth_type(myCtx
->hdsk
, &myCtx
->numAuthTypes
);
71 if (myCtx
->breakOnCertRequest
&& (myCtx
->localCertArray
==NULL
)) {
72 myCtx
->signalCertRequest
= true;
73 err
= errSSLClientCertRequested
;
76 case tls_handshake_message_client_hello
:
77 myCtx
->peerSigAlgs
= tls_handshake_get_peer_signature_algorithms(myCtx
->hdsk
, &myCtx
->numPeerSigAlgs
);
78 if (myCtx
->breakOnClientHello
) {
79 err
= errSSLClientHelloReceived
;
82 case tls_handshake_message_server_hello
:
83 myCtx
->serverHelloReceived
= true;
84 alpn_data
= tls_handshake_get_peer_alpn_data(myCtx
->hdsk
);
85 if (alpn_data
&& myCtx
->alpnFunc
!= NULL
) {
86 myCtx
->alpnFunc(myCtx
, myCtx
->alpnFuncInfo
, alpn_data
->data
, alpn_data
->length
);
88 npn_data
= tls_handshake_get_peer_npn_data(myCtx
->hdsk
);
90 myCtx
->npnFunc(myCtx
, myCtx
->npnFuncInfo
, npn_data
->data
, npn_data
->length
);
93 myCtx
->peerSigAlgs
= tls_handshake_get_peer_signature_algorithms(myCtx
->hdsk
, &myCtx
->numPeerSigAlgs
);
95 case tls_handshake_message_certificate
:
96 /* For clients, we only check the cert when we receive the ServerHelloDone message.
97 For servers, we check the client's cert right here. For both we set the public key */
98 err
= tls_helper_set_peer_pubkey(myCtx
->hdsk
);
99 if(!err
&& (myCtx
->protocolSide
== kSSLServerSide
)) {
100 err
= tls_verify_peer_cert(myCtx
);
103 case tls_handshake_message_server_hello_done
:
104 err
= tls_verify_peer_cert(myCtx
);
106 case tls_handshake_message_NPN_encrypted_extension
:
107 npn_data
= tls_handshake_get_peer_npn_data(myCtx
->hdsk
);
109 myCtx
->npnFunc(myCtx
, myCtx
->npnFuncInfo
, npn_data
->data
, npn_data
->length
);
111 case tls_handshake_message_certificate_status
:
121 tls_handshake_ready_callback(tls_handshake_ctx_t ctx
, bool write
, bool ready
)
123 SSLContext
*myCtx
= (SSLContext
*)ctx
;
125 sslDebugLog("%p %s ready=%d\n", myCtx
, write
?"write":"read", ready
);
128 myCtx
->writeCipher_ready
=ready
?1:0;
130 myCtx
->readCipher_ready
=ready
?1:0;
132 SSLChangeHdskState(myCtx
, SSL_HdskStateReady
);
134 SSLChangeHdskState(myCtx
, SSL_HdskStatePending
);
140 tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx
, int attempt
)
142 SSLContext
*myCtx
= (SSLContext
*)ctx
;
144 sslDebugLog("%p attempt=%d\n", ctx
, attempt
);
147 myCtx
->timeout_deadline
= CFAbsoluteTimeGetCurrent()+((1<<(attempt
-1))*myCtx
->timeout_duration
);
149 myCtx
->timeout_deadline
= 0; // cancel the timeout
155 tls_handshake_init_pending_cipher_callback(tls_handshake_ctx_t ctx
,
156 uint16_t selectedCipher
,
160 sslDebugLog("%p, cipher=%04x, server=%d\n", ctx
, selectedCipher
, server
);
161 SSLContext
*myCtx
= (SSLContext
*)ctx
;
162 return myCtx
->recFuncs
->initPendingCiphers(myCtx
->recCtx
, selectedCipher
, server
, key
);
166 tls_handshake_advance_write_callback(tls_handshake_ctx_t ctx
)
168 SSLContext
*myCtx
= (SSLContext
*)ctx
;
169 sslDebugLog("%p\n", myCtx
);
170 //FIXME: need to filter on cipher too - require missing coretls ciphersuite header */
171 bool split
= (myCtx
->oneByteRecordEnable
&& (myCtx
->negProtocolVersion
<=TLS_Version_1_0
));
172 myCtx
->recFuncs
->setOption(myCtx
->recCtx
, kSSLRecordOptionSendOneByteRecord
, split
);
173 return myCtx
->recFuncs
->advanceWriteCipher(myCtx
->recCtx
);
177 int tls_handshake_rollback_write_callback(tls_handshake_ctx_t ctx
)
179 SSLContext
*myCtx
= (SSLContext
*)ctx
;
180 sslDebugLog("%p\n", myCtx
);
181 return myCtx
->recFuncs
->rollbackWriteCipher(myCtx
->recCtx
);
185 int tls_handshake_advance_read_cipher_callback(tls_handshake_ctx_t ctx
)
187 SSLContext
*myCtx
= (SSLContext
*)ctx
;
188 sslDebugLog("%p\n", myCtx
);
189 return myCtx
->recFuncs
->advanceReadCipher(myCtx
->recCtx
);
193 int tls_handshake_set_protocol_version_callback(tls_handshake_ctx_t ctx
,
194 tls_protocol_version protocolVersion
)
196 SSLContext
*myCtx
= (SSLContext
*)ctx
;
197 myCtx
->negProtocolVersion
= protocolVersion
;
198 return myCtx
->recFuncs
->setProtocolVersion(myCtx
->recCtx
, protocolVersion
);
202 _buildConfigurationSpecificSessionCacheKey(SSLContext
*myCtx
, SSLBuffer
*sessionKey
, SSLBuffer
*outputBuffer
)
204 SSLBuffer configurationBuffer
;
205 configurationBuffer
.data
= NULL
;
206 configurationBuffer
.length
= 0;
207 int err
= SSLGetSessionConfigurationIdentifier(myCtx
, &configurationBuffer
);
208 if (err
!= errSecSuccess
) {
212 outputBuffer
->length
= configurationBuffer
.length
+ sessionKey
->length
;
213 outputBuffer
->data
= (uint8_t *) malloc(outputBuffer
->length
);
214 if (outputBuffer
->data
== NULL
) {
215 free(configurationBuffer
.data
);
216 return errSecAllocate
;
219 memcpy(outputBuffer
->data
, configurationBuffer
.data
, configurationBuffer
.length
);
220 memcpy(outputBuffer
->data
+ configurationBuffer
.length
, sessionKey
->data
, sessionKey
->length
);
222 free(configurationBuffer
.data
);
224 return errSecSuccess
;
228 tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
, SSLBuffer sessionData
)
230 int err
= errSSLSessionNotFound
;
231 SSLContext
*myCtx
= (SSLContext
*)ctx
;
233 if (myCtx
->cache
== NULL
) {
234 return errSSLSessionNotFound
;
237 SSLBuffer configurationSpecificKey
;
238 configurationSpecificKey
.data
= NULL
;
239 configurationSpecificKey
.length
= 0;
240 err
= _buildConfigurationSpecificSessionCacheKey(myCtx
, &sessionKey
, &configurationSpecificKey
);
241 if (err
!= errSecSuccess
) {
245 sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__
, myCtx
, configurationSpecificKey
.length
, configurationSpecificKey
.data
[0], sessionData
.length
);
247 err
= tls_cache_save_session_data(myCtx
->cache
, &configurationSpecificKey
, &sessionData
, myCtx
->sessionCacheTimeout
);
249 free(configurationSpecificKey
.data
);
255 tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
, SSLBuffer
*sessionData
)
257 SSLContext
*myCtx
= (SSLContext
*)ctx
;
258 int err
= errSSLSessionNotFound
;
260 SSLFreeBuffer(&myCtx
->resumableSession
);
261 if (myCtx
->cache
== NULL
) {
262 return errSSLSessionNotFound
;
265 SSLBuffer configurationSpecificKey
;
266 configurationSpecificKey
.data
= NULL
;
267 configurationSpecificKey
.length
= 0;
268 err
= _buildConfigurationSpecificSessionCacheKey(myCtx
, &sessionKey
, &configurationSpecificKey
);
269 if (err
!= errSecSuccess
) {
273 err
= tls_cache_load_session_data(myCtx
->cache
, &configurationSpecificKey
, &myCtx
->resumableSession
);
274 sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx
, configurationSpecificKey
.length
, sessionData
->length
, err
);
275 *sessionData
= myCtx
->resumableSession
;
277 free(configurationSpecificKey
.data
);
283 tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx
, SSLBuffer sessionKey
)
285 int err
= errSSLSessionNotFound
;
286 SSLContext
*myCtx
= (SSLContext
*)ctx
;
288 sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx
, sessionKey
.length
, sessionKey
.data
[0]);
290 err
= tls_cache_delete_session_data(myCtx
->cache
, &sessionKey
);
296 tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx
)
298 SSLContext
*myCtx
= (SSLContext
*)ctx
;
299 sslDebugLog("%p\n", ctx
);
302 tls_cache_empty(myCtx
->cache
);
307 tls_handshake_callbacks_t tls_handshake_callbacks
= {
308 .write
= tls_handshake_write_callback
,
309 .message
= tls_handshake_message_callback
,
310 .ready
= tls_handshake_ready_callback
,
311 .set_retransmit_timer
= tls_handshake_set_retransmit_timer_callback
,
312 .save_session_data
= tls_handshake_save_session_data_callback
,
313 .load_session_data
= tls_handshake_load_session_data_callback
,
314 .delete_session_data
= tls_handshake_delete_session_data_callback
,
315 .delete_all_sessions
= tls_handshake_delete_all_sessions_callback
,
316 .init_pending_cipher
= tls_handshake_init_pending_cipher_callback
,
317 .advance_write_cipher
= tls_handshake_advance_write_callback
,
318 .rollback_write_cipher
= tls_handshake_rollback_write_callback
,
319 .advance_read_cipher
= tls_handshake_advance_read_cipher_callback
,
320 .set_protocol_version
= tls_handshake_set_protocol_version_callback
,