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