]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_ssl/lib/sslHandshakeHello.c
Security-57031.1.35.tar.gz
[apple/security.git] / libsecurity_ssl / lib / sslHandshakeHello.c
diff --git a/libsecurity_ssl/lib/sslHandshakeHello.c b/libsecurity_ssl/lib/sslHandshakeHello.c
deleted file mode 100644 (file)
index 81daee8..0000000
+++ /dev/null
@@ -1,1030 +0,0 @@
-/*
- * Copyright (c) 1999-2001,2005-2008,2010-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@
- */
-
-/*
- * sslHandshakeHello.c - Support for client hello and server hello messages.
- */
-
-#include "sslContext.h"
-#include "sslHandshake.h"
-#include "sslMemory.h"
-#include "sslSession.h"
-#include "sslUtils.h"
-#include "sslDebug.h"
-#include "sslCrypto.h"
-#include "sslRand.h"
-#include "sslDigests.h"
-#include "sslCipherSpecs.h"
-
-#include <string.h>
-#include <time.h>
-#include <assert.h>
-
-#include <inttypes.h>
-
-/*
- * Given a protocol version sent by peer, determine if we accept that version
- * and downgrade if appropriate (which can not be done for the client side).
- */
-static
-OSStatus sslVerifyProtVersion(
-    SSLContext                         *ctx,
-    SSLProtocolVersion peerVersion,    // sent by peer
-    SSLProtocolVersion         *negVersion)    // final negotiated version if return success
-{
-    if ((ctx->isDTLS)
-        ? peerVersion > ctx->minProtocolVersion
-        : peerVersion < ctx->minProtocolVersion) {
-        return errSSLNegotiation;
-    }
-    if ((ctx->isDTLS)
-        ? peerVersion < ctx->maxProtocolVersion
-        : peerVersion > ctx->maxProtocolVersion) {
-        if (ctx->protocolSide == kSSLClientSide) {
-            return errSSLNegotiation;
-        }
-        *negVersion = ctx->maxProtocolVersion;
-    } else {
-        *negVersion = peerVersion;
-    }
-
-    return errSecSuccess;
-}
-
-
-/* IE treats null session id as valid; two consecutive sessions with NULL ID
- * are considered a match. Workaround: when resumable sessions are disabled,
- * send a random session ID. */
-#define SSL_IE_NULL_RESUME_BUG         1
-#if            SSL_IE_NULL_RESUME_BUG
-#define SSL_NULL_ID_LEN                                32      /* length of bogus session ID */
-#endif
-
-OSStatus
-SSLEncodeServerHello(SSLRecord *serverHello, SSLContext *ctx)
-{   OSStatus        err;
-    UInt8           *charPtr;
-    int             sessionIDLen;
-    size_t          msglen;
-    int             head;
-
-    sessionIDLen = 0;
-    if (ctx->sessionID.data != 0)
-        sessionIDLen = (UInt8)ctx->sessionID.length;
-       #if     SSL_IE_NULL_RESUME_BUG
-       if(sessionIDLen == 0) {
-               sessionIDLen = SSL_NULL_ID_LEN;
-       }
-       #endif  /* SSL_IE_NULL_RESUME_BUG */
-
-    msglen = 38 + sessionIDLen;
-
-       /* this was set to a known quantity in SSLProcessClientHello */
-       check(ctx->negProtocolVersion != SSL_Version_Undetermined);
-       /* should not be here in this case */
-       check(ctx->negProtocolVersion != SSL_Version_2_0);
-       sslLogNegotiateDebug("===SSL3 server: sending version %d_%d",
-               ctx->negProtocolVersion >> 8, ctx->negProtocolVersion & 0xff);
-       sslLogNegotiateDebug("...sessionIDLen = %d", sessionIDLen);
-    serverHello->protocolVersion = ctx->negProtocolVersion;
-    serverHello->contentType = SSL_RecordTypeHandshake;
-    head = SSLHandshakeHeaderSize(serverHello);
-    if ((err = SSLAllocBuffer(&serverHello->contents, msglen + head)))
-        return err;
-
-    charPtr = SSLEncodeHandshakeHeader(ctx, serverHello, SSL_HdskServerHello, msglen);
-
-    charPtr = SSLEncodeInt(charPtr, serverHello->protocolVersion, 2);
-
-    #if                SSL_PAC_SERVER_ENABLE
-       /* serverRandom might have already been set, in SSLAdvanceHandshake() */
-       if(!ctx->serverRandomValid) {
-       if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) {
-                       return err;
-               }
-       }
-       #else
-       /* This is the normal production code path */
-    if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0)
-        return err;
-       #endif  /* SSL_PAC_SERVER_ENABLE */
-
-       memcpy(charPtr, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
-
-    charPtr += SSL_CLIENT_SRVR_RAND_SIZE;
-       *(charPtr++) = (UInt8)sessionIDLen;
-       #if     SSL_IE_NULL_RESUME_BUG
-       if(ctx->sessionID.data != NULL) {
-               /* normal path for enabled resumable session */
-               memcpy(charPtr, ctx->sessionID.data, sessionIDLen);
-       }
-       else {
-               /* IE workaround */
-               SSLBuffer rb;
-               rb.data = charPtr;
-               rb.length = SSL_NULL_ID_LEN;
-               sslRand(&rb);
-       }
-       #else
-    if (sessionIDLen > 0)
-        memcpy(charPtr, ctx->sessionID.data, sessionIDLen);
-       #endif  /* SSL_IE_NULL_RESUME_BUG */
-       charPtr += sessionIDLen;
-    charPtr = SSLEncodeInt(charPtr, ctx->selectedCipher, 2);
-    *(charPtr++) = 0;      /* Null compression */
-
-    sslLogNegotiateDebug("ssl3: server specifying cipherSuite 0x%lx",
-               (unsigned long)ctx->selectedCipher);
-
-    assert(charPtr == serverHello->contents.data + serverHello->contents.length);
-
-    return errSecSuccess;
-}
-
-OSStatus
-SSLEncodeServerHelloVerifyRequest(SSLRecord *helloVerifyRequest, SSLContext *ctx)
-{   OSStatus        err;
-    UInt8           *charPtr;
-    size_t          msglen;
-    int             head;
-
-    assert(ctx->protocolSide == kSSLServerSide);
-    assert(ctx->negProtocolVersion == DTLS_Version_1_0);
-    assert(ctx->dtlsCookie.length);
-
-    msglen = 3 + ctx->dtlsCookie.length;
-
-    helloVerifyRequest->protocolVersion = DTLS_Version_1_0;
-    helloVerifyRequest->contentType = SSL_RecordTypeHandshake;
-    head = SSLHandshakeHeaderSize(helloVerifyRequest);
-    if ((err = SSLAllocBuffer(&helloVerifyRequest->contents, msglen + head)))
-        return err;
-
-    charPtr = SSLEncodeHandshakeHeader(ctx, helloVerifyRequest, SSL_HdskHelloVerifyRequest, msglen);
-
-    charPtr = SSLEncodeInt(charPtr, helloVerifyRequest->protocolVersion, 2);
-
-    *charPtr++ = ctx->dtlsCookie.length;
-    memcpy(charPtr, ctx->dtlsCookie.data, ctx->dtlsCookie.length);
-    charPtr += ctx->dtlsCookie.length;
-
-    assert(charPtr == (helloVerifyRequest->contents.data + helloVerifyRequest->contents.length));
-
-    return errSecSuccess;
-}
-
-
-OSStatus
-SSLProcessServerHelloVerifyRequest(SSLBuffer message, SSLContext *ctx)
-{   OSStatus            err;
-    SSLProtocolVersion  protocolVersion;
-    unsigned int        cookieLen;
-    UInt8               *p;
-
-    assert(ctx->protocolSide == kSSLClientSide);
-
-    /* TODO: those length values should not be hardcoded */
-    /* 3 bytes at least with empty cookie */
-    if (message.length < 3 ) {
-       sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error\n");
-        return errSSLProtocol;
-    }
-    p = message.data;
-
-    protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2);
-    p += 2;
-
-    /* TODO: Not clear what else to do with protocol version here */
-    if(protocolVersion != DTLS_Version_1_0) {
-        sslErrorLog("SSLProcessServerHelloVerifyRequest: protocol version error\n");
-        return errSSLProtocol;
-    }
-
-    cookieLen = *p++;
-    sslLogNegotiateDebug("cookieLen = %d, msglen=%d\n", (int)cookieLen, (int)message.length);
-    /* TODO: hardcoded '15' again */
-    if (message.length < (3 + cookieLen)) {
-       sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error 2\n");
-        return errSSLProtocol;
-    }
-
-    err = SSLAllocBuffer(&ctx->dtlsCookie, cookieLen);
-    if (err == 0)
-        memcpy(ctx->dtlsCookie.data, p, cookieLen);
-
-    return err;
-}
-
-static void
-SSLProcessServerHelloExtension_SecureRenegotiation(SSLContext *ctx, UInt16 extLen, UInt8 *p)
-{
-    if(extLen!= (1 + ctx->ownVerifyData.length + ctx->peerVerifyData.length))
-        return;
-
-    if(*p!=ctx->ownVerifyData.length + ctx->ownVerifyData.length)
-        return;
-    p++;
-
-    if(memcmp(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length))
-        return;
-    p+=ctx->ownVerifyData.length;
-
-    if(memcmp(p, ctx->peerVerifyData.data, ctx->peerVerifyData.length))
-        return;
-
-    ctx->secure_renegotiation_received = true;
-}
-
-
-static OSStatus
-SSLProcessServerHelloExtensions(SSLContext *ctx, UInt16 extensionsLen, UInt8 *p)
-{
-    Boolean got_secure_renegotiation = false;
-    UInt16 remaining;
-
-    if(extensionsLen<2) {
-        sslErrorLog("SSLProcessHelloExtensions: need a least 2 bytes\n");
-        return errSSLProtocol;
-    }
-
-    remaining = SSLDecodeInt(p, 2); p+=2;
-    extensionsLen -=2;
-
-    /* remaining = number of bytes remaining to process according to buffer data */
-    /* extensionsLen = number of bytes in the buffer */
-
-    if(remaining>extensionsLen) {
-        sslErrorLog("SSLProcessHelloExtensions: ext len error 1\n");
-        return errSSLProtocol;
-    }
-
-    if(remaining<extensionsLen) {
-        sslErrorLog("Warning: SSLProcessServerHelloExtensions: Too many bytes\n");
-    }
-
-    while(remaining) {
-        UInt16 extType;
-        UInt16 extLen;
-
-        if (remaining<4) {
-            sslErrorLog("SSLProcessHelloExtensions: ext len error\n");
-            return errSSLProtocol;
-        }
-
-        extType = SSLDecodeInt(p, 2); p+=2;
-        extLen = SSLDecodeInt(p, 2); p+=2;
-
-        if (remaining<(4+extLen)) {
-            sslErrorLog("SSLProcessHelloExtension: ext len error 2\n");
-            return errSSLProtocol;
-        }
-        remaining -= (4+extLen);
-
-        switch (extType) {
-            case SSL_HE_SecureRenegotation:
-                if(got_secure_renegotiation)
-                    return errSSLProtocol;            /* Fail if we already processed one */
-                got_secure_renegotiation = true;
-                SSLProcessServerHelloExtension_SecureRenegotiation(ctx, extLen, p);
-                break;
-            default:
-                /*
-                 Do nothing for other extensions. Per RFC 5246, we should (MUST) error
-                 if we received extensions we didnt specify in the Client Hello.
-                 Client should also abort handshake if multiple extensions of the same
-                 type are found
-                 */
-                break;
-        }
-        p+=extLen;
-    }
-
-    return errSecSuccess;
-}
-
-
-
-OSStatus
-SSLProcessServerHello(SSLBuffer message, SSLContext *ctx)
-{   OSStatus            err;
-    SSLProtocolVersion  protocolVersion, negVersion;
-    size_t              sessionIDLen;
-    size_t              extensionsLen;
-    UInt8               *p;
-
-    assert(ctx->protocolSide == kSSLClientSide);
-
-    if (message.length < 38) {
-       sslErrorLog("SSLProcessServerHello: msg len error\n");
-        return errSSLProtocol;
-    }
-    p = message.data;
-
-    protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2);
-    p += 2;
-       /* FIXME this should probably send appropriate alerts */
-       err = sslVerifyProtVersion(ctx, protocolVersion, &negVersion);
-       if(err) {
-               return err;
-       }
-    ctx->negProtocolVersion = negVersion;
-       switch(negVersion) {
-               case SSL_Version_3_0:
-                       ctx->sslTslCalls = &Ssl3Callouts;
-                       break;
-               case TLS_Version_1_0:
-        case TLS_Version_1_1:
-        case DTLS_Version_1_0:
-                       ctx->sslTslCalls = &Tls1Callouts;
-                       break;
-        case TLS_Version_1_2:
-                       ctx->sslTslCalls = &Tls12Callouts;
-                       break;
-               default:
-                       return errSSLNegotiation;
-       }
-    err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion);
-    if(err) {
-        return err;
-    }
-
-    sslLogNegotiateDebug("===SSL3 client: negVersion is %d_%d",
-               (negVersion >> 8) & 0xff, negVersion & 0xff);
-
-    memcpy(ctx->serverRandom, p, 32);
-    p += 32;
-
-    sessionIDLen = *p++;
-    if (message.length < (38 + sessionIDLen)) {
-       sslErrorLog("SSLProcessServerHello: msg len error 2\n");
-        return errSSLProtocol;
-    }
-    if (sessionIDLen > 0 && ctx->peerID.data != 0)
-    {   /* Don't die on error; just treat it as an uncached session */
-        if (ctx->sessionID.data)
-            SSLFreeBuffer(&ctx->sessionID);
-        err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen);
-        if (err == 0)
-            memcpy(ctx->sessionID.data, p, sessionIDLen);
-    }
-    p += sessionIDLen;
-
-    ctx->selectedCipher = (UInt16)SSLDecodeInt(p,2);
-    sslLogNegotiateDebug("===ssl3: server requests cipherKind %x",
-       (unsigned)ctx->selectedCipher);
-    p += 2;
-    if ((err = FindCipherSpec(ctx)) != 0) {
-        return err;
-    }
-
-    if (*p++ != 0)      /* Compression */
-        return errSecUnimplemented;
-
-    /* Process ServerHello extensions */
-    extensionsLen = message.length - (38 + sessionIDLen);
-
-    if(extensionsLen) {
-        err = SSLProcessServerHelloExtensions(ctx, extensionsLen, p);
-        if(err)
-            return err;
-    }
-
-    /* RFC 5746: Make sure the renegotiation is secure */
-    if(ctx->secure_renegotiation && !ctx->secure_renegotiation_received)
-        return errSSLNegotiation;
-
-    if(ctx->secure_renegotiation_received)
-        ctx->secure_renegotiation = true;
-
-    
-       /*
-        * Note: the server MAY send a SSL_HE_EC_PointFormats extension if
-        * we've negotiated an ECDSA ciphersuite...but
-        * a) the provided format list MUST contain SSL_PointFormatUncompressed per
-        *    RFC 4492 5.2; and
-        * b) The uncompressed format is the only one we support.
-        *
-        * Thus we drop a possible incoming SSL_HE_EC_PointFormats extension here.
-        * IF we ever support other point formats, we have to parse the extension
-        * to see what the server supports.
-        */
-    return errSecSuccess;
-}
-
-OSStatus
-SSLEncodeClientHello(SSLRecord *clientHello, SSLContext *ctx)
-{
-       size_t          length;
-    unsigned        i;
-    OSStatus        err;
-    unsigned char   *p;
-    SSLBuffer       sessionIdentifier = { 0, NULL };
-    size_t          sessionIDLen;
-       size_t                  sessionTicketLen = 0;
-       size_t                  serverNameLen = 0;
-       size_t                  pointFormatLen = 0;
-       size_t                  suppCurveLen = 0;
-       size_t                  signatureAlgorithmsLen = 0;
-       size_t                  totalExtenLen = 0;
-    UInt16          numCipherSuites;
-    int             head;
-
-    assert(ctx->protocolSide == kSSLClientSide);
-
-       clientHello->contents.length = 0;
-       clientHello->contents.data = NULL;
-
-    sessionIDLen = 0;
-    if (ctx->resumableSession.data != 0)
-    {   if ((err = SSLRetrieveSessionID(ctx->resumableSession,
-                               &sessionIdentifier, ctx)) != 0)
-        {   return err;
-        }
-        sessionIDLen = sessionIdentifier.length;
-    }
-
-       /*
-        * Since we're not in SSLv2 compatibility mode, only count non-SSLv2 ciphers.
-        */
-#if ENABLE_SSLV2
-    numCipherSuites = ctx->numValidNonSSLv2Specs;
-#else
-    numCipherSuites = ctx->numValidCipherSuites;
-#endif
-
-    /* RFC 5746 : add the fake ciphersuite unless we are including the extension */
-    if(!ctx->secure_renegotiation)
-        numCipherSuites+=1;
-
-    length = 39 + 2*numCipherSuites + sessionIDLen;
-
-    /* We always use the max enabled version in the ClientHello.client_version,
-       even in the renegotiation case. This value is saved in the context so it
-       can be used in the RSA key exchange */
-       err = sslGetMaxProtVersion(ctx, &ctx->clientReqProtocol);
-       if(err) {
-               /* we don't have a protocol enabled */
-               goto err_exit;
-       }
-
-    /* RFC 5746: If are starting a new handshake, so we didnt received this yet */
-    ctx->secure_renegotiation_received = false;
-
-    /* This is the protocol version used at the record layer, If we already
-     negotiated the protocol version previously, we should just use that,
-     otherwise we use the the minimum supported version.
-     We do not always use the minimum version because some TLS only servers
-     will reject an SSL 3 version in client_hello.
-    */
-    if(ctx->negProtocolVersion != SSL_Version_Undetermined) {
-        clientHello->protocolVersion = ctx->negProtocolVersion;
-    } else {
-        if(ctx->minProtocolVersion<TLS_Version_1_0 && ctx->maxProtocolVersion>=TLS_Version_1_0)
-            clientHello->protocolVersion = TLS_Version_1_0;
-        else
-            clientHello->protocolVersion = ctx->minProtocolVersion;
-    }
-
-#if ENABLE_DTLS
-    if(clientHello->protocolVersion == DTLS_Version_1_0) {
-        /* extra space for cookie */
-        /* TODO: cookie len - 0 for now */
-        length += 1 + ctx->dtlsCookie.length;
-        sslLogNegotiateDebug("==DTLS Hello: len=%lu\n", length);
-    }
-    /* Because of the way the version number for DTLS is encoded,
-     the following code mean that you can use extensions with DTLS... */
-#endif /* ENABLE_DTLS */
-
-    /* RFC 5746: We add the extension only for renegotiation ClientHello */
-    if(ctx->secure_renegotiation) {
-        totalExtenLen += 2 + /* extension type */
-                         2 + /* extension length */
-                         1 + /* lenght of renegotiated_conection (client verify data) */
-                         ctx->ownVerifyData.length;
-    }
-
-    /* prepare for optional ClientHello extensions */
-       if((ctx->clientReqProtocol >= TLS_Version_1_0) &&
-          (ctx->peerDomainName != NULL) &&
-          (ctx->peerDomainNameLen != 0)) {
-               serverNameLen = 2 +     /* extension type */
-                                               2 + /* 2-byte vector length, extension_data */
-                                               2 + /* length of server_name_list */
-                                               1 +     /* length of name_type */
-                                               2 + /* length of HostName */
-                                               ctx->peerDomainNameLen;
-               totalExtenLen += serverNameLen;
-       }
-       if(ctx->sessionTicket.length) {
-               sessionTicketLen = 2 +  /* extension type */
-                                                  2 + /* 2-byte vector length, extension_data */
-                                                  ctx->sessionTicket.length;
-               totalExtenLen += sessionTicketLen;
-       }
-       if((ctx->clientReqProtocol >= TLS_Version_1_0) &&
-          (ctx->ecdsaEnable)) {
-               /* Two more extensions: point format, supported curves */
-               pointFormatLen = 2 +    /* extension type */
-                                                2 +    /* 2-byte vector length, extension_data */
-                                                1 +    /* length of the ec_point_format_list */
-                                                1;             /* the single format we support */
-               suppCurveLen   = 2 +    /* extension type */
-                                                2 +    /* 2-byte vector length, extension_data */
-                                                2 +    /* length of the elliptic_curve_list */
-                                               (2 * ctx->ecdhNumCurves);       /* each curve is 2 bytes */
-               totalExtenLen += (pointFormatLen + suppCurveLen);
-       }
-    if(ctx->isDTLS
-       ? ctx->clientReqProtocol < DTLS_Version_1_0
-       : ctx->clientReqProtocol >= TLS_Version_1_2) {
-        signatureAlgorithmsLen = 2 +   /* extension type */
-                                 2 +   /* 2-byte vector length, extension_data */
-                                 2 +    /* length of signatureAlgorithms list */
-                                 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here.
-               totalExtenLen += signatureAlgorithmsLen;
-    }
-       if(totalExtenLen != 0) {
-               /*
-                * Total length extensions have to fit in a 16 bit field...
-                */
-               if(totalExtenLen > 0xffff) {
-                       sslErrorLog("Total extensions length EXCEEDED\n");
-                       totalExtenLen = 0;
-                       sessionTicketLen = 0;
-                       serverNameLen = 0;
-                       pointFormatLen = 0;
-                       suppCurveLen = 0;
-            signatureAlgorithmsLen = 0;
-               }
-               else {
-                       /* add length of total length plus lengths of extensions */
-                       length += (totalExtenLen + 2);
-               }
-       }
-
-    clientHello->contentType = SSL_RecordTypeHandshake;
-    head = SSLHandshakeHeaderSize(clientHello);
-    if ((err = SSLAllocBuffer(&clientHello->contents, length + head)))
-        goto err_exit;
-
-    p = SSLEncodeHandshakeHeader(ctx, clientHello, SSL_HdskClientHello, length);
-
-    p = SSLEncodeInt(p, ctx->clientReqProtocol, 2);
-
-       sslLogNegotiateDebug("===SSL3 client: proclaiming max protocol "
-               "%d_%d capable ONLY",
-               ctx->clientReqProtocol >> 8, ctx->clientReqProtocol & 0xff);
-   if ((err = SSLEncodeRandom(p, ctx)) != 0)
-    {   goto err_exit;
-    }
-    memcpy(ctx->clientRandom, p, SSL_CLIENT_SRVR_RAND_SIZE);
-    p += 32;
-    *p++ = sessionIDLen;                               /* 1 byte vector length */
-    if (sessionIDLen > 0)
-    {   memcpy(p, sessionIdentifier.data, sessionIDLen);
-    }
-    p += sessionIDLen;
-#if ENABLE_DTLS
-    if (ctx->clientReqProtocol == DTLS_Version_1_0) {
-        /* TODO: Add the cookie ! Currently: size=0 -> no cookie */
-        *p++ = ctx->dtlsCookie.length;
-        if(ctx->dtlsCookie.length) {
-            memcpy(p, ctx->dtlsCookie.data, ctx->dtlsCookie.length);
-            p+=ctx->dtlsCookie.length;
-        }
-        sslLogNegotiateDebug("==DTLS Hello: cookie len = %d\n",(int)ctx->dtlsCookie.length);
-    }
-#endif
-
-
-    p = SSLEncodeInt(p, 2*numCipherSuites, 2);
-    /* 2 byte long vector length */
-
-    /* RFC 5746 : add the fake ciphersuite unless we are including the extension */
-    if(!ctx->secure_renegotiation)
-        p = SSLEncodeInt(p, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, 2);
-
-    for (i = 0; i<ctx->numValidCipherSuites; ++i) {
-#if ENABLE_SSLV2
-               if(CIPHER_SUITE_IS_SSLv2(ctx->validCipherSuites[i])) {
-                       continue;
-               }
-#endif
-               sslLogNegotiateDebug("ssl3EncodeClientHello sending suite %x",
-                                       (unsigned)ctx->validCipherSuites[i]);
-        p = SSLEncodeInt(p, ctx->validCipherSuites[i], 2);
-       }
-    *p++ = 1;                               /* 1 byte long vector */
-    *p++ = 0;                               /* null compression */
-
-       /*
-        * Append ClientHello extensions.
-        */
-       if(totalExtenLen != 0) {
-               /* first, total length of all extensions */
-               p = SSLEncodeSize(p, totalExtenLen, 2);
-       }
-    if(ctx->secure_renegotiation){
-        assert(ctx->ownVerifyData.length<=255);
-        p = SSLEncodeInt(p, SSL_HE_SecureRenegotation, 2);
-        p = SSLEncodeSize(p, ctx->ownVerifyData.length+1, 2);
-        p = SSLEncodeSize(p, ctx->ownVerifyData.length, 1);
-        memcpy(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length);
-        p += ctx->ownVerifyData.length;
-    }
-       if(sessionTicketLen) {
-               sslEapDebug("Adding %lu bytes of sessionTicket to ClientHello",
-                       ctx->sessionTicket.length);
-               p = SSLEncodeInt(p, SSL_HE_SessionTicket, 2);
-               p = SSLEncodeSize(p, ctx->sessionTicket.length, 2);
-               memcpy(p, ctx->sessionTicket.data, ctx->sessionTicket.length);
-               p += ctx->sessionTicket.length;
-       }
-       if(serverNameLen) {
-               sslEapDebug("Specifying ServerNameIndication");
-               p = SSLEncodeInt(p, SSL_HE_ServerName, 2);
-               p = SSLEncodeSize(p, ctx->peerDomainNameLen + 5, 2);
-               p = SSLEncodeSize(p, ctx->peerDomainNameLen + 3, 2);
-               p = SSLEncodeInt(p, SSL_NT_HostName, 1);
-               p = SSLEncodeSize(p, ctx->peerDomainNameLen, 2);
-               memcpy(p, ctx->peerDomainName, ctx->peerDomainNameLen);
-               p += ctx->peerDomainNameLen;
-       }
-       if(suppCurveLen) {
-               UInt32 len = 2 * ctx->ecdhNumCurves;
-               unsigned dex;
-               p = SSLEncodeInt(p, SSL_HE_EllipticCurves, 2);
-               p = SSLEncodeSize(p, len+2, 2);         /* length of extension data */
-               p = SSLEncodeSize(p, len, 2);           /* length of elliptic_curve_list */
-               for(dex=0; dex<ctx->ecdhNumCurves; dex++) {
-                       sslEcdsaDebug("+++ adding supported curves %u to ClientHello",
-                               (unsigned)ctx->ecdhCurves[dex]);
-                       p = SSLEncodeInt(p, ctx->ecdhCurves[dex], 2);
-               }
-       }
-       if(pointFormatLen) {
-               sslEcdsaDebug("+++ adding point format to ClientHello");
-               p = SSLEncodeInt(p, SSL_HE_EC_PointFormats, 2);
-               p = SSLEncodeSize(p, 2, 2);             /* length of extension data */
-               p = SSLEncodeSize(p, 1, 1);             /* length of ec_point_format_list */
-               p = SSLEncodeInt(p, SSL_PointFormatUncompressed, 1);
-       }
-    if (signatureAlgorithmsLen) {
-               sslEcdsaDebug("+++ adding signature algorithms to ClientHello");
-        /* TODO: Don't hardcode this */
-        /* We dont support SHA512 or SHA224 because we didnot implement the digest abstraction for those
-         and we dont keep a running hash for those.
-         We dont support SHA384/ECDSA because corecrypto ec does not support it with 256 bits curves */
-               UInt32 len = 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here.
-               p = SSLEncodeInt(p, SSL_HE_SignatureAlgorithms, 2);
-               p = SSLEncodeSize(p, len+2, 2);         /* length of extension data */
-               p = SSLEncodeSize(p, len, 2);           /* length of extension data */
-        // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1);
-        // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
-        p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1);
-        p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
-        p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1);
-        p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
-        // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1);
-        // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
-        p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1);
-        p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
-        if (ctx->ecdsaEnable) {
-            // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1);
-            // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1);
-            // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1);
-            // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1);
-            p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1);
-            p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1);
-            // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1);
-            // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1);
-            p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1);
-            p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1);
-        }
-    }
-
-    sslLogNegotiateDebug("Client Hello : data=%p p=%p len=%08lx\n", clientHello->contents.data, p, (unsigned long)clientHello->contents.length);
-
-    assert(p == clientHello->contents.data + clientHello->contents.length);
-
-    if ((err = SSLInitMessageHashes(ctx)) != 0)
-        goto err_exit;
-
-err_exit:
-       if (err != 0) {
-               SSLFreeBuffer(&clientHello->contents);
-       }
-       SSLFreeBuffer(&sessionIdentifier);
-
-       return err;
-}
-
-OSStatus
-SSLProcessClientHello(SSLBuffer message, SSLContext *ctx)
-{   OSStatus            err;
-    SSLProtocolVersion  negVersion;
-    UInt16              cipherListLen, cipherCount, desiredSuite, cipherSuite;
-    UInt8               sessionIDLen, compressionCount;
-    UInt8               *charPtr;
-    unsigned            i;
-    UInt8                              *eom;           /* end of message */
-
-    if (message.length < 41) {
-       sslErrorLog("SSLProcessClientHello: msg len error 1\n");
-        return errSSLProtocol;
-    }
-    charPtr = message.data;
-       eom = charPtr + message.length;
-    ctx->clientReqProtocol = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
-    charPtr += 2;
-       err = sslVerifyProtVersion(ctx, ctx->clientReqProtocol, &negVersion);
-       if(err) {
-        sslErrorLog("SSLProcessClientHello: protocol version error %04x - %04x\n", ctx->clientReqProtocol, negVersion);
-               return err;
-       }
-       switch(negVersion) {
-               case SSL_Version_3_0:
-                       ctx->sslTslCalls = &Ssl3Callouts;
-                       break;
-               case TLS_Version_1_0:
-        case TLS_Version_1_1:
-               case DTLS_Version_1_0:
-                       ctx->sslTslCalls = &Tls1Callouts;
-                       break;
-        case TLS_Version_1_2:
-                       ctx->sslTslCalls = &Tls12Callouts;
-                       break;
-               default:
-                       return errSSLNegotiation;
-       }
-       ctx->negProtocolVersion = negVersion;
-    err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion);
-    if(err) {
-        return err;
-    }
-    sslLogNegotiateDebug("===SSL3 server: negVersion is %d_%d",
-               negVersion >> 8, negVersion & 0xff);
-
-    memcpy(ctx->clientRandom, charPtr, SSL_CLIENT_SRVR_RAND_SIZE);
-    charPtr += 32;
-    sessionIDLen = *(charPtr++);
-    if (message.length < (unsigned)(41 + sessionIDLen)) {
-       sslErrorLog("SSLProcessClientHello: msg len error 2\n");
-        return errSSLProtocol;
-    }
-       /* FIXME peerID is never set on server side.... */
-    if (sessionIDLen > 0 && ctx->peerID.data != 0)
-    {   /* Don't die on error; just treat it as an uncacheable session */
-        err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen);
-        if (err == 0)
-            memcpy(ctx->sessionID.data, charPtr, sessionIDLen);
-    }
-    charPtr += sessionIDLen;
-
-#if ENABLE_DTLS
-    /* TODO: actually do something with this cookie */
-    if(negVersion==DTLS_Version_1_0) {
-        UInt8 cookieLen = *charPtr++;
-
-        sslLogNegotiateDebug("cookieLen=%d\n", cookieLen);
-
-        if((ctx->dtlsCookie.length==0) || ((cookieLen==ctx->dtlsCookie.length) && (memcmp(ctx->dtlsCookie.data, charPtr, cookieLen)==0)))
-        {
-            ctx->cookieVerified=true;
-        } else {
-            ctx->cookieVerified=false;
-        }
-
-        charPtr+=cookieLen;
-    }
-
-    /* TODO: if we are about to send a HelloVerifyRequest, we probably dont need to process the cipherspecs */
-#endif
-
-    cipherListLen = (UInt16)SSLDecodeInt(charPtr, 2);
-                                                               /* Count of cipherSuites, must be even & >= 2 */
-    charPtr += 2;
-       if((charPtr + cipherListLen) > eom) {
-       sslErrorLog("SSLProcessClientHello: msg len error 5\n");
-        return errSSLProtocol;
-       }
-    if ((cipherListLen & 1) ||
-           (cipherListLen < 2) ||
-               (message.length < (unsigned)(39 + sessionIDLen + cipherListLen))) {
-       sslErrorLog("SSLProcessClientHello: msg len error 3\n");
-        return errSSLProtocol;
-    }
-    cipherCount = cipherListLen/2;
-    cipherSuite = 0xFFFF;        /* No match marker */
-    while (cipherSuite == 0xFFFF && cipherCount--)
-    {   desiredSuite = (UInt16)SSLDecodeInt(charPtr, 2);
-        charPtr += 2;
-        for (i = 0; i <ctx->numValidCipherSuites; i++)
-        {   if (ctx->validCipherSuites[i] == desiredSuite)
-            {   cipherSuite = desiredSuite;
-                break;
-            }
-        }
-    }
-
-    if (cipherSuite == 0xFFFF)
-        return errSSLNegotiation;
-    charPtr += 2 * cipherCount;    /* Advance past unchecked cipherCounts */
-    ctx->selectedCipher = cipherSuite;
-       /* validate cipher later, after we get possible sessionTicket */
-
-    compressionCount = *(charPtr++);
-    if ((compressionCount < 1) ||
-           (message.length <
-                   (unsigned)(38 + sessionIDLen + cipherListLen + compressionCount))) {
-       sslErrorLog("SSLProcessClientHello: msg len error 4\n");
-        return errSSLProtocol;
-    }
-    /* Ignore list; we're doing null */
-
-       /*
-        * Handle ClientHello extensions.
-        */
-       /* skip compression list */
-       charPtr += compressionCount;
-       if(charPtr < eom) {
-               ptrdiff_t remLen = eom - charPtr;
-               UInt32 totalExtensLen;
-               UInt32 extenType;
-               UInt32 extenLen;
-               if(remLen < 6) {
-                       /*
-                        * Not enough for extension type and length, but not an error...
-                        * skip it and proceed.
-                        */
-                       sslEapDebug("SSLProcessClientHello: too small for any extension");
-                       goto proceed;
-               }
-               totalExtensLen = SSLDecodeInt(charPtr, 2);
-               charPtr += 2;
-               if((charPtr + totalExtensLen) > eom) {
-                       sslEapDebug("SSLProcessClientHello: too small for specified total_extension_length");
-                       goto proceed;
-               }
-               while(charPtr < eom) {
-                       extenType = SSLDecodeInt(charPtr, 2);
-                       charPtr += 2;
-                       extenLen = SSLDecodeInt(charPtr, 2);
-                       charPtr += 2;
-                       if((charPtr + extenLen) > eom) {
-                               sslEapDebug("SSLProcessClientHello: too small for specified extension_length");
-                               break;
-                       }
-                       switch(extenType) {
-#if            SSL_PAC_SERVER_ENABLE
-
-                               case SSL_HE_SessionTicket:
-                                       SSLFreeBuffer(&ctx->sessionTicket);
-                                       SSLCopyBufferFromData(charPtr, extenLen, &ctx->sessionTicket);
-                                       sslEapDebug("Saved %lu bytes of sessionTicket from ClientHello",
-                                               (unsigned long)extenLen);
-                                       break;
-#endif
-                               case SSL_HE_ServerName:
-                               {
-                                       /*
-                                        * This is for debug only (it's disabled for Deployment builds).
-                                        * Someday, I imagine we'll have a getter in the API to get this info.
-                                        */
-                                       UInt8 *cp = charPtr;
-                                       UInt32 v = SSLDecodeInt(cp, 2);
-                                       cp += 2;
-                                       sslEapDebug("SSL_HE_ServerName: length of server_name_list %lu",
-                                               (unsigned long)v);
-                                       v = SSLDecodeInt(cp, 1);
-                                       cp++;
-                                       sslEapDebug("SSL_HE_ServerName: name_type %lu", (unsigned long)v);
-                                       v = SSLDecodeInt(cp, 2);
-                                       cp += 2;
-                                       sslEapDebug("SSL_HE_ServerName: length of HostName %lu",
-                                               (unsigned long)v);
-                                       char hostString[v + 1];
-                                       memmove(hostString, cp, v);
-                                       hostString[v] = '\0';
-                                       sslEapDebug("SSL_HE_ServerName: ServerName '%s'", hostString);
-                                       break;
-                               }
-                               case SSL_HE_SignatureAlgorithms:
-                               {
-                                       UInt8 *cp = charPtr;
-#ifndef NDEBUG
-                    UInt8 *end = charPtr + extenLen;
-#endif
-                    UInt32 sigAlgsSize = SSLDecodeInt(cp, 2);
-                                       cp += 2;
-
-                    if (extenLen != sigAlgsSize + 2 || extenLen & 1 || sigAlgsSize & 1) {
-                        sslEapDebug("SSL_HE_SignatureAlgorithms: odd length of signature algorithms list %lu %lu",
-                            (unsigned long)extenLen, (unsigned long)sigAlgsSize);
-                        break;
-                    }
-
-                    ctx->numClientSigAlgs = sigAlgsSize / 2;
-                    if(ctx->clientSigAlgs != NULL) {
-                        sslFree(ctx->clientSigAlgs);
-                    }
-                    ctx->clientSigAlgs = (SSLSignatureAndHashAlgorithm *)
-                    sslMalloc((ctx->numClientSigAlgs) * sizeof(SSLSignatureAndHashAlgorithm));
-                    for(i=0; i<ctx->numClientSigAlgs; i++) {
-                        /* TODO: Validate hash and signature fields. */
-                        ctx->clientSigAlgs[i].hash = *cp++;
-                        ctx->clientSigAlgs[i].signature = *cp++;
-                        sslLogNegotiateDebug("===Client specifies sigAlg %d %d",
-                                             ctx->clientSigAlgs[i].hash,
-                                             ctx->clientSigAlgs[i].signature);
-                    }
-                    assert(cp==end);
-                                       break;
-                }
-                               default:
-                                       sslEapDebug("SSLProcessClientHello: unknown extenType (%lu)",
-                                               (unsigned long)extenType);
-                                       break;
-                       }
-                       charPtr += extenLen;
-               }
-       }
-proceed:
-    if ((err = FindCipherSpec(ctx)) != 0) {
-        return err;
-    }
-    sslLogNegotiateDebug("ssl3 server: selecting cipherKind 0x%x", (unsigned)ctx->selectedCipher);
-    if ((err = SSLInitMessageHashes(ctx)) != 0)
-        return err;
-
-    return errSecSuccess;
-}
-
-static
-OSStatus sslTime(uint32_t *tim)
-{
-       time_t t;
-       time(&t);
-       *tim = (uint32_t)t;
-       return errSecSuccess;
-}
-
-OSStatus
-SSLEncodeRandom(unsigned char *p, SSLContext *ctx)
-{   SSLBuffer   randomData;
-    OSStatus    err;
-    uint32_t    now;
-
-    if ((err = sslTime(&now)) != 0)
-        return err;
-    SSLEncodeInt(p, now, 4);
-    randomData.data = p+4;
-    randomData.length = 28;
-       if((err = sslRand(&randomData)) != 0)
-        return err;
-    return errSecSuccess;
-}
-
-OSStatus
-SSLInitMessageHashes(SSLContext *ctx)
-{   OSStatus          err;
-
-    if ((err = CloseHash(&SSLHashSHA1, &ctx->shaState)) != 0)
-        return err;
-    if ((err = CloseHash(&SSLHashMD5,  &ctx->md5State)) != 0)
-        return err;
-    if ((err = CloseHash(&SSLHashSHA256,  &ctx->sha256State)) != 0)
-        return err;
-    if ((err = CloseHash(&SSLHashSHA384,  &ctx->sha512State)) != 0)
-        return err;
-    if ((err = ReadyHash(&SSLHashSHA1, &ctx->shaState)) != 0)
-        return err;
-    if ((err = ReadyHash(&SSLHashMD5,  &ctx->md5State)) != 0)
-        return err;
-    if ((err = ReadyHash(&SSLHashSHA256,  &ctx->sha256State)) != 0)
-        return err;
-    if ((err = ReadyHash(&SSLHashSHA384,  &ctx->sha512State)) != 0)
-        return err;
-    return errSecSuccess;
-}