2 * Copyright (c) 1999-2001,2005-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@
25 * sslTransport.c - SSL transport layer
29 #include "sslMemory.h"
30 #include "sslContext.h"
31 #include "sslRecord.h"
33 #include "sslCipherSpecs.h"
35 #include <utilities/simulatecrash_assert.h>
38 #include <utilities/SecIOFormat.h>
39 #include <utilities/SecCFWrappers.h>
40 #import <utilities/SecCoreAnalytics.h>
42 #include <CommonCrypto/CommonDigest.h>
43 #include <Security/SecCertificatePriv.h>
46 static inline void sslIoTrace(
53 sslLogRecordIo("[%p] ===%s: req %4lu moved %4lu status %d",
54 ctx
, op
, req
, moved
, (int)stat
);
57 #define sslIoTrace(ctx, op, req, moved, stat)
60 extern int kSplitDefaultValue
;
62 static OSStatus
SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
);
63 static OSStatus
SSLHandshakeProceed(SSLContext
*ctx
);
64 static OSStatus
SSLSendAlert(SSLContext
*ctx
, tls_alert_level_t level
, tls_alert_t description
);
71 size_t *bytesWritten
) /* RETURNED */
75 size_t dataLen
, processed
;
77 sslLogRecordIo("[%p] SSLWrite top", ctx
);
78 if((ctx
== NULL
) || (bytesWritten
== NULL
)) {
85 case SSL_HdskStateGracefulClose
:
86 err
= errSSLClosedGraceful
;
88 case SSL_HdskStateErrorClose
:
89 case SSL_HdskStateOutOfBandError
:
90 err
= errSSLClosedAbort
;
92 case SSL_HdskStateReady
:
94 case SSL_HdskStateUninit
:
95 /* not ready for I/O, and handshake not in progress */
96 sslIoTrace(ctx
, "SSLWrite(1)", dataLength
, 0, errSecBadReq
);
99 /* handshake in progress or done. Will call SSLHandshakeProceed below if necessary */
103 /* First, we have to wait until the session is ready to send data,
104 so the encryption keys and such have been established. */
105 while (!(ctx
->writeCipher_ready
))
106 { if ((err
= SSLHandshakeProceed(ctx
)) != 0)
110 /* Attempt to empty the write queue before queueing more data */
111 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
116 /* Skip empty writes, fragmentation is done at the coreTLS layer */
118 rec
.contentType
= SSL_RecordTypeAppData
;
119 rec
.contents
.data
= ((uint8_t *)data
) + processed
;
120 rec
.contents
.length
= dataLen
;
121 if ((err
= SSLWriteRecord(rec
, ctx
)) != 0)
123 processed
+= rec
.contents
.length
;
126 /* All the data has been advanced to the write queue */
127 *bytesWritten
= processed
;
128 if ((err
= SSLServiceWriteQueue(ctx
)) == 0) {
134 case errSSLWouldBlock
:
135 case errSSLUnexpectedRecord
:
136 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
137 case errSSLClientCertRequested
:
138 case errSSLClientHelloReceived
:
139 case errSSLClosedGraceful
:
142 sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
144 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
148 sslIoTrace(ctx
, "SSLWrite(2)", dataLength
, *bytesWritten
, err
);
157 size_t *processed
) /* RETURNED */
161 size_t bufSize
, remaining
, count
;
164 sslLogRecordIo("[%p] SSLRead top (dataLength=%ld)", ctx
, dataLength
);
165 if((ctx
== NULL
) || (data
== NULL
) || (processed
== NULL
)) {
168 bufSize
= dataLength
;
169 *processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
172 /* first handle cases in which we know we're finished */
174 case SSL_HdskStateGracefulClose
:
175 err
= errSSLClosedGraceful
;
177 case SSL_HdskStateErrorClose
:
178 case SSL_HdskStateOutOfBandError
:
179 err
= errSSLClosedAbort
;
181 case SSL_HdskStateNoNotifyClose
:
182 err
= errSSLClosedNoNotify
;
188 /* First, we have to wait until the session is ready to receive data,
189 so the encryption keys and such have been established. */
190 while (ctx
->readCipher_ready
== 0) {
191 if ((err
= SSLHandshakeProceed(ctx
)) != 0) {
196 /* Need this to handle the case were SSLRead returned
197 errSSLClientHelloReceived as readCipher_ready is not set yet in that case */
198 if ((err
= tls_handshake_continue(ctx
->hdsk
)) != 0)
201 /* Attempt to service the write queue */
202 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
203 if (err
!= errSSLWouldBlock
) {
209 charPtr
= (uint8_t *)data
;
211 /* If we have data in the buffer, use that first */
212 if (ctx
->receivedDataBuffer
.data
)
214 count
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
217 memcpy(data
, ctx
->receivedDataBuffer
.data
+ ctx
->receivedDataPos
, count
);
221 ctx
->receivedDataPos
+= count
;
224 assert(ctx
->receivedDataPos
<= ctx
->receivedDataBuffer
.length
);
225 assert(*processed
+ remaining
== bufSize
);
226 assert(charPtr
== ((uint8_t *)data
) + *processed
);
228 if (ctx
->receivedDataBuffer
.data
!= 0 &&
229 ctx
->receivedDataPos
>= ctx
->receivedDataBuffer
.length
)
231 SSLFreeBuffer(&ctx
->receivedDataBuffer
);
232 ctx
->receivedDataBuffer
.data
= 0;
233 ctx
->receivedDataPos
= 0;
237 * If we didnt fill up the users buffer, get some more data
239 if (remaining
> 0 && ctx
->state
!= SSL_HdskStateGracefulClose
)
241 assert(ctx
->receivedDataBuffer
.data
== 0);
242 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0) {
245 if (rec
.contentType
== SSL_RecordTypeAppData
||
246 rec
.contentType
== SSL_RecordTypeV2_0
)
248 if (rec
.contents
.length
<= remaining
)
249 { /* Copy all we got in the user's buffer */
250 memcpy(charPtr
, rec
.contents
.data
, rec
.contents
.length
);
251 *processed
+= rec
.contents
.length
;
253 if ((err
= SSLFreeRecord(rec
, ctx
))) {
259 { /* Copy what we can in the user's buffer, keep the rest for next SSLRead. */
260 memcpy(charPtr
, rec
.contents
.data
, remaining
);
261 *processed
+= remaining
;
262 ctx
->receivedDataBuffer
= rec
.contents
;
263 ctx
->receivedDataPos
= remaining
;
267 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0) {
268 /* This may not make much sense, but this is required so that we
269 process the write queue. This replicate exactly the behavior
270 before the coreTLS adoption */
271 if(err
== errSSLClosedGraceful
) {
277 if ((err
= SSLFreeRecord(rec
, ctx
))) {
286 /* test for renegotiate: loop until something useful happens */
287 if(((err
== errSecSuccess
) && (*processed
== 0) && dataLength
) || (err
== errSSLUnexpectedRecord
)) {
288 sslLogNegotiateDebug("SSLRead recursion");
291 /* shut down on serious errors */
294 case errSSLWouldBlock
:
295 case errSSLUnexpectedRecord
:
296 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
297 case errSSLClientCertRequested
:
298 case errSSLClientHelloReceived
:
299 case errSSLClosedGraceful
:
300 case errSSLClosedNoNotify
:
303 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
305 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
309 sslIoTrace(ctx
, "SSLRead returns", dataLength
, *processed
, err
);
314 #include "sslCrypto.h"
319 static void get_extended_peer_id(SSLContext
*ctx
, tls_buffer
*extended_peer_id
)
321 uint8_t md
[CC_SHA256_DIGEST_LENGTH
];
322 __block CC_SHA256_CTX hash_ctx
;
324 CC_SHA256_Init(&hash_ctx
);
326 CC_SHA256_Update(&hash_ctx
, &ctx
->allowAnyRoot
, sizeof(ctx
->allowAnyRoot
));
328 #if !TARGET_OS_IPHONE
329 if(ctx
->trustedLeafCerts
) {
330 CFArrayForEach(ctx
->trustedLeafCerts
, ^(const void *value
) {
331 SecCertificateRef cert
= (SecCertificateRef
) value
;
332 CC_SHA256_Update(&hash_ctx
, SecCertificateGetBytePtr(cert
), (CC_LONG
)SecCertificateGetLength(cert
));
337 CC_SHA256_Update(&hash_ctx
, &ctx
->trustedCertsOnly
, sizeof(ctx
->trustedCertsOnly
));
340 if(ctx
->trustedCerts
) {
341 CFArrayForEach(ctx
->trustedCerts
, ^(const void *value
) {
342 SecCertificateRef cert
= (SecCertificateRef
) value
;
343 CC_SHA256_Update(&hash_ctx
, SecCertificateGetBytePtr(cert
), (CC_LONG
)SecCertificateGetLength(cert
));
347 CC_SHA256_Final(md
, &hash_ctx
);
349 extended_peer_id
->length
= ctx
->peerID
.length
+ sizeof(md
);
350 extended_peer_id
->data
= sslMalloc(extended_peer_id
->length
);
351 memcpy(extended_peer_id
->data
, ctx
->peerID
.data
, ctx
->peerID
.length
);
352 memcpy(extended_peer_id
->data
+ctx
->peerID
.length
, md
, sizeof(md
));
355 /* Send the initial client hello */
357 SSLHandshakeStart(SSLContext
*ctx
)
360 tls_buffer extended_peer_id
;
361 get_extended_peer_id(ctx
, &extended_peer_id
);
362 err
= tls_handshake_negotiate(ctx
->hdsk
, &extended_peer_id
);
363 free(extended_peer_id
.data
);
367 ctx
->readCipher_ready
= 0;
368 ctx
->writeCipher_ready
= 0;
369 SSLChangeHdskState(ctx
, SSL_HdskStatePending
);
375 SSLReHandshake(SSLContext
*ctx
)
381 switch (ctx
->state
) {
382 case SSL_HdskStateGracefulClose
:
383 return errSSLClosedGraceful
;
384 case SSL_HdskStateErrorClose
:
385 case SSL_HdskStateOutOfBandError
:
386 return errSSLClosedAbort
;
387 case SSL_HdskStatePending
:
393 /* If we are the client, we start the negotiation */
394 if(ctx
->protocolSide
== kSSLClientSide
) {
395 return SSLHandshakeStart(ctx
);
397 return tls_handshake_request_renegotiation(ctx
->hdsk
);
402 SSLHandshake(SSLContext
*ctx
)
410 switch (ctx
->state
) {
411 case SSL_HdskStateGracefulClose
:
412 return errSSLClosedGraceful
;
413 case SSL_HdskStateErrorClose
:
414 return errSSLClosedAbort
;
419 if(ctx
->isDTLS
&& ctx
->timeout_deadline
) {
420 CFAbsoluteTime current
= CFAbsoluteTimeGetCurrent();
422 if (ctx
->timeout_deadline
<current
) {
423 sslDebugLog("%p, retransmition deadline expired\n", ctx
);
424 err
= tls_handshake_retransmit_timer_expired(ctx
->hdsk
);
431 /* Initial Client Hello */
432 if(ctx
->state
==SSL_HdskStateUninit
) {
433 /* If we are the client, we start the negotiation */
434 if(ctx
->protocolSide
== kSSLClientSide
) {
435 err
= SSLHandshakeStart(ctx
);
440 SSLChangeHdskState(ctx
, SSL_HdskStatePending
);
443 /* If an out-of-band error occurred, handle it here and then terminate
444 the connection as needed. */
445 if (ctx
->state
== SSL_HdskStateOutOfBandError
) {
446 bool shouldClose
= true;
447 switch (ctx
->outOfBandError
) {
448 case errSecCertificateExpired
:
449 SSLSendAlert(ctx
, tls_handshake_alert_level_fatal
, tls_handshake_alert_CertExpired
);
451 case errSecCertificateRevoked
:
452 SSLSendAlert(ctx
, tls_handshake_alert_level_fatal
, tls_handshake_alert_CertRevoked
);
460 return SSLClose(ctx
);
465 err
= SSLHandshakeProceed(ctx
);
466 if((err
!= 0) && (err
!= errSSLUnexpectedRecord
))
468 } while (ctx
->readCipher_ready
== 0 || ctx
->writeCipher_ready
== 0);
470 /* one more flush at completion of successful handshake */
471 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
475 return errSecSuccess
;
478 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
480 static void ad_log_SecureTransport_early_fail(long signature
)
482 CFStringRef key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature
);
485 SecCoreAnalyticsSendValue(key
, 1);
493 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
495 #include <msgtracer_client.h>
497 static void mt_log_SecureTransport_early_fail(long signature
)
499 char signature_string
[16];
501 snprintf(signature_string
, sizeof(signature_string
), "%ld", signature
);
503 msgtracer_log_with_keys("com.apple.SecureTransport.early_fail", ASL_LEVEL_NOTICE
,
504 "com.apple.message.signature", signature_string
,
505 "com.apple.message.summarize", "YES",
512 static void log_SecureTransport_early_fail(long signature
)
514 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
515 mt_log_SecureTransport_early_fail(signature
);
518 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
519 ad_log_SecureTransport_early_fail(signature
);
525 SSLHandshakeProceed(SSLContext
*ctx
)
529 if ((err
= tls_handshake_continue(ctx
->hdsk
)) != 0)
532 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
537 err
= SSLReadRecord(&rec
, ctx
);
540 sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx
, rec
.contents
.length
, rec
.contentType
);
541 err
= tls_handshake_process(ctx
->hdsk
, rec
.contents
, rec
.contentType
);
542 sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx
, rec
.contents
.length
, rec
.contentType
, (int)err
);
543 SSLFreeRecord(rec
, ctx
);
544 } else if(err
!=errSSLWouldBlock
) {
545 sslDebugLog("%p Read error err=%d\n\n", ctx
, (int)err
);
548 if(ctx
->protocolSide
== kSSLClientSide
&&
549 ctx
->dheEnabled
== false &&
550 !ctx
->serverHelloReceived
&&
551 err
&& err
!= errSSLWouldBlock
)
553 log_SecureTransport_early_fail(err
);
560 SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
)
562 return tls_handshake_process(ctx
->hdsk
, rec
->contents
, rec
->contentType
);
566 SSLClose(SSLContext
*ctx
)
568 OSStatus err
= errSecSuccess
;
570 sslHdskStateDebug("SSLClose");
575 err
= tls_handshake_close(ctx
->hdsk
);
578 err
= SSLServiceWriteQueue(ctx
);
580 SSLChangeHdskState(ctx
, SSL_HdskStateGracefulClose
);
582 err
= errSecSuccess
; /* Ignore errors related to closed streams */
587 SSLSendAlert(SSLContext
*ctx
, tls_alert_level_t alertLevel
, tls_alert_t alert
)
589 sslHdskStateDebug("SSLSendAlert");
594 return tls_handshake_send_alert(ctx
->hdsk
, alertLevel
, alert
);
598 SSLSetError(SSLContext
*ctx
, OSStatus error
)
600 ctx
->state
= SSL_HdskStateOutOfBandError
;
601 ctx
->outOfBandError
= error
;
602 return errSecSuccess
;
606 * Determine how much data the client can be guaranteed to
607 * obtain via SSLRead() without blocking or causing any low-level
608 * read operations to occur.
610 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
611 * and receivedDataPos) are only used in this file.
614 SSLGetBufferedReadSize(SSLContextRef ctx
,
615 size_t *bufSize
) /* RETURNED */
620 if(ctx
->receivedDataBuffer
.data
== NULL
) {
624 assert(ctx
->receivedDataBuffer
.length
>= ctx
->receivedDataPos
);
625 *bufSize
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
627 return errSecSuccess
;