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 "cipherSpecs.h"
42 static inline void sslIoTrace(
48 sslLogRecordIo("===%s: req %4lu moved %4lu status %ld",
49 op
, req
, moved
, stat
);
52 #define sslIoTrace(op, req, moved, stat)
55 extern int kSplitDefaultValue
;
57 static OSStatus
SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
);
58 static OSStatus
SSLHandshakeProceed(SSLContext
*ctx
);
59 static OSStatus
SSLInitConnection(SSLContext
*ctx
);
60 static OSStatus
SSLServiceWriteQueue(SSLContext
*ctx
);
67 size_t *bytesWritten
) /* RETURNED */
71 size_t dataLen
, processed
;
74 sslLogRecordIo("SSLWrite top");
75 if((ctx
== NULL
) || (bytesWritten
== NULL
)) {
79 processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
83 case SSL_HdskStateGracefulClose
:
84 err
= errSSLClosedGraceful
;
86 case SSL_HdskStateErrorClose
:
87 err
= errSSLClosedAbort
;
89 case SSL_HdskStateServerReady
:
90 case SSL_HdskStateClientReady
:
93 if(ctx
->state
< SSL_HdskStateServerHello
) {
94 /* not ready for I/O, and handshake not in progress */
95 sslIoTrace("SSLWrite", dataLength
, 0, badReqErr
);
98 /* handshake in progress; will call SSLHandshakeProceed below */
102 /* First, we have to wait until the session is ready to send data,
103 so the encryption keys and such have been established. */
105 while (ctx
->writeCipher
.ready
== 0)
106 { if ((err
= SSLHandshakeProceed(ctx
)) != 0)
110 /* Attempt to empty the write queue before queueing more data */
111 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
114 /* Check if we should split the data into 1/n-1 to avoid known-IV issue */
115 split
= (ctx
->oneByteRecordEnable
&& ctx
->negProtocolVersion
<= TLS_Version_1_0
);
117 /* Only split if cipher algorithm uses CBC mode */
118 SSL_CipherAlgorithm cipherAlg
= sslCipherSuiteGetSymmetricCipherAlgorithm(ctx
->selectedCipher
);
119 split
= (cipherAlg
> SSL_CipherAlgorithmRC4_128
&&
120 cipherAlg
< SSL_CipherAlgorithmAES_128_GCM
);
122 /* Determine whether we start splitting on second write */
123 split
= (kSplitDefaultValue
== 2 && !ctx
->wroteAppData
) ? false : true;
129 * Fragment, package and encrypt the data and queue the resulting data
133 { rec
.contentType
= SSL_RecordTypeAppData
;
134 rec
.protocolVersion
= ctx
->negProtocolVersion
;
135 rec
.contents
.data
= ((uint8_t *)data
) + processed
;
137 if (processed
== 0 && split
)
138 rec
.contents
.length
= 1;
139 else if (dataLen
< MAX_RECORD_LENGTH
)
140 rec
.contents
.length
= dataLen
;
142 rec
.contents
.length
= MAX_RECORD_LENGTH
;
144 assert(ctx
->sslTslCalls
!= NULL
);
145 if ((err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
147 processed
+= rec
.contents
.length
;
148 dataLen
-= rec
.contents
.length
;
149 ctx
->wroteAppData
= 1;
152 /* All the data has been advanced to the write queue */
153 *bytesWritten
= processed
;
154 if ((err
= SSLServiceWriteQueue(ctx
)) == 0) {
160 case errSSLWouldBlock
:
161 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
162 case errSSLClientCertRequested
:
163 case errSSLClosedGraceful
:
166 sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
168 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
172 sslIoTrace("SSLWrite", dataLength
, *bytesWritten
, err
);
181 size_t *processed
) /* RETURNED */
185 size_t bufSize
, remaining
, count
;
188 sslLogRecordIo("SSLRead top");
189 if((ctx
== NULL
) || (data
== NULL
) || (processed
== NULL
)) {
192 bufSize
= dataLength
;
193 *processed
= 0; /* Initialize in case we return with errSSLWouldBlock */
196 /* first handle cases in which we know we're finished */
198 case SSL_HdskStateGracefulClose
:
199 err
= errSSLClosedGraceful
;
201 case SSL_HdskStateErrorClose
:
202 err
= errSSLClosedAbort
;
204 case SSL_HdskStateNoNotifyClose
:
205 err
= errSSLClosedNoNotify
;
211 /* First, we have to wait until the session is ready to receive data,
212 so the encryption keys and such have been established. */
214 while (ctx
->readCipher
.ready
== 0) {
215 if ((err
= SSLHandshakeProceed(ctx
)) != 0) {
220 /* Attempt to service the write queue */
221 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
222 if (err
!= errSSLWouldBlock
) {
225 err
= noErr
; /* Write blocking shouldn't stop attempts to read */
229 charPtr
= (uint8_t *)data
;
230 if (ctx
->receivedDataBuffer
.data
)
231 { count
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;
234 memcpy(data
, ctx
->receivedDataBuffer
.data
+ ctx
->receivedDataPos
, count
);
238 ctx
->receivedDataPos
+= count
;
241 assert(ctx
->receivedDataPos
<= ctx
->receivedDataBuffer
.length
);
242 assert(*processed
+ remaining
== bufSize
);
243 assert(charPtr
== ((uint8_t *)data
) + *processed
);
245 if (ctx
->receivedDataBuffer
.data
!= 0 &&
246 ctx
->receivedDataPos
>= ctx
->receivedDataBuffer
.length
)
247 { SSLFreeBuffer(&ctx
->receivedDataBuffer
, ctx
);
248 ctx
->receivedDataBuffer
.data
= 0;
249 ctx
->receivedDataPos
= 0;
253 * This while statement causes a hang when using nonblocking low-level I/O!
254 while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
255 ..what we really have to do is just return as soon as we read one
256 record. A performance hit in the nonblocking case, but that is
257 the only way this code can work in both modes...
259 if (remaining
> 0 && ctx
->state
!= SSL_HdskStateGracefulClose
)
260 { assert(ctx
->receivedDataBuffer
.data
== 0);
261 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0) {
264 if (rec
.contentType
== SSL_RecordTypeAppData
||
265 rec
.contentType
== SSL_RecordTypeV2_0
)
266 { if (rec
.contents
.length
<= remaining
)
267 { memcpy(charPtr
, rec
.contents
.data
, rec
.contents
.length
);
268 remaining
-= rec
.contents
.length
;
269 charPtr
+= rec
.contents
.length
;
270 *processed
+= rec
.contents
.length
;
273 * if ((err = SSLFreeBuffer(rec.contents, ctx)) != 0)
274 * passes the address of rec to SSLFreeBuffer, not the address
275 * of the contents field (which should be offset 8 from the start
279 SSLBuffer
*b
= &rec
.contents
;
280 if ((err
= SSLFreeBuffer(b
, ctx
)) != 0) {
286 { memcpy(charPtr
, rec
.contents
.data
, remaining
);
287 charPtr
+= remaining
;
288 *processed
+= remaining
;
289 ctx
->receivedDataBuffer
= rec
.contents
;
290 ctx
->receivedDataPos
= remaining
;
295 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0) {
298 if ((err
= SSLFreeBuffer(&rec
.contents
, ctx
)) != 0) {
307 /* test for renegotiate: loop until something useful happens */
308 if((err
== noErr
) && (*processed
== 0) && !(dataLength
== 0)) {
309 sslLogNegotiateDebug("SSLRead recursion");
312 /* shut down on serious errors */
315 case errSSLWouldBlock
:
316 case errSSLServerAuthCompleted
: /* == errSSLClientAuthCompleted */
317 case errSSLClientCertRequested
:
318 case errSSLClosedGraceful
:
319 case errSSLClosedNoNotify
:
322 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
324 SSLChangeHdskState(ctx
, SSL_HdskStateErrorClose
);
328 sslIoTrace("SSLRead ", dataLength
, *processed
, err
);
333 #include "sslCrypto.h"
337 SSLHandshake(SSLContext
*ctx
)
344 if (ctx
->state
== SSL_HdskStateGracefulClose
)
345 return errSSLClosedGraceful
;
346 if (ctx
->state
== SSL_HdskStateErrorClose
)
347 return errSSLClosedAbort
;
350 /* Because of Radar 6133465, we have to disable this to allow the sending
351 of client hello extensions for ECDSA... */
352 ctx
->versionSsl2Enable
= false;
355 if(ctx
->validCipherSuites
== NULL
) {
356 /* build list of legal cipherSpecs */
357 err
= sslBuildCipherSuiteArray(ctx
);
365 if (ctx
->timeout_deadline
<CFAbsoluteTimeGetCurrent()) {
370 while (ctx
->readCipher
.ready
== 0 || ctx
->writeCipher
.ready
== 0)
371 { if ((err
= SSLHandshakeProceed(ctx
)) != 0)
375 /* one more flush at completion of successful handshake */
376 if ((err
= SSLServiceWriteQueue(ctx
)) != 0) {
384 SSLHandshakeProceed(SSLContext
*ctx
)
388 if (ctx
->signalServerAuth
) {
389 ctx
->signalServerAuth
= false;
390 return errSSLServerAuthCompleted
;
392 if (ctx
->signalCertRequest
) {
393 ctx
->signalCertRequest
= false;
394 return errSSLClientCertRequested
;
396 if (ctx
->signalClientAuth
) {
397 ctx
->signalClientAuth
= false;
398 return errSSLClientAuthCompleted
;
401 if (ctx
->state
== SSL_HdskStateUninit
)
402 if ((err
= SSLInitConnection(ctx
)) != 0)
405 /* This is our cue that we dropped out of the handshake
406 * to let the client pick an identity, move state back
407 * to server hello done and continue processing.
409 if ((ctx
->protocolSide
== kSSLClientSide
) &&
410 (ctx
->state
== SSL_HdskStateClientCert
))
411 if ((err
= SSLAdvanceHandshake(SSL_HdskServerHelloDone
, ctx
)) != 0)
414 if ((err
= SSLServiceWriteQueue(ctx
)) != 0)
416 assert(ctx
->readCipher
.ready
== 0);
417 if ((err
= SSLReadRecord(&rec
, ctx
)) != 0)
419 if ((err
= SSLProcessProtocolMessage(&rec
, ctx
)) != 0)
420 { SSLFreeBuffer(&rec
.contents
, ctx
);
423 if ((err
= SSLFreeBuffer(&rec
.contents
, ctx
)) != 0)
430 SSLInitConnection(SSLContext
*ctx
)
431 { OSStatus err
= noErr
;
433 if (ctx
->protocolSide
== kSSLClientSide
) {
434 SSLChangeHdskState(ctx
, SSL_HdskStateClientUninit
);
437 { assert(ctx
->protocolSide
== kSSLServerSide
);
438 SSLChangeHdskState(ctx
, SSL_HdskStateServerUninit
);
441 if (ctx
->peerID
.data
!= 0)
442 { SSLGetSessionData(&ctx
->resumableSession
, ctx
);
443 /* Ignore errors; just treat as uncached session */
447 * If we have a cached resumable session, blow it off if it's a version
448 * which is not currently enabled.
450 Boolean cachedV3OrTls1
= ctx
->isDTLS
;
452 if (ctx
->resumableSession
.data
!= 0) {
453 SSLProtocolVersion savedVersion
;
454 if ((err
= SSLRetrieveSessionProtocolVersion(ctx
->resumableSession
,
455 &savedVersion
, ctx
)) != 0)
459 ? (savedVersion
<= ctx
->minProtocolVersion
&&
460 savedVersion
>= ctx
->maxProtocolVersion
)
461 : (savedVersion
>= ctx
->minProtocolVersion
&&
462 savedVersion
<= ctx
->maxProtocolVersion
)) {
463 cachedV3OrTls1
= savedVersion
!= SSL_Version_2_0
;
464 sslLogResumSessDebug("===attempting to resume session");
466 sslLogResumSessDebug("===Resumable session protocol mismatch");
467 SSLFreeBuffer(&ctx
->resumableSession
, ctx
);
472 * If we're the client & handshake hasn't yet begun, start it by
473 * pretending we just received a hello request
475 if (ctx
->state
== SSL_HdskStateClientUninit
&& ctx
->writeCipher
.ready
== 0)
477 assert(ctx
->negProtocolVersion
== SSL_Version_Undetermined
);
479 if(!cachedV3OrTls1
) {
480 /* SSL2 client hello with possible upgrade */
481 err
= SSL2AdvanceHandshake(SSL2_MsgKickstart
, ctx
);
486 err
= SSLAdvanceHandshake(SSL_HdskHelloRequest
, ctx
);
494 SSLServiceWriteQueue(SSLContext
*ctx
)
495 { OSStatus err
= noErr
, werr
= noErr
;
500 while (!werr
&& ((rec
= ctx
->recordWriteQueue
) != 0))
501 { buf
.data
= rec
->data
+ rec
->sent
;
502 buf
.length
= rec
->length
- rec
->sent
;
503 werr
= sslIoWrite(buf
, &written
, ctx
);
504 rec
->sent
+= written
;
505 if (rec
->sent
>= rec
->length
)
506 { assert(rec
->sent
== rec
->length
);
508 ctx
->recordWriteQueue
= rec
->next
;
519 SSLProcessProtocolMessage(SSLRecord
*rec
, SSLContext
*ctx
)
522 switch (rec
->contentType
)
523 { case SSL_RecordTypeHandshake
:
524 sslLogRxProtocolDebug("Handshake");
526 err
= DTLSProcessHandshakeRecord(*rec
, ctx
);
528 err
= SSLProcessHandshakeRecord(*rec
, ctx
);
530 case SSL_RecordTypeAlert
:
531 sslLogRxProtocolDebug("Alert");
532 err
= SSLProcessAlert(*rec
, ctx
);
534 case SSL_RecordTypeChangeCipher
:
535 sslLogRxProtocolDebug("ChangeCipher");
536 err
= SSLProcessChangeCipherSpec(*rec
, ctx
);
539 case SSL_RecordTypeV2_0
:
540 sslLogRxProtocolDebug("RecordTypeV2_0");
541 err
= SSL2ProcessMessage(rec
, ctx
);
545 sslLogRxProtocolDebug("Bad msg");
546 return errSSLProtocol
;
553 SSLClose(SSLContext
*ctx
)
555 OSStatus err
= noErr
;
557 sslHdskStateDebug("SSLClose");
561 if (ctx
->negProtocolVersion
>= SSL_Version_3_0
)
562 err
= SSLSendAlert(SSL_AlertLevelWarning
, SSL_AlertCloseNotify
, ctx
);
564 err
= SSLServiceWriteQueue(ctx
);
565 SSLChangeHdskState(ctx
, SSL_HdskStateGracefulClose
);
567 err
= noErr
; /* Ignore errors related to closed streams */
572 * Determine how much data the client can be guaranteed to
573 * obtain via SSLRead() without blocking or causing any low-level
574 * read operations to occur.
576 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
577 * and receivedDataPos) are only used in this file.
580 SSLGetBufferedReadSize(SSLContextRef ctx
,
581 size_t *bufSize
) /* RETURNED */
586 if(ctx
->receivedDataBuffer
.data
== NULL
) {
590 assert(ctx
->receivedDataBuffer
.length
>= ctx
->receivedDataPos
);
591 *bufSize
= ctx
->receivedDataBuffer
.length
- ctx
->receivedDataPos
;