sslHandshakeHello.c [plain text]
#include "sslContext.h"
#include "sslHandshake.h"
#include "sslMemory.h"
#include "sslSession.h"
#include "sslUtils.h"
#include "sslDebug.h"
#include "sslCrypto.h"
#include "sslDigests.h"
#include "cipherSpecs.h"
#include <string.h>
#define SSL_IE_NULL_RESUME_BUG 1
#if SSL_IE_NULL_RESUME_BUG
#define SSL_NULL_ID_LEN 32
#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
msglen = 38 + sessionIDLen;
assert(ctx->negProtocolVersion != SSL_Version_Undetermined);
assert(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, ctx)) != 0)
return err;
charPtr = SSLEncodeHandshakeHeader(ctx, serverHello, SSL_HdskServerHello, msglen);
charPtr = SSLEncodeInt(charPtr, serverHello->protocolVersion, 2);
#if SSL_PAC_SERVER_ENABLE
if(!ctx->serverRandomValid) {
if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) {
return err;
}
}
#else
if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0)
return err;
#endif
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) {
memcpy(charPtr, ctx->sessionID.data, sessionIDLen);
}
else {
SSLBuffer rb;
rb.data = charPtr;
rb.length = SSL_NULL_ID_LEN;
sslRand(ctx, &rb);
}
#else
if (sessionIDLen > 0)
memcpy(charPtr, ctx->sessionID.data, sessionIDLen);
#endif
charPtr += sessionIDLen;
charPtr = SSLEncodeInt(charPtr, ctx->selectedCipher, 2);
*(charPtr++) = 0;
sslLogNegotiateDebug("ssl3: server specifying cipherSuite 0x%lx",
(UInt32)ctx->selectedCipher);
assert(charPtr == serverHello->contents.data + serverHello->contents.length);
return noErr;
}
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, ctx)) != 0)
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 noErr;
}
OSStatus
SSLProcessServerHelloVerifyRequest(SSLBuffer message, SSLContext *ctx)
{ OSStatus err;
SSLProtocolVersion protocolVersion;
unsigned int cookieLen;
UInt8 *p;
assert(ctx->protocolSide == kSSLClientSide);
if (message.length < 3 ) {
sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error\n");
return errSSLProtocol;
}
p = message.data;
protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2);
p += 2;
if(protocolVersion != DTLS_Version_1_0) {
sslErrorLog("SSLProcessServerHelloVerifyRequest: protocol version error\n");
return errSSLProtocol;
}
cookieLen = *p++;
sslLogNegotiateDebug("cookieLen = %d, msglen=%d\n", cookieLen, message.length);
if (message.length < (3 + cookieLen)) {
sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error 2\n");
return errSSLProtocol;
}
err = SSLAllocBuffer(&ctx->dtlsCookie, cookieLen, ctx);
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;
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;
got_secure_renegotiation = true;
SSLProcessServerHelloExtension_SecureRenegotiation(ctx, extLen, p);
break;
default:
break;
}
p+=extLen;
}
return noErr;
}
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;
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;
}
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)
{
if (ctx->sessionID.data)
SSLFreeBuffer(&ctx->sessionID, ctx);
err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen, ctx);
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)
return unimpErr;
extensionsLen = message.length - (38 + sessionIDLen);
if(extensionsLen) {
err = SSLProcessServerHelloExtensions(ctx, extensionsLen, p);
if(err)
return err;
}
if(ctx->secure_renegotiation && !ctx->secure_renegotiation_received)
return errSSLNegotiation;
if(ctx->secure_renegotiation_received)
ctx->secure_renegotiation = true;
return noErr;
}
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;
}
#if ENABLE_SSLV2
numCipherSuites = ctx->numValidNonSSLv2Specs;
#else
numCipherSuites = ctx->numValidCipherSuites;
#endif
if(!ctx->secure_renegotiation)
numCipherSuites+=1;
length = 39 + 2*numCipherSuites + sessionIDLen;
err = sslGetMaxProtVersion(ctx, &clientHello->protocolVersion);
if(err) {
goto err_exit;
}
ctx->secure_renegotiation_received = false;
if(ctx->negProtocolVersion != SSL_Version_Undetermined) {
clientHello->protocolVersion = ctx->negProtocolVersion;
}
#if ENABLE_DTLS
if(clientHello->protocolVersion == DTLS_Version_1_0) {
length += 1 + ctx->dtlsCookie.length;
sslLogNegotiateDebug("==DTLS Hello: len=%lu\n", length);
}
#endif
if(ctx->secure_renegotiation) {
totalExtenLen += 2 +
2 +
1 +
ctx->ownVerifyData.length;
}
if((clientHello->protocolVersion >= TLS_Version_1_0) &&
(ctx->peerDomainName != NULL) &&
(ctx->peerDomainNameLen != 0)) {
serverNameLen = 2 +
2 +
2 +
1 +
2 +
ctx->peerDomainNameLen;
totalExtenLen += serverNameLen;
}
if(ctx->sessionTicket.length) {
sessionTicketLen = 2 +
2 +
ctx->sessionTicket.length;
totalExtenLen += sessionTicketLen;
}
if((clientHello->protocolVersion >= TLS_Version_1_0) &&
(ctx->ecdsaEnable)) {
pointFormatLen = 2 +
2 +
1 +
1;
suppCurveLen = 2 +
2 +
2 +
(2 * ctx->ecdhNumCurves);
totalExtenLen += (pointFormatLen + suppCurveLen);
}
if(ctx->isDTLS
? clientHello->protocolVersion < DTLS_Version_1_0
: clientHello->protocolVersion >= TLS_Version_1_2) {
signatureAlgorithmsLen = 2 +
2 +
2 +
2 * (ctx->ecdsaEnable ? 5 : 3); totalExtenLen += signatureAlgorithmsLen;
}
if(totalExtenLen != 0) {
if(totalExtenLen > 0xffff) {
sslErrorLog("Total extensions length EXCEEDED\n");
totalExtenLen = 0;
sessionTicketLen = 0;
serverNameLen = 0;
pointFormatLen = 0;
suppCurveLen = 0;
signatureAlgorithmsLen = 0;
}
else {
length += (totalExtenLen + 2);
}
}
clientHello->contentType = SSL_RecordTypeHandshake;
head = SSLHandshakeHeaderSize(clientHello);
if ((err = SSLAllocBuffer(&clientHello->contents, length + head, ctx)) != 0)
goto err_exit;
p = SSLEncodeHandshakeHeader(ctx, clientHello, SSL_HdskClientHello, length);
p = SSLEncodeInt(p, clientHello->protocolVersion, 2);
sslLogNegotiateDebug("===SSL3 client: proclaiming max protocol "
"%d_%d capable ONLY",
clientHello->protocolVersion >> 8, clientHello->protocolVersion & 0xff);
if ((err = SSLEncodeRandom(p, ctx)) != 0)
{ goto err_exit;
}
memcpy(ctx->clientRandom, p, SSL_CLIENT_SRVR_RAND_SIZE);
p += 32;
*p++ = sessionIDLen;
if (sessionIDLen > 0)
{ memcpy(p, sessionIdentifier.data, sessionIDLen);
}
p += sessionIDLen;
#if ENABLE_DTLS
if (clientHello->protocolVersion == DTLS_Version_1_0) {
*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",ctx->dtlsCookie.length);
}
#endif
p = SSLEncodeInt(p, 2*numCipherSuites, 2);
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;
*p++ = 0;
if(totalExtenLen != 0) {
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);
p = SSLEncodeSize(p, len, 2);
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);
p = SSLEncodeSize(p, 1, 1);
p = SSLEncodeInt(p, SSL_PointFormatUncompressed, 1);
}
if (signatureAlgorithmsLen) {
sslEcdsaDebug("+++ adding signature algorithms to ClientHello");
UInt32 len = 2 * (ctx->ecdsaEnable ? 5 : 3); p = SSLEncodeInt(p, SSL_HE_SignatureAlgorithms, 2);
p = SSLEncodeSize(p, len+2, 2);
p = SSLEncodeSize(p, len, 2);
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_HashAlgorithmSHA1, 1);
p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1);
if (ctx->ecdsaEnable) {
p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 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=%08x\n", clientHello->contents.data, p, 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, ctx);
}
SSLFreeBuffer(&sessionIdentifier, ctx);
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;
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;
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;
}
if (sessionIDLen > 0 && ctx->peerID.data != 0)
{
err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen, ctx);
if (err == 0)
memcpy(ctx->sessionID.data, charPtr, sessionIDLen);
}
charPtr += sessionIDLen;
#if ENABLE_DTLS
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;
}
#endif
cipherListLen = (UInt16)SSLDecodeInt(charPtr, 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;
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;
ctx->selectedCipher = cipherSuite;
compressionCount = *(charPtr++);
if ((compressionCount < 1) ||
(message.length <
(unsigned)(38 + sessionIDLen + cipherListLen + compressionCount))) {
sslErrorLog("SSLProcessClientHello: msg len error 4\n");
return errSSLProtocol;
}
charPtr += compressionCount;
if(charPtr < eom) {
ptrdiff_t remLen = eom - charPtr;
UInt32 totalExtensLen;
UInt32 extenType;
UInt32 extenLen;
if(remLen < 6) {
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, NULL);
SSLCopyBufferFromData(charPtr, extenLen, &ctx->sessionTicket);
sslEapDebug("Saved %lu bytes of sessionTicket from ClientHello",
(unsigned long)extenLen);
break;
#endif
case SSL_HE_ServerName:
{
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, *end = charPtr + extenLen;
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++) {
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 noErr;
}
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(ctx, &randomData)) != 0)
return err;
return noErr;
}
OSStatus
SSLInitMessageHashes(SSLContext *ctx)
{ OSStatus err;
if ((err = CloseHash(&SSLHashSHA1, &ctx->shaState, ctx)) != 0)
return err;
if ((err = CloseHash(&SSLHashMD5, &ctx->md5State, ctx)) != 0)
return err;
if ((err = CloseHash(&SSLHashSHA256, &ctx->sha256State, ctx)) != 0)
return err;
if ((err = CloseHash(&SSLHashSHA384, &ctx->sha512State, ctx)) != 0)
return err;
if ((err = ReadyHash(&SSLHashSHA1, &ctx->shaState, ctx)) != 0)
return err;
if ((err = ReadyHash(&SSLHashMD5, &ctx->md5State, ctx)) != 0)
return err;
if ((err = ReadyHash(&SSLHashSHA256, &ctx->sha256State, ctx)) != 0)
return err;
if ((err = ReadyHash(&SSLHashSHA384, &ctx->sha512State, ctx)) != 0)
return err;
return noErr;
}