#ifndef _SSLCTX_H_
#include "sslctx.h"
#endif
#ifndef _SSLHDSHK_H_
#include "sslhdshk.h"
#endif
#ifndef _SSLALLOC_H_
#include "sslalloc.h"
#endif
#ifndef _SSL_DEBUG_H_
#include "sslDebug.h"
#endif
#ifndef _SSLUTIL_H_
#include "sslutil.h"
#endif
#ifndef _DIGESTS_H_
#include "digests.h"
#endif
#include <string.h>
#include <assert.h>
SSLErr
SSLEncodeFinishedMessage(SSLRecord *finished, SSLContext *ctx)
{ SSLErr err;
SSLBuffer finishedMsg, shaMsgState, md5MsgState;
Boolean isServerMsg;
unsigned finishedSize;
shaMsgState.data = 0;
md5MsgState.data = 0;
switch(ctx->negProtocolVersion) {
case SSL_Version_3_0:
finished->protocolVersion = SSL_Version_3_0;
finishedSize = 36;
break;
case TLS_Version_1_0:
finished->protocolVersion = TLS_Version_1_0;
finishedSize = 12;
break;
default:
assert(0);
return SSLInternalError;
}
finished->contentType = SSL_handshake;
if ((err = SSLAllocBuffer(&finished->contents, finishedSize + 4,
&ctx->sysCtx)) != 0)
return err;
finished->contents.data[0] = SSL_finished;
SSLEncodeInt(finished->contents.data + 1, finishedSize, 3);
finishedMsg.data = finished->contents.data + 4;
finishedMsg.length = finishedSize;
if ((err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
goto fail;
if ((err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
goto fail;
isServerMsg = (ctx->protocolSide == SSL_ServerSide) ? true : false;
if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, finishedMsg,
shaMsgState, md5MsgState, isServerMsg)) != 0)
goto fail;
fail:
SSLFreeBuffer(&shaMsgState, &ctx->sysCtx);
SSLFreeBuffer(&md5MsgState, &ctx->sysCtx);
return err;
}
SSLErr
SSLProcessFinished(SSLBuffer message, SSLContext *ctx)
{ SSLErr err;
SSLBuffer expectedFinished, shaMsgState, md5MsgState;
Boolean isServerMsg;
unsigned finishedSize;
switch(ctx->negProtocolVersion) {
case SSL_Version_3_0:
finishedSize = 36;
break;
case TLS_Version_1_0:
finishedSize = 12;
break;
default:
assert(0);
return SSLInternalError;
}
if (message.length != finishedSize) {
errorLog0("SSLProcessFinished: msg len error 1\n");
return SSLProtocolErr;
}
expectedFinished.data = 0;
if ((err = SSLAllocBuffer(&expectedFinished, finishedSize, &ctx->sysCtx)) != 0)
return err;
shaMsgState.data = 0;
if ((err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
goto fail;
md5MsgState.data = 0;
if ((err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
goto fail;
isServerMsg = (ctx->protocolSide == SSL_ServerSide) ? false : true;
if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, expectedFinished,
shaMsgState, md5MsgState, isServerMsg)) != 0)
goto fail;
if (memcmp(expectedFinished.data, message.data, finishedSize) != 0)
{
errorLog0("SSLProcessFinished: memcmp failure\n");
err = SSLProtocolErr;
goto fail;
}
fail:
SSLFreeBuffer(&expectedFinished, &ctx->sysCtx);
SSLFreeBuffer(&shaMsgState, &ctx->sysCtx);
SSLFreeBuffer(&md5MsgState, &ctx->sysCtx);
return err;
}
SSLErr
SSLEncodeServerHelloDone(SSLRecord *helloDone, SSLContext *ctx)
{ SSLErr err;
helloDone->contentType = SSL_handshake;
assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
(ctx->negProtocolVersion == TLS_Version_1_0));
helloDone->protocolVersion = ctx->negProtocolVersion;
if ((err = SSLAllocBuffer(&helloDone->contents, 4, &ctx->sysCtx)) != 0)
return err;
helloDone->contents.data[0] = SSL_server_hello_done;
SSLEncodeInt(helloDone->contents.data+1, 0, 3);
return SSLNoErr;
}
SSLErr
SSLProcessServerHelloDone(SSLBuffer message, SSLContext *ctx)
{ CASSERT(ctx->protocolSide == SSL_ClientSide);
if (message.length != 0) {
errorLog0("SSLProcessServerHelloDone: nonzero msg len\n");
return SSLProtocolErr;
}
return SSLNoErr;
}