]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/lib/sslTransport.c
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / libsecurity_ssl / lib / sslTransport.c
1 /*
2 * Copyright (c) 1999-2001,2005-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 * sslTransport.c - SSL transport layer
26 */
27
28 #include "ssl.h"
29 #include "sslMemory.h"
30 #include "sslContext.h"
31 #include "sslRecord.h"
32 #include "sslDebug.h"
33 #include "sslCipherSpecs.h"
34 #include "sslUtils.h"
35
36 #include <assert.h>
37 #include <string.h>
38
39 #include <utilities/SecIOFormat.h>
40
41 #ifndef NDEBUG
42 static inline void sslIoTrace(
43 SSLContext *ctx,
44 const char *op,
45 size_t req,
46 size_t moved,
47 OSStatus stat)
48 {
49 sslLogRecordIo("[%p] ===%s: req %4lu moved %4lu status %d",
50 ctx, op, req, moved, (int)stat);
51 }
52 #else
53 #define sslIoTrace(ctx, op, req, moved, stat)
54 #endif /* NDEBUG */
55
56 extern int kSplitDefaultValue;
57
58 static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx);
59 static OSStatus SSLHandshakeProceed(SSLContext *ctx);
60 //static OSStatus SSLInitConnection(SSLContext *ctx);
61
62 OSStatus
63 SSLWrite(
64 SSLContext *ctx,
65 const void * data,
66 size_t dataLength,
67 size_t *bytesWritten) /* RETURNED */
68 {
69 OSStatus err;
70 SSLRecord rec;
71 size_t dataLen, processed;
72
73 sslLogRecordIo("[%p] SSLWrite top", ctx);
74 if((ctx == NULL) || (bytesWritten == NULL)) {
75 return errSecParam;
76 }
77 dataLen = dataLength;
78 processed = 0; /* Initialize in case we return with errSSLWouldBlock */
79 *bytesWritten = 0;
80
81 switch(ctx->state) {
82 case SSL_HdskStateGracefulClose:
83 err = errSSLClosedGraceful;
84 goto abort;
85 case SSL_HdskStateErrorClose:
86 err = errSSLClosedAbort;
87 goto abort;
88 case SSL_HdskStateReady:
89 break;
90 case SSL_HdskStateUninit:
91 /* not ready for I/O, and handshake not in progress */
92 sslIoTrace(ctx, "SSLWrite(1)", dataLength, 0, errSecBadReq);
93 return errSecBadReq;
94 default:
95 /* handshake in progress or done. Will call SSLHandshakeProceed below if necessary */
96 break;
97 }
98
99 /* First, we have to wait until the session is ready to send data,
100 so the encryption keys and such have been established. */
101 err = errSecSuccess;
102 while (!(ctx->writeCipher_ready))
103 { if ((err = SSLHandshakeProceed(ctx)) != 0)
104 goto exit;
105 }
106
107 /* Attempt to empty the write queue before queueing more data */
108 if ((err = SSLServiceWriteQueue(ctx)) != 0)
109 goto abort;
110
111 processed = 0;
112
113 /* Skip empty writes, fragmentation is done at the coreTLS layer */
114 if(dataLen) {
115 rec.contentType = SSL_RecordTypeAppData;
116 rec.protocolVersion = ctx->negProtocolVersion;
117 rec.contents.data = ((uint8_t *)data) + processed;
118 rec.contents.length = dataLen;
119 if ((err = SSLWriteRecord(rec, ctx)) != 0)
120 goto exit;
121 processed += rec.contents.length;
122 }
123
124 /* All the data has been advanced to the write queue */
125 *bytesWritten = processed;
126 if ((err = SSLServiceWriteQueue(ctx)) == 0) {
127 err = errSecSuccess;
128 }
129 exit:
130 switch(err) {
131 case errSecSuccess:
132 case errSSLWouldBlock:
133 case errSSLUnexpectedRecord:
134 case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */
135 case errSSLClientCertRequested:
136 case errSSLClosedGraceful:
137 break;
138 default:
139 sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
140 (int)err);
141 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
142 break;
143 }
144 abort:
145 sslIoTrace(ctx, "SSLWrite(2)", dataLength, *bytesWritten, err);
146 return err;
147 }
148
149 OSStatus
150 SSLRead (
151 SSLContext *ctx,
152 void * data,
153 size_t dataLength,
154 size_t *processed) /* RETURNED */
155 {
156 OSStatus err;
157 uint8_t *charPtr;
158 size_t bufSize, remaining, count;
159 SSLRecord rec;
160
161 sslLogRecordIo("[%p] SSLRead top (dataLength=%ld)", ctx, dataLength);
162 if((ctx == NULL) || (data == NULL) || (processed == NULL)) {
163 return errSecParam;
164 }
165 bufSize = dataLength;
166 *processed = 0; /* Initialize in case we return with errSSLWouldBlock */
167
168 readRetry:
169 /* first handle cases in which we know we're finished */
170 switch(ctx->state) {
171 case SSL_HdskStateGracefulClose:
172 err = errSSLClosedGraceful;
173 goto abort;
174 case SSL_HdskStateErrorClose:
175 err = errSSLClosedAbort;
176 goto abort;
177 case SSL_HdskStateNoNotifyClose:
178 err = errSSLClosedNoNotify;
179 goto abort;
180 default:
181 break;
182 }
183
184 /* First, we have to wait until the session is ready to receive data,
185 so the encryption keys and such have been established. */
186 err = errSecSuccess;
187 while (ctx->readCipher_ready == 0) {
188 if ((err = SSLHandshakeProceed(ctx)) != 0) {
189 goto exit;
190 }
191 }
192
193 /* Attempt to service the write queue */
194 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
195 if (err != errSSLWouldBlock) {
196 goto exit;
197 }
198 err = errSecSuccess; /* Write blocking shouldn't stop attempts to read */
199 }
200
201 remaining = bufSize;
202 charPtr = (uint8_t *)data;
203 if (ctx->receivedDataBuffer.data)
204 { count = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
205 if (count > bufSize)
206 count = bufSize;
207 memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count);
208 remaining -= count;
209 charPtr += count;
210 *processed += count;
211 ctx->receivedDataPos += count;
212 }
213
214 assert(ctx->receivedDataPos <= ctx->receivedDataBuffer.length);
215 assert(*processed + remaining == bufSize);
216 assert(charPtr == ((uint8_t *)data) + *processed);
217
218 if (ctx->receivedDataBuffer.data != 0 &&
219 ctx->receivedDataPos >= ctx->receivedDataBuffer.length)
220 { SSLFreeBuffer(&ctx->receivedDataBuffer);
221 ctx->receivedDataBuffer.data = 0;
222 ctx->receivedDataPos = 0;
223 }
224
225 /*
226 * This while statement causes a hang when using nonblocking low-level I/O!
227 while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
228 ..what we really have to do is just return as soon as we read one
229 record. A performance hit in the nonblocking case, but that is
230 the only way this code can work in both modes...
231 */
232 if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
233 { assert(ctx->receivedDataBuffer.data == 0);
234 if ((err = SSLReadRecord(&rec, ctx)) != 0) {
235 goto exit;
236 }
237 if (rec.contentType == SSL_RecordTypeAppData ||
238 rec.contentType == SSL_RecordTypeV2_0)
239 { if (rec.contents.length <= remaining)
240 { memcpy(charPtr, rec.contents.data, rec.contents.length);
241 remaining -= rec.contents.length;
242 charPtr += rec.contents.length;
243 *processed += rec.contents.length;
244 {
245 if ((err = SSLFreeRecord(rec, ctx))) {
246 goto exit;
247 }
248 }
249 }
250 else
251 { memcpy(charPtr, rec.contents.data, remaining);
252 charPtr += remaining;
253 *processed += remaining;
254 ctx->receivedDataBuffer = rec.contents;
255 ctx->receivedDataPos = remaining;
256 remaining = 0;
257 }
258 }
259 else {
260 if ((err = SSLProcessProtocolMessage(&rec, ctx)) != 0) {
261 /* This may not make much sense, but this is required so that we
262 process the write queue. This replicate exactly the behavior
263 before the coreTLS adoption */
264 if(err == errSSLClosedGraceful) {
265 err = SSLClose(ctx);
266 } else {
267 goto exit;
268 }
269 }
270 if ((err = SSLFreeRecord(rec, ctx))) {
271 goto exit;
272 }
273 }
274 }
275
276 err = errSecSuccess;
277
278 exit:
279 /* test for renegotiate: loop until something useful happens */
280 if(((err == errSecSuccess) && (*processed == 0) && dataLength) || (err == errSSLUnexpectedRecord)) {
281 sslLogNegotiateDebug("SSLRead recursion");
282 goto readRetry;
283 }
284 /* shut down on serious errors */
285 switch(err) {
286 case errSecSuccess:
287 case errSSLWouldBlock:
288 case errSSLUnexpectedRecord:
289 case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */
290 case errSSLClientCertRequested:
291 case errSSLClosedGraceful:
292 case errSSLClosedNoNotify:
293 break;
294 default:
295 sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
296 (int)err);
297 SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
298 break;
299 }
300 abort:
301 sslIoTrace(ctx, "SSLRead returns", dataLength, *processed, err);
302 return err;
303 }
304
305 #if SSL_DEBUG
306 #include "sslCrypto.h"
307 #endif
308
309 OSStatus
310 SSLHandshake(SSLContext *ctx)
311 {
312 OSStatus err;
313
314 if(ctx == NULL) {
315 return errSecParam;
316 }
317 if (ctx->state == SSL_HdskStateGracefulClose)
318 return errSSLClosedGraceful;
319 if (ctx->state == SSL_HdskStateErrorClose)
320 return errSSLClosedAbort;
321
322 err = errSecSuccess;
323
324 if(ctx->isDTLS && ctx->timeout_deadline) {
325 CFAbsoluteTime current = CFAbsoluteTimeGetCurrent();
326
327 if (ctx->timeout_deadline<current) {
328 sslDebugLog("%p, retransmition deadline expired\n", ctx);
329 err = tls_handshake_retransmit_timer_expired(ctx->hdsk);
330 if(err) {
331 return err;
332 }
333 }
334 }
335
336 while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0)
337 {
338 err = SSLHandshakeProceed(ctx);
339 if((err != 0) && (err != errSSLUnexpectedRecord))
340 return err;
341 }
342
343 /* one more flush at completion of successful handshake */
344 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
345 return err;
346 }
347
348 return errSecSuccess;
349 }
350
351 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
352
353 #include <AggregateDictionary/ADClient.h>
354
355 typedef void (*type_ADClientAddValueForScalarKey)(CFStringRef key, int64_t value);
356 static type_ADClientAddValueForScalarKey gADClientAddValueForScalarKey = NULL;
357 static dispatch_once_t gADFunctionPointersSet = 0;
358 static CFBundleRef gAggdBundleRef = NULL;
359
360 static bool InitializeADFunctionPointers()
361 {
362 if (gADClientAddValueForScalarKey)
363 {
364 return true;
365 }
366
367 dispatch_once(&gADFunctionPointersSet,
368 ^{
369 CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
370
371 CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true);
372
373 if (NULL != aggd_url)
374 {
375 gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url);
376 if (NULL != gAggdBundleRef)
377 {
378 gADClientAddValueForScalarKey = (type_ADClientAddValueForScalarKey)
379 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientAddValueForScalarKey"));
380 }
381 CFRelease(aggd_url);
382 }
383 });
384
385 return (gADClientAddValueForScalarKey!=NULL);
386 }
387
388 static void ad_log_SecureTransport_early_fail(long signature)
389 {
390 if (InitializeADFunctionPointers()) {
391
392 CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature);
393
394 if(key)
395 gADClientAddValueForScalarKey(key, 1);
396
397 CFRelease(key);
398 }
399 }
400
401 #endif
402
403
404 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
405
406 #include <msgtracer_client.h>
407
408 static void mt_log_SecureTransport_early_fail(long signature)
409 {
410 char signature_string[16];
411
412 snprintf(signature_string, sizeof(signature_string), "%ld", signature);
413
414 msgtracer_log_with_keys("com.apple.SecureTransport.early_fail", ASL_LEVEL_NOTICE,
415 "com.apple.message.signature", signature_string,
416 "com.apple.message.summarize", "YES",
417 NULL);
418 }
419
420 #endif
421
422
423 static void log_SecureTransport_early_fail(long signature)
424 {
425 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
426 mt_log_SecureTransport_early_fail(signature);
427 #endif
428
429 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
430 ad_log_SecureTransport_early_fail(signature);
431 #endif
432 }
433
434 static OSStatus
435 SSLHandshakeProceed(SSLContext *ctx)
436 {
437 OSStatus err;
438
439
440 if(ctx->state==SSL_HdskStateUninit) {
441 /* If we are the client, we start the negotiation */
442 if(ctx->protocolSide == kSSLClientSide) {
443 err = tls_handshake_negotiate(ctx->hdsk, &ctx->peerID);
444 if(err)
445 return err;
446 }
447 SSLChangeHdskState(ctx, SSL_HdskStatePending);
448 }
449
450 if ((err = tls_handshake_continue(ctx->hdsk)) != 0)
451 return err;
452
453 if ((err = SSLServiceWriteQueue(ctx)) != 0)
454 return err;
455
456 SSLRecord rec;
457
458 err = SSLReadRecord(&rec, ctx);
459
460 if(!err) {
461 sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx, rec.contents.length, rec.contentType);
462 err = tls_handshake_process(ctx->hdsk, rec.contents, rec.contentType);
463 sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx, rec.contents.length, rec.contentType, (int)err);
464 SSLFreeRecord(rec, ctx);
465 } else if(err!=errSSLWouldBlock) {
466 sslDebugLog("%p Read error err=%d\n\n", ctx, (int)err);
467 }
468
469 if(ctx->protocolSide == kSSLClientSide &&
470 ctx->dheEnabled == false &&
471 !ctx->serverHelloReceived &&
472 err && err != errSSLWouldBlock)
473 {
474 log_SecureTransport_early_fail(err);
475 }
476
477 return err;
478 }
479
480 static OSStatus
481 SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx)
482 {
483 return tls_handshake_process(ctx->hdsk, rec->contents, rec->contentType);
484 }
485
486 OSStatus
487 SSLClose(SSLContext *ctx)
488 {
489 OSStatus err = errSecSuccess;
490
491 sslHdskStateDebug("SSLClose");
492 if(ctx == NULL) {
493 return errSecParam;
494 }
495
496 err = tls_handshake_close(ctx->hdsk);
497
498 if (err == 0)
499 err = SSLServiceWriteQueue(ctx);
500
501 SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose);
502 if (err == errSecIO)
503 err = errSecSuccess; /* Ignore errors related to closed streams */
504 return err;
505 }
506
507 /*
508 * Determine how much data the client can be guaranteed to
509 * obtain via SSLRead() without blocking or causing any low-level
510 * read operations to occur.
511 *
512 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
513 * and receivedDataPos) are only used in this file.
514 */
515 OSStatus
516 SSLGetBufferedReadSize(SSLContextRef ctx,
517 size_t *bufSize) /* RETURNED */
518 {
519 if(ctx == NULL) {
520 return errSecParam;
521 }
522 if(ctx->receivedDataBuffer.data == NULL) {
523 *bufSize = 0;
524 }
525 else {
526 assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
527 *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
528 }
529 return errSecSuccess;
530 }