2 * Copyright (c) 1999-2001,2005-2012 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"
32 #include "sslAlertMessage.h"
33 #include "sslSession.h"
35 #include "sslCipherSpecs.h"
41 #include <utilities/SecIOFormat.h>
44 static inline void sslIoTrace(
50 sslLogRecordIo("===%s: req %4lu moved %4lu status %d",
51 op
, req
, moved
, (int)stat
);
54 #define sslIoTrace(op, req, moved, stat)
57 extern int kSplitDefaultValue
;
59 static OSStatus
SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
);
60 static OSStatus
SSLHandshakeProceed(SSLContext
*ctx
);
61 static OSStatus
SSLInitConnection(SSLContext
*ctx
);
63 static Boolean
isFalseStartAllowed(SSLContext
*ctx
)
65 SSL_CipherAlgorithm c
=sslCipherSuiteGetSymmetricCipherAlgorithm(ctx
->selectedCipher
);
66 KeyExchangeMethod kem
=sslCipherSuiteGetKeyExchangeMethod(ctx
->selectedCipher
);
69 /* Whitelisting allowed ciphers, kem and client auth type */
72 (c
==SSL_CipherAlgorithmAES_128_CBC
) ||
73 (c
==SSL_CipherAlgorithmAES_128_GCM
) ||
74 (c
==SSL_CipherAlgorithmAES_256_CBC
) ||
75 (c
==SSL_CipherAlgorithmAES_256_GCM
) ||
76 (c
==SSL_CipherAlgorithmRC4_128
)
78 (kem
==SSL_ECDHE_ECDSA
) ||
79 (kem
==SSL_ECDHE_RSA
) ||
83 (ctx
->negAuthType
==SSLClientAuthNone
) ||
84 (ctx
->negAuthType
==SSLClientAuth_DSSSign
) ||
85 (ctx
->negAuthType
==SSLClientAuth_RSASign
) ||
86 (ctx
->negAuthType
==SSLClientAuth_ECDSASign
)
96 size_t *bytesWritten
) /* RETURNED */
100 size_t dataLen
, processed
;
103 sslLogRecordIo("SSLWrite top");
104 if((ctx
== NULL
) || (bytesWritten
== NULL
)) {
107 dataLen
= dataLength
;
108 processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
112 case SSL_HdskStateGracefulClose
:
113 err
= errSSLClosedGraceful
;
115 case SSL_HdskStateErrorClose
:
116 err
= errSSLClosedAbort
;
118 case SSL_HdskStateServerReady
:
119 case SSL_HdskStateClientReady
:
122 if(ctx
->state
< SSL_HdskStateServerHello
) {
123 /* not ready for I/O, and handshake not in progress */
124 sslIoTrace("SSLWrite", dataLength
, 0, errSecBadReq
);
127 /* handshake in progress; will call SSLHandshakeProceed below */
131 /* First, we have to wait until the session is ready to send data,
132 so the encryption keys and such have been established. */
135 (ctx
->state
==SSL_HdskStateServerReady
) ||
136 (ctx
->state
==SSL_HdskStateClientReady
) ||
137 (ctx
->writeCipher_ready
&& ctx
->falseStartEnabled
&& isFalseStartAllowed(ctx
))
139 { if ((err
= SSLHandshakeProceed(ctx
)) != 0)
143 /* Attempt to empty the write queue before queueing more data */
144 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
147 /* Check if we should split the data into 1/n-1 to avoid known-IV issue */
148 split
= (ctx
->oneByteRecordEnable
&& ctx
->negProtocolVersion
<= TLS_Version_1_0
);
150 /* Only split if cipher algorithm uses CBC mode */
151 SSL_CipherAlgorithm cipherAlg
= sslCipherSuiteGetSymmetricCipherAlgorithm(ctx
->selectedCipher
);
152 split
= (cipherAlg
> SSL_CipherAlgorithmRC4_128
&&
153 cipherAlg
< SSL_CipherAlgorithmAES_128_GCM
);
155 /* Determine whether we start splitting on second write */
156 split
= (kSplitDefaultValue
== 2 && !ctx
->wroteAppData
) ? false : true;
162 * Fragment, package and encrypt the data and queue the resulting data
166 { rec
.contentType
= SSL_RecordTypeAppData
;
167 rec
.protocolVersion
= ctx
->negProtocolVersion
;
168 rec
.contents
.data
= ((uint8_t *)data
) + processed
;
170 if (processed
== 0 && split
)
171 rec
.contents
.length
= 1;
172 else if (dataLen
< MAX_RECORD_LENGTH
)
173 rec
.contents
.length
= dataLen
;
175 rec
.contents
.length
= MAX_RECORD_LENGTH
;
177 if ((err
= SSLWriteRecord(rec
, ctx
)) != 0)
179 processed
+= rec
.contents
.length
;
180 dataLen
-= rec
.contents
.length
;
181 ctx
->wroteAppData
= 1;
184 /* All the data has been advanced to the write queue */
185 *bytesWritten
= processed
;
186 if ((err
= SSLServiceWriteQueue(ctx
)) == 0) {
192 case errSSLWouldBlock
:
193 case errSSLUnexpectedRecord
:
194 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
195 case errSSLClientCertRequested
:
196 case errSSLClosedGraceful
:
199 sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
201 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
205 sslIoTrace("SSLWrite", dataLength
, *bytesWritten
, err
);
214 size_t *processed
) /* RETURNED */
218 size_t bufSize
, remaining
, count
;
221 sslLogRecordIo("SSLRead top");
222 if((ctx
== NULL
) || (data
== NULL
) || (processed
== NULL
)) {
225 bufSize
= dataLength
;
226 *processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
229 /* first handle cases in which we know we're finished */
231 case SSL_HdskStateGracefulClose
:
232 err
= errSSLClosedGraceful
;
234 case SSL_HdskStateErrorClose
:
235 err
= errSSLClosedAbort
;
237 case SSL_HdskStateNoNotifyClose
:
238 err
= errSSLClosedNoNotify
;
244 /* First, we have to wait until the session is ready to receive data,
245 so the encryption keys and such have been established. */
247 while (ctx
->readCipher_ready
== 0) {
248 if ((err
= SSLHandshakeProceed(ctx
)) != 0) {
253 /* Attempt to service the write queue */
254 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
255 if (err
!= errSSLWouldBlock
) {
258 err
= errSecSuccess
; /* Write blocking shouldn't stop attempts to read */
262 charPtr
= (uint8_t *)data
;
263 if (ctx
->receivedDataBuffer
.data
)
264 { count
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
267 memcpy(data
, ctx
->receivedDataBuffer
.data
+ ctx
->receivedDataPos
, count
);
271 ctx
->receivedDataPos
+= count
;
274 assert(ctx
->receivedDataPos
<= ctx
->receivedDataBuffer
.length
);
275 assert(*processed
+ remaining
== bufSize
);
276 assert(charPtr
== ((uint8_t *)data
) + *processed
);
278 if (ctx
->receivedDataBuffer
.data
!= 0 &&
279 ctx
->receivedDataPos
>= ctx
->receivedDataBuffer
.length
)
280 { SSLFreeBuffer(&ctx
->receivedDataBuffer
);
281 ctx
->receivedDataBuffer
.data
= 0;
282 ctx
->receivedDataPos
= 0;
286 * This while statement causes a hang when using nonblocking low-level I/O!
287 while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
288 ..what we really have to do is just return as soon as we read one
289 record. A performance hit in the nonblocking case, but that is
290 the only way this code can work in both modes...
292 if (remaining
> 0 && ctx
->state
!= SSL_HdskStateGracefulClose
)
293 { assert(ctx
->receivedDataBuffer
.data
== 0);
294 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0) {
297 if (rec
.contentType
== SSL_RecordTypeAppData
||
298 rec
.contentType
== SSL_RecordTypeV2_0
)
299 { if (rec
.contents
.length
<= remaining
)
300 { memcpy(charPtr
, rec
.contents
.data
, rec
.contents
.length
);
301 remaining
-= rec
.contents
.length
;
302 charPtr
+= rec
.contents
.length
;
303 *processed
+= rec
.contents
.length
;
305 if ((err
= SSLFreeRecord(rec
, ctx
))) {
311 { memcpy(charPtr
, rec
.contents
.data
, remaining
);
312 charPtr
+= remaining
;
313 *processed
+= remaining
;
314 ctx
->receivedDataBuffer
= rec
.contents
;
315 ctx
->receivedDataPos
= remaining
;
320 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0) {
323 if ((err
= SSLFreeRecord(rec
, ctx
))) {
332 /* test for renegotiate: loop until something useful happens */
333 if(((err
== errSecSuccess
) && (*processed
== 0) && dataLength
) || (err
== errSSLUnexpectedRecord
)) {
334 sslLogNegotiateDebug("SSLRead recursion");
337 /* shut down on serious errors */
340 case errSSLWouldBlock
:
341 case errSSLUnexpectedRecord
:
342 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
343 case errSSLClientCertRequested
:
344 case errSSLClosedGraceful
:
345 case errSSLClosedNoNotify
:
348 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
350 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
354 sslIoTrace("SSLRead ", dataLength
, *processed
, err
);
359 #include "sslCrypto.h"
363 SSLHandshake(SSLContext
*ctx
)
370 if (ctx
->state
== SSL_HdskStateGracefulClose
)
371 return errSSLClosedGraceful
;
372 if (ctx
->state
== SSL_HdskStateErrorClose
)
373 return errSSLClosedAbort
;
376 /* Because of Radar 6133465, we have to disable this to allow the sending
377 of client hello extensions for ECDSA... */
378 ctx
->versionSsl2Enable
= false;
381 if(ctx
->validCipherSuites
== NULL
) {
382 /* build list of legal cipherSpecs */
383 err
= sslBuildCipherSuiteArray(ctx
);
391 if (ctx
->timeout_deadline
<CFAbsoluteTimeGetCurrent()) {
396 while (ctx
->readCipher_ready
== 0 || ctx
->writeCipher_ready
== 0)
398 err
= SSLHandshakeProceed(ctx
);
399 if((err
!= 0) && (err
!= errSSLUnexpectedRecord
))
403 /* one more flush at completion of successful handshake */
404 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
408 return errSecSuccess
;
413 SSLHandshakeProceed(SSLContext
*ctx
)
417 if (ctx
->signalServerAuth
) {
418 ctx
->signalServerAuth
= false;
419 return errSSLServerAuthCompleted
;
421 if (ctx
->signalCertRequest
) {
422 ctx
->signalCertRequest
= false;
423 return errSSLClientCertRequested
;
425 if (ctx
->signalClientAuth
) {
426 ctx
->signalClientAuth
= false;
427 return errSSLClientAuthCompleted
;
430 if (ctx
->state
== SSL_HdskStateUninit
)
431 if ((err
= SSLInitConnection(ctx
)) != 0)
434 /* This is our cue that we dropped out of the handshake
435 * to let the client pick an identity, move state back
436 * to server hello done and continue processing.
438 if ((ctx
->protocolSide
== kSSLClientSide
) &&
439 (ctx
->state
== SSL_HdskStateClientCert
))
440 if ((err
= SSLAdvanceHandshake(SSL_HdskServerHelloDone
, ctx
)) != 0)
443 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
446 assert(ctx
->readCipher_ready
== 0);
447 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0)
449 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0)
451 SSLFreeRecord(rec
, ctx
);
454 if ((err
= SSLFreeRecord(rec
, ctx
)))
457 return errSecSuccess
;
461 SSLInitConnection(SSLContext
*ctx
)
462 { OSStatus err
= errSecSuccess
;
464 if (ctx
->protocolSide
== kSSLClientSide
) {
465 SSLChangeHdskState(ctx
, SSL_HdskStateClientUninit
);
468 { assert(ctx
->protocolSide
== kSSLServerSide
);
469 SSLChangeHdskState(ctx
, SSL_HdskStateServerUninit
);
472 if (ctx
->peerID
.data
!= 0)
473 { SSLGetSessionData(&ctx
->resumableSession
, ctx
);
474 /* Ignore errors; just treat as uncached session */
478 * If we have a cached resumable session, blow it off if it's a version
479 * which is not currently enabled.
481 Boolean cachedV3OrTls1
= ctx
->isDTLS
;
483 if (ctx
->resumableSession
.data
!= 0) {
484 SSLProtocolVersion savedVersion
;
485 if ((err
= SSLRetrieveSessionProtocolVersion(ctx
->resumableSession
,
486 &savedVersion
, ctx
)) != 0)
490 ? (savedVersion
<= ctx
->minProtocolVersion
&&
491 savedVersion
>= ctx
->maxProtocolVersion
)
492 : (savedVersion
>= ctx
->minProtocolVersion
&&
493 savedVersion
<= ctx
->maxProtocolVersion
)) {
494 cachedV3OrTls1
= savedVersion
!= SSL_Version_2_0
;
495 sslLogResumSessDebug("===attempting to resume session");
497 sslLogResumSessDebug("===Resumable session protocol mismatch");
498 SSLFreeBuffer(&ctx
->resumableSession
);
503 * If we're the client & handshake hasn't yet begun, start it by
504 * pretending we just received a hello request
506 if (ctx
->state
== SSL_HdskStateClientUninit
&& ctx
->writeCipher_ready
== 0)
508 assert(ctx
->negProtocolVersion
== SSL_Version_Undetermined
);
510 if(!cachedV3OrTls1
) {
511 /* SSL2 client hello with possible upgrade */
512 err
= SSL2AdvanceHandshake(SSL2_MsgKickstart
, ctx
);
517 err
= SSLAdvanceHandshake(SSL_HdskHelloRequest
, ctx
);
526 SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
)
529 switch (rec
->contentType
)
530 { case SSL_RecordTypeHandshake
:
531 sslLogRxProtocolDebug("Handshake");
533 err
= DTLSProcessHandshakeRecord(*rec
, ctx
);
535 err
= SSLProcessHandshakeRecord(*rec
, ctx
);
537 case SSL_RecordTypeAlert
:
538 sslLogRxProtocolDebug("Alert");
539 err
= SSLProcessAlert(*rec
, ctx
);
541 case SSL_RecordTypeChangeCipher
:
542 sslLogRxProtocolDebug("ChangeCipher");
543 err
= SSLProcessChangeCipherSpec(*rec
, ctx
);
546 case SSL_RecordTypeV2_0
:
547 sslLogRxProtocolDebug("RecordTypeV2_0");
548 err
= SSL2ProcessMessage(rec
, ctx
);
552 sslLogRxProtocolDebug("Bad msg");
553 return errSSLProtocol
;
560 SSLClose(SSLContext
*ctx
)
562 OSStatus err
= errSecSuccess
;
564 sslHdskStateDebug("SSLClose");
568 if (ctx
->negProtocolVersion
>= SSL_Version_3_0
)
569 err
= SSLSendAlert(SSL_AlertLevelWarning
, SSL_AlertCloseNotify
, ctx
);
572 err
= SSLServiceWriteQueue(ctx
);
574 SSLChangeHdskState(ctx
, SSL_HdskStateGracefulClose
);
576 err
= errSecSuccess
; /* Ignore errors related to closed streams */
581 * Determine how much data the client can be guaranteed to
582 * obtain via SSLRead() without blocking or causing any low-level
583 * read operations to occur.
585 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
586 * and receivedDataPos) are only used in this file.
589 SSLGetBufferedReadSize(SSLContextRef ctx
,
590 size_t *bufSize
) /* RETURNED */
595 if(ctx
->receivedDataBuffer
.data
== NULL
) {
599 assert(ctx
->receivedDataBuffer
.length
>= ctx
->receivedDataPos
);
600 *bufSize
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
602 return errSecSuccess
;