sslHandshakeFinish.c [plain text]
#include "tls_handshake_priv.h"
#include "sslHandshake.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include "sslUtils.h"
#include "sslDigests.h"
#include <string.h>
#include <assert.h>
#define NPN_MSG_HAS_EXT_TYPE 0
int
SSLEncodeNPNEncryptedExtensionMessage(tls_buffer *npn, tls_handshake_t ctx)
{
OSStatus err;
unsigned msgSize;
unsigned extnSize;
unsigned paddingSize;
UInt8 *p;
int head;
if(ctx->npnOwnData.data == NULL)
return errSSLBadConfiguration;
assert(ctx->npnOwnData.length < 256);
paddingSize = 32 - ((ctx->npnOwnData.length + 2) % 32);
extnSize = 1 + (unsigned)ctx->npnOwnData.length + 1 + paddingSize;
msgSize = extnSize;
#if NPN_MSG_HAS_EXT_TYPE
msgSize += 4;
#endif
head = SSLHandshakeHeaderSize(ctx);
if ((err = SSLAllocBuffer(npn, msgSize + head)) != 0) {
return err;
}
p = SSLEncodeHandshakeHeader(ctx, npn, SSL_HdskNPNEncryptedExtension, msgSize);
#if NPN_MSG_HAS_EXT_TYPE
p = SSLEncodeInt(p, SSL_HE_NPN, 2);
p = SSLEncodeInt(p, extnSize, 2);
#endif
p = SSLEncodeInt(p, ctx->npnOwnData.length, 1);
memcpy(p, ctx->npnOwnData.data, ctx->npnOwnData.length);
p += ctx->npnOwnData.length;
p = SSLEncodeInt(p, paddingSize, 1);
memset(p, 0, paddingSize);
ctx->npn_confirmed = true;
return errSSLSuccess;
}
static int
SSLProcessEncryptedNPNExtension(const uint8_t *p, size_t extLen, tls_handshake_t ctx)
{
int err;
if (!ctx->npn_announced)
return errSSLProtocol;
ctx->npn_received = true;
if ((err = SSLAllocBuffer(&ctx->npnPeerData, extLen)) != 0)
return err;
memcpy(ctx->npnPeerData.data, p, ctx->npnPeerData.length);
return 0;
}
int
SSLProcessEncryptedExtension(tls_buffer message, tls_handshake_t ctx)
{
const uint8_t *p = message.data;
#if NPN_MSG_HAS_EXT_TYPE
int err;
while (message.length) {
unsigned int extName, extLen;
if (message.length < 4)
return errSSLProtocol;
extName = SSLDecodeInt(p, 2);
p += 2;
extLen = SSLDecodeInt(p, 2);
p += 2;
message.length -= 4;
if (message.length < extLen)
return errSSLProtocol;
switch (extName) {
case SSL_HE_NPN:
if((err = SSLProcessEncryptedNPNExtension(p, extLen, ctx)))
return err;
p += extLen;
break;
default:
p += extLen;
break;
}
message.length -= extLen;
}
return errSSLSuccess;
#else
return SSLProcessEncryptedNPNExtension(p, message.length, ctx);
#endif
}
int
SSLEncodeFinishedMessage(tls_buffer *finished, tls_handshake_t ctx)
{
int err;
tls_buffer finishedMsg;
unsigned finishedSize;
UInt8 *p;
int head;
switch(ctx->negProtocolVersion) {
case tls_protocol_version_SSL_3:
finishedSize = 36;
break;
case tls_protocol_version_DTLS_1_0:
case tls_protocol_version_TLS_1_0:
case tls_protocol_version_TLS_1_1:
case tls_protocol_version_TLS_1_2:
finishedSize = 12;
break;
default:
assert(0);
return errSSLInternal;
}
head = SSLHandshakeHeaderSize(ctx);
if ((err = SSLAllocBuffer(finished, finishedSize + head)) != 0)
return err;
p = SSLEncodeHandshakeHeader(ctx, finished, SSL_HdskFinished, finishedSize);
finishedMsg.data = p;
finishedMsg.length = finishedSize;
err = ctx->sslTslCalls->computeFinishedMac(ctx, finishedMsg, ctx->isServer);
if(err)
return err;
SSLFreeBuffer(&ctx->ownVerifyData);
return SSLCopyBuffer(&finishedMsg, &ctx->ownVerifyData);
}
int
SSLProcessFinished(tls_buffer message, tls_handshake_t ctx)
{ int err;
tls_buffer expectedFinished;
unsigned finishedSize;
switch(ctx->negProtocolVersion) {
case tls_protocol_version_SSL_3:
finishedSize = 36;
break;
case tls_protocol_version_DTLS_1_0:
case tls_protocol_version_TLS_1_0:
case tls_protocol_version_TLS_1_1:
case tls_protocol_version_TLS_1_2:
finishedSize = 12;
break;
default:
assert(0);
return errSSLInternal;
}
if (message.length != finishedSize) {
sslErrorLog("SSLProcessFinished: msg len error 1\n");
return errSSLProtocol;
}
expectedFinished.data = 0;
if ((err = SSLAllocBuffer(&expectedFinished, finishedSize)))
return err;
if ((err = ctx->sslTslCalls->computeFinishedMac(ctx, expectedFinished, !ctx->isServer)) != 0)
goto fail;
if (memcmp(expectedFinished.data, message.data, finishedSize) != 0)
{
sslErrorLog("SSLProcessFinished: memcmp failure\n");
err = errSSLProtocol;
goto fail;
}
SSLFreeBuffer(&ctx->peerVerifyData);
err = SSLCopyBuffer(&expectedFinished, &ctx->peerVerifyData);
fail:
SSLFreeBuffer(&expectedFinished);
return err;
}
int
SSLEncodeServerHelloDone(tls_buffer *helloDone, tls_handshake_t ctx)
{ int err;
int head;
assert(ctx->negProtocolVersion >= tls_protocol_version_SSL_3);
head = SSLHandshakeHeaderSize(ctx);
if ((err = SSLAllocBuffer(helloDone, head)))
return err;
SSLEncodeHandshakeHeader(ctx, helloDone, SSL_HdskServerHelloDone, 0);
return errSSLSuccess;
}
int
SSLProcessServerHelloDone(tls_buffer message, tls_handshake_t ctx)
{
assert(!ctx->isServer);
if (message.length != 0) {
sslErrorLog("SSLProcessServerHelloDone: nonzero msg len\n");
return errSSLProtocol;
}
return errSSLSuccess;
}