]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_ssl/lib/sslTransport.c
Security-57336.1.9.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 if(ctx->validCipherSuites == NULL) {
323 /* build list of legal cipherSpecs */
324 err = sslBuildCipherSuiteArray(ctx);
325 if(err) {
326 return err;
327 }
328 }
329
330 err = errSecSuccess;
331
332 if(ctx->isDTLS && ctx->timeout_deadline) {
333 CFAbsoluteTime current = CFAbsoluteTimeGetCurrent();
334
335 if (ctx->timeout_deadline<current) {
336 sslDebugLog("%p, retransmition deadline expired\n", ctx);
337 err = tls_handshake_retransmit_timer_expired(ctx->hdsk);
338 if(err) {
339 return err;
340 }
341 }
342 }
343
344 while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0)
345 {
346 err = SSLHandshakeProceed(ctx);
347 if((err != 0) && (err != errSSLUnexpectedRecord))
348 return err;
349 }
350
351 /* one more flush at completion of successful handshake */
352 if ((err = SSLServiceWriteQueue(ctx)) != 0) {
353 return err;
354 }
355
356 return errSecSuccess;
357 }
358
359 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR)
360
361 #include <AggregateDictionary/ADClient.h>
362
363 typedef void (*type_ADClientAddValueForScalarKey)(CFStringRef key, int64_t value);
364 static type_ADClientAddValueForScalarKey gADClientAddValueForScalarKey = NULL;
365 static dispatch_once_t gADFunctionPointersSet = 0;
366 static CFBundleRef gAggdBundleRef = NULL;
367
368 static bool InitializeADFunctionPointers()
369 {
370 if (gADClientAddValueForScalarKey)
371 {
372 return true;
373 }
374
375 dispatch_once(&gADFunctionPointersSet,
376 ^{
377 CFStringRef path_to_aggd_framework = CFSTR("/System/Library/PrivateFrameworks/AggregateDictionary.framework");
378
379 CFURLRef aggd_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, path_to_aggd_framework, kCFURLPOSIXPathStyle, true);
380
381 if (NULL != aggd_url)
382 {
383 gAggdBundleRef = CFBundleCreate(kCFAllocatorDefault, aggd_url);
384 if (NULL != gAggdBundleRef)
385 {
386 gADClientAddValueForScalarKey = (type_ADClientAddValueForScalarKey)
387 CFBundleGetFunctionPointerForName(gAggdBundleRef, CFSTR("ADClientAddValueForScalarKey"));
388 }
389 CFRelease(aggd_url);
390 }
391 });
392
393 return (gADClientAddValueForScalarKey!=NULL);
394 }
395
396 static void ad_log_SecureTransport_early_fail(long signature)
397 {
398 if (InitializeADFunctionPointers()) {
399
400 CFStringRef key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("com.apple.SecureTransport.early_fail.%ld"), signature);
401
402 if(key)
403 gADClientAddValueForScalarKey(key, 1);
404
405 CFRelease(key);
406 }
407 }
408
409 #endif
410
411
412 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
413
414 #include <msgtracer_client.h>
415
416 static void mt_log_SecureTransport_early_fail(long signature)
417 {
418 char signature_string[16];
419
420 snprintf(signature_string, sizeof(signature_string), "%ld", signature);
421
422 msgtracer_log_with_keys("com.apple.SecureTransport.early_fail", ASL_LEVEL_NOTICE,
423 "com.apple.message.signature", signature_string,
424 "com.apple.message.summarize", "YES",
425 NULL);
426 }
427
428 #endif
429
430
431 static void log_SecureTransport_early_fail(long signature)
432 {
433 #if (!TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
434 mt_log_SecureTransport_early_fail(signature);
435 #endif
436
437 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
438 ad_log_SecureTransport_early_fail(signature);
439 #endif
440 }
441
442 static OSStatus
443 SSLHandshakeProceed(SSLContext *ctx)
444 {
445 OSStatus err;
446
447
448 if(ctx->state==SSL_HdskStateUninit) {
449 /* If we are the client, we start the negotiation */
450 if(ctx->protocolSide == kSSLClientSide) {
451 err = tls_handshake_negotiate(ctx->hdsk, &ctx->peerID);
452 if(err)
453 return err;
454 }
455 SSLChangeHdskState(ctx, SSL_HdskStatePending);
456 }
457
458 if ((err = tls_handshake_continue(ctx->hdsk)) != 0)
459 return err;
460
461 if ((err = SSLServiceWriteQueue(ctx)) != 0)
462 return err;
463
464 SSLRecord rec;
465
466 err = SSLReadRecord(&rec, ctx);
467
468 if(!err) {
469 sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx, rec.contents.length, rec.contentType);
470 err = tls_handshake_process(ctx->hdsk, rec.contents, rec.contentType);
471 sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx, rec.contents.length, rec.contentType, (int)err);
472 SSLFreeRecord(rec, ctx);
473 } else if(err!=errSSLWouldBlock) {
474 sslDebugLog("%p Read error err=%d\n\n", ctx, (int)err);
475 }
476
477 if(ctx->protocolSide == kSSLClientSide &&
478 ctx->dheEnabled == false &&
479 !ctx->serverHelloReceived &&
480 err && err != errSSLWouldBlock)
481 {
482 log_SecureTransport_early_fail(err);
483 }
484
485 return err;
486 }
487
488 static OSStatus
489 SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx)
490 {
491 return tls_handshake_process(ctx->hdsk, rec->contents, rec->contentType);
492 }
493
494 OSStatus
495 SSLClose(SSLContext *ctx)
496 {
497 OSStatus err = errSecSuccess;
498
499 sslHdskStateDebug("SSLClose");
500 if(ctx == NULL) {
501 return errSecParam;
502 }
503
504 err = tls_handshake_close(ctx->hdsk);
505
506 if (err == 0)
507 err = SSLServiceWriteQueue(ctx);
508
509 SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose);
510 if (err == errSecIO)
511 err = errSecSuccess; /* Ignore errors related to closed streams */
512 return err;
513 }
514
515 /*
516 * Determine how much data the client can be guaranteed to
517 * obtain via SSLRead() without blocking or causing any low-level
518 * read operations to occur.
519 *
520 * Implemented here because the relevant info in SSLContext (receivedDataBuffer
521 * and receivedDataPos) are only used in this file.
522 */
523 OSStatus
524 SSLGetBufferedReadSize(SSLContextRef ctx,
525 size_t *bufSize) /* RETURNED */
526 {
527 if(ctx == NULL) {
528 return errSecParam;
529 }
530 if(ctx->receivedDataBuffer.data == NULL) {
531 *bufSize = 0;
532 }
533 else {
534 assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
535 *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
536 }
537 return errSecSuccess;
538 }