]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_ssl/lib/sslHandshake.c
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_ssl / lib / sslHandshake.c
diff --git a/libsecurity_ssl/lib/sslHandshake.c b/libsecurity_ssl/lib/sslHandshake.c
deleted file mode 100644 (file)
index 6914908..0000000
+++ /dev/null
@@ -1,1383 +0,0 @@
-/*
- * Copyright (c) 1999-2001,2005-2012 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@
- */
-
-
-/*
- * sslHandshake.c - SSL 3.0 handshake state machine.
- */
-
-#include "sslContext.h"
-#include "sslHandshake.h"
-#include "sslMemory.h"
-#include "sslAlertMessage.h"
-#include "sslSession.h"
-#include "sslUtils.h"
-#include "sslDebug.h"
-#include "sslCrypto.h"
-#include "sslRand.h"
-#include "sslDigests.h"
-#include "sslCipherSpecs.h"
-#include "cipherSpecs.h"
-
-#include <utilities/SecIOFormat.h>
-
-#include <AssertMacros.h>
-#include <string.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#define REQUEST_CERT_CORRECT        0
-
-#if __LP64__
-#define PRIstatus "d"
-#else
-#define PRIstatus "ld"
-#endif
-
-
-uint8_t *
-SSLEncodeHandshakeHeader(SSLContext *ctx, SSLRecord *rec, SSLHandshakeType type, size_t msglen)
-{
-    uint8_t *charPtr;
-
-    charPtr = rec->contents.data;
-    *charPtr++ = type;
-    charPtr = SSLEncodeSize(charPtr, msglen, 3);
-
-    if(rec->protocolVersion == DTLS_Version_1_0) {
-        charPtr = SSLEncodeInt(charPtr, ctx->hdskMessageSeq, 2);
-        /* fragmentation -- we encode header as if unfragmented,
-         actual fragmentation happens at lower layer. */
-        charPtr = SSLEncodeInt(charPtr, 0, 3);
-        charPtr = SSLEncodeSize(charPtr, msglen, 3);
-    }
-
-    return charPtr;
-}
-
-static OSStatus SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx);
-
-static OSStatus
-SSLUpdateHandshakeMacs(const SSLBuffer *messageData, SSLContext *ctx)
-{
-    OSStatus err = errSSLInternal;
-    bool do_md5 = false;
-    bool do_sha1 = false;
-    bool do_sha256 = false;
-    bool do_sha384 = false;
-
-    //TODO: We can stop updating the unecessary hashes once the CertVerify message is processed in case where we do Client Side Auth, or .
-
-    if(ctx->negProtocolVersion == SSL_Version_Undetermined)
-    {
-        // we dont know yet, so we might need MD5 & SHA1 - Server should always call in with known protocol version.
-        assert(ctx->protocolSide==kSSLClientSide);
-        do_md5 = do_sha1 = true;
-        if(ctx->isDTLS
-           ? ctx->maxProtocolVersion < DTLS_Version_1_0
-           : ctx->maxProtocolVersion >= TLS_Version_1_2)
-        {
-            // We wil need those too, unless we are sure we wont end up doing TLS 1.2
-            do_sha256 = do_sha384 = true;
-        }
-    } else {
-        // we know which version we use at this point
-        if(sslVersionIsLikeTls12(ctx)) {
-            do_sha1 = do_sha256 = do_sha384 = true;
-        } else {
-            do_md5 = do_sha1 = true;
-        }
-    }
-
-    if (do_md5 &&
-        (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0)
-        goto done;
-    if (do_sha1 &&
-        (err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0)
-        goto done;
-    if (do_sha256 &&
-        (err = SSLHashSHA256.update(&ctx->sha256State, messageData)) != 0)
-        goto done;
-    if (do_sha384 &&
-        (err = SSLHashSHA384.update(&ctx->sha512State, messageData)) != 0)
-        goto done;
-
-    sslLogNegotiateDebug("%s protocol: %02X max: %02X cipher: %02X%s%s%s%s",
-                         ctx->protocolSide == kSSLClientSide ? "client" : "server",
-                         ctx->negProtocolVersion,
-                         ctx->maxProtocolVersion,
-                         ctx->selectedCipher,
-                         do_md5 ? " md5" : "",
-                         do_sha1 ? " sha1" : "",
-                         do_sha256 ? " sha256" : "",
-                         do_sha384 ? " sha384" : "");
-done:
-    return err;
-}
-
-OSStatus
-SSLProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx)
-{   OSStatus        err;
-    size_t          remaining;
-    UInt8           *p;
-       UInt8                   *startingP;             // top of record we're parsing
-    SSLHandshakeMsg message = {};
-    SSLBuffer       messageData;
-
-    if (ctx->fragmentedMessageCache.data != 0)
-    {
-               size_t origLen = ctx->fragmentedMessageCache.length;
-               if ((err = SSLReallocBuffer(&ctx->fragmentedMessageCache,
-                    ctx->fragmentedMessageCache.length + rec.contents.length)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            return err;
-        }
-        memcpy(ctx->fragmentedMessageCache.data + origLen,
-            rec.contents.data, rec.contents.length);
-        remaining = ctx->fragmentedMessageCache.length;
-        p = ctx->fragmentedMessageCache.data;
-    }
-    else
-    {   remaining = rec.contents.length;
-        p = rec.contents.data;
-    }
-       startingP = p;
-
-    size_t head = 4;
-
-    while (remaining > 0)
-    {
-        if (remaining < head)
-            break;  /* we must have at least a header */
-
-        messageData.data = p;
-        message.type = (SSLHandshakeType)*p++;
-        message.contents.length = SSLDecodeSize(p, 3);
-
-
-        p += 3;
-
-        if ((message.contents.length + head) > remaining)
-            break;
-
-        message.contents.data = p;
-        p += message.contents.length;
-        messageData.length = head + message.contents.length;
-        assert(p == messageData.data + messageData.length);
-
-        /* message fragmentation */
-        remaining -= messageData.length;
-        if ((err = SSLProcessHandshakeMessage(message, ctx)) != 0)
-            return err;
-
-        if (message.type != SSL_HdskHelloRequest)
-
-        {   if ((err = SSLUpdateHandshakeMacs(&messageData, ctx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-        }
-
-        if ((err = SSLAdvanceHandshake(message.type, ctx)) != 0)
-            return err;
-    }
-
-    if (remaining > 0)      /* Fragmented handshake message */
-    {   /* If there isn't a cache, allocate one */
-        if (ctx->fragmentedMessageCache.data == 0)
-        {   if ((err = SSLAllocBuffer(&ctx->fragmentedMessageCache, remaining)))
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-        }
-        if (startingP != ctx->fragmentedMessageCache.data)
-        {   memcpy(ctx->fragmentedMessageCache.data, startingP, remaining);
-            ctx->fragmentedMessageCache.length = remaining;
-        }
-    }
-    else if (ctx->fragmentedMessageCache.data != 0)
-    {   if ((err = SSLFreeBuffer(&ctx->fragmentedMessageCache)))
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            return err;
-        }
-    }
-
-    return errSecSuccess;
-}
-
-OSStatus
-DTLSProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx)
-{   OSStatus        err = errSecParam;
-    size_t          remaining;
-    UInt8           *p;
-       UInt8                   *startingP;             // top of record we're parsing
-
-    const UInt32 head = 12;
-
-    assert(ctx->isDTLS);
-
-    remaining = rec.contents.length;
-    p = rec.contents.data;
-       startingP = p;
-
-    while (remaining > 0)
-    {
-        UInt8 msgtype;
-        UInt32 msglen;
-        UInt32 msgseq;
-        UInt32 fraglen;
-        UInt32 fragofs;
-
-        if (remaining < head) {
-            /* flush it - record is too small */
-            sslErrorLog("DTLSProcessHandshakeRecord: remaining too small (%lu out of %lu)\n", remaining, rec.contents.length);
-            assert(0); // keep this assert until we find a test case that triggers it
-            err = errSSLProtocol;
-            goto flushit;
-        }
-
-        /* Thats the 12 bytes of header : */
-        msgtype = (SSLHandshakeType)*p++;
-        msglen = SSLDecodeInt(p, 3); p+=3;
-        msgseq = SSLDecodeInt(p, 2); p+=2;
-        fragofs = SSLDecodeInt(p, 3); p+=3;
-        fraglen = SSLDecodeInt(p, 3); p+=3;
-
-        remaining -= head;
-
-        SSLLogHdskMsg(msgtype, 0);
-        sslHdskMsgDebug("DTLS Hdsk Record: type=%u, len=%u, seq=%u (%u), f_ofs=%u, f_len=%u, remaining=%u",
-                             msgtype, (int)msglen, (int)msgseq, (int)ctx->hdskMessageSeqNext, (int)fragofs, (int)fraglen, (int)remaining);
-
-        if(
-           ((fraglen+fragofs) > msglen)
-           || (fraglen > remaining)
-           || (msgseq!=ctx->hdskMessageSeqNext)
-           || (fragofs!=ctx->hdskMessageCurrentOfs)
-           || (fragofs && (msgtype!=ctx->hdskMessageCurrent.type))
-           || (fragofs && (msglen != ctx->hdskMessageCurrent.contents.length))
-           )
-        {
-            sslErrorLog("DTLSProcessHandshakeRecord: wrong fragment\n");
-            // assert(0); // keep this assert until we find a test case that triggers it
-            // This is a recoverable error, we just drop this fragment.
-            // TODO: this should probably trigger a retransmit
-            err = errSecSuccess;
-            goto flushit;
-        }
-
-        /* First fragment - allocate */
-        if(fragofs==0) {
-            sslHdskMsgDebug("Allocating hdsk buf for msg type %d", msgtype);
-            assert(ctx->hdskMessageCurrent.contents.data==NULL);
-            assert(ctx->hdskMessageCurrent.contents.length==0);
-            if((err=SSLAllocBuffer(&(ctx->hdskMessageCurrent.contents), msglen))) {
-                SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-            ctx->hdskMessageCurrent.type = msgtype;
-        }
-
-        /* We have the next fragment, lets save it */
-        memcpy(ctx->hdskMessageCurrent.contents.data + ctx->hdskMessageCurrentOfs, p, fraglen);
-        ctx->hdskMessageCurrentOfs+=fraglen;
-        p+=fraglen;
-        remaining-=fraglen;
-
-        /* This was the last fragment, lets process the message */
-        if(ctx->hdskMessageCurrentOfs == ctx->hdskMessageCurrent.contents.length) {
-            err = SSLProcessHandshakeMessage(ctx->hdskMessageCurrent, ctx);
-            if(err)
-                goto flushit;
-
-            if ((msgtype != SSL_HdskHelloRequest) && (msgtype != SSL_HdskHelloVerifyRequest))
-            {
-                /* We need to hash a fake header as if no fragmentation */
-                uint8_t pseudo_header[head];
-                SSLBuffer header;
-                header.data=pseudo_header;
-                header.length=head;
-
-                pseudo_header[0]=msgtype;
-                SSLEncodeInt(pseudo_header+1, msglen, 3);
-                SSLEncodeInt(pseudo_header+4, msgseq, 2);
-                SSLEncodeInt(pseudo_header+6, 0, 3);
-                SSLEncodeInt(pseudo_header+9, msglen, 3);
-
-                if ((err = SSLHashSHA1.update(&ctx->shaState, &header)) != 0 ||
-                    (err = SSLHashMD5.update(&ctx->md5State, &header)) != 0)
-                {
-                    SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    goto flushit;
-                }
-
-                SSLBuffer *messageData=&ctx->hdskMessageCurrent.contents;
-                if ((err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0 ||
-                    (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0)
-                {
-                    SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    goto flushit;
-                }
-
-                sslHdskMsgDebug("Hashing %d bytes of msg seq %d\n", (int)messageData->length, (int)msgseq);
-            }
-
-            sslHdskMsgDebug("processed message of type %d", msgtype);
-
-            if ((err = SSLAdvanceHandshake(msgtype, ctx)) != 0)
-            {
-                sslErrorLog("AdvanceHandshake error: %" PRIdOSStatus "\n", err);
-                goto flushit;
-            }
-
-            /* Free the buffer for current message, and reset offset */
-            SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents));
-            ctx->hdskMessageCurrentOfs=0;
-
-            /* If we successfully processed a message, we wait for the next one */
-            ctx->hdskMessageSeqNext++;
-
-        }
-
-        sslHdskMsgDebug("remaining = %ld", remaining);
-    }
-
-    return errSecSuccess;
-
-flushit:
-    sslErrorLog("DTLSProcessHandshakeRecord: flusing record (err=%"PRIstatus")\n", err);
-
-    /* This will flush the current handshake message */
-    SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents));
-    ctx->hdskMessageCurrentOfs=0;
-
-    return err;
-}
-
-OSStatus
-DTLSRetransmit(SSLContext *ctx)
-{
-    sslHdskMsgDebug("DTLSRetransmit in state %s. Last Sent = %d, Last Recv=%d, timeout=%f\n",
-                hdskStateToStr(ctx->state), ctx->hdskMessageSeq, ctx->hdskMessageSeqNext, ctx->timeout_duration);
-
-    /* Too many retransmits, just give up!! */
-    if(ctx->hdskMessageRetryCount>10)
-        return errSSLConnectionRefused;
-
-    /* go back to previous cipher if retransmitting a flight including changecipherspec */
-    if(ctx->messageQueueContainsChangeCipherSpec) {
-        OSStatus err;
-        err = ctx->recFuncs->rollbackWriteCipher(ctx->recCtx);
-        if(err)
-            return err;
-    }
-
-    /* set timeout deadline */
-    ctx->hdskMessageRetryCount++;
-    ctx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<<ctx->hdskMessageRetryCount)*ctx->timeout_duration);
-
-    /* Lets resend the last flight */
-    return SSLSendFlight(ctx);
-}
-
-static OSStatus
-SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx)
-{   OSStatus      err;
-
-    err = errSecSuccess;
-    SSLLogHdskMsg(message.type, 0);
-    switch (message.type)
-    {   case SSL_HdskHelloRequest:
-            if (ctx->protocolSide != kSSLClientSide)
-                goto wrongMessage;
-            if (message.contents.length > 0)
-                err = errSSLProtocol;
-            break;
-        case SSL_HdskClientHello:
-            if (ctx->state != SSL_HdskStateServerUninit)
-                goto wrongMessage;
-            err = SSLProcessClientHello(message.contents, ctx);
-            break;
-        case SSL_HdskServerHello:
-            if (ctx->state != SSL_HdskStateServerHello)
-                goto wrongMessage;
-            err = SSLProcessServerHello(message.contents, ctx);
-            break;
-#if ENABLE_DTLS
-        case SSL_HdskHelloVerifyRequest:
-            if (ctx->protocolSide != kSSLClientSide)
-                goto wrongMessage;
-            if(ctx->state != SSL_HdskStateServerHello)
-                goto wrongMessage;
-            /* TODO: Do we need to check the client state here ? */
-            err = SSLProcessServerHelloVerifyRequest(message.contents, ctx);
-            break;
-#endif
-        case SSL_HdskCert:
-            if (ctx->state != SSL_HdskStateCert &&
-                ctx->state != SSL_HdskStateClientCert)
-                goto wrongMessage;
-                       err = SSLProcessCertificate(message.contents, ctx);
-                       /*
-                        * Note that cert evaluation can now be performed asynchronously,
-                        * so SSLProcessCertificate may return errSSLWouldBlock here.
-                        */
-            break;
-        case SSL_HdskCertRequest:
-            if (((ctx->state != SSL_HdskStateHelloDone) &&
-                            (ctx->state != SSL_HdskStateKeyExchange))
-                 || ctx->certRequested)
-                goto wrongMessage;
-            err = SSLProcessCertificateRequest(message.contents, ctx);
-            if (ctx->breakOnCertRequest)
-                ctx->signalCertRequest = true;
-            break;
-        case SSL_HdskServerKeyExchange:
-                       /*
-                * Since this message is optional for some key exchange
-                        * mechanisms, and completely at the server's discretion,
-                        * we need to be able to handle this in one of two states...
-                */
-               switch(ctx->state) {
-                       case SSL_HdskStateKeyExchange:  /* explicitly waiting for this */
-                       case SSL_HdskStateHelloDone:
-                               break;
-                       default:
-                       goto wrongMessage;
-               }
-            err = SSLProcessServerKeyExchange(message.contents, ctx);
-            break;
-        case SSL_HdskServerHelloDone:
-            if (ctx->state != SSL_HdskStateHelloDone)
-                goto wrongMessage;
-            err = SSLProcessServerHelloDone(message.contents, ctx);
-            break;
-        case SSL_HdskCertVerify:
-            if (ctx->state != SSL_HdskStateClientCertVerify)
-                goto wrongMessage;
-            err = SSLProcessCertificateVerify(message.contents, ctx);
-                       assert(ctx->protocolSide == kSSLServerSide);
-                       if(err) {
-                               ctx->clientCertState = kSSLClientCertRejected;
-                       }
-            break;
-        case SSL_HdskClientKeyExchange:
-            if (ctx->state != SSL_HdskStateClientKeyExchange)
-                goto wrongMessage;
-            err = SSLProcessKeyExchange(message.contents, ctx);
-            break;
-        case SSL_HdskFinished:
-            if (ctx->state != SSL_HdskStateFinished)
-                goto wrongMessage;
-            err = SSLProcessFinished(message.contents, ctx);
-            break;
-        default:
-            goto wrongMessage;
-            break;
-    }
-
-    if (err && !ctx->sentFatalAlert)
-    {   if (err == errSSLProtocol)
-            SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx);
-        else if (err == errSSLNegotiation)
-            SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
-        else if (err != errSSLWouldBlock &&
-                                err != errSSLServerAuthCompleted /* == errSSLClientAuthCompleted */ &&
-                                err != errSSLClientCertRequested)
-            SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
-    }
-    return err;
-
-wrongMessage:
-    SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
-    return errSSLProtocol;
-}
-
-/*
- * Given a server-side SSLContext that's fully restored for a resumed session,
- * queue up the remaining outgoing messages to finish the handshake.
- */
-static OSStatus
-SSLResumeServerSide(
-       SSLContext *ctx)
-{
-       OSStatus err;
-       if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0)
-               return err;
-       if ((err = SSLInitPendingCiphers(ctx)) != 0)
-       {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-               return err;
-       }
-       if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
-                               ctx)) != 0)
-               return err;
-
-       if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage,
-                       ctx)) != 0)
-               return err;
-
-       SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-
-       return errSecSuccess;
-
-}
-
-OSStatus
-SSLAdvanceHandshake(SSLHandshakeType processed, SSLContext *ctx)
-{   OSStatus        err;
-    SSLBuffer       sessionIdentifier;
-
-    SSLResetFlight(ctx);
-
-    switch (processed)
-    {
-#if ENABLE_DTLS
-        case SSL_HdskHelloVerifyRequest:
-            /* Just fall through */
-#endif
-        case SSL_HdskHelloRequest:
-                       /*
-                        * Reset the client auth state machine in case this is
-                        * a renegotiation.
-                        */
-                       ctx->certRequested = 0;
-                       ctx->certSent = 0;
-                       ctx->certReceived = 0;
-                       ctx->x509Requested = 0;
-                       ctx->clientCertState = kSSLClientCertNone;
-                       ctx->readCipher_ready = 0;
-                       ctx->writeCipher_ready = 0;
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeClientHello, ctx)) != 0)
-                return err;
-            SSLChangeHdskState(ctx, SSL_HdskStateServerHello);
-            break;
-        case SSL_HdskClientHello:
-            assert(ctx->protocolSide == kSSLServerSide);
-                       ctx->sessionMatch = 0;
-
-            if((ctx->negProtocolVersion==DTLS_Version_1_0) && (ctx->cookieVerified==false))
-            {   /* Send Hello Verify Request */
-                if((err=SSLPrepareAndQueueMessage(SSLEncodeServerHelloVerifyRequest, ctx)) !=0 )
-                    return err;
-                break;
-            }
-
-                       #if     SSL_PAC_SERVER_ENABLE
-                       if((ctx->sessionTicket.data != NULL) &&
-                          (ctx->masterSecretCallback != NULL)) {
-                               /*
-                                * Client sent us a session ticket and we know how to ask
-                                * the app for master secret. Go for it.
-                                */
-                               size_t secretLen = SSL_MASTER_SECRET_SIZE;
-                               sslEapDebug("Server side resuming based on masterSecretCallback");
-
-                               /* the master secret callback requires serverRandom, now... */
-                           if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0)
-                                        return err;
-                               ctx->serverRandomValid = 1;
-
-                               ctx->masterSecretCallback(ctx, ctx->masterSecretArg,
-                                       ctx->masterSecret, &secretLen);
-                               ctx->sessionMatch = 1;
-                               /* set up selectedCipherSpec */
-                               if ((err = FindCipherSpec(ctx)) != 0) {
-                                       return err;
-                               }
-                               /* queue up remaining messages to finish handshake */
-                               if((err = SSLResumeServerSide(ctx)) != 0)
-                                       return err;
-                               break;
-                       }
-                       #endif  /* SSL_PAC_SERVER_ENABLE */
-            if (ctx->sessionID.data != 0)
-                       /* If session ID != 0, client is trying to resume */
-            {   if (ctx->resumableSession.data != 0)
-                {
-                                       SSLProtocolVersion sessionProt;
-                                       if ((err = SSLRetrieveSessionID(ctx->resumableSession,
-                                                               &sessionIdentifier, ctx)) != 0)
-                        return err;
-                                       if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession,
-                                                       &sessionProt, ctx)) != 0)
-                                       {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                                               return err;
-                                       }
-                                       if ((sessionIdentifier.length == ctx->sessionID.length) &&
-                        (memcmp(sessionIdentifier.data, ctx->sessionID.data,
-                                                       ctx->sessionID.length) == 0) &&
-                                           (sessionProt == ctx->negProtocolVersion))
-                    {   /* Everything matches; resume the session */
-                                               sslLogResumSessDebug("===RESUMING SSL3 server-side session");
-                        if ((err = SSLInstallSessionFromData(ctx->resumableSession,
-                                                               ctx)) != 0)
-                        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                            return err;
-                        }
-                                               ctx->sessionMatch = 1;
-                                               SSLFreeBuffer(&sessionIdentifier);
-
-                                               /* queue up remaining messages to finish handshake */
-                                               if((err = SSLResumeServerSide(ctx)) != 0)
-                                                       return err;
-                        break;
-                    }
-                                       else {
-                                               sslLogResumSessDebug(
-                                                       "===FAILED TO RESUME SSL3 server-side session");
-                                       }
-                    if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0 ||
-                        (err = SSLDeleteSessionData(ctx)) != 0)
-                    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                        return err;
-                    }
-                }
-                if ((err = SSLFreeBuffer(&ctx->sessionID)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-            }
-
-            /*
-                        * If we get here, we're not resuming; generate a new session ID
-                        * if we know our peer
-                        */
-            if (ctx->peerID.data != 0)
-            {   /* Ignore errors; just treat as uncached session */
-                assert(ctx->sessionID.data == 0);
-                err = SSLAllocBuffer(&ctx->sessionID, SSL_SESSION_ID_LEN);
-                if (err == 0)
-                {   
-                    if((err = sslRand(&ctx->sessionID)) != 0)
-                    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                        return err;
-                    }
-                }
-            }
-
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0)
-                return err;
-            switch (ctx->selectedCipherSpecParams.keyExchangeMethod)
-            {   case SSL_NULL_auth:
-               #if             APPLE_DH
-                case SSL_DH_anon:
-                case SSL_ECDH_anon:
-                       if(ctx->clientAuth == kAlwaysAuthenticate) {
-                               /* app requires this; abort */
-                               SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
-                               return errSSLNegotiation;
-                       }
-                       ctx->tryClientAuth = false;
-                                       /* DH server side needs work */
-                    break;
-                #endif /* APPLE_DH */
-                case TLS_PSK:
-                    /* skip the cert */
-                    break;
-
-                case SSL_RSA:
-                case SSL_DH_DSS:
-                case SSL_DH_RSA:
-                case SSL_DHE_DSS:
-                case SSL_DHE_RSA:
-                case SSL_ECDH_ECDSA:
-                case SSL_ECDHE_ECDSA:
-                case SSL_ECDH_RSA:
-                case SSL_ECDHE_RSA:
-                                       if(ctx->localCert == NULL) {
-                                               /* no cert but configured for, and negotiated, a
-                                                * ciphersuite which requires one */
-                                               sslErrorLog("SSLAdvanceHandshake: No server key!\n");
-                                               return errSSLBadConfiguration;
-                                       }
-                    if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
-                                                       ctx)) != 0)
-                        return err;
-                    break;
-
-                default:        /* everything else */
-                    sslErrorLog("SSLAdvanceHandshake: Unsupported KEM!\n");
-                    return errSSLInternal;
-            }
-                       /*
-                        * At this point we decide whether to send a server key exchange
-                        * method. For Apple servers, I think we'll ALWAYS do this, because
-                        * of key usage restrictions (can't decrypt and sign with the same
-                        * private key), but conceptually in this code, we do it if
-                        * enabled by the presence of encryptPrivKey.
-                        */
-                       {
-                               bool doServerKeyExch = false;
-                               switch(ctx->selectedCipherSpecParams.keyExchangeMethod) {
-                                       case SSL_RSA:
-                                               if(ctx->encryptPrivKeyRef != NULL) {
-                                                       doServerKeyExch = true;
-                                               }
-                                               break;
-                                       case SSL_DH_anon:
-                                       case SSL_DHE_RSA:
-                                       case SSL_DHE_DSS:
-                                               doServerKeyExch = true;
-                                               break;
-                                       default: /* In all other cases, we don't send a ServerkeyExchange message */
-                                               break;
-                               }
-                               if(doServerKeyExch) {
-                                       err = SSLPrepareAndQueueMessage(SSLEncodeServerKeyExchange, ctx);
-                                       if(err) {
-                                               return err;
-                                       }
-                               }
-                       }
-            if (ctx->tryClientAuth)
-            {   if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateRequest,
-                                               ctx)) != 0)
-                    return err;
-                ctx->certRequested = 1;
-                               ctx->clientCertState = kSSLClientCertRequested;
-            }
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHelloDone, ctx)) != 0)
-                return err;
-            if (ctx->certRequested) {
-                SSLChangeHdskState(ctx, SSL_HdskStateClientCert);
-            }
-            else {
-                SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange);
-            }
-            break;
-        case SSL_HdskServerHello:
-                       ctx->sessionMatch = 0;
-            if (ctx->resumableSession.data != 0 && ctx->sessionID.data != 0)
-            {
-                               SSLProtocolVersion sessionProt;
-                               if ((err = SSLRetrieveSessionID(ctx->resumableSession,
-                                               &sessionIdentifier, ctx)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-                               if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession,
-                                               &sessionProt, ctx)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-                if ((sessionIdentifier.length == ctx->sessionID.length) &&
-                    (memcmp(sessionIdentifier.data, ctx->sessionID.data,
-                                                       ctx->sessionID.length) == 0) &&
-                                       (sessionProt == ctx->negProtocolVersion))
-                {   /* Everything matches; resume the session */
-                                       sslLogResumSessDebug("===RESUMING SSL3 client-side session");
-                    if ((err = SSLInstallSessionFromData(ctx->resumableSession,
-                                                       ctx)) != 0 ||
-                        (err = SSLInitPendingCiphers(ctx)) != 0 ||
-                        (err = SSLFreeBuffer(&sessionIdentifier)) != 0)
-                    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                        return err;
-                    }
-                                       ctx->sessionMatch = 1;
-                    SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-                    break;
-                }
-                               else {
-                                       sslLogResumSessDebug("===FAILED TO RESUME SSL3 client-side "
-                                                       "session");
-                               }
-                if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-            }
-            switch (ctx->selectedCipherSpecParams.keyExchangeMethod)
-            {   
-               /* these require a key exchange message */
-               case SSL_NULL_auth:
-                case SSL_DH_anon:
-                    SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange);
-                    break;
-                case SSL_RSA:
-                case SSL_DH_DSS:
-                case SSL_DH_RSA:
-                case SSL_RSA_EXPORT:
-                case SSL_DHE_DSS:
-                case SSL_DHE_RSA:
-                case SSL_Fortezza:
-                               case SSL_ECDH_ECDSA:
-                               case SSL_ECDHE_ECDSA:
-                               case SSL_ECDH_RSA:
-                               case SSL_ECDHE_RSA:
-                    SSLChangeHdskState(ctx, SSL_HdskStateCert);
-                    break;
-                case TLS_PSK:
-                    SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
-                    break;
-                default:
-                    assert("Unknown key exchange method");
-                    break;
-            }
-            break;
-        case SSL_HdskCert:
-            if (ctx->state == SSL_HdskStateCert)
-                switch (ctx->selectedCipherSpecParams.keyExchangeMethod)
-                {   case SSL_RSA:
-                       /*
-                        * I really think the two RSA cases should be
-                        * handled the same here - the server key exchange is
-                        * optional, and is up to the server.
-                        * Note this isn't the same as SSL_SERVER_KEYEXCH_HACK;
-                        * we're a client here.
-                        */
-                    case SSL_DH_DSS:
-                    case SSL_DH_RSA:
-                                       case SSL_ECDH_ECDSA:
-                                       case SSL_ECDH_RSA:
-                        SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
-                        break;
-                    case SSL_DHE_DSS:
-                    case SSL_DHE_RSA:
-                    case SSL_Fortezza:
-                                       case SSL_ECDHE_ECDSA:
-                                       case SSL_ECDHE_RSA:
-                        SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange);
-                        break;
-                    default:
-                        assert("Unknown or unexpected key exchange method");
-                        break;
-                }
-            else if (ctx->state == SSL_HdskStateClientCert)
-            {   SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange);
-                if (ctx->peerCert != 0)
-                    ctx->certReceived = 1;
-            }
-            break;
-        case SSL_HdskCertRequest:
-                       /* state stays in SSL_HdskStateHelloDone; distinction is in
-                        *  ctx->certRequested */
-            if (ctx->peerCert == 0)
-            {   SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx);
-                return errSSLProtocol;
-            }
-            assert(ctx->protocolSide == kSSLClientSide);
-            ctx->certRequested = 1;
-            ctx->clientCertState = kSSLClientCertRequested;
-            break;
-        case SSL_HdskServerKeyExchange:
-            SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
-            break;
-        case SSL_HdskServerHelloDone:
-                       /*
-             * Waiting until server has sent hello done to interrupt and allow
-             * setting client cert, so we can send certificate, keyexchange and
-             * cert verify message together
-                        */
-            if (ctx->state != SSL_HdskStateClientCert) {
-                if (ctx->signalServerAuth) {
-                    ctx->signalServerAuth = false;
-                    SSLChangeHdskState(ctx, SSL_HdskStateClientCert);
-                    return errSSLServerAuthCompleted;
-                } else if (ctx->signalCertRequest) {
-                    ctx->signalCertRequest = false;
-                    SSLChangeHdskState(ctx, SSL_HdskStateClientCert);
-                    return errSSLClientCertRequested;
-                } else if (ctx->signalClientAuth) {
-                    ctx->signalClientAuth = false;
-                    return errSSLClientAuthCompleted;
-                }
-            }
-
-                       if (ctx->clientCertState == kSSLClientCertRequested) {
-                               /*
-                                * Server wants a client authentication cert - do
-                                * we have one?
-                                */
-                if (ctx->localCert != 0 && ctx->x509Requested) {
-                                       if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
-                                                       ctx)) != 0) {
-                                               return err;
-                                       }
-                }
-                else {
-                                       /* response for no cert depends on protocol version */
-                                       if(ctx->negProtocolVersion >= TLS_Version_1_0) {
-                                               /* TLS: send empty cert msg */
-                                               if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate,
-                                                               ctx)) != 0) {
-                                                       return err;
-                                               }
-                                       }
-                                       else {
-                                               /* SSL3: "no cert" alert */
-                                               if ((err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertNoCert_RESERVED,
-                                                               ctx)) != 0) {
-                                                       return err;
-                                               }
-                                       }
-                }      /* no cert to send */
-            }  /* server requested a cert */
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeKeyExchange, ctx)) != 0)
-                return err;
-                       assert(ctx->sslTslCalls != NULL);
-            if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 ||
-                (err = SSLInitPendingCiphers(ctx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-                       memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length);
-            if ((err = SSLFreeBuffer(&ctx->preMasterSecret))) {
-                return err;
-                       }
-            if (ctx->certSent) {
-                               /* Not all client auth mechanisms require a cert verify message */
-                               switch(ctx->negAuthType) {
-                                       case SSLClientAuth_RSASign:
-                                       case SSLClientAuth_ECDSASign:
-                                               if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateVerify,
-                                                               ctx)) != 0) {
-                                                       return err;
-                                               }
-                                               break;
-                                       default:
-                                               break;
-                               }
-                       }
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
-                                       ctx)) != 0) {
-                return err;
-                       }
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, ctx)) != 0)
-                return err;
-            SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-            break;
-        case SSL_HdskCertVerify:
-            SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-            break;
-        case SSL_HdskClientKeyExchange:
-                       assert(ctx->sslTslCalls != NULL);
-                       if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 ||
-                (err = SSLInitPendingCiphers(ctx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-                       memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length);
-            if ((err = SSLFreeBuffer(&ctx->preMasterSecret)))
-                return err;
-            if (ctx->certReceived) {
-                SSLChangeHdskState(ctx, SSL_HdskStateClientCertVerify);
-            }
-            else {
-                SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-            }
-            break;
-        case SSL_HdskFinished:
-            /* Handshake is over; enable data transfer on read channel */
-            ctx->readCipher_ready = 1;
-            /* If writePending is set, we haven't yet sent a finished message; 
-                        * send it */
-            /* Note: If using session resumption, the client will hit this, otherwise the server will */
-            if (ctx->writePending_ready != 0)
-            {   if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, 
-                                               ctx)) != 0)
-                    return err;
-                if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage,
-                                                       ctx)) != 0)
-                    return err;
-            }
-            if (ctx->protocolSide == kSSLServerSide) {
-                SSLChangeHdskState(ctx, SSL_HdskStateServerReady);
-            }
-            else {
-                SSLChangeHdskState(ctx, SSL_HdskStateClientReady);
-            }
-            if ((ctx->peerID.data != 0) && (ctx->sessionTicket.data == NULL)) {
-                               /* note we avoid caching session data for PAC-style resumption */
-                SSLAddSessionData(ctx);
-                       }
-            break;
-        default:
-            assert(0);
-            break;
-    }
-
-    /* We should have a full flight when we reach here, sending it for the first time */
-    ctx->hdskMessageRetryCount = 0;
-    ctx->timeout_deadline = CFAbsoluteTimeGetCurrent() + ctx->timeout_duration;
-    return SSLSendFlight(ctx);
-}
-
-OSStatus
-SSLPrepareAndQueueMessage(EncodeMessageFunc msgFunc, SSLContext *ctx)
-{   OSStatus        err;
-    SSLRecord       rec = {0, 0, {0, NULL}};
-    WaitingMessage  *out;
-    WaitingMessage  *queue;
-
-    if ((err = msgFunc(&rec, ctx)) != 0)
-    {   SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
-        goto fail;
-    }
-
-    if (rec.contentType == SSL_RecordTypeHandshake)
-    {
-        if ((err = SSLUpdateHandshakeMacs(&rec.contents, ctx)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            goto fail;
-        }
-        SSLLogHdskMsg((SSLHandshakeType)rec.contents.data[0], 1);
-        ctx->hdskMessageSeq++;
-    }
-
-    err=errSSLInternal;
-    out = (WaitingMessage *)sslMalloc(sizeof(WaitingMessage));
-    if(out==NULL) goto fail;
-
-    out->next = NULL;
-       out->rec = rec;
-
-    queue=ctx->messageWriteQueue;
-    if (queue == NULL) {
-        sslHdskMsgDebug("Queuing first message in flight\n");
-        ctx->messageWriteQueue = out;
-    } else {
-        int n=1;
-        while (queue->next != 0) {
-            queue = queue->next;
-            n++;
-        }
-        sslHdskMsgDebug("Queuing message %d in flight\n", n);
-        queue->next = out;
-    }
-
-    return errSecSuccess;
-fail:
-    SSLFreeBuffer(&rec.contents);
-    return err;
-}
-
-static
-OSStatus SSLSendMessage(SSLRecord rec, SSLContext *ctx)
-{
-    OSStatus err;
-
-
-    if ((err = SSLWriteRecord(rec, ctx)) != 0)
-        return err;
-    if(rec.contentType == SSL_RecordTypeChangeCipher) {
-        /* Install new cipher spec on write side */
-        /* Can't send data until Finished is sent */
-        ctx->writeCipher_ready = 0;
-       ctx->wroteAppData = 0;
-
-        if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            return err;
-        }
-
-        /* pending cipher is invalid now - this is currently used to figure out if we need
-           to send out the last flight */
-        ctx->writePending_ready = 0;
-
-        /* TODO: that should only happen after Finished message is sent. <rdar://problem/9682471> */
-        ctx->writeCipher_ready = 1;
-    }
-
-    return errSecSuccess;
-}
-
-static
-OSStatus DTLSSendMessage(SSLRecord rec, SSLContext *ctx)
-{
-    OSStatus err=errSecSuccess;
-
-    if(rec.contentType != SSL_RecordTypeHandshake) {
-        sslHdskMsgDebug("Not fragmenting message type=%d len=%d\n", (int)rec.contentType, (int)rec.contents.length);
-        if ((err = SSLWriteRecord(rec, ctx)) != 0)
-            return err;
-        if(rec.contentType == SSL_RecordTypeChangeCipher) {
-                       /* Can't send data until Finished is sent */
-            ctx->writeCipher_ready = 0;
-            ctx->wroteAppData = 0;
-
-            /* Install new cipher spec on write side */
-            if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-
-            /* pending cipher is invalid now - this is currently used to figure out if we need
-             to send out the last flight */
-            ctx->writePending_ready = 0;
-
-            /* TODO: that should only happen after Finished message is sent. See <rdar://problem/9682471> */
-            ctx->writeCipher_ready = 1;
-
-        }
-    } else {
-    /* fragmenting */
-        SSLRecord fragrec;
-
-        int msghead = 12;  /* size of message header in DTLS */
-        size_t fraglen;
-        size_t len = rec.contents.length-msghead;
-        UInt32 seq = SSLDecodeInt(rec.contents.data+4, 2);
-        (void) seq; // Suppress warnings
-        size_t ofs = 0;
-
-        sslHdskMsgDebug("Fragmenting msg seq %d (rl=%d, ml=%d)", (int)seq, (int)rec.contents.length,
-                        SSLDecodeInt(rec.contents.data+1, 3));
-
-
-        SSLGetDatagramWriteSize(ctx, &fraglen);
-        fraglen -=  msghead;
-
-        fragrec.contentType = rec.contentType;
-        fragrec.protocolVersion = rec.protocolVersion;
-        if((err=SSLAllocBuffer(&fragrec.contents, fraglen + msghead)))
-            return err;
-
-        /* copy the constant part of the header */
-        memcpy(fragrec.contents.data,rec.contents.data, 6);
-
-        while(len>fraglen) {
-
-            sslHdskMsgDebug("Fragmenting msg seq %d (o=%d,l=%d)", (int)seq, (int)ofs, (int)fraglen);
-
-            /* fragment offset and fragment length */
-            SSLEncodeSize(fragrec.contents.data+6, ofs, 3);
-            SSLEncodeSize(fragrec.contents.data+9, fraglen, 3);
-            /* copy the payload */
-            memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, fraglen);
-            if ((err = SSLWriteRecord(fragrec, ctx)) != 0)
-                goto cleanup;
-            len-=fraglen;
-            ofs+=fraglen;
-        }
-
-        sslHdskMsgDebug("Fragmenting msg seq %d - Last Fragment (o=%d,l=%d)", (int)seq, (int)ofs, (int)len);
-
-        /* last fragment */
-        /* fragment offset and fragment length */
-        SSLEncodeSize(fragrec.contents.data+6, ofs, 3);
-        SSLEncodeSize(fragrec.contents.data+9, len, 3);
-        /* copy the payload */
-        memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, len);
-        fragrec.contents.length=len+msghead;
-        err = SSLWriteRecord(fragrec, ctx);
-
-    cleanup:
-        /* Free the allocated fragment buffer */
-        SSLFreeBuffer(&fragrec.contents);
-
-    }
-
-    return err;
-}
-
-
-OSStatus SSLResetFlight(SSLContext *ctx)
-{
-    OSStatus err;
-    WaitingMessage *queue;
-    WaitingMessage *next;
-    int n=0;
-
-    queue=ctx->messageWriteQueue;
-    ctx->messageQueueContainsChangeCipherSpec=false;
-
-    while(queue) {
-        n++;
-        err = SSLFreeBuffer(&queue->rec.contents);
-        if (err != 0)
-            goto fail;
-        next=queue->next;
-        sslFree(queue);
-        queue=next;
-    }
-
-    ctx->messageWriteQueue=NULL;
-
-    return errSecSuccess;
-fail:
-    check_noerr(err);
-    return err;
-}
-
-OSStatus SSLSendFlight(SSLContext *ctx)
-{
-    OSStatus err;
-    WaitingMessage  *queue;
-    int n=0;
-
-    queue=ctx->messageWriteQueue;
-
-    while(queue) {
-        if (ctx->isDTLS) {
-            err=DTLSSendMessage(queue->rec, ctx);
-        } else {
-            err=SSLSendMessage(queue->rec, ctx);
-        }
-        if (err != 0)
-            goto fail;
-        queue=queue->next;
-        n++;
-    }
-
-    return errSecSuccess;
-fail:
-    check_noerr(err);
-    return err;
-}
-
-OSStatus
-SSL3ReceiveSSL2ClientHello(SSLRecord rec, SSLContext *ctx)
-{   OSStatus      err;
-
-    if ((err = SSLInitMessageHashes(ctx)) != 0)
-        return err;
-
-    if ((err = SSLHashSHA1.update(&ctx->shaState, &rec.contents)) != 0 ||
-        (err = SSLHashMD5.update(&ctx->md5State, &rec.contents)) != 0)
-    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-        return err;
-    }
-
-    if ((err = SSLAdvanceHandshake(SSL_HdskClientHello, ctx)) != 0)
-        return err;
-
-    return errSecSuccess;
-}
-
-/*
- * Determine max enabled protocol, i.e., the one we try to negotiate for.
- * Only returns an error (errSecParam) if NO protocols are enabled, which can
- * in fact happen by malicious or ignorant use of SSLSetProtocolVersionEnabled().
- */
-OSStatus sslGetMaxProtVersion(
-                              SSLContext                       *ctx,
-                              SSLProtocolVersion       *version)       // RETURNED
-{
-    /* This check is here until SSLSetProtocolVersionEnabled() is gone .*/
-    if (ctx->maxProtocolVersion == SSL_Version_Undetermined)
-        return errSecBadReq;
-
-    *version = ctx->maxProtocolVersion;
-    return errSecSuccess;
-}
-
-
-/* log changes in handshake state */
-#ifndef        NDEBUG
-#include <stdio.h>
-
-char *hdskStateToStr(SSLHandshakeState state)
-{
-       static char badStr[100];
-
-       switch(state) {
-               case SSL_HdskStateUninit:
-                       return "Uninit";
-               case SSL_HdskStateServerUninit:
-                       return "ServerUninit";
-               case SSL_HdskStateClientUninit:
-                       return "ClientUninit";
-               case SSL_HdskStateGracefulClose:
-                       return "GracefulClose";
-               case SSL_HdskStateErrorClose:
-                       return "ErrorClose";
-               case SSL_HdskStateNoNotifyClose:
-                       return "NoNotifyClose";
-               case SSL_HdskStateServerHello:
-                       return "ServerHello";
-               case SSL_HdskStateKeyExchange:
-                       return "KeyExchange";
-               case SSL_HdskStateCert:
-                       return "Cert";
-               case SSL_HdskStateHelloDone:
-                       return "HelloDone";
-               case SSL_HdskStateClientCert:
-                       return "ClientCert";
-               case SSL_HdskStateClientKeyExchange:
-                       return "ClientKeyExchange";
-               case SSL_HdskStateClientCertVerify:
-                       return "ClientCertVerify";
-               case SSL_HdskStateChangeCipherSpec:
-                       return "ChangeCipherSpec";
-               case SSL_HdskStateFinished:
-                       return "Finished";
-               case SSL_HdskStateServerReady:
-                       return "SSL_ServerReady";
-               case SSL_HdskStateClientReady:
-                       return "SSL_ClientReady";
-               default:
-                       sprintf(badStr, "Unknown state (%d(d)", state);
-                       return badStr;
-       }
-}
-
-/* This is a macro in Release mode */
-void SSLChangeHdskState(SSLContext *ctx, SSLHandshakeState newState)
-{
-       sslHdskStateDebug("...hdskState = %s", hdskStateToStr(newState));
-       ctx->state = newState;
-}
-
-/* log handshake messages */
-
-static char *hdskMsgToStr(SSLHandshakeType msg)
-{
-       static char badStr[100];
-
-       switch(msg) {
-               case SSL_HdskHelloRequest:
-                       return "SSL_HdskHelloRequest";
-               case SSL_HdskClientHello:
-                       return "SSL_HdskClientHello";
-               case SSL_HdskServerHello:
-                       return "SSL_HdskServerHello";
-        case SSL_HdskHelloVerifyRequest:
-                       return "SSL_HdskHelloVerifyRequest";
-               case SSL_HdskCert:
-                       return "SSL_HdskCert";
-               case SSL_HdskServerKeyExchange:
-                       return "SSL_HdskServerKeyExchange";
-               case SSL_HdskCertRequest:
-                       return "SSL_HdskCertRequest";
-               case SSL_HdskServerHelloDone:
-                       return "SSL_HdskServerHelloDone";
-               case SSL_HdskCertVerify:
-                       return "SSL_HdskCertVerify";
-               case SSL_HdskClientKeyExchange:
-                       return "SSL_HdskClientKeyExchange";
-               case SSL_HdskFinished:
-                       return "SSL_HdskFinished";
-               default:
-                       sprintf(badStr, "Unknown msg (%d(d))", msg);
-                       return badStr;
-       }
-}
-
-void SSLLogHdskMsg(SSLHandshakeType msg, char sent)
-{
-       sslHdskMsgDebug("---%s handshake msg %s",
-               hdskMsgToStr(msg), (sent ? "sent" : "recv"));
-}
-
-#endif /* NDEBUG */
-