]> git.saurik.com Git - apple/security.git/blobdiff - SecureTransport/sslHandshake.cpp
Security-222.tar.gz
[apple/security.git] / SecureTransport / sslHandshake.cpp
diff --git a/SecureTransport/sslHandshake.cpp b/SecureTransport/sslHandshake.cpp
deleted file mode 100644 (file)
index 8ec94a0..0000000
+++ /dev/null
@@ -1,847 +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:           sslHandshake.cpp
-
-       Contains:       SSL 3.0 handshake state machine. 
-
-       Written by:     Doug Mitchell
-
-       Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
-
-*/
-
-#include "sslContext.h"
-#include "sslHandshake.h"
-#include "sslMemory.h"
-#include "sslAlertMessage.h"
-#include "sslSession.h"
-#include "sslUtils.h"
-#include "sslDebug.h"
-#include "appleCdsa.h"
-#include "sslDigests.h"
-
-#include <string.h>
-#include <assert.h>
-
-#define REQUEST_CERT_CORRECT        0
-
-static OSStatus SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx);
-
-OSStatus
-SSLProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx)
-{   OSStatus        err;
-    sint32          remaining;
-    UInt8           *p;
-    SSLHandshakeMsg message;
-    SSLBuffer       messageData;
-    
-    if (ctx->fragmentedMessageCache.data != 0)
-    {   if ((err = SSLReallocBuffer(ctx->fragmentedMessageCache,
-                    ctx->fragmentedMessageCache.length + rec.contents.length,
-                    ctx)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            return err;
-        }
-        memcpy(ctx->fragmentedMessageCache.data + ctx->fragmentedMessageCache.length,
-            rec.contents.data, rec.contents.length);
-        remaining = ctx->fragmentedMessageCache.length;
-        p = ctx->fragmentedMessageCache.data;
-    }
-    else
-    {   remaining = rec.contents.length;
-        p = rec.contents.data;
-    }
-
-    while (remaining > 0)
-    {   if (remaining < 4)
-            break;  /* we must have at least a header */
-        
-        messageData.data = p;
-        message.type = (SSLHandshakeType)*p++;
-        message.contents.length = SSLDecodeInt(p, 3);
-        if (((int)(message.contents.length + 4)) > remaining)
-            break;
-        
-        p += 3;
-        message.contents.data = p;
-        p += message.contents.length;
-        messageData.length = 4 + 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 = SSLHashSHA1.update(ctx->shaState, messageData)) != 0 ||
-                (err = SSLHashMD5.update(ctx->md5State, messageData)) != 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, ctx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-        }
-        if (p != ctx->fragmentedMessageCache.data)
-        {   memcpy(ctx->fragmentedMessageCache.data, p, remaining);
-            ctx->fragmentedMessageCache.length = remaining;
-        }
-    }
-    else if (ctx->fragmentedMessageCache.data != 0)
-    {   if ((err = SSLFreeBuffer(ctx->fragmentedMessageCache, ctx)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            return err;
-        }
-    }
-    
-    return noErr;
-}
-
-static OSStatus
-SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx)
-{   OSStatus      err;
-    
-    err = noErr;
-    SSLLogHdskMsg(message.type, 0);
-    switch (message.type)
-    {   case SSL_HdskHelloRequest:
-            if (ctx->protocolSide != SSL_ClientSide)
-                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 &&
-                ctx->state != SSL_HdskStateServerHelloUnknownVersion)
-                goto wrongMessage;
-            err = SSLProcessServerHello(message.contents, ctx);
-            break;
-        case SSL_HdskCert:
-            if (ctx->state != SSL_HdskStateCert &&
-                ctx->state != SSL_HdskStateClientCert)
-                goto wrongMessage;
-            err = SSLProcessCertificate(message.contents, ctx);
-                       if(ctx->protocolSide == SSL_ServerSide) {
-                               if(err) {
-                                       /*
-                                        * Error could be from no cert (when we require one) 
-                                        * or invalid cert
-                                        */
-                                       if(ctx->peerCert != NULL) {
-                                               ctx->clientCertState = kSSLClientCertRejected;
-                                       }
-                               }
-                               else if(ctx->peerCert != NULL) {
-                                       /* 
-                                        * This still might change if cert verify msg
-                                        * fails. Note we avoid going to state
-                                        * if we get en empty cert message which is
-                                        * otherwise valid.
-                                        */
-                                       ctx->clientCertState = kSSLClientCertSent;
-                               }
-                       }
-            break;
-        case SSL_HdskCertRequest:
-            if (((ctx->state != SSL_HdskStateHelloDone) && 
-                            (ctx->state != SSL_HdskStateKeyExchange))
-                 || ctx->certRequested)
-                goto wrongMessage;
-            err = SSLProcessCertificateRequest(message.contents, ctx);
-            break;
-        case SSL_HdskServerKeyExchange:
-                       /* 
-                * Since this message is optional, 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 == SSL_ServerSide);
-                       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
-            SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
-    }
-    return err;
-    
-wrongMessage:
-    SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
-    return errSSLProtocol;
-}
-
-OSStatus
-SSLAdvanceHandshake(SSLHandshakeType processed, SSLContext *ctx)
-{   OSStatus        err;
-    SSLBuffer       sessionIdentifier;
-    
-    switch (processed)
-    {   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;
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeClientHello, ctx)) != 0)
-                return err;
-            SSLChangeHdskState(ctx, SSL_HdskStateServerHello);
-            break;
-        case SSL_HdskClientHello:
-            assert(ctx->protocolSide == SSL_ServerSide);
-                       ctx->sessionMatch = 0;
-            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;
-                        if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, 
-                                                                       ctx)) != 0)
-                            return err;
-                        if ((err = SSLInitPendingCiphers(ctx)) != 0 ||
-                            (err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0)
-                        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                            return err;
-                        }
-                        if ((err = 
-                                                               SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec,
-                                                                       ctx)) != 0)
-                            return err;
-                        /* Install new cipher spec on write side */
-                        if ((err = SSLDisposeCipherSuite(&ctx->writeCipher, 
-                                                               ctx)) != 0)
-                        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                            return err;
-                        }
-                        ctx->writeCipher = ctx->writePending;
-                        ctx->writeCipher.ready = 0;     
-                                                               /* Can't send data until Finished is sent */
-                        memset(&ctx->writePending, 0, sizeof(CipherContext));       
-                                                               /* Zero out old data */
-                        if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, 
-                                                               ctx)) != 0)
-                            return err;
-                        /* Finished has been sent; enable data t6ransfer on 
-                                                * write channel */
-                        ctx->writeCipher.ready = 1;
-                        SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
-                        break;
-                    }
-                                       else {
-                                               sslLogResumSessDebug(
-                                                       "===FAILED TO RESUME SSL3 server-side session");
-                                       }
-                    if ((err = SSLFreeBuffer(sessionIdentifier, ctx)) != 0 ||
-                        (err = SSLDeleteSessionData(ctx)) != 0)
-                    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                        return err;
-                    }
-                }
-                if ((err = SSLFreeBuffer(ctx->sessionID, ctx)) != 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, ctx);
-                if (err == 0)
-                {   
-                       if((err = sslRand(ctx, &ctx->sessionID)) != 0)
-                    {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                        return err;
-                    }
-                }
-            }
-            
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0)
-                return err;
-            switch (ctx->selectedCipherSpec->keyExchangeMethod)
-            {   case SSL_NULL_auth:
-               #if             APPLE_DH
-                case SSL_DH_anon:
-                case SSL_DH_anon_EXPORT:
-                       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 */
-                default:        /* everything else */
-                                       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;
-            }
-                       /*
-                        * 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->selectedCipherSpec->keyExchangeMethod) {
-                                       case SSL_RSA_EXPORT:
-                                       #if !SSL_SERVER_KEYEXCH_HACK
-                                       /* the "proper" way - app decides. */
-                                       case SSL_RSA:
-                                       #endif
-                                               if(ctx->encryptPrivKeyRef != NULL) {
-                                                       doServerKeyExch = true;
-                                               }
-                                               break;
-                                       case SSL_DH_anon:
-                                       case SSL_DH_anon_EXPORT:
-                                       case SSL_DHE_RSA:
-                                       case SSL_DHE_RSA_EXPORT:
-                                       case SSL_DHE_DSS:
-                                       case SSL_DHE_DSS_EXPORT:
-                                               doServerKeyExch = true;
-                                               break;
-                                       default:
-                                               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, ctx)) != 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, ctx)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-            }
-            switch (ctx->selectedCipherSpec->keyExchangeMethod)
-            {   
-               /* these require a key exchange message */
-               case SSL_NULL_auth:
-                case SSL_DH_anon:
-                case SSL_DH_anon_EXPORT:
-                    SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange);
-                    break;
-                case SSL_RSA:
-                case SSL_DH_DSS:
-                case SSL_DH_DSS_EXPORT:
-                case SSL_DH_RSA:
-                case SSL_DH_RSA_EXPORT:
-                case SSL_RSA_EXPORT:
-                case SSL_DHE_DSS:
-                case SSL_DHE_DSS_EXPORT:
-                case SSL_DHE_RSA:
-                case SSL_DHE_RSA_EXPORT:
-                case SSL_Fortezza:
-                    SSLChangeHdskState(ctx, SSL_HdskStateCert);
-                    break;
-                default:
-                    assert("Unknown key exchange method");
-                    break;
-            }
-            break;
-        case SSL_HdskCert:
-            if (ctx->state == SSL_HdskStateCert)
-                switch (ctx->selectedCipherSpec->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_RSA_EXPORT:
-                    case SSL_DH_DSS:
-                    case SSL_DH_DSS_EXPORT:
-                    case SSL_DH_RSA:
-                    case SSL_DH_RSA_EXPORT:
-                        SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
-                        break;
-                    case SSL_DHE_DSS:
-                    case SSL_DHE_DSS_EXPORT:
-                    case SSL_DHE_RSA:
-                    case SSL_DHE_RSA_EXPORT:
-                    case SSL_Fortezza:
-                        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;
-            }
-            ctx->certRequested = 1;
-                       ctx->clientCertState = kSSLClientCertRequested;
-            break;
-        case SSL_HdskServerKeyExchange:
-            SSLChangeHdskState(ctx, SSL_HdskStateHelloDone);
-            break;
-        case SSL_HdskServerHelloDone:
-            if (ctx->certRequested) {
-                               /* 
-                                * 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,
-                                                               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, ctx)) != 0) {
-                return err;
-                       }
-            if (ctx->certSent) {
-                if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateVerify, 
-                                               ctx)) != 0) {
-                    return err;
-                               }
-                       }
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, 
-                                       ctx)) != 0) {
-                return err;
-                       }
-            /* Install new cipher spec on write side */
-            if ((err = SSLDisposeCipherSuite(&ctx->writeCipher, ctx)) != 0)
-            {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                return err;
-            }
-            ctx->writeCipher = ctx->writePending;
-                       /* Can't send data until Finished is sent */
-            ctx->writeCipher.ready = 0;     
-                       
-                       /* Zero out old data */
-            memset(&ctx->writePending, 0, sizeof(CipherContext));    
-                       ctx->writePending.encrypting = 1;   
-            if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, ctx)) != 0)
-                return err;
-            /* Finished has been sent; enable data transfer on write channel */
-            ctx->writeCipher.ready = 1;
-            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, ctx)) != 0)
-                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 */
-            if (ctx->writePending.ready != 0)
-            {   if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, 
-                                               ctx)) != 0)
-                    return err;
-                
-                /* Install new cipher spec on write side */
-                if ((err = SSLDisposeCipherSuite(&ctx->writeCipher, ctx)) != 0)
-                {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-                    return err;
-                }
-                ctx->writeCipher = ctx->writePending;
-                ctx->writeCipher.ready = 0;     
-                                               /* Can't send data until Finished is sent */
-                memset(&ctx->writePending, 0, sizeof(CipherContext));       
-                                               /* Zero out old data */
-                if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, 
-                                                       ctx)) != 0)
-                    return err;
-                ctx->writeCipher.ready = 1;
-            }
-            if (ctx->protocolSide == SSL_ServerSide) {
-                SSLChangeHdskState(ctx, SSL_HdskStateServerReady);
-            }
-            else {
-                SSLChangeHdskState(ctx, SSL_HdskStateClientReady);
-            }
-            if (ctx->peerID.data != 0)
-                SSLAddSessionData(ctx);
-            break;
-        default:
-            assert("Unknown State");
-            break;
-    }
-    
-    return noErr;
-}
-
-OSStatus
-SSLPrepareAndQueueMessage(EncodeMessageFunc msgFunc, SSLContext *ctx)
-{   OSStatus        err;
-    SSLRecord       rec;
-    
-    if ((err = msgFunc(rec, ctx)) != 0)
-    {   SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
-        goto fail;
-    }
-    
-    if (rec.contentType == SSL_RecordTypeHandshake)
-    {   if ((err = SSLHashSHA1.update(ctx->shaState, rec.contents)) != 0 ||
-            (err = SSLHashMD5.update(ctx->md5State, rec.contents)) != 0)
-        {   SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
-            goto fail;
-        }
-        SSLLogHdskMsg((SSLHandshakeType)rec.contents.data[0], 1);
-    }
-    
-       assert(ctx->sslTslCalls != NULL);
-    if ((err = ctx->sslTslCalls->writeRecord(rec, ctx)) != 0)
-        goto fail;
-    
-    err = noErr;
-fail:
-    SSLFreeBuffer(rec.contents, ctx);
-    
-    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 noErr;
-}
-
-/* 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_HdskStateServerHelloUnknownVersion:
-                       return "ServerHelloUnknownVersion";     
-               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 SSL2_HdskStateClientMasterKey:
-                       return "SSL2_ClientMasterKey";
-               case SSL2_HdskStateClientFinished:
-                       return "SSL2_ClientFinished";   
-               case SSL2_HdskStateServerHello:
-                       return "SSL2_ServerHello";      
-               case SSL2_HdskStateServerVerify:
-                       return "SSL2_ServerVerify";     
-               case SSL2_HdskStateServerFinished:
-                       return "SSL2_ServerFinished";   
-               case SSL_HdskStateServerReady:
-                       return "SSL_ServerReady";       
-               case SSL_HdskStateClientReady:
-                       return "SSL_ClientReady";
-               default:
-                       sprintf(badStr, "Unknown state (%d(d)", state);
-                       return badStr;
-       }
-}
-
-void SSLChangeHdskState(SSLContext *ctx, SSLHandshakeState newState)
-{
-       /* FIXME - this ifndef should not be necessary */
-       #ifndef NDEBUG
-       sslHdskStateDebug("...hdskState = %s", hdskStateToStr(newState));
-       #endif
-       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_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";      
-               case SSL_HdskNoCertAlert:
-                       return "SSL_HdskNoCertAlert";   
-               default:
-                       sprintf(badStr, "Unknown state (%d(d)", msg);
-                       return badStr;
-       }
-}
-
-void SSLLogHdskMsg(SSLHandshakeType msg, char sent)
-{
-       sslHdskMsgDebug("---%s handshake msg %s", 
-               hdskMsgToStr(msg), (sent ? "sent" : "recv"));
-}
-
-#endif /* NDEBUG */
-