2 * Copyright (c) 2011-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 /* THIS FILE CONTAINS KERNEL CODE */
27 #include "sslBuildFlags.h"
28 #include "SSLRecordInternal.h"
30 #include "cipherSpecs.h"
31 #include "symCipher.h"
33 #include "tls_record_internal.h"
35 #include <AssertMacros.h>
41 /* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */
42 #define DEFAULT_BUFFER_SIZE (16384 + 2048)
46 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
49 int sslIoRead(SSLBuffer buf
,
51 struct SSLRecordInternalContext
*ctx
)
53 size_t dataLength
= buf
.length
;
57 ortn
= (ctx
->read
)(ctx
->ioRef
,
60 *actualLength
= dataLength
;
62 sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d",
63 ctx
, buf
.length
, dataLength
, (int)ortn
);
69 int sslIoWrite(SSLBuffer buf
,
71 struct SSLRecordInternalContext
*ctx
)
73 size_t dataLength
= buf
.length
;
77 ortn
= (ctx
->write
)(ctx
->ioRef
,
80 *actualLength
= dataLength
;
82 sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d",
83 ctx
, buf
.length
, dataLength
, (int)ortn
);
88 /* Entry points to Record Layer */
90 static int SSLRecordReadInternal(SSLRecordContextRef ref
, SSLRecord
*rec
)
92 struct SSLRecordInternalContext
*ctx
= ref
;
95 size_t len
, contentLen
;
98 size_t head
=tls_record_get_header_size(ctx
->filter
);
100 if (ctx
->amountRead
< head
)
102 readData
.length
= head
- ctx
->amountRead
;
103 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
104 len
= readData
.length
;
105 err
= sslIoRead(readData
, &len
, ctx
);
109 case errSSLRecordWouldBlock
:
110 ctx
->amountRead
+= len
;
113 /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */
114 err
= errSSLRecordClosedAbort
;
119 ctx
->amountRead
+= len
;
121 check(ctx
->amountRead
== head
);
126 header
.data
=ctx
->partialReadBuffer
.data
;
129 uint8_t content_type
;
131 tls_record_parse_header(ctx
->filter
, header
, &contentLen
, &content_type
);
133 if(content_type
&0x80) {
134 // Looks like SSL2 record, reset expectations.
136 err
=tls_record_parse_ssl2_header(ctx
->filter
, header
, &contentLen
, &content_type
);
137 if(err
!=0) return errSSLRecordUnexpectedRecord
;
140 check(ctx
->partialReadBuffer
.length
>=head
+contentLen
);
142 if(head
+contentLen
>ctx
->partialReadBuffer
.length
)
143 return errSSLRecordRecordOverflow
;
145 if (ctx
->amountRead
< head
+ contentLen
)
146 { readData
.length
= head
+ contentLen
- ctx
->amountRead
;
147 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
148 len
= readData
.length
;
149 err
= sslIoRead(readData
, &len
, ctx
);
151 { if (err
== errSSLRecordWouldBlock
)
152 ctx
->amountRead
+= len
;
155 ctx
->amountRead
+= len
;
158 check(ctx
->amountRead
== head
+ contentLen
);
161 record
.data
= ctx
->partialReadBuffer
.data
;
162 record
.length
= ctx
->amountRead
;
164 rec
->contentType
= content_type
;
166 ctx
->amountRead
= 0; /* We've used all the data in the cache */
168 if(content_type
==tls_record_type_SSL2
) {
169 /* Just copy the SSL2 record, dont decrypt since this is only for SSL2 Client Hello */
170 return SSLCopyBuffer(&record
, &rec
->contents
);
172 size_t sz
= tls_record_decrypted_size(ctx
->filter
, record
.length
);
174 /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */
176 sslErrorLog("underflow in SSLReadRecordInternal");
178 // For DTLS, we should just drop it.
179 return errSSLRecordUnexpectedRecord
;
181 // For TLS, we are going to close the connection.
182 return errSSLRecordClosedAbort
;
186 /* Allocate a buffer for the plaintext */
187 if ((err
= SSLAllocBuffer(&rec
->contents
, sz
)))
192 return tls_record_decrypt(ctx
->filter
, record
, &rec
->contents
, NULL
);
196 static int SSLRecordWriteInternal(SSLRecordContextRef ref
, SSLRecord rec
)
199 struct SSLRecordInternalContext
*ctx
= ref
;
200 WaitingRecord
*queue
, *out
;
205 err
= errSSLRecordInternal
; /* FIXME: allocation error */
206 len
=tls_record_encrypted_size(ctx
->filter
, rec
.contentType
, rec
.contents
.length
);
208 require((out
= (WaitingRecord
*)sslMalloc(offsetof(WaitingRecord
, data
) + len
)), fail
);
213 data
.data
=&out
->data
[0];
214 data
.length
=out
->length
;
216 content
.data
= rec
.contents
.data
;
217 content
.length
= rec
.contents
.length
;
219 require_noerr((err
=tls_record_encrypt(ctx
->filter
, content
, rec
.contentType
, &data
)), fail
);
221 out
->length
= data
.length
; // This should not be needed if tls_record_encrypted_size works properly.
223 /* Enqueue the record to be written from the idle loop */
224 if (ctx
->recordWriteQueue
== 0)
225 ctx
->recordWriteQueue
= out
;
227 { queue
= ctx
->recordWriteQueue
;
228 while (queue
->next
!= 0)
240 /* Record Layer Entry Points */
243 SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
245 struct SSLRecordInternalContext
*ctx
= ref
;
246 return tls_record_rollback_write_cipher(ctx
->filter
);
250 SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
252 struct SSLRecordInternalContext
*ctx
= ref
;
253 return tls_record_advance_write_cipher(ctx
->filter
);
257 SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref
)
259 struct SSLRecordInternalContext
*ctx
= ref
;
260 return tls_record_advance_read_cipher(ctx
->filter
);
264 SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref
, uint16_t selectedCipher
, bool isServer
, SSLBuffer key
)
266 struct SSLRecordInternalContext
*ctx
= ref
;
267 return tls_record_init_pending_ciphers(ctx
->filter
, selectedCipher
, isServer
, key
);
271 SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref
, SSLProtocolVersion negVersion
)
273 struct SSLRecordInternalContext
*ctx
= ref
;
274 return tls_record_set_protocol_version(ctx
->filter
, negVersion
);
278 SSLRecordFreeInternal(SSLRecordContextRef ref
, SSLRecord rec
)
280 return SSLFreeBuffer(&rec
.contents
);
284 SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref
)
286 int err
= 0, werr
= 0;
290 struct SSLRecordInternalContext
*ctx
= ref
;
292 while (!werr
&& ((rec
= ctx
->recordWriteQueue
) != 0))
293 { buf
.data
= rec
->data
+ rec
->sent
;
294 buf
.length
= rec
->length
- rec
->sent
;
295 werr
= sslIoWrite(buf
, &written
, ctx
);
296 rec
->sent
+= written
;
297 if (rec
->sent
>= rec
->length
)
299 check(rec
->sent
== rec
->length
);
301 ctx
->recordWriteQueue
= rec
->next
;
314 SSLRecordSetOption(SSLRecordContextRef ref
, SSLRecordOption option
, bool value
)
316 struct SSLRecordInternalContext
*ctx
= (struct SSLRecordInternalContext
*)ref
;
318 case kSSLRecordOptionSendOneByteRecord
:
319 return tls_record_set_record_splitting(ctx
->filter
, value
);
327 /***** Internal Record Layer APIs *****/
329 #include <CommonCrypto/CommonRandomSPI.h>
330 #define CCRNGSTATE ccDRBGGetRngState()
333 SSLCreateInternalRecordLayer(bool dtls
)
335 struct SSLRecordInternalContext
*ctx
;
337 ctx
= sslMalloc(sizeof(struct SSLRecordInternalContext
));
341 memset(ctx
, 0, sizeof(struct SSLRecordInternalContext
));
344 require((ctx
->filter
=tls_record_create(dtls
, CCRNGSTATE
)), fail
);
345 require_noerr(SSLAllocBuffer(&ctx
->partialReadBuffer
,
346 DEFAULT_BUFFER_SIZE
), fail
);
352 tls_record_destroy(ctx
->filter
);
358 SSLSetInternalRecordLayerIOFuncs(
359 SSLRecordContextRef ref
,
360 SSLIOReadFunc readFunc
,
361 SSLIOWriteFunc writeFunc
)
363 struct SSLRecordInternalContext
*ctx
= ref
;
365 ctx
->read
= readFunc
;
366 ctx
->write
= writeFunc
;
372 SSLSetInternalRecordLayerConnection(
373 SSLRecordContextRef ref
,
374 SSLIOConnectionRef ioRef
)
376 struct SSLRecordInternalContext
*ctx
= ref
;
384 SSLDestroyInternalRecordLayer(SSLRecordContextRef ref
)
386 struct SSLRecordInternalContext
*ctx
= ref
;
387 WaitingRecord
*waitRecord
, *next
;
389 /* RecordContext cleanup : */
390 SSLFreeBuffer(&ctx
->partialReadBuffer
);
391 waitRecord
= ctx
->recordWriteQueue
;
393 { next
= waitRecord
->next
;
399 tls_record_destroy(ctx
->filter
);
405 struct SSLRecordFuncs SSLRecordLayerInternal
=
407 .read
= SSLRecordReadInternal
,
408 .write
= SSLRecordWriteInternal
,
409 .initPendingCiphers
= SSLInitInternalRecordLayerPendingCiphers
,
410 .advanceWriteCipher
= SSLAdvanceInternalRecordLayerWriteCipher
,
411 .advanceReadCipher
= SSLAdvanceInternalRecordLayerReadCipher
,
412 .rollbackWriteCipher
= SSLRollbackInternalRecordLayerWriteCipher
,
413 .setProtocolVersion
= SSLSetInternalRecordLayerProtocolVersion
,
414 .free
= SSLRecordFreeInternal
,
415 .serviceWriteQueue
= SSLRecordServiceWriteQueueInternal
,
416 .setOption
= SSLRecordSetOption
,