forked from wolfSSL/wolfssl
Added support for the extended master secret extension to the sniffer.
This commit is contained in:
226
src/sniffer.c
226
src/sniffer.c
@ -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;
|
||||
|
Reference in New Issue
Block a user