]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_ssl/lib/sslTransport.c
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_ssl / lib / sslTransport.c
diff --git a/Security/libsecurity_ssl/lib/sslTransport.c b/Security/libsecurity_ssl/lib/sslTransport.c
deleted file mode 100644 (file)
index c7627b3..0000000
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * Copyright (c) 1999-2001,2005-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-
-/*
- * sslTransport.c - SSL transport layer
- */
-
-#include "ssl.h"
-#include "sslMemory.h"
-#include "sslContext.h"
-#include "sslRecord.h"
-#include "sslAlertMessage.h"
-#include "sslSession.h"
-#include "sslDebug.h"
-#include "sslCipherSpecs.h"
-#include "sslUtils.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include <utilities/SecIOFormat.h>
-
-#ifndef        NDEBUG
-static inline void sslIoTrace(
-    SSLContext *ctx,
-       const char *op,
-       size_t req,
-       size_t moved,
-       OSStatus stat)
-{
-       sslLogRecordIo("[%p] ===%s: req %4lu moved %4lu status %d",
-               ctx, op, req, moved, (int)stat);
-}
-#else
-#define sslIoTrace(ctx, op, req, moved, stat)
-#endif /* NDEBUG */
-
-extern int kSplitDefaultValue;
-
-static OSStatus SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx);
-static OSStatus SSLHandshakeProceed(SSLContext *ctx);
-//static OSStatus SSLInitConnection(SSLContext *ctx);
-
-OSStatus 
-SSLWrite(
-       SSLContext                      *ctx,
-       const void *            data,
-       size_t                          dataLength,
-       size_t                          *bytesWritten)  /* RETURNED */
-{
-       OSStatus        err;
-    SSLRecord       rec;
-    size_t          dataLen, processed;
-
-       sslLogRecordIo("[%p] SSLWrite top", ctx);
-    if((ctx == NULL) || (bytesWritten == NULL)) {
-       return errSecParam;
-    }
-    dataLen = dataLength;
-    processed = 0;        /* Initialize in case we return with errSSLWouldBlock */
-    *bytesWritten = 0;
-
-    switch(ctx->state) {
-       case SSL_HdskStateGracefulClose:
-               err = errSSLClosedGraceful;
-                       goto abort;
-        case SSL_HdskStateErrorClose:
-               err = errSSLClosedAbort;
-                       goto abort;
-           case SSL_HdskStateReady:
-                       break;
-        case SSL_HdskStateUninit:
-            /* not ready for I/O, and handshake not in progress */
-            sslIoTrace(ctx, "SSLWrite(1)", dataLength, 0, errSecBadReq);
-            return errSecBadReq;
-        default:
-                       /* handshake in progress or done. Will call SSLHandshakeProceed below if necessary */
-                       break;
-       }
-
-    /* First, we have to wait until the session is ready to send data,
-        so the encryption keys and such have been established. */
-    err = errSecSuccess;
-    while (!(ctx->writeCipher_ready))
-    {   if ((err = SSLHandshakeProceed(ctx)) != 0)
-            goto exit;
-    }
-
-    /* Attempt to empty the write queue before queueing more data */
-    if ((err = SSLServiceWriteQueue(ctx)) != 0)
-        goto abort;
-
-    processed = 0;
-
-    /* Skip empty writes, fragmentation is done at the coreTLS layer */
-    if(dataLen) {
-        rec.contentType = SSL_RecordTypeAppData;
-        rec.protocolVersion = ctx->negProtocolVersion;
-        rec.contents.data = ((uint8_t *)data) + processed;
-        rec.contents.length = dataLen;
-        if ((err = SSLWriteRecord(rec, ctx)) != 0)
-            goto exit;
-        processed += rec.contents.length;
-    }
-
-    /* All the data has been advanced to the write queue */
-    *bytesWritten = processed;
-    if ((err = SSLServiceWriteQueue(ctx)) == 0) {
-               err = errSecSuccess;
-       }
-exit:
-       switch(err) {
-               case errSecSuccess:
-               case errSSLWouldBlock:
-        case errSSLUnexpectedRecord:
-               case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */
-               case errSSLClientCertRequested:
-               case errSSLClosedGraceful:
-                       break;
-               default:
-                       sslErrorLog("SSLWrite: going to state errorClose due to err %d\n",
-                               (int)err);
-                       SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
-                       break;
-    }
-abort:
-       sslIoTrace(ctx, "SSLWrite(2)", dataLength, *bytesWritten, err);
-    return err;
-}
-
-OSStatus
-SSLRead        (
-       SSLContext                      *ctx,
-       void *                          data,
-       size_t                          dataLength,
-       size_t                          *processed)             /* RETURNED */
-{
-       OSStatus        err;
-    uint8_t         *charPtr;
-    size_t          bufSize, remaining, count;
-    SSLRecord       rec;
-
-       sslLogRecordIo("[%p] SSLRead top (dataLength=%ld)", ctx, dataLength);
-    if((ctx == NULL) || (data == NULL) || (processed == NULL)) {
-       return errSecParam;
-    }
-    bufSize = dataLength;
-    *processed = 0;        /* Initialize in case we return with errSSLWouldBlock */
-
-readRetry:
-       /* first handle cases in which we know we're finished */
-       switch(ctx->state) {
-               case SSL_HdskStateGracefulClose:
-                       err = errSSLClosedGraceful;
-                       goto abort;
-               case SSL_HdskStateErrorClose:
-                       err = errSSLClosedAbort;
-                       goto abort;
-               case SSL_HdskStateNoNotifyClose:
-                       err = errSSLClosedNoNotify;
-                       goto abort;
-               default:
-                       break;
-       }
-
-    /* First, we have to wait until the session is ready to receive data,
-        so the encryption keys and such have been established. */
-    err = errSecSuccess;
-    while (ctx->readCipher_ready == 0) {
-               if ((err = SSLHandshakeProceed(ctx)) != 0) {
-            goto exit;
-               }
-    }
-
-    /* Attempt to service the write queue */
-    if ((err = SSLServiceWriteQueue(ctx)) != 0) {
-               if (err != errSSLWouldBlock) {
-            goto exit;
-               }
-        err = errSecSuccess; /* Write blocking shouldn't stop attempts to read */
-    }
-
-    remaining = bufSize;
-    charPtr = (uint8_t *)data;
-    if (ctx->receivedDataBuffer.data)
-    {   count = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
-        if (count > bufSize)
-            count = bufSize;
-        memcpy(data, ctx->receivedDataBuffer.data + ctx->receivedDataPos, count);
-        remaining -= count;
-        charPtr += count;
-        *processed += count;
-        ctx->receivedDataPos += count;
-    }
-
-    assert(ctx->receivedDataPos <= ctx->receivedDataBuffer.length);
-    assert(*processed + remaining == bufSize);
-    assert(charPtr == ((uint8_t *)data) + *processed);
-
-    if (ctx->receivedDataBuffer.data != 0 &&
-        ctx->receivedDataPos >= ctx->receivedDataBuffer.length)
-    {   SSLFreeBuffer(&ctx->receivedDataBuffer);
-        ctx->receivedDataBuffer.data = 0;
-        ctx->receivedDataPos = 0;
-    }
-
-       /*
-        * This while statement causes a hang when using nonblocking low-level I/O!
-    while (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
-        ..what we really have to do is just return as soon as we read one
-          record. A performance hit in the nonblocking case, but that is
-          the only way this code can work in both modes...
-        */
-    if (remaining > 0 && ctx->state != SSL_HdskStateGracefulClose)
-    {   assert(ctx->receivedDataBuffer.data == 0);
-        if ((err = SSLReadRecord(&rec, ctx)) != 0) {
-            goto exit;
-        }
-        if (rec.contentType == SSL_RecordTypeAppData ||
-            rec.contentType == SSL_RecordTypeV2_0)
-        {   if (rec.contents.length <= remaining)
-            {   memcpy(charPtr, rec.contents.data, rec.contents.length);
-                remaining -= rec.contents.length;
-                charPtr += rec.contents.length;
-                *processed += rec.contents.length;
-                {
-                    if ((err = SSLFreeRecord(rec, ctx))) {
-                       goto exit;
-                    }
-                }
-            }
-            else
-            {   memcpy(charPtr, rec.contents.data, remaining);
-                charPtr += remaining;
-                *processed += remaining;
-                ctx->receivedDataBuffer = rec.contents;
-                ctx->receivedDataPos = remaining;
-                remaining = 0;
-            }
-        }
-        else {
-            if ((err = SSLProcessProtocolMessage(&rec, ctx)) != 0) {
-                /* This may not make much sense, but this is required so that we
-                 process the write queue. This replicate exactly the behavior 
-                 before the coreTLS adoption */
-                if(err == errSSLClosedGraceful) {
-                    err = SSLClose(ctx);
-                } else {
-                    goto exit;
-                }
-                       }
-            if ((err = SSLFreeRecord(rec, ctx))) {
-                goto exit;
-                       }
-        }
-    }
-
-    err = errSecSuccess;
-
-exit:
-       /* test for renegotiate: loop until something useful happens */
-       if(((err == errSecSuccess)  && (*processed == 0) && dataLength) || (err == errSSLUnexpectedRecord)) {
-               sslLogNegotiateDebug("SSLRead recursion");
-               goto readRetry;
-       }
-       /* shut down on serious errors */
-       switch(err) {
-               case errSecSuccess:
-               case errSSLWouldBlock:
-        case errSSLUnexpectedRecord:
-               case errSSLServerAuthCompleted: /* == errSSLClientAuthCompleted */
-               case errSSLClientCertRequested:
-               case errSSLClosedGraceful:
-               case errSSLClosedNoNotify:
-                       break;
-               default:
-                       sslErrorLog("SSLRead: going to state errorClose due to err %d\n",
-                               (int)err);
-                       SSLChangeHdskState(ctx, SSL_HdskStateErrorClose);
-                       break;
-    }
-abort:
-       sslIoTrace(ctx, "SSLRead returns", dataLength, *processed, err);
-    return err;
-}
-
-#if    SSL_DEBUG
-#include "sslCrypto.h"
-#endif
-
-OSStatus
-SSLHandshake(SSLContext *ctx)
-{
-       OSStatus  err;
-
-       if(ctx == NULL) {
-               return errSecParam;
-       }
-    if (ctx->state == SSL_HdskStateGracefulClose)
-        return errSSLClosedGraceful;
-    if (ctx->state == SSL_HdskStateErrorClose)
-        return errSSLClosedAbort;
-
-    if(ctx->validCipherSuites == NULL) {
-       /* build list of legal cipherSpecs */
-        err = sslBuildCipherSuiteArray(ctx);
-       if(err) {
-               return err;
-       }
-    }
-
-    err = errSecSuccess;
-
-    if(ctx->isDTLS && ctx->timeout_deadline) {
-        CFAbsoluteTime current = CFAbsoluteTimeGetCurrent();
-
-        if (ctx->timeout_deadline<current) {
-            sslDebugLog("%p, retransmition deadline expired\n", ctx);
-            err = tls_handshake_retransmit_timer_expired(ctx->hdsk);
-            if(err) {
-                return err;
-            }
-        }
-    }
-
-    while (ctx->readCipher_ready == 0 || ctx->writeCipher_ready == 0)
-    {
-        err = SSLHandshakeProceed(ctx);
-        if((err != 0) && (err != errSSLUnexpectedRecord))
-            return err;
-    }
-
-       /* one more flush at completion of successful handshake */
-    if ((err = SSLServiceWriteQueue(ctx)) != 0) {
-               return err;
-       }
-
-    return errSecSuccess;
-}
-
-
-static OSStatus
-SSLHandshakeProceed(SSLContext *ctx)
-{
-    OSStatus  err;
-
-
-    if(ctx->state==SSL_HdskStateUninit) {
-        /* If we are the client, we start the negotiation */
-        if(ctx->protocolSide == kSSLClientSide) {
-            err = tls_handshake_negotiate(ctx->hdsk, &ctx->peerID);
-            if(err)
-                return err;
-        }
-        SSLChangeHdskState(ctx, SSL_HdskStatePending);
-    }
-
-    if ((err = tls_handshake_continue(ctx->hdsk)) != 0)
-        return err;
-
-    if ((err = SSLServiceWriteQueue(ctx)) != 0)
-        return err;
-
-    SSLRecord rec;
-
-    err = SSLReadRecord(&rec, ctx);
-
-    if(!err) {
-        sslDebugLog("%p going to process a record (rec.len=%zd, ct=%d)\n", ctx, rec.contents.length, rec.contentType);
-        err = tls_handshake_process(ctx->hdsk, rec.contents, rec.contentType);
-        sslDebugLog("%p processed a record (rec.len=%zd, ct=%d, err=%d)\n", ctx, rec.contents.length, rec.contentType, (int)err);
-        SSLFreeRecord(rec, ctx);
-    } else if(err!=errSSLWouldBlock) {
-        sslDebugLog("%p Read error err=%d\n\n", ctx, (int)err);
-    }
-
-    return err;
-}
-
-static OSStatus
-SSLProcessProtocolMessage(SSLRecord *rec, SSLContext *ctx)
-{
-    return tls_handshake_process(ctx->hdsk, rec->contents, rec->contentType);
-}
-
-OSStatus
-SSLClose(SSLContext *ctx)
-{
-       OSStatus      err = errSecSuccess;
-
-       sslHdskStateDebug("SSLClose");
-       if(ctx == NULL) {
-               return errSecParam;
-       }
-
-    err = tls_handshake_close(ctx->hdsk);
-
-    if (err == 0)
-        err = SSLServiceWriteQueue(ctx);
-
-    SSLChangeHdskState(ctx, SSL_HdskStateGracefulClose);
-    if (err == errSecIO)
-        err = errSecSuccess;     /* Ignore errors related to closed streams */
-    return err;
-}
-
-/*
- * Determine how much data the client can be guaranteed to
- * obtain via SSLRead() without blocking or causing any low-level
- * read operations to occur.
- *
- * Implemented here because the relevant info in SSLContext (receivedDataBuffer
- * and receivedDataPos) are only used in this file.
- */
-OSStatus
-SSLGetBufferedReadSize(SSLContextRef ctx,
-       size_t *bufSize)                        /* RETURNED */
-{
-       if(ctx == NULL) {
-               return errSecParam;
-       }
-       if(ctx->receivedDataBuffer.data == NULL) {
-               *bufSize = 0;
-       }
-       else {
-               assert(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
-               *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
-       }
-       return errSecSuccess;
-}