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 "tls_record_internal.h"
33 #include <AssertMacros.h>
39 /* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */
40 #define DEFAULT_BUFFER_SIZE (16384 + 2048)
44 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
47 int sslIoRead(SSLBuffer buf
,
49 struct SSLRecordInternalContext
*ctx
)
52 SSLContextRef sslCtx
= ctx
->sslCtx
;
54 *actualLength
= buf
.length
;
56 ortn
= sslCtx
->ioCtx
.read(sslCtx
->ioCtx
.ioRef
, buf
.data
, actualLength
);
58 /* We may need to translate error codes at this layer */
59 if(ortn
==errSSLWouldBlock
) {
60 ortn
=errSSLRecordWouldBlock
;
63 sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d",
64 ctx
, buf
.length
, *actualLength
, (int)ortn
);
70 int sslIoWrite(SSLBuffer buf
,
72 struct SSLRecordInternalContext
*ctx
)
75 SSLContextRef sslCtx
= ctx
->sslCtx
;
77 *actualLength
= buf
.length
;
79 ortn
= sslCtx
->ioCtx
.write(sslCtx
->ioCtx
.ioRef
, buf
.data
, actualLength
);
81 /* We may need to translate error codes at this layer */
82 if(ortn
==errSSLWouldBlock
) {
83 ortn
=errSSLRecordWouldBlock
;
86 sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d",
87 ctx
, buf
.length
, *actualLength
, (int)ortn
);
92 /* Entry points to Record Layer */
94 static int SSLRecordReadInternal(SSLRecordContextRef ref
, SSLRecord
*rec
)
96 struct SSLRecordInternalContext
*ctx
= ref
;
99 size_t len
, contentLen
;
102 size_t head
=tls_record_get_header_size(ctx
->filter
);
104 if (ctx
->amountRead
< head
)
106 readData
.length
= head
- ctx
->amountRead
;
107 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
108 len
= readData
.length
;
109 err
= sslIoRead(readData
, &len
, ctx
);
113 case errSSLRecordWouldBlock
:
114 ctx
->amountRead
+= len
;
117 /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */
118 err
= errSSLRecordClosedAbort
;
123 ctx
->amountRead
+= len
;
125 check(ctx
->amountRead
== head
);
130 header
.data
=ctx
->partialReadBuffer
.data
;
133 uint8_t content_type
;
135 tls_record_parse_header(ctx
->filter
, header
, &contentLen
, &content_type
);
137 if(content_type
&0x80) {
138 sslDebugLog("Detected SSL2 record in SSLReadRecordInternal");
139 // Looks like SSL2 record, reset expectations.
141 err
=tls_record_parse_ssl2_header(ctx
->filter
, header
, &contentLen
, &content_type
);
142 if(err
!=0) return errSSLRecordUnexpectedRecord
;
145 check(ctx
->partialReadBuffer
.length
>=head
+contentLen
);
147 if(head
+contentLen
>ctx
->partialReadBuffer
.length
) {
148 sslDebugLog("overflow in SSLReadRecordInternal");
149 return errSSLRecordRecordOverflow
;
152 if (ctx
->amountRead
< head
+ contentLen
)
154 readData
.length
= head
+ contentLen
- ctx
->amountRead
;
155 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
156 len
= readData
.length
;
157 err
= sslIoRead(readData
, &len
, ctx
);
160 if (err
== errSSLRecordWouldBlock
)
162 ctx
->amountRead
+= len
;
166 ctx
->amountRead
+= len
;
169 check(ctx
->amountRead
== head
+ contentLen
);
172 record
.data
= ctx
->partialReadBuffer
.data
;
173 record
.length
= ctx
->amountRead
;
175 rec
->contentType
= content_type
;
177 ctx
->amountRead
= 0; /* We've used all the data in the cache */
179 if(content_type
==tls_record_type_SSL2
) {
180 /* Just copy the SSL2 record, dont decrypt since this is only for SSL2 Client Hello */
181 return SSLCopyBuffer(&record
, &rec
->contents
);
183 size_t sz
= tls_record_decrypted_size(ctx
->filter
, record
.length
);
185 /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */
187 sslErrorLog("underflow in SSLReadRecordInternal");
188 if(ctx
->sslCtx
->isDTLS
) {
189 // For DTLS, we should just drop it.
190 return errSSLRecordUnexpectedRecord
;
192 // For TLS, we are going to close the connection.
193 return errSSLRecordClosedAbort
;
197 /* Allocate a buffer for the plaintext */
198 if ((err
= SSLAllocBuffer(&rec
->contents
, sz
)))
203 return tls_record_decrypt(ctx
->filter
, record
, &rec
->contents
, NULL
);
207 static int SSLRecordWriteInternal(SSLRecordContextRef ref
, SSLRecord rec
)
210 struct SSLRecordInternalContext
*ctx
= ref
;
211 WaitingRecord
*queue
, *out
;
216 err
= errSSLRecordInternal
; /* FIXME: allocation error */
217 len
=tls_record_encrypted_size(ctx
->filter
, rec
.contentType
, rec
.contents
.length
);
219 require((out
= (WaitingRecord
*)sslMalloc(offsetof(WaitingRecord
, data
) + len
)), fail
);
224 data
.data
=&out
->data
[0];
225 data
.length
=out
->length
;
227 content
.data
= rec
.contents
.data
;
228 content
.length
= rec
.contents
.length
;
230 require_noerr((err
=tls_record_encrypt(ctx
->filter
, content
, rec
.contentType
, &data
)), fail
);
232 out
->length
= data
.length
; // This should not be needed if tls_record_encrypted_size works properly.
234 /* Enqueue the record to be written from the idle loop */
235 if (ctx
->recordWriteQueue
== 0)
236 ctx
->recordWriteQueue
= out
;
238 { queue
= ctx
->recordWriteQueue
;
239 while (queue
->next
!= 0)
251 /* Record Layer Entry Points */
254 SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
256 struct SSLRecordInternalContext
*ctx
= ref
;
257 return tls_record_rollback_write_cipher(ctx
->filter
);
261 SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
263 struct SSLRecordInternalContext
*ctx
= ref
;
264 return tls_record_advance_write_cipher(ctx
->filter
);
268 SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref
)
270 struct SSLRecordInternalContext
*ctx
= ref
;
271 return tls_record_advance_read_cipher(ctx
->filter
);
275 SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref
, uint16_t selectedCipher
, bool isServer
, SSLBuffer key
)
277 struct SSLRecordInternalContext
*ctx
= ref
;
278 return tls_record_init_pending_ciphers(ctx
->filter
, selectedCipher
, isServer
, key
);
282 SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref
, SSLProtocolVersion negVersion
)
284 struct SSLRecordInternalContext
*ctx
= ref
;
285 return tls_record_set_protocol_version(ctx
->filter
, (tls_protocol_version
) negVersion
);
289 SSLRecordFreeInternal(SSLRecordContextRef ref
, SSLRecord rec
)
291 return SSLFreeBuffer(&rec
.contents
);
295 SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref
)
301 struct SSLRecordInternalContext
*ctx
= ref
;
303 while (!werr
&& ((rec
= ctx
->recordWriteQueue
) != 0))
304 { buf
.data
= rec
->data
+ rec
->sent
;
305 buf
.length
= rec
->length
- rec
->sent
;
306 werr
= sslIoWrite(buf
, &written
, ctx
);
307 rec
->sent
+= written
;
308 if (rec
->sent
>= rec
->length
)
310 check(rec
->sent
== rec
->length
);
311 ctx
->recordWriteQueue
= rec
->next
;
320 SSLRecordSetOption(SSLRecordContextRef ref
, SSLRecordOption option
, bool value
)
322 struct SSLRecordInternalContext
*ctx
= (struct SSLRecordInternalContext
*)ref
;
324 case kSSLRecordOptionSendOneByteRecord
:
325 return tls_record_set_record_splitting(ctx
->filter
, value
);
331 /***** Internal Record Layer APIs *****/
333 #include <corecrypto/ccrng.h>
334 #define CCRNGSTATE ccrng(NULL)
337 SSLCreateInternalRecordLayer(SSLContextRef sslCtx
)
339 struct SSLRecordInternalContext
*ctx
;
341 ctx
= sslMalloc(sizeof(struct SSLRecordInternalContext
));
345 memset(ctx
, 0, sizeof(struct SSLRecordInternalContext
));
347 require((ctx
->filter
=tls_record_create(sslCtx
->isDTLS
, CCRNGSTATE
)), fail
);
348 require_noerr(SSLAllocBuffer(&ctx
->partialReadBuffer
,
349 DEFAULT_BUFFER_SIZE
), fail
);
351 ctx
->sslCtx
= sslCtx
;
356 tls_record_destroy(ctx
->filter
);
362 SSLDestroyInternalRecordLayer(SSLRecordContextRef ref
)
364 struct SSLRecordInternalContext
*ctx
= ref
;
365 WaitingRecord
*waitRecord
, *next
;
367 /* RecordContext cleanup : */
368 SSLFreeBuffer(&ctx
->partialReadBuffer
);
369 waitRecord
= ctx
->recordWriteQueue
;
371 { next
= waitRecord
->next
;
377 tls_record_destroy(ctx
->filter
);
383 struct SSLRecordFuncs SSLRecordLayerInternal
=
385 .read
= SSLRecordReadInternal
,
386 .write
= SSLRecordWriteInternal
,
387 .initPendingCiphers
= SSLInitInternalRecordLayerPendingCiphers
,
388 .advanceWriteCipher
= SSLAdvanceInternalRecordLayerWriteCipher
,
389 .advanceReadCipher
= SSLAdvanceInternalRecordLayerReadCipher
,
390 .rollbackWriteCipher
= SSLRollbackInternalRecordLayerWriteCipher
,
391 .setProtocolVersion
= SSLSetInternalRecordLayerProtocolVersion
,
392 .free
= SSLRecordFreeInternal
,
393 .serviceWriteQueue
= SSLRecordServiceWriteQueueInternal
,
394 .setOption
= SSLRecordSetOption
,