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"
38 #include <utilities/SecIOFormat.h>
39 #include <utilities/SecCFWrappers.h>
41 #include <CommonCrypto/CommonDigest.h>
42 #include <Security/SecCertificatePriv.h>
45 static inline void sslIoTrace(
52 sslLogRecordIo("[%p] ===%s: req %4lu moved %4lu status %d",
53 ctx
, op
, req
, moved
, (int)stat
);
56 #define sslIoTrace(ctx, op, req, moved, stat)
59 extern int kSplitDefaultValue
;
61 static OSStatus
SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
);
62 static OSStatus
SSLHandshakeProceed(SSLContext
*ctx
);
63 static OSStatus
SSLSendAlert(SSLContext
*ctx
, tls_alert_level_t level
, tls_alert_t description
);
70 size_t *bytesWritten
) /* RETURNED */
74 size_t dataLen
, processed
;
76 sslLogRecordIo("[%p] SSLWrite top", ctx
);
77 if((ctx
== NULL
) || (bytesWritten
== NULL
)) {
84 case SSL_HdskStateGracefulClose
:
85 err
= errSSLClosedGraceful
;
87 case SSL_HdskStateErrorClose
:
88 case SSL_HdskStateOutOfBandError
:
89 err
= errSSLClosedAbort
;
91 case SSL_HdskStateReady
:
93 case SSL_HdskStateUninit
:
94 /* not ready for I/O, and handshake not in progress */
95 sslIoTrace(ctx
, "SSLWrite(1)", dataLength
, 0, errSecBadReq
);
98 /* handshake in progress or done. Will call SSLHandshakeProceed below if necessary */
102 /* First, we have to wait until the session is ready to send data,
103 so the encryption keys and such have been established. */
104 while (!(ctx
->writeCipher_ready
))
105 { if ((err
= SSLHandshakeProceed(ctx
)) != 0)
109 /* Attempt to empty the write queue before queueing more data */
110 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
115 /* Skip empty writes, fragmentation is done at the coreTLS layer */
117 rec
.contentType
= SSL_RecordTypeAppData
;
118 rec
.contents
.data
= ((uint8_t *)data
) + processed
;
119 rec
.contents
.length
= dataLen
;
120 if ((err
= SSLWriteRecord(rec
, ctx
)) != 0)
122 processed
+= rec
.contents
.length
;
125 /* All the data has been advanced to the write queue */
126 *bytesWritten
= processed
;
127 if ((err
= SSLServiceWriteQueue(ctx
)) == 0) {
133 case errSSLWouldBlock
:
134 case errSSLUnexpectedRecord
:
135 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
136 case errSSLClientCertRequested
:
137 case errSSLClientHelloReceived
:
138 case errSSLClosedGraceful
:
141 sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
143 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
147 sslIoTrace(ctx
, "SSLWrite(2)", dataLength
, *bytesWritten
, err
);
156 size_t *processed
) /* RETURNED */
160 size_t bufSize
, remaining
, count
;
163 sslLogRecordIo("[%p] SSLRead top (dataLength=%ld)", ctx
, dataLength
);
164 if((ctx
== NULL
) || (data
== NULL
) || (processed
== NULL
)) {
167 bufSize
= dataLength
;
168 *processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
171 /* first handle cases in which we know we're finished */
173 case SSL_HdskStateGracefulClose
:
174 err
= errSSLClosedGraceful
;
176 case SSL_HdskStateErrorClose
:
177 case SSL_HdskStateOutOfBandError
:
178 err
= errSSLClosedAbort
;
180 case SSL_HdskStateNoNotifyClose
:
181 err
= errSSLClosedNoNotify
;
187 /* First, we have to wait until the session is ready to receive data,
188 so the encryption keys and such have been established. */
189 while (ctx
->readCipher_ready
== 0) {
190 if ((err
= SSLHandshakeProceed(ctx
)) != 0) {
195 /* Need this to handle the case were SSLRead returned
196 errSSLClientHelloReceived as readCipher_ready is not set yet in that case */
197 if ((err
= tls_handshake_continue(ctx
->hdsk
)) != 0)
200 /* Attempt to service the write queue */
201 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
202 if (err
!= errSSLWouldBlock
) {
208 charPtr
= (uint8_t *)data
;
210 /* If we have data in the buffer, use that first */
211 if (ctx
->receivedDataBuffer
.data
)
213 count
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
216 memcpy(data
, ctx
->receivedDataBuffer
.data
+ ctx
->receivedDataPos
, count
);
220 ctx
->receivedDataPos
+= count
;
223 assert(ctx
->receivedDataPos
<= ctx
->receivedDataBuffer
.length
);
224 assert(*processed
+ remaining
== bufSize
);
225 assert(charPtr
== ((uint8_t *)data
) + *processed
);
227 if (ctx
->receivedDataBuffer
.data
!= 0 &&
228 ctx
->receivedDataPos
>= ctx
->receivedDataBuffer
.length
)
230 SSLFreeBuffer(&ctx
->receivedDataBuffer
);
231 ctx
->receivedDataBuffer
.data
= 0;
232 ctx
->receivedDataPos
= 0;
236 * If we didnt fill up the users buffer, get some more data
238 if (remaining
> 0 && ctx
->state
!= SSL_HdskStateGracefulClose
)
240 assert(ctx
->receivedDataBuffer
.data
== 0);
241 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0) {
244 if (rec
.contentType
== SSL_RecordTypeAppData
||
245 rec
.contentType
== SSL_RecordTypeV2_0
)
247 if (rec
.contents
.length
<= remaining
)
248 { /* Copy all we got in the user's buffer */
249 memcpy(charPtr
, rec
.contents
.data
, rec
.contents
.length
);
250 *processed
+= rec
.contents
.length
;
252 if ((err
= SSLFreeRecord(rec
, ctx
))) {
258 { /* Copy what we can in the user's buffer, keep the rest for next SSLRead. */
259 memcpy(charPtr
, rec
.contents
.data
, remaining
);
260 *processed
+= remaining
;
261 ctx
->receivedDataBuffer
= rec
.contents
;
262 ctx
->receivedDataPos
= remaining
;
266 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0) {
267 /* This may not make much sense, but this is required so that we
268 process the write queue. This replicate exactly the behavior
269 before the coreTLS adoption */
270 if(err
== errSSLClosedGraceful
) {
276 if ((err
= SSLFreeRecord(rec
, ctx
))) {
285 /* test for renegotiate: loop until something useful happens */
286 if(((err
== errSecSuccess
) && (*processed
== 0) && dataLength
) || (err
== errSSLUnexpectedRecord
)) {
287 sslLogNegotiateDebug("SSLRead recursion");
290 /* shut down on serious errors */
293 case errSSLWouldBlock
:
294 case errSSLUnexpectedRecord
:
295 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
296 case errSSLClientCertRequested
:
297 case errSSLClientHelloReceived
:
298 case errSSLClosedGraceful
:
299 case errSSLClosedNoNotify
:
302 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
304 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
308 sslIoTrace(ctx
, "SSLRead returns", dataLength
, *processed
, err
);
313 #include "sslCrypto.h"
318 static void get_extended_peer_id(SSLContext
*ctx
, tls_buffer
*extended_peer_id
)
320 uint8_t md
[CC_SHA256_DIGEST_LENGTH
];
321 __block CC_SHA256_CTX hash_ctx
;
323 CC_SHA256_Init(&hash_ctx
);
325 CC_SHA256_Update(&hash_ctx
, &ctx
->allowAnyRoot
, sizeof(ctx
->allowAnyRoot
));
327 #if !TARGET_OS_IPHONE
328 if(ctx
->trustedLeafCerts
) {
329 CFArrayForEach(ctx
->trustedLeafCerts
, ^(const void *value
) {
330 SecCertificateRef cert
= (SecCertificateRef
) value
;
331 CC_SHA256_Update(&hash_ctx
, SecCertificateGetBytePtr(cert
), (CC_LONG
)SecCertificateGetLength(cert
));
336 CC_SHA256_Update(&hash_ctx
, &ctx
->trustedCertsOnly
, sizeof(ctx
->trustedCertsOnly
));
339 if(ctx
->trustedCerts
) {
340 CFArrayForEach(ctx
->trustedCerts
, ^(const void *value
) {
341 SecCertificateRef cert
= (SecCertificateRef
) value
;
342 CC_SHA256_Update(&hash_ctx
, SecCertificateGetBytePtr(cert
), (CC_LONG
)SecCertificateGetLength(cert
));
346 CC_SHA256_Final(md
, &hash_ctx
);
348 extended_peer_id
->length
= ctx
->peerID
.length
+ sizeof(md
);
349 extended_peer_id
->data
= sslMalloc(extended_peer_id
->length
);
350 memcpy(extended_peer_id
->data
, ctx
->peerID
.data
, ctx
->peerID
.length
);
351 memcpy(extended_peer_id
->data
+ctx
->peerID
.length
, md
, sizeof(md
));
354 /* Send the initial client hello */
356 SSLHandshakeStart(SSLContext
*ctx
)
359 tls_buffer extended_peer_id
;
360 get_extended_peer_id(ctx
, &extended_peer_id
);
361 err
= tls_handshake_negotiate(ctx
->hdsk
, &extended_peer_id
);
362 free(extended_peer_id
.data
);
366 ctx
->readCipher_ready
= 0;
367 ctx
->writeCipher_ready
= 0;
368 SSLChangeHdskState(ctx
, SSL_HdskStatePending
);
374 SSLReHandshake(SSLContext
*ctx
)
380 switch (ctx
->state
) {
381 case SSL_HdskStateGracefulClose
:
382 return errSSLClosedGraceful
;
383 case SSL_HdskStateErrorClose
:
384 case SSL_HdskStateOutOfBandError
:
385 return errSSLClosedAbort
;
386 case SSL_HdskStatePending
:
392 /* If we are the client, we start the negotiation */
393 if(ctx
->protocolSide
== kSSLClientSide
) {
394 return SSLHandshakeStart(ctx
);
396 return tls_handshake_request_renegotiation(ctx
->hdsk
);
401 SSLHandshake(SSLContext
*ctx
)
409 switch (ctx
->state
) {
410 case SSL_HdskStateGracefulClose
:
411 return errSSLClosedGraceful
;
412 case SSL_HdskStateErrorClose
:
413 return errSSLClosedAbort
;
418 if(ctx
->isDTLS
&& ctx
->timeout_deadline
) {
419 CFAbsoluteTime current
= CFAbsoluteTimeGetCurrent();
421 if (ctx
->timeout_deadline
<current
) {
422 sslDebugLog("%p, retransmition deadline expired\n", ctx
);
423 err
= tls_handshake_retransmit_timer_expired(ctx
->hdsk
);
430 /* Initial Client Hello */
431 if(ctx
->state
==SSL_HdskStateUninit
) {
432 /* If we are the client, we start the negotiation */
433 if(ctx
->protocolSide
== kSSLClientSide
) {
434 err
= SSLHandshakeStart(ctx
);
439 SSLChangeHdskState(ctx
, SSL_HdskStatePending
);
442 /* If an out-of-band error occurred, handle it here and then terminate
443 the connection as needed. */
444 if (ctx
->state
== SSL_HdskStateOutOfBandError
) {
445 bool shouldClose
= true;
446 switch (ctx
->outOfBandError
) {
447 case errSecCertificateExpired
:
448 SSLSendAlert(ctx
, tls_handshake_alert_level_fatal
, tls_handshake_alert_CertExpired
);
450 case errSecCertificateRevoked
:
451 SSLSendAlert(ctx
, tls_handshake_alert_level_fatal
, tls_handshake_alert_CertRevoked
);
459 return SSLClose(ctx
);
464 err
= SSLHandshakeProceed(ctx
);
465 if((err
!= 0) && (err
!= errSSLUnexpectedRecord
))
467 } while (ctx
->readCipher_ready
== 0 || ctx
->writeCipher_ready
== 0);
469 /* one more flush at completion of successful handshake */
470 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
474 return errSecSuccess
;
477 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
479 #include "SecADWrapper.h"
481 static void ad_log_SecureTransport_early_fail(long signature
)
483 CFStringRef key
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature
);
486 SecADAddValueForScalarKey(key
, 1);
494 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
496 #include <msgtracer_client.h>
498 static void mt_log_SecureTransport_early_fail(long signature
)
500 char signature_string
[16];
502 snprintf(signature_string
, sizeof(signature_string
), "%ld", signature
);
504 msgtracer_log_with_keys("com.apple.SecureTransport.early_fail", ASL_LEVEL_NOTICE
,
505 "com.apple.message.signature", signature_string
,
506 "com.apple.message.summarize", "YES",
513 static void log_SecureTransport_early_fail(long signature
)
515 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
516 mt_log_SecureTransport_early_fail(signature
);
519 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
520 ad_log_SecureTransport_early_fail(signature
);
526 SSLHandshakeProceed(SSLContext
*ctx
)
530 if ((err
= tls_handshake_continue(ctx
->hdsk
)) != 0)
533 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
538 err
= SSLReadRecord(&rec
, ctx
);
541 sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx
, rec
.contents
.length
, rec
.contentType
);
542 err
= tls_handshake_process(ctx
->hdsk
, rec
.contents
, rec
.contentType
);
543 sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx
, rec
.contents
.length
, rec
.contentType
, (int)err
);
544 SSLFreeRecord(rec
, ctx
);
545 } else if(err
!=errSSLWouldBlock
) {
546 sslDebugLog("%p Read error err=%d\n\n", ctx
, (int)err
);
549 if(ctx
->protocolSide
== kSSLClientSide
&&
550 ctx
->dheEnabled
== false &&
551 !ctx
->serverHelloReceived
&&
552 err
&& err
!= errSSLWouldBlock
)
554 log_SecureTransport_early_fail(err
);
561 SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
)
563 return tls_handshake_process(ctx
->hdsk
, rec
->contents
, rec
->contentType
);
567 SSLClose(SSLContext
*ctx
)
569 OSStatus err
= errSecSuccess
;
571 sslHdskStateDebug("SSLClose");
576 err
= tls_handshake_close(ctx
->hdsk
);
579 err
= SSLServiceWriteQueue(ctx
);
581 SSLChangeHdskState(ctx
, SSL_HdskStateGracefulClose
);
583 err
= errSecSuccess
; /* Ignore errors related to closed streams */
588 SSLSendAlert(SSLContext
*ctx
, tls_alert_level_t alertLevel
, tls_alert_t alert
)
590 sslHdskStateDebug("SSLSendAlert");
595 return tls_handshake_send_alert(ctx
->hdsk
, alertLevel
, alert
);
599 SSLSetError(SSLContext
*ctx
, OSStatus error
)
601 ctx
->state
= SSL_HdskStateOutOfBandError
;
602 ctx
->outOfBandError
= error
;
603 return errSecSuccess
;
607 * Determine how much data the client can be guaranteed to
608 * obtain via SSLRead() without blocking or causing any low-level
609 * read operations to occur.
611 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
612 * and receivedDataPos) are only used in this file.
615 SSLGetBufferedReadSize(SSLContextRef ctx
,
616 size_t *bufSize
) /* RETURNED */
621 if(ctx
->receivedDataBuffer
.data
== NULL
) {
625 assert(ctx
->receivedDataBuffer
.length
>= ctx
->receivedDataPos
);
626 *bufSize
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
628 return errSecSuccess
;