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 */
|
EXT_TYPE_SZ = 2, /* Extension length */
|
||||||
MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
|
MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
|
||||||
MTU_EXTRA, /* Max input sz of reassembly */
|
MTU_EXTRA, /* Max input sz of reassembly */
|
||||||
|
EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */
|
||||||
TICKET_EXT_ID = 0x23 /* Session Ticket 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 srvAckFault; /* server acked unseen data from client */
|
||||||
byte cliSkipPartial; /* client skips partial data to catch up */
|
byte cliSkipPartial; /* client skips partial data to catch up */
|
||||||
byte srvSkipPartial; /* server 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;
|
} Flags;
|
||||||
|
|
||||||
|
|
||||||
@@ -341,6 +345,27 @@ typedef struct FinCaputre {
|
|||||||
} 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 */
|
/* Sniffer Session holds info for each client/server SSL/TLS session */
|
||||||
typedef struct SnifferSession {
|
typedef struct SnifferSession {
|
||||||
SnifferServer* context; /* server context */
|
SnifferServer* context; /* server context */
|
||||||
@@ -363,6 +388,9 @@ typedef struct SnifferSession {
|
|||||||
word32 srvReassemblyMemory; /* server packet memory used */
|
word32 srvReassemblyMemory; /* server packet memory used */
|
||||||
struct SnifferSession* next; /* for hash table list */
|
struct SnifferSession* next; /* for hash table list */
|
||||||
byte* ticketID; /* mac ID of session ticket */
|
byte* ticketID; /* mac ID of session ticket */
|
||||||
|
#ifdef HAVE_EXTENDED_MASTER
|
||||||
|
HsHashes* hash;
|
||||||
|
#endif
|
||||||
} SnifferSession;
|
} SnifferSession;
|
||||||
|
|
||||||
|
|
||||||
@@ -483,6 +511,9 @@ static void FreeSnifferSession(SnifferSession* session)
|
|||||||
FreePacketList(session->srvReassemblyList);
|
FreePacketList(session->srvReassemblyList);
|
||||||
|
|
||||||
free(session->ticketID);
|
free(session->ticketID);
|
||||||
|
#ifdef HAVE_EXTENDED_MASTER
|
||||||
|
free(session->hash);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
free(session);
|
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 */
|
/* Initialize a SnifferServer */
|
||||||
static void InitSnifferServer(SnifferServer* sniffer)
|
static void InitSnifferServer(SnifferServer* sniffer)
|
||||||
{
|
{
|
||||||
@@ -563,6 +690,9 @@ static void InitFlags(Flags* flags)
|
|||||||
flags->srvAckFault = 0;
|
flags->srvAckFault = 0;
|
||||||
flags->cliSkipPartial = 0;
|
flags->cliSkipPartial = 0;
|
||||||
flags->srvSkipPartial = 0;
|
flags->srvSkipPartial = 0;
|
||||||
|
#ifdef HAVE_EXTENDED_MASTER
|
||||||
|
flags->expectEms = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -600,6 +730,9 @@ static void InitSession(SnifferSession* session)
|
|||||||
|
|
||||||
InitFlags(&session->flags);
|
InitFlags(&session->flags);
|
||||||
InitFinCapture(&session->finCaputre);
|
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 */
|
/* 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)
|
SnifferSession* session, char* error)
|
||||||
{
|
{
|
||||||
ProtocolVersion pv;
|
ProtocolVersion pv;
|
||||||
byte b;
|
byte b;
|
||||||
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
|
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
|
||||||
int doResume = 0;
|
int doResume = 0;
|
||||||
|
int initialBytes = *sslBytes;
|
||||||
|
|
||||||
|
(void)msgSz;
|
||||||
|
(void)initialBytes;
|
||||||
|
|
||||||
/* make sure we didn't miss ClientHello */
|
/* make sure we didn't miss ClientHello */
|
||||||
if (session->flags.clientHello == 0) {
|
if (session->flags.clientHello == 0) {
|
||||||
@@ -1548,6 +1685,62 @@ static int ProcessServerHello(const byte* input, int* sslBytes,
|
|||||||
return -1;
|
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 &&
|
if (session->sslServer->options.haveSessionId &&
|
||||||
XMEMCMP(session->sslServer->arrays->sessionID,
|
XMEMCMP(session->sslServer->arrays->sessionID,
|
||||||
session->sslClient->arrays->sessionID, ID_LEN) == 0)
|
session->sslClient->arrays->sessionID, ID_LEN) == 0)
|
||||||
@@ -1758,7 +1951,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len > EXT_TYPE_SZ + LENGTH_SZ) {
|
while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
|
||||||
byte extType[EXT_TYPE_SZ];
|
byte extType[EXT_TYPE_SZ];
|
||||||
word16 extLen;
|
word16 extLen;
|
||||||
|
|
||||||
@@ -1883,6 +2076,11 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_EXTENDED_MASTER
|
||||||
|
if (session->hash)
|
||||||
|
HashUpdate(session->hash, input, size);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case hello_verify_request:
|
case hello_verify_request:
|
||||||
Trace(GOT_HELLO_VERIFY_STR);
|
Trace(GOT_HELLO_VERIFY_STR);
|
||||||
@@ -1896,7 +2094,7 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||||||
break;
|
break;
|
||||||
case server_hello:
|
case server_hello:
|
||||||
Trace(GOT_SERVER_HELLO_STR);
|
Trace(GOT_SERVER_HELLO_STR);
|
||||||
ret = ProcessServerHello(input, sslBytes, session, error);
|
ret = ProcessServerHello(size, input, sslBytes, session, error);
|
||||||
break;
|
break;
|
||||||
case certificate_request:
|
case certificate_request:
|
||||||
Trace(GOT_CERT_REQ_STR);
|
Trace(GOT_CERT_REQ_STR);
|
||||||
@@ -1923,6 +2121,16 @@ static int DoHandShake(const byte* input, int* sslBytes,
|
|||||||
break;
|
break;
|
||||||
case client_key_exchange:
|
case client_key_exchange:
|
||||||
Trace(GOT_CLIENT_KEY_EX_STR);
|
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);
|
ret = ProcessClientKeyExchange(input, sslBytes, session, error);
|
||||||
break;
|
break;
|
||||||
case certificate_verify:
|
case certificate_verify:
|
||||||
@@ -2135,6 +2343,18 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
InitSession(session);
|
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->server = ipInfo->dst;
|
||||||
session->client = ipInfo->src;
|
session->client = ipInfo->src;
|
||||||
session->srvPort = (word16)tcpInfo->dstPort;
|
session->srvPort = (word16)tcpInfo->dstPort;
|
||||||
|
Reference in New Issue
Block a user