#include "tls_handshake_priv.h"
#include "sslHandshake.h"
#include "sslMemory.h"
#include "sslAlertMessage.h"
#include "sslDebug.h"
#include "sslCipherSpecs.h"
#include <assert.h>
#include <string.h>
int
SSLEncodeChangeCipherSpec(tls_buffer *rec, tls_handshake_t ctx)
{ int err;
assert(ctx->writePending_ready);
sslLogNegotiateDebug("===Sending changeCipherSpec msg");
assert(ctx->negProtocolVersion >= tls_protocol_version_SSL_3);
rec->length = 1;
if ((err = SSLAllocBuffer(rec, 1)))
return err;
rec->data[0] = 1;
ctx->messageQueueContainsChangeCipherSpec=true;
return errSSLSuccess;
}
int
SSLProcessChangeCipherSpec(tls_buffer rec, tls_handshake_t ctx)
{ int err;
if (rec.length != 1 || rec.data[0] != 1)
{
#warning This is fishy:
if(ctx->isDTLS)
return errSSLUnexpectedRecord;
SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
sslErrorLog("***bad changeCipherSpec msg: length %d data 0x%x\n",
(unsigned)rec.length, (unsigned)rec.data[0]);
return errSSLProtocol;
}
if((!ctx->isServer) &&
(ctx->externalSessionTicket.length != 0) &&
((ctx->state == SSL_HdskStateKeyExchange) || (ctx->state == SSL_HdskStateCert)) &&
(ctx->masterSecretCallback != NULL)) {
size_t secretLen = SSL_MASTER_SECRET_SIZE;
sslEapDebug("Client side resuming based on masterSecretCallback");
ctx->masterSecretCallback(ctx->masterSecretArg,
ctx->masterSecret, &secretLen);
ctx->sessionMatch = 1;
if ((err = ValidateSelectedCiphersuite(ctx)) != 0) {
return err;
}
if((err = SSLInitPendingCiphers(ctx)) != 0) {
SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
return err;
}
SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec);
}
if (!ctx->readPending_ready || ctx->state != SSL_HdskStateChangeCipherSpec)
{
if(ctx->isDTLS)
return errSSLUnexpectedRecord;
SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx);
sslErrorLog("***bad changeCipherSpec msg: readPending.ready %d state %d\n",
(unsigned)ctx->readPending_ready, (unsigned)ctx->state);
return errSSLProtocol;
}
sslLogNegotiateDebug("===Processing changeCipherSpec msg");
if ((err = ctx->callbacks->advance_read_cipher(ctx->callback_ctx)) != 0)
{
SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
return err;
}
ctx->readPending_ready = 0;
SSLChangeHdskState(ctx, SSL_HdskStateFinished);
return errSSLSuccess;
}