]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/Security/SSLRecordInternal.c
Security-57336.1.9.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / Security / 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 "sslUtils.h"
32 #include "tls_record_internal.h"
33
34 #include <AssertMacros.h>
35 #include <string.h>
36
37 #include <inttypes.h>
38 #include <stddef.h>
39
40 /* Maximum encrypted record size, defined in TLS 1.2 RFC, section 6.2.3 */
41 #define DEFAULT_BUFFER_SIZE (16384 + 2048)
42
43
44 /*
45 * Redirect SSLBuffer-based I/O call to user-supplied I/O.
46 */
47 static
48 int sslIoRead(SSLBuffer buf,
49 size_t *actualLength,
50 struct SSLRecordInternalContext *ctx)
51 {
52 int ortn;
53 SSLContextRef sslCtx = ctx->sslCtx;
54
55 *actualLength = buf.length;
56
57 ortn = sslCtx->ioCtx.read(sslCtx->ioCtx.ioRef, buf.data, actualLength);
58
59 /* We may need to translate error codes at this layer */
60 if(ortn==errSSLWouldBlock) {
61 ortn=errSSLRecordWouldBlock;
62 }
63
64 sslLogRecordIo("sslIoRead: [%p] req %4lu actual %4lu status %d",
65 ctx, buf.length, *actualLength, (int)ortn);
66
67 return ortn;
68 }
69
70 static
71 int sslIoWrite(SSLBuffer buf,
72 size_t *actualLength,
73 struct SSLRecordInternalContext *ctx)
74 {
75 int ortn;
76 SSLContextRef sslCtx = ctx->sslCtx;
77
78 *actualLength = buf.length;
79
80 ortn = sslCtx->ioCtx.write(sslCtx->ioCtx.ioRef, buf.data, actualLength);
81
82 /* We may need to translate error codes at this layer */
83 if(ortn==errSSLWouldBlock) {
84 ortn=errSSLRecordWouldBlock;
85 }
86
87 sslLogRecordIo("sslIoWrite: [%p] req %4lu actual %4lu status %d",
88 ctx, buf.length, *actualLength, (int)ortn);
89
90 return ortn;
91 }
92
93 /* Entry points to Record Layer */
94
95 static int SSLRecordReadInternal(SSLRecordContextRef ref, SSLRecord *rec)
96 {
97 struct SSLRecordInternalContext *ctx = ref;
98
99 int err;
100 size_t len, contentLen;
101 SSLBuffer readData;
102
103 size_t head=tls_record_get_header_size(ctx->filter);
104
105 if (ctx->amountRead < head)
106 {
107 readData.length = head - ctx->amountRead;
108 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
109 len = readData.length;
110 err = sslIoRead(readData, &len, ctx);
111 if(err != 0)
112 {
113 switch(err) {
114 case errSSLRecordWouldBlock:
115 ctx->amountRead += len;
116 break;
117 default:
118 /* Any other error but errSSLWouldBlock is translated to errSSLRecordClosedAbort */
119 err = errSSLRecordClosedAbort;
120 break;
121 }
122 return err;
123 }
124 ctx->amountRead += len;
125
126 check(ctx->amountRead == head);
127 }
128
129
130 tls_buffer header;
131 header.data=ctx->partialReadBuffer.data;
132 header.length=head;
133
134 uint8_t content_type;
135
136 tls_record_parse_header(ctx->filter, header, &contentLen, &content_type);
137
138 if(content_type&0x80) {
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 return errSSLRecordRecordOverflow;
149
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);
155 if(err != 0)
156 { if (err == errSSLRecordWouldBlock)
157 ctx->amountRead += len;
158 return err;
159 }
160 ctx->amountRead += len;
161 }
162
163 check(ctx->amountRead == head + contentLen);
164
165 tls_buffer record;
166 record.data = ctx->partialReadBuffer.data;
167 record.length = ctx->amountRead;
168
169 rec->contentType = content_type;
170
171 ctx->amountRead = 0; /* We've used all the data in the cache */
172
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);
176 } else {
177 size_t sz = tls_record_decrypted_size(ctx->filter, record.length);
178
179 /* There was an underflow - For TLS, we return errSSLRecordClosedAbort for historical reason - see ssl-44-crashes test */
180 if(sz==0) {
181 sslErrorLog("underflow in SSLReadRecordInternal");
182 if(ctx->dtls) {
183 // For DTLS, we should just drop it.
184 return errSSLRecordUnexpectedRecord;
185 } else {
186 // For TLS, we are going to close the connection.
187 return errSSLRecordClosedAbort;
188 }
189 }
190
191 /* Allocate a buffer for the plaintext */
192 if ((err = SSLAllocBuffer(&rec->contents, sz)))
193 {
194 return err;
195 }
196
197 return tls_record_decrypt(ctx->filter, record, &rec->contents, NULL);
198 }
199 }
200
201 static int SSLRecordWriteInternal(SSLRecordContextRef ref, SSLRecord rec)
202 {
203 int err;
204 struct SSLRecordInternalContext *ctx = ref;
205 WaitingRecord *queue, *out;
206 tls_buffer data;
207 tls_buffer content;
208 size_t len;
209
210 err = errSSLRecordInternal; /* FIXME: allocation error */
211 len=tls_record_encrypted_size(ctx->filter, rec.contentType, rec.contents.length);
212
213 require((out = (WaitingRecord *)sslMalloc(offsetof(WaitingRecord, data) + len)), fail);
214 out->next = NULL;
215 out->sent = 0;
216 out->length = len;
217
218 data.data=&out->data[0];
219 data.length=out->length;
220
221 content.data = rec.contents.data;
222 content.length = rec.contents.length;
223
224 require_noerr((err=tls_record_encrypt(ctx->filter, content, rec.contentType, &data)), fail);
225
226 out->length = data.length; // This should not be needed if tls_record_encrypted_size works properly.
227
228 /* Enqueue the record to be written from the idle loop */
229 if (ctx->recordWriteQueue == 0)
230 ctx->recordWriteQueue = out;
231 else
232 { queue = ctx->recordWriteQueue;
233 while (queue->next != 0)
234 queue = queue->next;
235 queue->next = out;
236 }
237
238 return 0;
239 fail:
240 if(out)
241 sslFree(out);
242 return err;
243 }
244
245 /* Record Layer Entry Points */
246
247 static int
248 SSLRollbackInternalRecordLayerWriteCipher(SSLRecordContextRef ref)
249 {
250 struct SSLRecordInternalContext *ctx = ref;
251 return tls_record_rollback_write_cipher(ctx->filter);
252 }
253
254 static int
255 SSLAdvanceInternalRecordLayerWriteCipher(SSLRecordContextRef ref)
256 {
257 struct SSLRecordInternalContext *ctx = ref;
258 return tls_record_advance_write_cipher(ctx->filter);
259 }
260
261 static int
262 SSLAdvanceInternalRecordLayerReadCipher(SSLRecordContextRef ref)
263 {
264 struct SSLRecordInternalContext *ctx = ref;
265 return tls_record_advance_read_cipher(ctx->filter);
266 }
267
268 static int
269 SSLInitInternalRecordLayerPendingCiphers(SSLRecordContextRef ref, uint16_t selectedCipher, bool isServer, SSLBuffer key)
270 {
271 struct SSLRecordInternalContext *ctx = ref;
272 return tls_record_init_pending_ciphers(ctx->filter, selectedCipher, isServer, key);
273 }
274
275 static int
276 SSLSetInternalRecordLayerProtocolVersion(SSLRecordContextRef ref, SSLProtocolVersion negVersion)
277 {
278 struct SSLRecordInternalContext *ctx = ref;
279 return tls_record_set_protocol_version(ctx->filter, negVersion);
280 }
281
282 static int
283 SSLRecordFreeInternal(SSLRecordContextRef ref, SSLRecord rec)
284 {
285 return SSLFreeBuffer(&rec.contents);
286 }
287
288 static int
289 SSLRecordServiceWriteQueueInternal(SSLRecordContextRef ref)
290 {
291 int werr = 0;
292 size_t written = 0;
293 SSLBuffer buf;
294 WaitingRecord *rec;
295 struct SSLRecordInternalContext *ctx= ref;
296
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)
303 {
304 check(rec->sent == rec->length);
305 ctx->recordWriteQueue = rec->next;
306 sslFree(rec);
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(SSLContextRef sslCtx)
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 require((ctx->filter=tls_record_create(sslCtx->isDTLS, CCRNGSTATE)), fail);
344 require_noerr(SSLAllocBuffer(&ctx->partialReadBuffer,
345 DEFAULT_BUFFER_SIZE), fail);
346
347 ctx->sslCtx = sslCtx;
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 void
358 SSLDestroyInternalRecordLayer(SSLRecordContextRef ref)
359 {
360 struct SSLRecordInternalContext *ctx = ref;
361 WaitingRecord *waitRecord, *next;
362
363 /* RecordContext cleanup : */
364 SSLFreeBuffer(&ctx->partialReadBuffer);
365 waitRecord = ctx->recordWriteQueue;
366 while (waitRecord)
367 { next = waitRecord->next;
368 sslFree(waitRecord);
369 waitRecord = next;
370 }
371
372 if(ctx->filter)
373 tls_record_destroy(ctx->filter);
374
375 sslFree(ctx);
376
377 }
378
379 struct SSLRecordFuncs SSLRecordLayerInternal =
380 {
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,
391 };
392