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