]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/lib/SSLRecordInternal.c
Security-59754.60.13.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / lib / SSLRecordInternal.c
1 /*
2 * Copyright (c) 2011-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25 /* THIS FILE CONTAINS KERNEL CODE */
26
27 #include "sslBuildFlags.h"
28 #include "SSLRecordInternal.h"
29 #include "sslDebug.h"
30 #include "cipherSpecs.h"
31 #include "tls_record_internal.h"
32
33 #include <AssertMacros.h>
34 #include <string.h>
35
36 #include <inttypes.h>
37 #include <stddef.h>
38
39 /* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */
40 #define DEFAULT_BUFFER_SIZE (16384 + 2048)
41
42
43 /*
44 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
45 */
46 static
47 int sslIoRead(SSLBuffer buf,
48 size_t *actualLength,
49 struct SSLRecordInternalContext *ctx)
50 {
51 int ortn;
52 SSLContextRef sslCtx = ctx->sslCtx;
53
54 *actualLength = buf.length;
55
56 ortn = sslCtx->ioCtx.read(sslCtx->ioCtx.ioRef, buf.data, actualLength);
57
58 /* We may need to translate error codes at this layer */
59 if(ortn==errSSLWouldBlock) {
60 ortn=errSSLRecordWouldBlock;
61 }
62
63 sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d",
64 ctx, buf.length, *actualLength, (int)ortn);
65
66 return ortn;
67 }
68
69 static
70 int sslIoWrite(SSLBuffer buf,
71 size_t *actualLength,
72 struct SSLRecordInternalContext *ctx)
73 {
74 int ortn;
75 SSLContextRef sslCtx = ctx->sslCtx;
76
77 *actualLength = buf.length;
78
79 ortn = sslCtx->ioCtx.write(sslCtx->ioCtx.ioRef, buf.data, actualLength);
80
81 /* We may need to translate error codes at this layer */
82 if(ortn==errSSLWouldBlock) {
83 ortn=errSSLRecordWouldBlock;
84 }
85
86 sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d",
87 ctx, buf.length, *actualLength, (int)ortn);
88
89 return ortn;
90 }
91
92 /* Entry points to Record Layer */
93
94 static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec)
95 {
96 struct SSLRecordInternalContext *ctx = ref;
97
98 int err;
99 size_t len, contentLen;
100 SSLBuffer readData;
101
102 size_t head=tls_record_get_header_size(ctx->filter);
103
104 if (ctx->amountRead < head)
105 {
106 readData.length = head - ctx->amountRead;
107 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
108 len = readData.length;
109 err = sslIoRead(readData, &len, ctx);
110 if(err != 0)
111 {
112 switch(err) {
113 case errSSLRecordWouldBlock:
114 ctx->amountRead += len;
115 break;
116 default:
117 /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */
118 err = errSSLRecordClosedAbort;
119 break;
120 }
121 return err;
122 }
123 ctx->amountRead += len;
124
125 check(ctx->amountRead == head);
126 }
127
128
129 tls_buffer header;
130 header.data=ctx->partialReadBuffer.data;
131 header.length=head;
132
133 uint8_t content_type;
134
135 tls_record_parse_header(ctx->filter, header, &contentLen, &content_type);
136
137 if(content_type&0x80) {
138 sslDebugLog("Detected SSL2 record in SSLReadRecordInternal");
139 // Looks like SSL2 record, reset expectations.
140 head = 2;
141 err=tls_record_parse_ssl2_header(ctx->filter, header, &contentLen, &content_type);
142 if(err!=0) return errSSLRecordUnexpectedRecord;
143 }
144
145 check(ctx->partialReadBuffer.length>=head+contentLen);
146
147 if(head+contentLen>ctx->partialReadBuffer.length) {
148 sslDebugLog("overflow in SSLReadRecordInternal");
149 return errSSLRecordRecordOverflow;
150 }
151
152 if (ctx->amountRead < head + contentLen)
153 {
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);
158 if(err != 0)
159 {
160 if (err == errSSLRecordWouldBlock)
161 {
162 ctx->amountRead += len;
163 }
164 return err;
165 }
166 ctx->amountRead += len;
167 }
168
169 check(ctx->amountRead == head + contentLen);
170
171 tls_buffer record;
172 record.data = ctx->partialReadBuffer.data;
173 record.length = ctx->amountRead;
174
175 rec->contentType = content_type;
176
177 ctx->amountRead = 0; /* We've used all the data in the cache */
178
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);
182 } else {
183 size_t sz = tls_record_decrypted_size(ctx->filter, record.length);
184
185 /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */
186 if(sz==0) {
187 sslErrorLog("underflow in SSLReadRecordInternal");
188 if(ctx->sslCtx->isDTLS) {
189 // For DTLS, we should just drop it.
190 return errSSLRecordUnexpectedRecord;
191 } else {
192 // For TLS, we are going to close the connection.
193 return errSSLRecordClosedAbort;
194 }
195 }
196
197 /* Allocate a buffer for the plaintext */
198 if ((err = SSLAllocBuffer(&rec->contents, sz)))
199 {
200 return err;
201 }
202
203 return tls_record_decrypt(ctx->filter, record, &rec->contents, NULL);
204 }
205 }
206
207 static int SSLRecordWriteInternal(SSLRecordContextRef ref, SSLRecord rec)
208 {
209 int err;
210 struct SSLRecordInternalContext *ctx = ref;
211 WaitingRecord *queue, *out;
212 tls_buffer data;
213 tls_buffer content;
214 size_t len;
215
216 err = errSSLRecordInternal; /* FIXME: allocation error */
217 len=tls_record_encrypted_size(ctx->filter, rec.contentType, rec.contents.length);
218
219 require((out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) + len)), fail);
220 out->next = NULL;
221 out->sent = 0;
222 out->length = len;
223
224 data.data=&out->data[0];
225 data.length=out->length;
226
227 content.data = rec.contents.data;
228 content.length = rec.contents.length;
229
230 require_noerr((err=tls_record_encrypt(ctx->filter, content, rec.contentType, &data)), fail);
231
232 out->length = data.length; // This should not be needed if tls_record_encrypted_size works properly.
233
234 /* Enqueue the record to be written from the idle loop */
235 if (ctx->recordWriteQueue == 0)
236 ctx->recordWriteQueue = out;
237 else
238 { queue = ctx->recordWriteQueue;
239 while (queue->next != 0)
240 queue = queue->next;
241 queue->next = out;
242 }
243
244 return 0;
245 fail:
246 if(out)
247 sslFree(out);
248 return err;
249 }
250
251 /* Record Layer Entry Points */
252
253 static int
254 SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref)
255 {
256 struct SSLRecordInternalContext *ctx = ref;
257 return tls_record_rollback_write_cipher(ctx->filter);
258 }
259
260 static int
261 SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref)
262 {
263 struct SSLRecordInternalContext *ctx = ref;
264 return tls_record_advance_write_cipher(ctx->filter);
265 }
266
267 static int
268 SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref)
269 {
270 struct SSLRecordInternalContext *ctx = ref;
271 return tls_record_advance_read_cipher(ctx->filter);
272 }
273
274 static int
275 SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref, uint16_t selectedCipher, bool isServer, SSLBuffer key)
276 {
277 struct SSLRecordInternalContext *ctx = ref;
278 return tls_record_init_pending_ciphers(ctx->filter, selectedCipher, isServer, key);
279 }
280
281 static int
282 SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref, SSLProtocolVersion negVersion)
283 {
284 struct SSLRecordInternalContext *ctx = ref;
285 return tls_record_set_protocol_version(ctx->filter, (tls_protocol_version) negVersion);
286 }
287
288 static int
289 SSLRecordFreeInternal(SSLRecordContextRef ref, SSLRecord rec)
290 {
291 return SSLFreeBuffer(&rec.contents);
292 }
293
294 static int
295 SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref)
296 {
297 int werr = 0;
298 size_t written = 0;
299 SSLBuffer buf;
300 WaitingRecord *rec;
301 struct SSLRecordInternalContext *ctx= ref;
302
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)
309 {
310 check(rec->sent == rec->length);
311 ctx->recordWriteQueue = rec->next;
312 sslFree(rec);
313 }
314 }
315
316 return werr;
317 }
318
319 static int
320 SSLRecordSetOption(SSLRecordContextRef ref, SSLRecordOption option, bool value)
321 {
322 struct SSLRecordInternalContext *ctx = (struct SSLRecordInternalContext *)ref;
323 switch (option) {
324 case kSSLRecordOptionSendOneByteRecord:
325 return tls_record_set_record_splitting(ctx->filter, value);
326 default:
327 return 0;
328 }
329 }
330
331 /***** Internal Record Layer APIs *****/
332
333 #include <corecrypto/ccrng.h>
334 #define CCRNGSTATE ccrng(NULL)
335
336 SSLRecordContextRef
337 SSLCreateInternalRecordLayer(SSLContextRef sslCtx)
338 {
339 struct SSLRecordInternalContext *ctx;
340
341 ctx = sslMalloc(sizeof(struct SSLRecordInternalContext));
342 if(ctx==NULL)
343 return NULL;
344
345 memset(ctx, 0, sizeof(struct SSLRecordInternalContext));
346
347 require((ctx->filter=tls_record_create(sslCtx->isDTLS, CCRNGSTATE)), fail);
348 require_noerr(SSLAllocBuffer(&ctx->partialReadBuffer,
349 DEFAULT_BUFFER_SIZE), fail);
350
351 ctx->sslCtx = sslCtx;
352 return ctx;
353
354 fail:
355 if(ctx->filter)
356 tls_record_destroy(ctx->filter);
357 sslFree(ctx);
358 return NULL;
359 }
360
361 void
362 SSLDestroyInternalRecordLayer(SSLRecordContextRef ref)
363 {
364 struct SSLRecordInternalContext *ctx = ref;
365 WaitingRecord *waitRecord, *next;
366
367 /* RecordContext cleanup : */
368 SSLFreeBuffer(&ctx->partialReadBuffer);
369 waitRecord = ctx->recordWriteQueue;
370 while (waitRecord)
371 { next = waitRecord->next;
372 sslFree(waitRecord);
373 waitRecord = next;
374 }
375
376 if(ctx->filter)
377 tls_record_destroy(ctx->filter);
378
379 sslFree(ctx);
380
381 }
382
383 struct SSLRecordFuncs SSLRecordLayerInternal =
384 {
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,
395 };
396