Added support for the extended master secret extension to the sniffer.

This commit is contained in:
John Safranek
2016-09-08 11:25:02 -07:00
parent 0f0e0ca9a5
commit 4fb1431727

View File

@ -90,6 +90,7 @@ enum {
EXT_TYPE_SZ = 2, /* Extension length */
MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
MTU_EXTRA, /* Max input sz of reassembly */
EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */
TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
};
@ -329,6 +330,9 @@ typedef struct Flags {
byte srvAckFault; /* server acked unseen data from client */
byte cliSkipPartial; /* client skips partial data to catch up */
byte srvSkipPartial; /* server skips partial data to catch up */
#ifdef HAVE_EXTENDED_MASTER
byte expectEms; /* expect extended master secret */
#endif
} Flags;
@ -341,6 +345,27 @@ typedef struct FinCaputre {
} FinCaputre;
typedef struct HsHashes {
#ifndef NO_OLD_TLS
#ifndef NO_SHA
Sha hashSha;
#endif
#ifndef NO_MD5
Md5 hashMd5;
#endif
#endif
#ifndef NO_SHA256
Sha256 hashSha256;
#endif
#ifdef WOLFSSL_SHA384
Sha384 hashSha384;
#endif
#ifdef WOLFSSL_SHA512
Sha512 hashSha512;
#endif
} HsHashes;
/* Sniffer Session holds info for each client/server SSL/TLS session */
typedef struct SnifferSession {
SnifferServer* context; /* server context */
@ -363,6 +388,9 @@ typedef struct SnifferSession {
word32 srvReassemblyMemory; /* server packet memory used */
struct SnifferSession* next; /* for hash table list */
byte* ticketID; /* mac ID of session ticket */
#ifdef HAVE_EXTENDED_MASTER
HsHashes* hash;
#endif
} SnifferSession;
@ -483,6 +511,9 @@ static void FreeSnifferSession(SnifferSession* session)
FreePacketList(session->srvReassemblyList);
free(session->ticketID);
#ifdef HAVE_EXTENDED_MASTER
free(session->hash);
#endif
}
free(session);
}
@ -533,6 +564,102 @@ void ssl_FreeSniffer(void)
}
#ifdef HAVE_EXTENDED_MASTER
static int HashInit(HsHashes* hash)
{
int ret = 0;
XMEMSET(hash, 0, sizeof(HsHashes));
#ifndef NO_OLD_TLS
#ifndef NO_SHA
if (ret == 0)
ret = wc_InitSha(&hash->hashSha);
#endif
#ifndef NO_MD5
if (ret == 0)
wc_InitMd5(&hash->hashMd5);
#endif
#endif
#ifndef NO_SHA256
if (ret == 0)
ret = wc_InitSha256(&hash->hashSha256);
#endif
#ifdef WOLFSSL_SHA384
if (ret == 0)
ret = wc_InitSha384(&hash->hashSha384);
#endif
#ifdef WOLFSSL_SHA512
if (ret == 0)
ret = wc_InitSha512(&hash->hashSha512);
#endif
return ret;
}
static int HashUpdate(HsHashes* hash, const byte* input, int sz)
{
int ret = 0;
input -= HANDSHAKE_HEADER_SZ;
sz += HANDSHAKE_HEADER_SZ;
#ifndef NO_OLD_TLS
#ifndef NO_SHA
if (ret == 0)
ret = wc_ShaUpdate(&hash->hashSha, input, sz);
#endif
#ifndef NO_MD5
if (ret == 0)
wc_Md5Update(&hash->hashMd5, input, sz);
#endif
#endif
#ifndef NO_SHA256
if (ret == 0)
ret = wc_Sha256Update(&hash->hashSha256, input, sz);
#endif
#ifdef WOLFSSL_SHA384
if (ret == 0)
ret = wc_Sha384Update(&hash->hashSha384, input, sz);
#endif
#ifdef WOLFSSL_SHA512
if (ret == 0)
ret = wc_Sha512Update(&hash->hashSha512, input, sz);
#endif
return ret;
}
static int HashCopy(HS_Hashes* d, HsHashes* s)
{
#ifndef NO_OLD_TLS
#ifndef NO_SHA
XMEMCPY(&d->hashSha, &s->hashSha, sizeof(Sha));
#endif
#ifndef NO_MD5
XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(Md5));
#endif
#endif
#ifndef NO_SHA256
XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(Sha256));
#endif
#ifdef WOLFSSL_SHA384
XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(Sha384));
#endif
#ifdef WOLFSSL_SHA512
XMEMCPY(&d->hashSha512, &s->hashSha512, sizeof(Sha512));
#endif
return 0;
}
#endif
/* Initialize a SnifferServer */
static void InitSnifferServer(SnifferServer* sniffer)
{
@ -563,6 +690,9 @@ static void InitFlags(Flags* flags)
flags->srvAckFault = 0;
flags->cliSkipPartial = 0;
flags->srvSkipPartial = 0;
#ifdef HAVE_EXTENDED_MASTER
flags->expectEms = 0;
#endif
}
@ -600,6 +730,9 @@ static void InitSession(SnifferSession* session)
InitFlags(&session->flags);
InitFinCapture(&session->finCaputre);
#ifdef HAVE_EXTENDED_MASTER
session->hash = 0;
#endif
}
@ -1483,13 +1616,17 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
/* Process Server Hello */
static int ProcessServerHello(const byte* input, int* sslBytes,
static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
SnifferSession* session, char* error)
{
ProtocolVersion pv;
byte b;
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
int doResume = 0;
int initialBytes = *sslBytes;
(void)msgSz;
(void)initialBytes;
/* make sure we didn't miss ClientHello */
if (session->flags.clientHello == 0) {
@ -1548,6 +1685,62 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
return -1;
}
#ifdef HAVE_EXTENDED_MASTER
/* extensions */
if ((initialBytes - *sslBytes) < msgSz) {
word16 len;
/* skip extensions until extended master secret */
/* make sure can read len */
if (SUITE_LEN > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
len = (word16)((input[0] << 8) | input[1]);
input += SUITE_LEN;
*sslBytes -= SUITE_LEN;
/* make sure can read through all extensions */
if (len > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
byte extType[EXT_TYPE_SZ];
word16 extLen;
extType[0] = input[0];
extType[1] = input[1];
input += EXT_TYPE_SZ;
*sslBytes -= EXT_TYPE_SZ;
extLen = (word16)((input[0] << 8) | input[1]);
input += LENGTH_SZ;
*sslBytes -= LENGTH_SZ;
/* make sure can read through individual extension */
if (extLen > *sslBytes) {
SetError(SERVER_HELLO_INPUT_STR, error, session,
FATAL_ERROR_STATE);
return -1;
}
if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
session->flags.expectEms = 1;
}
input += extLen;
*sslBytes -= extLen;
len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
}
}
if (!session->flags.expectEms) {
free(session->hash);
session->hash = NULL;
}
#endif
if (session->sslServer->options.haveSessionId &&
XMEMCMP(session->sslServer->arrays->sessionID,
session->sslClient->arrays->sessionID, ID_LEN) == 0)
@ -1758,7 +1951,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
return -1;
}
while (len > EXT_TYPE_SZ + LENGTH_SZ) {
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
byte extType[EXT_TYPE_SZ];
word16 extLen;
@ -1883,6 +2076,11 @@ static int DoHandShake(const byte* input, int* sslBytes,
return -1;
}
#ifdef HAVE_EXTENDED_MASTER
if (session->hash)
HashUpdate(session->hash, input, size);
#endif
switch (type) {
case hello_verify_request:
Trace(GOT_HELLO_VERIFY_STR);
@ -1896,7 +2094,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
break;
case server_hello:
Trace(GOT_SERVER_HELLO_STR);
ret = ProcessServerHello(input, sslBytes, session, error);
ret = ProcessServerHello(size, input, sslBytes, session, error);
break;
case certificate_request:
Trace(GOT_CERT_REQ_STR);
@ -1923,6 +2121,16 @@ static int DoHandShake(const byte* input, int* sslBytes,
break;
case client_key_exchange:
Trace(GOT_CLIENT_KEY_EX_STR);
#ifdef HAVE_EXTENDED_MASTER
if (session->flags.expectEms && session->hash != NULL) {
HashCopy(session->sslServer->hsHashes, session->hash);
HashCopy(session->sslClient->hsHashes, session->hash);
session->sslServer->options.haveEMS = 1;
session->sslClient->options.haveEMS = 1;
free(session->hash);
session->hash = NULL;
}
#endif
ret = ProcessClientKeyExchange(input, sslBytes, session, error);
break;
case certificate_verify:
@ -2135,6 +2343,18 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
return 0;
}
InitSession(session);
#ifdef HAVE_EXTENDED_MASTER
{
HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
if (newHash == NULL) {
SetError(MEMORY_STR, error, NULL, 0);
free(session);
return 0;
}
HashInit(newHash);
session->hash = newHash;
}
#endif
session->server = ipInfo->dst;
session->client = ipInfo->src;
session->srvPort = (word16)tcpInfo->dstPort;