X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/67c7378dcb8de24c86b7fedff90b4b496f2e474c..5a719ac813caa6f2ceaa192274fad2e1c2cec162:/SecureTransport/ssltrspt.c
diff --git a/SecureTransport/ssltrspt.c b/SecureTransport/ssltrspt.c
deleted file mode 100644
index b6354204..00000000
--- a/SecureTransport/ssltrspt.c
+++ /dev/null
@@ -1,606 +0,0 @@
-/*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
- *
- * The contents of this file constitute Original Code as defined in and are
- * subject to the Apple Public Source License Version 1.2 (the 'License').
- * You may not use this file except in compliance with the License. Please obtain
- * a copy of the License at http://www.apple.com/publicsource and read it before
- * using this file.
- *
- * This 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.
- */
-
-
-/*
- File: ssltrspt.c
-
- Contains: SSLContext transport layer
-
- Written by: Doug Mitchell, based on Netscape SSLRef 3.0
-
- Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
-
-*/
-/* *********************************************************************
- File: ssltrspt.c
-
- SSLRef 3.0 Final -- 11/19/96
-
- Copyright (c)1996 by Netscape Communications Corp.
-
- By retrieving this software you are bound by the licensing terms
- disclosed in the file "LICENSE.txt". Please read it, and if you don't
- accept the terms, delete this software.
-
- SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
- View, California and Consensus Development
- Corporation of Berkeley, California .
-
- *********************************************************************
-
- File: ssltrspt.c Data transportation functionality
-
- Transports data between the application and the record layer; also
- hands off handshake, alert, and change cipher spec messages to their
- handlers. Also, ensures that negotiation happens before application
- data goes out on the wire.
-
- ****************************************************************** */
-
-#ifndef _SSLTRSPT_H_
-#include "ssltrspt.h"
-#endif
-
-#ifndef _SSLALLOC_H_
-#include "sslalloc.h"
-#endif
-
-#ifndef _SSLCTX_H_
-#include "sslctx.h"
-#endif
-
-#ifndef _SSLCTX_H_
-#include "sslrec.h"
-#endif
-
-#ifndef _SSLALERT_H_
-#include "sslalert.h"
-#endif
-
-#ifndef _SSLSESS_H_
-#include "sslsess.h"
-#endif
-
-#ifndef _SSL2_H_
-#include "ssl2.h"
-#endif
-
-#ifndef _APPLE_GLUE_H_
-#include "appleGlue.h"
-#endif
-
-#ifndef _SSL_DEBUG_H_
-#include "sslDebug.h"
-#endif
-
-#ifndef _CIPHER_SPECS_H_
-#include "cipherSpecs.h"
-#endif
-
-#include
-
-#include
-#include
-
-#define SSL_IO_TRACE 0
-#if SSL_IO_TRACE
-static void sslIoTrace(
- const char *op,
- UInt32 req,
- UInt32 moved,
- OSStatus stat)
-{
- printf("===%s: req %4d moved %4d status %d\n",
- op, req, moved, stat);
-}
-
-#else
-#define sslIoTrace(op, req, moved, stat)
-#endif /* SSL_IO_TRACE */
-
-static SSLErr SSLProcessProtocolMessage(SSLRecord rec, SSLContext *ctx);
-static SSLErr SSLHandshakeProceed(SSLContext *ctx);
-static SSLErr SSLInitConnection(SSLContext *ctx);
-static SSLErr SSLServiceWriteQueue(SSLContext *ctx);
-
-OSStatus
-SSLWrite(
- SSLContext *ctx,
- const void * data,
- UInt32 dataLength,
- UInt32 *bytesWritten) /* RETURNED */
-{
- SSLErr err;
- SSLRecord rec;
- UInt32 dataLen, processed;
-
- if((ctx == NULL) || (bytesWritten == NULL)) {
- return paramErr;
- }
- dataLen = dataLength;
- processed = 0; /* Initialize in case we return with SSLWouldBlockErr */
- *bytesWritten = 0;
-
- switch(ctx->state) {
- case SSLGracefulClose:
- err = SSLConnectionClosedGraceful;
- goto abort;
- case SSLErrorClose:
- err = SSLConnectionClosedError;
- goto abort;
- default:
- /* FIXME - original code didn't check for handshake in progress -
- * should we?
- */
- sslIoTrace("SSLWrite", dataLength, 0, badReqErr);
- return badReqErr;
- case HandshakeServerReady:
- case HandshakeClientReady:
- break;
- }
-
- /* First, we have to wait until the session is ready to send data,
- so the encryption keys and such have been established. */
- err = SSLNoErr;
- while (ctx->writeCipher.ready == 0)
- { 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;
- /* Fragment, package and encrypt the data and queue the resulting data for sending */
- while (dataLen > 0)
- { rec.contentType = SSL_application_data;
- rec.protocolVersion = ctx->negProtocolVersion;
- rec.contents.data = ((UInt8*)data) + processed;
-
- if (dataLen < MAX_RECORD_LENGTH)
- rec.contents.length = dataLen;
- else
- rec.contents.length = MAX_RECORD_LENGTH;
-
- assert(ctx->sslTslCalls != NULL);
- if (ERR(err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
- goto exit;
-
- processed += rec.contents.length;
- dataLen -= rec.contents.length;
- }
-
- /* All the data has been advanced to the write queue */
- *bytesWritten = processed;
- if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
- goto exit;
-
- err = SSLNoErr;
-exit:
- if (err != 0 && err != SSLWouldBlockErr && err != SSLConnectionClosedGraceful) {
- dprintf1("SSLWrite: going to state errorCLose due to err %d\n",
- err);
- SSLChangeHdskState(ctx, SSLErrorClose);
- }
-abort:
- sslIoTrace("SSLWrite", dataLength, *bytesWritten, sslErrToOsStatus(err));
- return sslErrToOsStatus(err);
-}
-
-OSStatus
-SSLRead (
- SSLContext *ctx,
- void * data,
- UInt32 dataLength,
- UInt32 *processed) /* RETURNED */
-{
- SSLErr err;
- UInt8 *progress;
- UInt32 bufSize, remaining, count;
- SSLRecord rec;
-
- if((ctx == NULL) || (processed == NULL)) {
- return paramErr;
- }
- bufSize = dataLength;
- *processed = 0; /* Initialize in case we return with SSLWouldBlockErr */
-
- /* first handle cases in which we know we're finished */
- switch(ctx->state) {
- case SSLGracefulClose:
- err = SSLConnectionClosedGraceful;
- goto abort;
- case SSLErrorClose:
- err = SSLConnectionClosedError;
- goto abort;
- case SSLNoNotifyClose:
- err = SSLConnectionClosedNoNotify;
- 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 = SSLNoErr;
- while (ctx->readCipher.ready == 0)
- { if (ERR(err = SSLHandshakeProceed(ctx)) != 0)
- goto exit;
- }
-
- /* Attempt to service the write queue */
- if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
- { if (err != SSLWouldBlockErr)
- goto exit;
- err = SSLNoErr; /* Write blocking shouldn't stop attempts to read */
- }
-
- remaining = bufSize;
- progress = (UInt8*)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;
- progress += count;
- *processed += count;
- ctx->receivedDataPos += count;
- }
-
- CASSERT(ctx->receivedDataPos <= ctx->receivedDataBuffer.length);
- CASSERT(*processed + remaining == bufSize);
- CASSERT(progress == ((UInt8*)data) + *processed);
-
- if (ctx->receivedDataBuffer.data != 0 &&
- ctx->receivedDataPos >= ctx->receivedDataBuffer.length)
- { SSLFreeBuffer(&ctx->receivedDataBuffer, &ctx->sysCtx);
- 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 != SSLGracefulClose)
- ..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 != SSLGracefulClose)
- { CASSERT(ctx->receivedDataBuffer.data == 0);
- if (ERR(err = SSLReadRecord(&rec, ctx)) != 0)
- goto exit;
-
- if (rec.contentType == SSL_application_data ||
- rec.contentType == SSL_version_2_0_record)
- { if (rec.contents.length <= remaining)
- { memcpy(progress, rec.contents.data, rec.contents.length);
- remaining -= rec.contents.length;
- progress += rec.contents.length;
- *processed += rec.contents.length;
- /* COMPILER BUG!
- * This:
- * if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
- * passes the address of rec to SSLFreeBuffer, not the address
- * of the contents field (which should be offset 8 from the start
- * of rec).
- */
- {
- SSLBuffer *b = &rec.contents;
- if (ERR(err = SSLFreeBuffer(b, &ctx->sysCtx)) != 0) {
- goto exit;
- }
- }
- }
- else
- { memcpy(progress, rec.contents.data, remaining);
- progress += remaining;
- *processed += remaining;
- ctx->receivedDataBuffer = rec.contents;
- ctx->receivedDataPos = remaining;
- remaining = 0;
- }
- }
- else
- { if (ERR(err = SSLProcessProtocolMessage(rec, ctx)) != 0)
- goto exit;
- if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
- goto exit;
- }
- }
-
- err = SSLNoErr;
-
-exit:
- /* shut down on serious errors */
- switch(err) {
- case SSLNoErr:
- case SSLWouldBlockErr:
- case SSLConnectionClosedGraceful:
- case SSLConnectionClosedNoNotify:
- break;
- default:
- dprintf1("SSLRead: going to state errorClose due to err %d\n",
- err);
- SSLChangeHdskState(ctx, SSLErrorClose);
- break;
- }
-abort:
- sslIoTrace("SSLRead ", dataLength, *processed, sslErrToOsStatus(err));
- return sslErrToOsStatus(err);
-}
-
-#if SSL_DEBUG
-#include "appleCdsa.h"
-#endif
-
-OSStatus
-SSLHandshake(SSLContext *ctx)
-{
- SSLErr err;
-
- if(ctx == NULL) {
- return paramErr;
- }
- if (ctx->state == SSLGracefulClose)
- return sslErrToOsStatus(SSLConnectionClosedGraceful);
- if (ctx->state == SSLErrorClose)
- return sslErrToOsStatus(SSLConnectionClosedError);
-
- if(ctx->protocolSide == SSL_ServerSide) {
- /* some things the caller really has to have done by now... */
- if((ctx->localCert == NULL) ||
- (ctx->signingPrivKey == NULL) ||
- (ctx->signingPubKey == NULL) ||
- (ctx->signingKeyCsp == 0)) {
- errorLog0("SSLHandshake: insufficient init\n");
- return badReqErr;
- }
- }
- if(ctx->validCipherSpecs == NULL) {
- /* build list of legal cipherSpecs */
- err = sslBuildCipherSpecArray(ctx);
- if(err) {
- return err;
- }
- }
- err = SSLNoErr;
- while (ctx->readCipher.ready == 0 || ctx->writeCipher.ready == 0)
- { if (ERR(err = SSLHandshakeProceed(ctx)) != 0)
- return sslErrToOsStatus(err);
- }
-
- /* one more flush at completion of successful handshake */
- if ((err = SSLServiceWriteQueue(ctx)) != 0) {
- return sslErrToOsStatus(err);
- }
- return noErr;
-}
-
-
-static SSLErr
-SSLHandshakeProceed(SSLContext *ctx)
-{ SSLErr err;
- SSLRecord rec;
-
- if (ctx->state == SSLUninitialized)
- if (ERR(err = SSLInitConnection(ctx)) != 0)
- return err;
- if (ERR(err = SSLServiceWriteQueue(ctx)) != 0)
- return err;
- CASSERT(ctx->readCipher.ready == 0);
- if (ERR(err = SSLReadRecord(&rec, ctx)) != 0)
- return err;
- if (ERR(err = SSLProcessProtocolMessage(rec, ctx)) != 0)
- { SSLFreeBuffer(&rec.contents, &ctx->sysCtx);
- return err;
- }
- if (ERR(err = SSLFreeBuffer(&rec.contents, &ctx->sysCtx)) != 0)
- return err;
-
- return SSLNoErr;
-}
-
-static SSLErr
-SSLInitConnection(SSLContext *ctx)
-{ SSLErr err;
-
- if (ctx->protocolSide == SSL_ClientSide) {
- SSLChangeHdskState(ctx, HandshakeClientUninit);
- }
- else
- { CASSERT(ctx->protocolSide == SSL_ServerSide);
- SSLChangeHdskState(ctx, HandshakeServerUninit);
- }
-
- if (ctx->peerID.data != 0)
- { ERR(SSLGetSessionData(&ctx->resumableSession, ctx));
- /* Ignore errors; just treat as uncached session */
- }
-
- /*
- * If we have a cached resumable session, blow it off if it's a higher
- * version than the max currently allowed. Note that this means that once
- * a process negotiates a given version with a given server/port, it won't
- * be able to negotiate a higher version. We might want to revisit this.
- */
- if (ctx->resumableSession.data != 0) {
-
- SSLProtocolVersion savedVersion;
-
- if (ERR(err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession,
- &savedVersion, ctx)) != 0) {
- return err;
- }
- if(savedVersion > ctx->maxProtocolVersion) {
- SSLLogResumSess("===Resumable session protocol mismatch\n");
- SSLFreeBuffer(&ctx->resumableSession, &ctx->sysCtx);
- }
- else {
- SSLLogResumSess("===attempting to resume session\n");
- /*
- * A bit of a special case for server side here. If currently
- * configged to allow for SSL3/TLS1 with an SSL2 hello, we
- * don't want to preclude the possiblity of an SSL2 hello...
- * so we'll just leave the negProtocolVersion alone in the server case.
- */
- if(ctx->protocolSide == SSL_ClientSide) {
- ctx->negProtocolVersion = savedVersion;
- }
- }
- }
-
-/* If we're the client & handshake hasn't yet begun, start it by
- * pretending we just received a hello request
- */
- if (ctx->state == HandshakeClientUninit && ctx->writeCipher.ready == 0)
- { switch (ctx->negProtocolVersion)
- { case SSL_Version_Undetermined:
- case SSL_Version_3_0_With_2_0_Hello:
- case SSL_Version_2_0:
- if (ERR(err = SSL2AdvanceHandshake(ssl2_mt_kickstart_handshake, ctx)) != 0)
- return err;
- break;
- case SSL_Version_3_0_Only:
- case SSL_Version_3_0:
- case TLS_Version_1_0_Only:
- case TLS_Version_1_0:
- if (ERR(err = SSLAdvanceHandshake(SSL_hello_request, ctx)) != 0)
- return err;
- break;
- default:
- sslPanic("Bad protocol version");
- break;
- }
- }
-
- return SSLNoErr;
-}
-
-static SSLErr
-SSLServiceWriteQueue(SSLContext *ctx)
-{ SSLErr err = SSLNoErr, werr = SSLNoErr;
- UInt32 written = 0;
- SSLBuffer buf, recBuf;
- WaitingRecord *rec;
-
- while (!werr && ((rec = ctx->recordWriteQueue) != 0))
- { buf.data = rec->data.data + rec->sent;
- buf.length = rec->data.length - rec->sent;
- werr = sslIoWrite(buf, &written, ctx);
- rec->sent += written;
- if (rec->sent >= rec->data.length)
- { CASSERT(rec->sent == rec->data.length);
- CASSERT(err == 0);
- err = SSLFreeBuffer(&rec->data, &ctx->sysCtx);
- CASSERT(err == 0);
- recBuf.data = (UInt8*)rec;
- recBuf.length = sizeof(WaitingRecord);
- ctx->recordWriteQueue = rec->next;
- err = SSLFreeBuffer(&recBuf, &ctx->sysCtx);
- CASSERT(err == 0);
- }
- if (ERR(err))
- return err;
- CASSERT(ctx->recordWriteQueue == 0 || ctx->recordWriteQueue->sent == 0);
- }
-
- return werr;
-}
-
-#if LOG_RX_PROTOCOL
-static void sslLogRxProto(const char *msgType)
-{
- printf("---received protoMsg %s\n", msgType);
-}
-#else
-#define sslLogRxProto(msgType)
-#endif /* LOG_RX_PROTOCOL */
-
-static SSLErr
-SSLProcessProtocolMessage(SSLRecord rec, SSLContext *ctx)
-{ SSLErr err;
-
- switch (rec.contentType)
- { case SSL_handshake:
- sslLogRxProto("SSL_handshake");
- ERR(err = SSLProcessHandshakeRecord(rec, ctx));
- break;
- case SSL_alert:
- sslLogRxProto("SSL_alert");
- ERR(err = SSLProcessAlert(rec, ctx));
- break;
- case SSL_change_cipher_spec:
- sslLogRxProto("SSL_change_cipher_spec");
- ERR(err = SSLProcessChangeCipherSpec(rec, ctx));
- break;
- case SSL_version_2_0_record:
- sslLogRxProto("SSL_version_2_0_record");
- ERR(err = SSL2ProcessMessage(rec, ctx));
- break;
- default:
- sslLogRxProto("Bad msg");
- return ERR(SSLProtocolErr);
- }
-
- return err;
-}
-
-OSStatus
-SSLClose(SSLContext *ctx)
-{
- SSLErr err = SSLNoErr;
-
- if(ctx == NULL) {
- return paramErr;
- }
- if (ctx->negProtocolVersion >= SSL_Version_3_0)
- ERR(err = SSLSendAlert(alert_warning, alert_close_notify, ctx));
- if (err == 0)
- ERR(err = SSLServiceWriteQueue(ctx));
- SSLChangeHdskState(ctx, SSLGracefulClose);
- if (err == SSLIOErr)
- err = SSLNoErr; /* Ignore errors related to closed streams */
- return sslErrToOsStatus(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 paramErr;
- }
- if(ctx->receivedDataBuffer.data == NULL) {
- *bufSize = 0;
- }
- else {
- CASSERT(ctx->receivedDataBuffer.length >= ctx->receivedDataPos);
- *bufSize = ctx->receivedDataBuffer.length - ctx->receivedDataPos;
- }
- return noErr;
-}