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"
32 #include "tls_record_internal.h"
34 #include <AssertMacros.h>
40 /* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */
41 #define DEFAULT_BUFFER_SIZE (16384 + 2048)
45 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
48 int sslIoRead(SSLBuffer buf
,
50 struct SSLRecordInternalContext
*ctx
)
53 SSLContextRef sslCtx
= ctx
->sslCtx
;
55 *actualLength
= buf
.length
;
57 ortn
= sslCtx
->ioCtx
.read(sslCtx
->ioCtx
.ioRef
, buf
.data
, actualLength
);
59 /* We may need to translate error codes at this layer */
60 if(ortn
==errSSLWouldBlock
) {
61 ortn
=errSSLRecordWouldBlock
;
64 sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d",
65 ctx
, buf
.length
, *actualLength
, (int)ortn
);
71 int sslIoWrite(SSLBuffer buf
,
73 struct SSLRecordInternalContext
*ctx
)
76 SSLContextRef sslCtx
= ctx
->sslCtx
;
78 *actualLength
= buf
.length
;
80 ortn
= sslCtx
->ioCtx
.write(sslCtx
->ioCtx
.ioRef
, buf
.data
, actualLength
);
82 /* We may need to translate error codes at this layer */
83 if(ortn
==errSSLWouldBlock
) {
84 ortn
=errSSLRecordWouldBlock
;
87 sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d",
88 ctx
, buf
.length
, *actualLength
, (int)ortn
);
93 /* Entry points to Record Layer */
95 static int SSLRecordReadInternal(SSLRecordContextRef ref
, SSLRecord
*rec
)
97 struct SSLRecordInternalContext
*ctx
= ref
;
100 size_t len
, contentLen
;
103 size_t head
=tls_record_get_header_size(ctx
->filter
);
105 if (ctx
->amountRead
< head
)
107 readData
.length
= head
- ctx
->amountRead
;
108 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
109 len
= readData
.length
;
110 err
= sslIoRead(readData
, &len
, ctx
);
114 case errSSLRecordWouldBlock
:
115 ctx
->amountRead
+= len
;
118 /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */
119 err
= errSSLRecordClosedAbort
;
124 ctx
->amountRead
+= len
;
126 check(ctx
->amountRead
== head
);
131 header
.data
=ctx
->partialReadBuffer
.data
;
134 uint8_t content_type
;
136 tls_record_parse_header(ctx
->filter
, header
, &contentLen
, &content_type
);
138 if(content_type
&0x80) {
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 return errSSLRecordRecordOverflow
;
150 if (ctx
->amountRead
< head
+ contentLen
)
151 { readData
.length
= head
+ contentLen
- ctx
->amountRead
;
152 readData
.data
= ctx
->partialReadBuffer
.data
+ ctx
->amountRead
;
153 len
= readData
.length
;
154 err
= sslIoRead(readData
, &len
, ctx
);
156 { if (err
== errSSLRecordWouldBlock
)
157 ctx
->amountRead
+= len
;
160 ctx
->amountRead
+= len
;
163 check(ctx
->amountRead
== head
+ contentLen
);
166 record
.data
= ctx
->partialReadBuffer
.data
;
167 record
.length
= ctx
->amountRead
;
169 rec
->contentType
= content_type
;
171 ctx
->amountRead
= 0; /* We've used all the data in the cache */
173 if(content_type
==tls_record_type_SSL2
) {
174 /* Just copy the SSL2 record, dont decrypt since this is only for SSL2 Client Hello */
175 return SSLCopyBuffer(&record
, &rec
->contents
);
177 size_t sz
= tls_record_decrypted_size(ctx
->filter
, record
.length
);
179 /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */
181 sslErrorLog("underflow in SSLReadRecordInternal");
183 // For DTLS, we should just drop it.
184 return errSSLRecordUnexpectedRecord
;
186 // For TLS, we are going to close the connection.
187 return errSSLRecordClosedAbort
;
191 /* Allocate a buffer for the plaintext */
192 if ((err
= SSLAllocBuffer(&rec
->contents
, sz
)))
197 return tls_record_decrypt(ctx
->filter
, record
, &rec
->contents
, NULL
);
201 static int SSLRecordWriteInternal(SSLRecordContextRef ref
, SSLRecord rec
)
204 struct SSLRecordInternalContext
*ctx
= ref
;
205 WaitingRecord
*queue
, *out
;
210 err
= errSSLRecordInternal
; /* FIXME: allocation error */
211 len
=tls_record_encrypted_size(ctx
->filter
, rec
.contentType
, rec
.contents
.length
);
213 require((out
= (WaitingRecord
*)sslMalloc(offsetof(WaitingRecord
, data
) + len
)), fail
);
218 data
.data
=&out
->data
[0];
219 data
.length
=out
->length
;
221 content
.data
= rec
.contents
.data
;
222 content
.length
= rec
.contents
.length
;
224 require_noerr((err
=tls_record_encrypt(ctx
->filter
, content
, rec
.contentType
, &data
)), fail
);
226 out
->length
= data
.length
; // This should not be needed if tls_record_encrypted_size works properly.
228 /* Enqueue the record to be written from the idle loop */
229 if (ctx
->recordWriteQueue
== 0)
230 ctx
->recordWriteQueue
= out
;
232 { queue
= ctx
->recordWriteQueue
;
233 while (queue
->next
!= 0)
245 /* Record Layer Entry Points */
248 SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
250 struct SSLRecordInternalContext
*ctx
= ref
;
251 return tls_record_rollback_write_cipher(ctx
->filter
);
255 SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref
)
257 struct SSLRecordInternalContext
*ctx
= ref
;
258 return tls_record_advance_write_cipher(ctx
->filter
);
262 SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref
)
264 struct SSLRecordInternalContext
*ctx
= ref
;
265 return tls_record_advance_read_cipher(ctx
->filter
);
269 SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref
, uint16_t selectedCipher
, bool isServer
, SSLBuffer key
)
271 struct SSLRecordInternalContext
*ctx
= ref
;
272 return tls_record_init_pending_ciphers(ctx
->filter
, selectedCipher
, isServer
, key
);
276 SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref
, SSLProtocolVersion negVersion
)
278 struct SSLRecordInternalContext
*ctx
= ref
;
279 return tls_record_set_protocol_version(ctx
->filter
, negVersion
);
283 SSLRecordFreeInternal(SSLRecordContextRef ref
, SSLRecord rec
)
285 return SSLFreeBuffer(&rec
.contents
);
289 SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref
)
295 struct SSLRecordInternalContext
*ctx
= ref
;
297 while (!werr
&& ((rec
= ctx
->recordWriteQueue
) != 0))
298 { buf
.data
= rec
->data
+ rec
->sent
;
299 buf
.length
= rec
->length
- rec
->sent
;
300 werr
= sslIoWrite(buf
, &written
, ctx
);
301 rec
->sent
+= written
;
302 if (rec
->sent
>= rec
->length
)
304 check(rec
->sent
== rec
->length
);
305 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(SSLContextRef sslCtx
)
335 struct SSLRecordInternalContext
*ctx
;
337 ctx
= sslMalloc(sizeof(struct SSLRecordInternalContext
));
341 memset(ctx
, 0, sizeof(struct SSLRecordInternalContext
));
343 require((ctx
->filter
=tls_record_create(sslCtx
->isDTLS
, CCRNGSTATE
)), fail
);
344 require_noerr(SSLAllocBuffer(&ctx
->partialReadBuffer
,
345 DEFAULT_BUFFER_SIZE
), fail
);
347 ctx
->sslCtx
= sslCtx
;
352 tls_record_destroy(ctx
->filter
);
358 SSLDestroyInternalRecordLayer(SSLRecordContextRef ref
)
360 struct SSLRecordInternalContext
*ctx
= ref
;
361 WaitingRecord
*waitRecord
, *next
;
363 /* RecordContext cleanup : */
364 SSLFreeBuffer(&ctx
->partialReadBuffer
);
365 waitRecord
= ctx
->recordWriteQueue
;
367 { next
= waitRecord
->next
;
373 tls_record_destroy(ctx
->filter
);
379 struct SSLRecordFuncs SSLRecordLayerInternal
=
381 .read
= SSLRecordReadInternal
,
382 .write
= SSLRecordWriteInternal
,
383 .initPendingCiphers
= SSLInitInternalRecordLayerPendingCiphers
,
384 .advanceWriteCipher
= SSLAdvanceInternalRecordLayerWriteCipher
,
385 .advanceReadCipher
= SSLAdvanceInternalRecordLayerReadCipher
,
386 .rollbackWriteCipher
= SSLRollbackInternalRecordLayerWriteCipher
,
387 .setProtocolVersion
= SSLSetInternalRecordLayerProtocolVersion
,
388 .free
= SSLRecordFreeInternal
,
389 .serviceWriteQueue
= SSLRecordServiceWriteQueueInternal
,
390 .setOption
= SSLRecordSetOption
,