1/*
2 * Copyright (c) 2013-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25#include <stdio.h>
26#include "tlsCallbacks.h"
27#include "sslContext.h"
28#include "sslCrypto.h"
29#include "sslDebug.h"
30#include "appleSession.h"
31#include <Security/SecCertificate.h>
32#include <Security/SecCertificatePriv.h>
33#include "utilities/SecCFRelease.h"
34
35
36static
37int tls_handshake_write_callback(tls_handshake_ctx_t ctx, const SSLBuffer data, uint8_t content_type)
38{
39    SSLContext *myCtx = (SSLContext *)ctx;
40    sslDebugLog("%p (rec.len=%zd, ct=%d, d[0]=%d)\n", myCtx, data.length, content_type, data.data[0]);
41
42    SSLRecord rec;
43
44    rec.contents=data;
45    rec.contentType=content_type;
46
47    return myCtx->recFuncs->write(myCtx->recCtx,rec);
48}
49
50
51static int
52tls_handshake_message_callback(tls_handshake_ctx_t ctx, tls_handshake_message_t event)
53{
54    SSLContext *myCtx = (SSLContext *)ctx;
55    const tls_buffer *npn_data;
56
57    sslDebugLog("%p, message = %d\n", ctx, event);
58
59    switch(event) {
60        case tls_handshake_message_certificate_request:
61            assert(myCtx->protocolSide == kSSLClientSide);
62            // Need to call this here, in case SetCertificate was already called.
63            myCtx->clientCertState = kSSLClientCertRequested;
64            myCtx->clientAuthTypes = tls_handshake_get_peer_acceptable_client_auth_type(myCtx->hdsk, &myCtx->numAuthTypes);
65            SSLUpdateNegotiatedClientAuthType(myCtx);
66            if (myCtx->breakOnCertRequest && (myCtx->localCert==NULL))
67            {
68                myCtx->signalCertRequest = true;
69                return errSSLClientCertRequested;
70            }
71            break;
72        case tls_handshake_message_client_hello:
73            myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs);
74            break;
75        case tls_handshake_message_server_hello:
76            npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk);
77            if(npn_data)
78                myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length);
79            myCtx->peerSigAlgs = tls_handshake_get_peer_signature_algorithms(myCtx->hdsk, &myCtx->numPeerSigAlgs);
80            break;
81        case tls_handshake_message_certificate:
82            return tls_verify_peer_cert(myCtx);
83        case tls_handshake_message_NPN_encrypted_extension:
84            npn_data = tls_handshake_get_peer_npn_data(myCtx->hdsk);
85            if(npn_data)
86                myCtx->npnFunc(myCtx, myCtx->npnFuncInfo, npn_data->data, npn_data->length);
87            break;
88        default:
89            break;
90    }
91
92    return 0;
93}
94
95static void
96tls_handshake_ready_callback(tls_handshake_ctx_t ctx, bool write, bool ready)
97{
98    SSLContext *myCtx = (SSLContext *)ctx;
99
100    sslDebugLog("%p %s ready=%d\n", myCtx, write?"write":"read", ready);
101
102    if(write) {
103        myCtx->writeCipher_ready=ready?1:0;
104    } else {
105        myCtx->readCipher_ready=ready?1:0;
106        if(ready) {
107            SSLChangeHdskState(myCtx, SSL_HdskStateReady);
108        } else {
109            SSLChangeHdskState(myCtx, SSL_HdskStatePending);
110        }
111    }
112}
113
114static int
115tls_handshake_set_retransmit_timer_callback(tls_handshake_ctx_t ctx, int attempt)
116{
117    SSLContext *myCtx = (SSLContext *)ctx;
118
119    sslDebugLog("%p attempt=%d\n", ctx, attempt);
120
121    if(attempt) {
122        myCtx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<<(attempt-1))*myCtx->timeout_duration);
123    } else {
124        myCtx->timeout_deadline = 0; // cancel the timeout
125    }
126    return 0;
127}
128
129static int
130tls_handshake_init_pending_cipher_callback(tls_handshake_ctx_t ctx,
131                                                  uint16_t            selectedCipher,
132                                                  bool                server,
133                                                  SSLBuffer           key)
134{
135    sslDebugLog("%p, cipher=%04x, server=%d\n", ctx, selectedCipher, server);
136    SSLContext *myCtx = (SSLContext *)ctx;
137    return myCtx->recFuncs->initPendingCiphers(myCtx->recCtx, selectedCipher, server, key);
138}
139
140static int
141tls_handshake_advance_write_callback(tls_handshake_ctx_t ctx)
142{
143    SSLContext *myCtx = (SSLContext *)ctx;
144    sslDebugLog("%p\n", myCtx);
145    //FIXME: need to filter on cipher too - require missing coretls ciphersuite header */
146    bool split = (myCtx->oneByteRecordEnable && (myCtx->negProtocolVersion<=TLS_Version_1_0));
147    myCtx->recFuncs->setOption(myCtx->recCtx, kSSLRecordOptionSendOneByteRecord, split);
148    return myCtx->recFuncs->advanceWriteCipher(myCtx->recCtx);
149}
150
151static
152int tls_handshake_rollback_write_callback(tls_handshake_ctx_t ctx)
153{
154    SSLContext *myCtx = (SSLContext *)ctx;
155    sslDebugLog("%p\n", myCtx);
156    return myCtx->recFuncs->rollbackWriteCipher(myCtx->recCtx);
157}
158
159static
160int tls_handshake_advance_read_cipher_callback(tls_handshake_ctx_t ctx)
161{
162    SSLContext *myCtx = (SSLContext *)ctx;
163    sslDebugLog("%p\n", myCtx);
164    return myCtx->recFuncs->advanceReadCipher(myCtx->recCtx);
165}
166
167static
168int tls_handshake_set_protocol_version_callback(tls_handshake_ctx_t ctx,
169                                      tls_protocol_version  protocolVersion)
170{
171    SSLContext *myCtx = (SSLContext *)ctx;
172    //printf("%s: %p, pv=%04x\n", __FUNCTION__, ctx, protocolVersion);
173    myCtx->negProtocolVersion = protocolVersion;
174    return myCtx->recFuncs->setProtocolVersion(myCtx->recCtx, protocolVersion);
175}
176
177static int
178tls_handshake_save_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer sessionData)
179{
180    sslDebugLog("%s: %p, key len=%zd, k[0]=%02x, data len=%zd\n", __FUNCTION__, (SSLContext *)ctx, sessionKey.length, sessionKey.data[0], sessionData.length);
181    return sslAddSession(sessionKey, sessionData, 0);
182}
183
184static int
185tls_handshake_load_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey, SSLBuffer *sessionData)
186{
187    SSLContext *myCtx = (SSLContext *)ctx;
188    int err;
189
190    SSLFreeBuffer(&myCtx->resumableSession);
191    err = sslCopySession(sessionKey, &myCtx->resumableSession);
192
193    sslDebugLog("%p, key len=%zd, data len=%zd, err=%d\n", ctx, sessionKey.length, sessionData->length, err);
194
195    *sessionData = myCtx->resumableSession;
196
197    return err;
198}
199
200static int
201tls_handshake_delete_session_data_callback(tls_handshake_ctx_t ctx, SSLBuffer sessionKey)
202{
203    sslDebugLog("%p, key len=%zd k[0]=%02x\n", ctx, sessionKey.length, sessionKey.data[0]);
204    return sslDeleteSession(sessionKey);
205}
206
207static int
208tls_handshake_delete_all_sessions_callback(tls_handshake_ctx_t ctx)
209{
210    sslDebugLog("%p\n", ctx);
211
212    return sslCleanupSession();
213}
214
215tls_handshake_callbacks_t tls_handshake_callbacks = {
216    .write = tls_handshake_write_callback,
217    .message = tls_handshake_message_callback,
218    .ready = tls_handshake_ready_callback,
219    .set_retransmit_timer = tls_handshake_set_retransmit_timer_callback,
220    .save_session_data = tls_handshake_save_session_data_callback,
221    .load_session_data = tls_handshake_load_session_data_callback,
222    .delete_session_data = tls_handshake_delete_session_data_callback,
223    .delete_all_sessions = tls_handshake_delete_all_sessions_callback,
224    .init_pending_cipher = tls_handshake_init_pending_cipher_callback,
225    .advance_write_cipher = tls_handshake_advance_write_callback,
226    .rollback_write_cipher = tls_handshake_rollback_write_callback,
227    .advance_read_cipher = tls_handshake_advance_read_cipher_callback,
228    .set_protocol_version = tls_handshake_set_protocol_version_callback,
229};
230
231
232