From 743a6ab829bb758821b6cb5d7665310c598a229b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 11 Jul 2019 10:28:04 -0500 Subject: [PATCH 01/30] Update the decrypted packet and byte counts. --- src/sniffer.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/sniffer.c b/src/sniffer.c index 194b78554..44c14be25 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3763,6 +3763,12 @@ doMessage: SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } +#ifdef WOLFSSL_SNIFFER_STATS + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); + UNLOCK_STAT(); +#endif sslFrame = DecryptMessage(ssl, sslFrame, rhSize, ssl->buffers.outputBuffer.buffer, &errCode, &ivAdvance); From 87a8447f0d0873ecb624e500a11494e5d062d6cc Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 11 Jul 2019 17:28:21 -0500 Subject: [PATCH 02/30] 1. Added a tag for global variables in environments where they aren't shared across threads by default. 2. Set the Trace file and flag up with the shared flag. --- src/sniffer.c | 17 ++++++++++------- tests/api.c | 2 ++ wolfssl/wolfcrypt/wc_port.h | 9 +++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 44c14be25..d82516182 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -129,8 +129,8 @@ BOOL APIENTRY DllMain( HMODULE hModule, #endif /* _WIN32 */ -static int TraceOn = 0; /* Trace is off by default */ -static FILE* TraceFile = 0; +static WOLFSSL_SHARED int TraceOn = 0; /* Trace is off by default */ +static WOLFSSL_SHARED FILE* TraceFile = 0; /* windows uses .rc table for this */ @@ -4077,12 +4077,15 @@ int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error) int ssl_Trace(const char* traceFile, char* error) { if (traceFile) { - TraceFile = fopen(traceFile, "a"); - if (!TraceFile) { - SetError(BAD_TRACE_FILE_STR, error, NULL, 0); - return -1; + /* Don't try to reopen the file */ + if (TraceFile == NULL) { + TraceFile = fopen(traceFile, "a"); + if (!TraceFile) { + SetError(BAD_TRACE_FILE_STR, error, NULL, 0); + return -1; + } + TraceOn = 1; } - TraceOn = 1; } else TraceOn = 0; diff --git a/tests/api.c b/tests/api.c index ab95d98a4..f966bf207 100644 --- a/tests/api.c +++ b/tests/api.c @@ -18548,6 +18548,7 @@ static void test_wc_PemToDer(void) if (cert_buf) free(cert_buf); + printf(resultFmt, passed); #endif } @@ -18564,6 +18565,7 @@ static void test_wc_AllocDer(void) AssertIntEQ(ret, 0); AssertNotNull(pDer); wc_FreeDer(&pDer); + printf(resultFmt, passed); #endif } diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 680e3a6d8..e9af1a756 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -720,6 +720,15 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); will use dynamic buffer if not big enough */ #endif +#ifdef HAVE_CAVIUM_OCTEON + /* By default, the OCTEON's global variables are all thread local. This + * tag allows them to be shared between threads. */ + #include "cvmx-platform.h" + #define WOLFSSL_SHARED CVMX_SHARED +#else + #define WOLFSSL_SHARED +#endif + #ifdef __cplusplus } /* extern "C" */ From a991cc42f4cefb32044b893e4b5d1cacb5a2e071 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 10 Jul 2019 15:29:35 -0500 Subject: [PATCH 03/30] Add function wolfSSL_get_cipher_name_iana_from_suite() a wrapper around internal API GetCipherNameIana(). --- src/ssl.c | 6 ++++++ tests/api.c | 7 ++++++- wolfssl/ssl.h | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/ssl.c b/src/ssl.c index 77fd26684..6bdec2214 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -19221,6 +19221,12 @@ const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, return GetCipherNameInternal(cipherSuite0, cipherSuite); } +const char* wolfSSL_get_cipher_name_iana_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameIana(cipherSuite0, cipherSuite); +} + word32 wolfSSL_CIPHER_get_id(const WOLFSSL_CIPHER* cipher) { word16 cipher_id = 0; diff --git a/tests/api.c b/tests/api.c index f966bf207..665eb19d3 100644 --- a/tests/api.c +++ b/tests/api.c @@ -2574,11 +2574,16 @@ static void test_client_nofail(void* args, void *cb) /* IANA Cipher Suites Names */ /* Unless WOLFSSL_CIPHER_INTERNALNAME or NO_ERROR_STRINGS, - then its the internal cipher suite name */ + then it's the internal cipher suite name */ cipher = wolfSSL_get_current_cipher(ssl); cipherName1 = wolfSSL_CIPHER_get_name(cipher); cipherName2 = wolfSSL_get_cipher(ssl); AssertStrEQ(cipherName1, cipherName2); +#if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) + cipherName1 = wolfSSL_get_cipher_name_iana_from_suite( + (cipherSuite >> 8), cipherSuite & 0xFF); + AssertStrEQ(cipherName1, cipherName2); +#endif if (cb != NULL) ((cbType)cb)(ctx, ssl); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 3b66a279b..744cc8131 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -815,6 +815,8 @@ WOLFSSL_API int wolfSSL_get_ciphers_iana(char*, int); WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, const unsigned char); +WOLFSSL_API const char* wolfSSL_get_cipher_name_iana_from_suite( + const unsigned char, const unsigned char); WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len); WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); From bbc208ad336335de2a0316041b36f177599e394d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 11 Jul 2019 17:39:54 -0500 Subject: [PATCH 04/30] Updated some more globals in the sniffer and session cache with being shared. --- src/sniffer.c | 32 +++++++++++++++++--------------- src/ssl.c | 9 +++++---- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index d82516182..8931b5310 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -404,35 +404,37 @@ typedef struct SnifferSession { /* Sniffer Server List and mutex */ -static SnifferServer* ServerList = 0; -static wolfSSL_Mutex ServerListMutex; +static WOLFSSL_SHARED SnifferServer* ServerList = 0; +static WOLFSSL_SHARED wolfSSL_Mutex ServerListMutex; /* Session Hash Table, mutex, and count */ -static SnifferSession* SessionTable[HASH_SIZE]; -static wolfSSL_Mutex SessionMutex; -static int SessionCount = 0; +static WOLFSSL_SHARED SnifferSession* SessionTable[HASH_SIZE]; +static WOLFSSL_SHARED wolfSSL_Mutex SessionMutex; +static WOLFSSL_SHARED int SessionCount = 0; /* Recovery of missed data switches and stats */ -static wolfSSL_Mutex RecoveryMutex; /* for stats */ -static int RecoveryEnabled = 0; /* global switch */ -static int MaxRecoveryMemory = -1; /* per session max recovery memory */ -static word32 MissedDataSessions = 0; /* # of sessions with missed data */ +static WOLFSSL_SHARED wolfSSL_Mutex RecoveryMutex; /* for stats */ +static WOLFSSL_SHARED int RecoveryEnabled = 0; /* global switch */ +static WOLFSSL_SHARED int MaxRecoveryMemory = -1; + /* per session max recovery memory */ +static WOLFSSL_SHARED word32 MissedDataSessions = 0; + /* # of sessions with missed data */ /* Connection Info Callback */ -static SSLConnCb ConnectionCb; -static void* ConnectionCbCtx = NULL; +static WOLFSSL_SHARED SSLConnCb ConnectionCb; +static WOLFSSL_SHARED void* ConnectionCbCtx = NULL; #ifdef WOLFSSL_SNIFFER_STATS /* Sessions Statistics */ -static SSLStats SnifferStats; -static wolfSSL_Mutex StatsMutex; +static WOLFSSL_SHARED SSLStats SnifferStats; +static WOLFSSL_SHARED wolfSSL_Mutex StatsMutex; #endif #ifdef WOLFSSL_SNIFFER_WATCH /* Watch Key Callback */ -static SSLWatchCb WatchCb; -static void* WatchCbCtx = NULL; +static WOLFSSL_SHARED SSLWatchCb WatchCb; +static WOLFSSL_SHARED void* WatchCbCtx = NULL; #endif diff --git a/src/ssl.c b/src/ssl.c index 6bdec2214..6c190dfdd 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4658,13 +4658,13 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; } SessionRow; - static SessionRow SessionCache[SESSION_ROWS]; + static WOLFSSL_SHARED SessionRow SessionCache[SESSION_ROWS]; #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - static word32 PeakSessions; + static WOLFSSL_SHARED word32 PeakSessions; #endif - static wolfSSL_Mutex session_mutex; /* SessionCache mutex */ + static WOLFSSL_SHARED wolfSSL_Mutex session_mutex; /* SessionCache mutex */ #ifndef NO_CLIENT_CACHE @@ -4679,7 +4679,8 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) ClientSession Clients[SESSIONS_PER_ROW]; } ClientRow; - static ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */ + static WOLFSSL_SHARED ClientRow ClientCache[SESSION_ROWS]; + /* Client Cache */ /* uses session mutex */ #endif /* NO_CLIENT_CACHE */ From 4292936efc8921a2584e3b20fc499277593a6a93 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 17 Jul 2019 15:21:09 -0700 Subject: [PATCH 05/30] wolfSSL Global 1. Renamed the global variable tag to WOLFSSL_GLOBAL. 2. Tagged several more global variables with WOLFSSL_GLOBAL. --- src/internal.c | 4 ++-- src/sniffer.c | 34 +++++++++++++++++----------------- src/ssl.c | 12 ++++++------ wolfssl/wolfcrypt/wc_port.h | 4 ++-- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/internal.c b/src/internal.c index cf2d88bee..f0f86619d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -325,8 +325,8 @@ static int QSH_FreeAll(WOLFSSL* ssl) #ifdef HAVE_NTRU -static WC_RNG* rng; -static wolfSSL_Mutex* rngMutex; +static WOLFSSL_GLOBAL WC_RNG* rng; +static WOLFSSL_GLOBAL wolfSSL_Mutex* rngMutex; static word32 GetEntropy(unsigned char* out, word32 num_bytes) { diff --git a/src/sniffer.c b/src/sniffer.c index 8931b5310..52c9dfc07 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -129,8 +129,8 @@ BOOL APIENTRY DllMain( HMODULE hModule, #endif /* _WIN32 */ -static WOLFSSL_SHARED int TraceOn = 0; /* Trace is off by default */ -static WOLFSSL_SHARED FILE* TraceFile = 0; +static WOLFSSL_GLOBAL int TraceOn = 0; /* Trace is off by default */ +static WOLFSSL_GLOBAL FILE* TraceFile = 0; /* windows uses .rc table for this */ @@ -404,37 +404,37 @@ typedef struct SnifferSession { /* Sniffer Server List and mutex */ -static WOLFSSL_SHARED SnifferServer* ServerList = 0; -static WOLFSSL_SHARED wolfSSL_Mutex ServerListMutex; +static WOLFSSL_GLOBAL SnifferServer* ServerList = 0; +static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex; /* Session Hash Table, mutex, and count */ -static WOLFSSL_SHARED SnifferSession* SessionTable[HASH_SIZE]; -static WOLFSSL_SHARED wolfSSL_Mutex SessionMutex; -static WOLFSSL_SHARED int SessionCount = 0; +static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE]; +static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex; +static WOLFSSL_GLOBAL int SessionCount = 0; /* Recovery of missed data switches and stats */ -static WOLFSSL_SHARED wolfSSL_Mutex RecoveryMutex; /* for stats */ -static WOLFSSL_SHARED int RecoveryEnabled = 0; /* global switch */ -static WOLFSSL_SHARED int MaxRecoveryMemory = -1; +static WOLFSSL_GLOBAL wolfSSL_Mutex RecoveryMutex; /* for stats */ +static WOLFSSL_GLOBAL int RecoveryEnabled = 0; /* global switch */ +static WOLFSSL_GLOBAL int MaxRecoveryMemory = -1; /* per session max recovery memory */ -static WOLFSSL_SHARED word32 MissedDataSessions = 0; +static WOLFSSL_GLOBAL word32 MissedDataSessions = 0; /* # of sessions with missed data */ /* Connection Info Callback */ -static WOLFSSL_SHARED SSLConnCb ConnectionCb; -static WOLFSSL_SHARED void* ConnectionCbCtx = NULL; +static WOLFSSL_GLOBAL SSLConnCb ConnectionCb; +static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL; #ifdef WOLFSSL_SNIFFER_STATS /* Sessions Statistics */ -static WOLFSSL_SHARED SSLStats SnifferStats; -static WOLFSSL_SHARED wolfSSL_Mutex StatsMutex; +static WOLFSSL_GLOBAL SSLStats SnifferStats; +static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex; #endif #ifdef WOLFSSL_SNIFFER_WATCH /* Watch Key Callback */ -static WOLFSSL_SHARED SSLWatchCb WatchCb; -static WOLFSSL_SHARED void* WatchCbCtx = NULL; +static WOLFSSL_GLOBAL SSLWatchCb WatchCb; +static WOLFSSL_GLOBAL void* WatchCbCtx = NULL; #endif diff --git a/src/ssl.c b/src/ssl.c index 6c190dfdd..f07d97001 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -292,8 +292,8 @@ int wolfSSL_send_session(WOLFSSL* ssl) /* prevent multiple mutex initializations */ -static volatile int initRefCount = 0; -static wolfSSL_Mutex count_mutex; /* init ref count mutex */ +static volatile WOLFSSL_GLOBAL int initRefCount = 0; +static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */ /* Create a new WOLFSSL_CTX struct and return the pointer to created struct. WOLFSSL_METHOD pointer passed in is given to ctx to manage. @@ -4658,13 +4658,13 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; } SessionRow; - static WOLFSSL_SHARED SessionRow SessionCache[SESSION_ROWS]; + static WOLFSSL_GLOBAL SessionRow SessionCache[SESSION_ROWS]; #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - static WOLFSSL_SHARED word32 PeakSessions; + static WOLFSSL_GLOBAL word32 PeakSessions; #endif - static WOLFSSL_SHARED wolfSSL_Mutex session_mutex; /* SessionCache mutex */ + static WOLFSSL_GLOBAL wolfSSL_Mutex session_mutex; /* SessionCache mutex */ #ifndef NO_CLIENT_CACHE @@ -4679,7 +4679,7 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) ClientSession Clients[SESSIONS_PER_ROW]; } ClientRow; - static WOLFSSL_SHARED ClientRow ClientCache[SESSION_ROWS]; + static WOLFSSL_GLOBAL ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */ /* uses session mutex */ #endif /* NO_CLIENT_CACHE */ diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index e9af1a756..28a840463 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -724,9 +724,9 @@ WOLFSSL_API int wolfCrypt_Cleanup(void); /* By default, the OCTEON's global variables are all thread local. This * tag allows them to be shared between threads. */ #include "cvmx-platform.h" - #define WOLFSSL_SHARED CVMX_SHARED + #define WOLFSSL_GLOBAL CVMX_SHARED #else - #define WOLFSSL_SHARED + #define WOLFSSL_GLOBAL #endif From 0e1073f622c52c10f859b812506e807bd8ad1bfb Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 17 Jul 2019 16:08:23 -0700 Subject: [PATCH 06/30] Sniffer Statistics Addded two more statistics, cache hits and cache inserts. --- src/sniffer.c | 7 ++++++- wolfssl/sniffer.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/sniffer.c b/src/sniffer.c index 52c9dfc07..1f2c44479 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2125,6 +2125,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, Trace(SERVER_DID_RESUMPTION_STR); #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslResumedConns); + INC_STAT(SnifferStats.sslResumptionValid); #endif if (SetCipherSpecs(session->sslServer) != 0) { SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); @@ -2464,8 +2465,12 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, if (ret == 0 && session->flags.cached == 0) { if (session->sslServer->options.haveSessionId) { WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); - if (sess == NULL) + if (sess == NULL) { AddSession(session->sslServer); /* don't re add */ +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumptionInserts); +#endif + } session->flags.cached = 1; } } diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index bf2306e11..fedab6c06 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -152,6 +152,9 @@ typedef struct SSLStats unsigned long int sslDecryptedPackets; unsigned long int sslKeyMatches; unsigned long int sslEncryptedConns; + + unsigned long int sslResumptionValid; + unsigned long int sslResumptionInserts; } SSLStats; From 73273f4fec2badf9a8820d0cbfa0bedeb27825b7 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 14 Aug 2019 10:02:33 -0700 Subject: [PATCH 07/30] Sniffer Memory 1. Modify the sniffer code to use XMALLOC and XFREE. 2. Added some new dynamic memory types for the sniffer. --- src/sniffer.c | 75 +++++++++++++++++++++------------------ wolfssl/wolfcrypt/types.h | 6 ++++ 2 files changed, 47 insertions(+), 34 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 1f2c44479..4c71564ae 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -508,9 +508,9 @@ static void FreeNamedKey(NamedKey* in) if (in) { if (in->key) { ForceZero(in->key, in->keySz); - free(in->key); + XFREE(in->key, NULL, DYNAMIC_TYPE_X509); } - free(in); + XFREE(in, NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY); } } @@ -541,7 +541,7 @@ static void FreeSnifferServer(SnifferServer* srv) #endif SSL_CTX_free(srv->ctx); } - free(srv); + XFREE(srv, NULL, DYNAMIC_TYPE_SNIFFER_SERVER); } @@ -549,8 +549,8 @@ static void FreeSnifferServer(SnifferServer* srv) static void FreePacketBuffer(PacketBuffer* del) { if (del) { - free(del->data); - free(del); + XFREE(del->data, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER); + XFREE(del, NULL, DYNAMIC_TYPE_SNIFFER_PB); } } @@ -581,12 +581,12 @@ static void FreeSnifferSession(SnifferSession* session) FreePacketList(session->cliReassemblyList); FreePacketList(session->srvReassemblyList); - free(session->ticketID); + XFREE(session->ticketID, NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); #ifdef HAVE_EXTENDED_MASTER - free(session->hash); + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); #endif } - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); } @@ -1311,7 +1311,7 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, fileSz = XFTELL(file); XREWIND(file); - loadBuf = (byte*)malloc(fileSz); + loadBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_FILE); if (loadBuf == NULL) { XFCLOSE(file); return -1; @@ -1321,12 +1321,12 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, XFCLOSE(file); if (ret != fileSz) { - free(loadBuf); + XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE); return -1; } if (typeKey == WOLFSSL_FILETYPE_PEM) { - byte* saveBuf = (byte*)malloc(fileSz); + byte* saveBuf = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_X509); int saveBufSz = 0; ret = -1; @@ -1335,7 +1335,7 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, saveBuf, (int)fileSz, password); if (saveBufSz < 0) { saveBufSz = 0; - free(saveBuf); + XFREE(saveBuf, NULL, DYNAMIC_TYPE_X509); saveBuf = NULL; } else @@ -1343,7 +1343,7 @@ static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, } ForceZero(loadBuf, (word32)fileSz); - free(loadBuf); + XFREE(loadBuf, NULL, DYNAMIC_TYPE_FILE); if (saveBuf) { *keyBuf = saveBuf; @@ -1371,7 +1371,7 @@ static int CreateWatchSnifferServer(char* error) { SnifferServer* sniffer; - sniffer = (SnifferServer*)malloc(sizeof(SnifferServer)); + sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL, DYNAMIC_TYPE_SNIFFER_SERVER); if (sniffer == NULL) { SetError(MEMORY_STR, error, NULL, 0); return -1; @@ -1411,7 +1411,8 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, (void)name; #ifdef HAVE_SNI if (name != NULL) { - namedKey = (NamedKey*)malloc(sizeof(NamedKey)); + namedKey = (NamedKey*)XMALLOC(sizeof(NamedKey), + NULL, DYNAMIC_TYPE_SNIFFER_NAMED_KEY); if (namedKey == NULL) { SetError(MEMORY_STR, error, NULL, 0); return -1; @@ -1443,7 +1444,8 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, if (sniffer == NULL) { isNew = 1; - sniffer = (SnifferServer*)malloc(sizeof(SnifferServer)); + sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), + NULL, DYNAMIC_TYPE_SNIFFER_SERVER); if (sniffer == NULL) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -2082,7 +2084,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } if (!session->flags.expectEms) { - free(session->hash); + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); session->hash = NULL; } #endif @@ -2343,7 +2345,8 @@ static int ProcessClientHello(const byte* input, int* sslBytes, if (extLen) { if (session->ticketID == 0) { - session->ticketID = (byte*)malloc(ID_LEN); + session->ticketID = (byte*)XMALLOC(ID_LEN, + NULL, DYNAMIC_TYPE_SNIFFER_TICKET_ID); if (session->ticketID == 0) { SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); @@ -2597,7 +2600,7 @@ static int DoHandShake(const byte* input, int* sslBytes, ret = -1; } XMEMSET(session->hash, 0, sizeof(HsHashes)); - free(session->hash); + XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); session->hash = NULL; } else { @@ -2825,7 +2828,8 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, Trace(NEW_SESSION_STR); /* create a new one */ - session = (SnifferSession*)malloc(sizeof(SnifferSession)); + session = (SnifferSession*)XMALLOC(sizeof(SnifferSession), + NULL, DYNAMIC_TYPE_SNIFFER_SESSION); if (session == NULL) { SetError(MEMORY_STR, error, NULL, 0); return 0; @@ -2833,15 +2837,16 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, InitSession(session); #ifdef HAVE_EXTENDED_MASTER { - HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes)); + HsHashes* newHash = (HsHashes*)XMALLOC(sizeof(HsHashes), + NULL, DYNAMIC_TYPE_HASHES); if (newHash == NULL) { SetError(MEMORY_STR, error, NULL, 0); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } if (HashInit(newHash) != 0) { SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } session->hash = newHash; @@ -2862,14 +2867,14 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } session->sslServer = SSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } session->sslClient = SSL_new(session->context->ctx); @@ -2878,7 +2883,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->sslServer = 0; SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); - free(session); + XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); return 0; } /* put server back into server mode */ @@ -3102,16 +3107,17 @@ static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data, int added = end - *begin + 1; assert(*begin <= end); - pb = (PacketBuffer*)malloc(sizeof(PacketBuffer)); + pb = (PacketBuffer*)XMALLOC(sizeof(PacketBuffer), + NULL, DYNAMIC_TYPE_SNIFFER_PB); if (pb == NULL) return NULL; pb->next = 0; pb->begin = *begin; pb->end = end; - pb->data = (byte*)malloc(added); + pb->data = (byte*)XMALLOC(added, NULL, DYNAMIC_TYPE_SNIFFER_PB_BUFFER); if (pb->data == NULL) { - free(pb); + XFREE(pb, NULL, DYNAMIC_TYPE_SNIFFER_PB); return NULL; } XMEMCPY(pb->data, data, added); @@ -3838,10 +3844,11 @@ doPart: byte* tmpData; /* don't leak on realloc free */ /* add an extra byte at end of allocation in case user * wants to null terminate plaintext */ - tmpData = (byte*)realloc(*data, decoded + ret + 1); + tmpData = (byte*)XREALLOC(*data, decoded + ret + 1, + NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmpData == NULL) { ForceZero(*data, decoded); - free(*data); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); *data = NULL; SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); @@ -4071,7 +4078,7 @@ int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error) if (data != NULL) { ForceZero(*data, (word32)sz); - free(*data); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); *data = NULL; } @@ -4288,13 +4295,13 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, keyType, password); if (ret < 0) { SetError(KEY_FILE_STR, error, NULL, 0); - free(keyBuf); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); return -1; } ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER, error); - free(keyBuf); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); return ret; } diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 7820f9214..7c8cc1d7d 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -620,6 +620,12 @@ DYNAMIC_TYPE_HASH_TMP = 88, DYNAMIC_TYPE_BLOB = 89, DYNAMIC_TYPE_NAME_ENTRY = 90, + DYNAMIC_TYPE_SNIFFER_SERVER = 1000, + DYNAMIC_TYPE_SNIFFER_SESSION = 1001, + DYNAMIC_TYPE_SNIFFER_PB = 1002, + DYNAMIC_TYPE_SNIFFER_PB_BUFFER = 1003, + DYNAMIC_TYPE_SNIFFER_TICKET_ID = 1004, + DYNAMIC_TYPE_SNIFFER_NAMED_KEY = 1005, }; /* max error buffer string size */ From a0ad39cf70a86830e947285e3fc7093b26c6aaa9 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 15 Aug 2019 12:25:34 -0700 Subject: [PATCH 08/30] Sniffer Stats Moved the increment of the resume misses statistic. --- src/sniffer.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 4c71564ae..f332ef8fc 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2093,11 +2093,6 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, if (XMEMCMP(session->sslServer->arrays->sessionID, session->sslClient->arrays->sessionID, ID_LEN) == 0) doResume = 1; - else if (session->sslClient->options.haveSessionId) { -#ifdef WOLFSSL_SNIFFER_STATS - INC_STAT(SnifferStats.sslResumeMisses); -#endif - } } else if (session->sslClient->options.haveSessionId == 0 && session->sslServer->options.haveSessionId == 0 && @@ -2116,6 +2111,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, SSL_SESSION* resume = GetSession(session->sslServer, session->sslServer->arrays->masterSecret, 0); if (resume == NULL) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumeMisses); +#endif SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); return -1; } From 98e94a6f0f54ebd7d597e2e5e4ec1d993d7507bb Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 19 Aug 2019 14:43:32 -0700 Subject: [PATCH 09/30] Added a preprocessor guard around ssl_GetSessionStats(). --- src/sniffer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sniffer.c b/src/sniffer.c index f332ef8fc..156f400fb 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -4123,6 +4123,8 @@ int ssl_EnableRecovery(int onOff, int maxMemory, char* error) +#ifdef WOLFSSL_SESSION_STATS + int ssl_GetSessionStats(unsigned int* active, unsigned int* total, unsigned int* peak, unsigned int* maxSessions, unsigned int* missedData, unsigned int* reassemblyMem, @@ -4163,6 +4165,8 @@ int ssl_GetSessionStats(unsigned int* active, unsigned int* total, } } +#endif + int ssl_SetConnectionCb(SSLConnCb cb) From 62ac388f55e3de526627c0ed0a4a3746c659c1dc Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 19 Aug 2019 15:33:43 -0700 Subject: [PATCH 10/30] Store Data Callback Added a callback and support to allow one to handle storing the data directly without reallocating the data buffer. Also added an example that uses this callback if the callback is enabled in the build. --- src/sniffer.c | 108 +++++++++++++++++++++----- sslSniffer/sslSnifferTest/snifftest.c | 44 +++++++++++ wolfssl/sniffer.h | 11 +++ wolfssl/sniffer_error.h | 4 + wolfssl/sniffer_error.rc | 4 + 5 files changed, 150 insertions(+), 21 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 156f400fb..8696c5945 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -261,7 +261,12 @@ static const char* const msgTable[] = "Watch callback not set", "Watch hash failed", "Watch callback failed", - "Bad Certificate Message" + "Bad Certificate Message", + "Store data callback not set", + + /* 91 */ + "No data destination Error", + "Store data callback failed" }; @@ -437,6 +442,11 @@ static WOLFSSL_GLOBAL SSLWatchCb WatchCb; static WOLFSSL_GLOBAL void* WatchCbCtx = NULL; #endif +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB +/* Store Data Callback */ +static WOLFSSL_GLOBAL SSLStoreDataCb StoreDataCb; +#endif + static void UpdateMissedDataSessions(void) { @@ -3707,7 +3717,7 @@ static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, /* return Number of bytes on success, 0 for no data yet, and -1 on error */ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, int sslBytes, byte** data, const byte* end, - char* error) + void* ctx, char* error) { const byte* sslBegin = sslFrame; const byte* recordEnd; /* end of record indicator */ @@ -3839,22 +3849,55 @@ doPart: ret = ssl->buffers.clearOutputBuffer.length; TraceGotData(ret); if (ret) { /* may be blank message */ - byte* tmpData; /* don't leak on realloc free */ - /* add an extra byte at end of allocation in case user - * wants to null terminate plaintext */ - tmpData = (byte*)XREALLOC(*data, decoded + ret + 1, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (tmpData == NULL) { - ForceZero(*data, decoded); - XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); - *data = NULL; - SetError(MEMORY_STR, error, session, - FATAL_ERROR_STATE); - return -1; + if (data != NULL) { + byte* tmpData; /* don't leak on realloc free */ + /* add an extra byte at end of allocation in case + * user wants to null terminate plaintext */ + tmpData = (byte*)XREALLOC(*data, decoded + ret + 1, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpData == NULL) { + ForceZero(*data, decoded); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *data = NULL; + SetError(MEMORY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + *data = tmpData; + XMEMCPY(*data + decoded, + ssl->buffers.clearOutputBuffer.buffer, ret); + } + else { +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + if (StoreDataCb) { + const byte* buf; + word32 offset = 0; + word32 bufSz; + int stored; + + buf = ssl->buffers.clearOutputBuffer.buffer; + bufSz = ssl->buffers.clearOutputBuffer.length; + do { + stored = StoreDataCb(buf, bufSz, offset, + ctx); + if (stored <= 0) { + return -1; + } + offset += stored; + } while (offset < bufSz); + } + else { + SetError(STORE_DATA_CB_MISSING_STR, error, + session, FATAL_ERROR_STATE); + return -1; + } +#else + (void)ctx; + SetError(NO_DATA_DEST_STR, error, session, + FATAL_ERROR_STATE); + return -1; +#endif } - *data = tmpData; - XMEMCPY(*data + decoded, - ssl->buffers.clearOutputBuffer.buffer, ret); TraceAddedData(ret, decoded); decoded += ret; ssl->buffers.clearOutputBuffer.length = 0; @@ -3965,7 +4008,8 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ /* returns Number of bytes on success, 0 for no data yet, and -1 on error */ static int ssl_DecodePacketInternal(const byte* packet, int length, - byte** data, SSLInfo* sslInfo, char* error) + byte** data, SSLInfo* sslInfo, + void* ctx, char* error) { TcpInfo tcpInfo; IpInfo ipInfo; @@ -4028,7 +4072,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, INC_STAT(SnifferStats.sslDecryptedPackets); #endif - ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error); + ret = ProcessMessage(sslFrame, session, sslBytes, data, end, ctx, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) { CopySessionInfo(session, sslInfo); @@ -4044,7 +4088,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, unsigned char** data, SSLInfo* sslInfo, char* error) { - return ssl_DecodePacketInternal(packet, length, data, sslInfo, error); + return ssl_DecodePacketInternal(packet, length, data, sslInfo, NULL, error); } @@ -4052,10 +4096,21 @@ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, /* returns Number of bytes on success, 0 for no data yet, and -1 on error */ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) { - return ssl_DecodePacketInternal(packet, length, data, NULL, error); + return ssl_DecodePacketInternal(packet, length, data, NULL, NULL, error); } +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, + int length, void* ctx, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(packet, length, NULL, sslInfo, ctx, error); +} + +#endif + + /* Deallocator for the decoded data buffer. */ /* returns 0 on success, -1 on error */ int ssl_FreeDecodeBuffer(byte** data, char* error) @@ -4310,5 +4365,16 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, #endif /* WOLFSSL_SNIFFER_WATCH */ + +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +int ssl_SetStoreDataCallback(SSLStoreDataCb cb) +{ + StoreDataCb = cb; + return 0; +} + +#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */ + #endif /* WOLFSSL_SNIFFER */ #endif /* WOLFCRYPT_ONLY */ diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 69757b7e4..67e942f03 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -214,6 +214,42 @@ static int myWatchCb(void* vSniffer, #endif +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + +static int myStoreDataCb(const unsigned char* decryptBuf, + unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx) +{ + byte** data = (byte**)ctx; + unsigned int qty; + + if (data == NULL) + return -1; + + if (decryptBufSz < decryptBufOffset) + return -1; + + qty = (decryptBufSz - decryptBufOffset) < 32 ? + (decryptBufSz - decryptBufOffset) : 32; + + if (*data == NULL) { + byte* tmpData; + tmpData = (byte*)realloc(*data, decryptBufSz + 1); + if (tmpData == NULL) { + free(*data); + *data = NULL; + return -1; + } + *data = tmpData; + } + + memcpy(*data + decryptBufOffset, decryptBuf + decryptBufOffset, qty); + + return qty; +} + +#endif + + int main(int argc, char** argv) { int ret = 0; @@ -240,6 +276,9 @@ int main(int argc, char** argv) #ifdef WOLFSSL_SNIFFER_WATCH ssl_SetWatchKeyCallback(myWatchCb, err); #endif +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + ssl_SetStoreDataCallback(myStoreDataCb); +#endif if (argc == 1) { /* normal case, user chooses device and port */ @@ -405,8 +444,13 @@ int main(int argc, char** argv) else continue; +#ifndef WOLFSSL_SNIFFER_STORE_DATA_CB ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data, &sslInfo, err); +#else + ret = ssl_DecodePacketWithSessionInfoStoreData(packet, + header.caplen, &data, &sslInfo, err); +#endif if (ret < 0) { printf("ssl_Decode ret = %d, %s\n", ret, err); hadBadPacket = 1; diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index fedab6c06..28e26ba4e 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -194,6 +194,17 @@ SSL_SNIFFER_API int ssl_SetWatchKey_file(void* vSniffer, const char* password, char* error); +typedef int (*SSLStoreDataCb)(const unsigned char* decryptBuf, + unsigned int decryptBufSz, unsigned int decryptBufOffset, void* ctx); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetStoreDataCallback(SSLStoreDataCb cb); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData( + const unsigned char* packet, int length, void* ctx, + SSLInfo* sslInfo, char* error); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index e3bc38b78..f3fe93ca4 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -125,6 +125,10 @@ #define WATCH_HASH_STR 87 #define WATCH_FAIL_STR 88 #define BAD_CERT_MSG_STR 89 +#define STORE_DATA_CB_MISSING_STR 90 + +#define NO_DATA_DEST_STR 91 +#define STORE_DATA_FAIL_STR 92 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/wolfssl/sniffer_error.rc b/wolfssl/sniffer_error.rc index 336cf33e8..31e1317cc 100644 --- a/wolfssl/sniffer_error.rc +++ b/wolfssl/sniffer_error.rc @@ -107,5 +107,9 @@ STRINGTABLE 87, "Watch hash failed" 88, "Watch callback failed" 89, "Bad Certificate Message" + 90, "Store data callback not set" + + 91, "No data destination Error" + 92, "Store Data callback failed" } From dea5e73852b6641bf404031c0f11a82f5d03b21d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 22 Aug 2019 15:57:27 -0700 Subject: [PATCH 11/30] Sniffer Chain Input Add a new method for handling input records where the input is in the form of an iovec list. --- src/sniffer.c | 97 +++++++++++++++++++++++++-- sslSniffer/sslSnifferTest/snifftest.c | 69 +++++++++++++++++-- wolfssl/sniffer.h | 11 +++ wolfssl/sniffer_error.h | 1 + wolfssl/sniffer_error.rc | 1 + 5 files changed, 166 insertions(+), 13 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 8696c5945..a4da757cd 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -266,7 +266,8 @@ static const char* const msgTable[] = /* 91 */ "No data destination Error", - "Store data callback failed" + "Store data callback failed", + "Loading chain input" }; @@ -3562,7 +3563,8 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, /* returns 0 on success (continue), -1 on error, 1 on success (end) */ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte** sslFrame, SnifferSession** session, - int* sslBytes, const byte** end, char* error) + int* sslBytes, const byte** end, + void* vChain, word32 chainSz, char* error) { word32 length; SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? @@ -3604,7 +3606,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ - if ( !skipPartial && + if ( !skipPartial && !vChain && (length = ssl->buffers.inputBuffer.length) ) { Trace(PARTIAL_ADD_STR); @@ -3621,6 +3623,44 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, *end = *sslFrame + *sslBytes; } + if (vChain != NULL) { +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + struct iovec* chain = (struct iovec*)vChain; + word32 i, offset, headerOffset, qty; + + Trace(CHAIN_INPUT_STR); + headerOffset = (word32)*sslFrame - (word32)chain[0].iov_base; + length = *sslBytes + headerOffset; + if (length > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, length, 0) < 0) { + SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + return -1; + } + } + + offset = 0; + for (i = 0; i < chainSz; i++) { + /* In case there is extra data in the chain that isn't covered + * by the sizes in the TCP headers, don't copy too much. This + * case has been seen where there are 4 extra bytes in the + * packet capture than the TCP header indicates. */ + if (offset + chain[i].iov_len > length) + qty = length - offset; + else + qty = (word32)chain[i].iov_len; + XMEMCPY(ssl->buffers.inputBuffer.buffer + offset, + chain[i].iov_base, qty); + offset += qty; + } + + ssl->buffers.inputBuffer.length = length; + *sslFrame = ssl->buffers.inputBuffer.buffer + headerOffset; + *end = *sslFrame + *sslBytes; +#else + (void)chainSz; +#endif + } + if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { /* Sanity check the packet for an old style client hello. */ int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]); @@ -3637,6 +3677,8 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, } else { #ifdef STARTTLS_ALLOWED + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); return 1; #endif } @@ -4008,6 +4050,7 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ /* returns Number of bytes on success, 0 for no data yet, and -1 on error */ static int ssl_DecodePacketInternal(const byte* packet, int length, + void* vChain, word32 chainSz, byte** data, SSLInfo* sslInfo, void* ctx, char* error) { @@ -4019,6 +4062,18 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int ret; SnifferSession* session = 0; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + if (packet == NULL && vChain != NULL) { + struct iovec* chain = (struct iovec*)vChain; + word32 i; + + length = 0; + for (i = 0; i < chainSz; i++) + length += chain[i].iov_len; + packet = (const byte*)chain[0].iov_base; + } +#endif + if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, error) != 0) return -1; @@ -4051,7 +4106,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, } ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, - &end, error); + &end, vChain, chainSz, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; else if (ret == 1) { @@ -4088,7 +4143,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, unsigned char** data, SSLInfo* sslInfo, char* error) { - return ssl_DecodePacketInternal(packet, length, data, sslInfo, NULL, error); + return ssl_DecodePacketInternal(packet, length, NULL, 0, data, sslInfo, + NULL, error); } @@ -4096,7 +4152,8 @@ int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, /* returns Number of bytes on success, 0 for no data yet, and -1 on error */ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) { - return ssl_DecodePacketInternal(packet, length, data, NULL, NULL, error); + return ssl_DecodePacketInternal(packet, length, NULL, 0, data, NULL, NULL, + error); } @@ -4105,7 +4162,33 @@ int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) int ssl_DecodePacketWithSessionInfoStoreData(const unsigned char* packet, int length, void* ctx, SSLInfo* sslInfo, char* error) { - return ssl_DecodePacketInternal(packet, length, NULL, sslInfo, ctx, error); + return ssl_DecodePacketInternal(packet, length, NULL, 0, NULL, sslInfo, + ctx, error); +} + +#endif + + +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + +int ssl_DecodePacketWithChain(void* vChain, word32 chainSz, byte** data, + char* error) +{ + return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, data, NULL, NULL, + error); +} + +#endif + + +#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ + defined(WOLFSSL_SNIFFER_STORE_DATA_CB) + +int ssl_DecodePacketWithChainSessionInfoStoreData(void* vChain, word32 chainSz, + void* ctx, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(NULL, 0, vChain, chainSz, NULL, sslInfo, + ctx, error); } #endif diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 67e942f03..71781e160 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -72,6 +72,25 @@ enum { }; +/* A TLS record can be 16k and change. The chain is broken up into 2K chunks. + * This covers the TLS record, plus a chunk for TCP/IP headers. */ +#ifndef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 2048 +#elif (CHAIN_INPUT_CHUNK_SIZE < 256) + #undef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 256 +#elif (CHAIN_INPUT_CHUNK_SIZE > 16384) + #undef CHAIN_INPUT_CHUNK_SIZE + #define CHAIN_INPUT_CHUNK_SIZE 16384 +#endif +#define CHAIN_INPUT_COUNT ((16384 / CHAIN_INPUT_CHUNK_SIZE) + 1) + + +#ifndef STORE_DATA_BLOCK_SZ + #define STORE_DATA_BLOCK_SZ 1024 +#endif + + pcap_t* pcap = NULL; pcap_if_t* alldevs = NULL; @@ -170,6 +189,16 @@ static char* iptos(unsigned int addr) } +#if defined(WOLFSSL_SNIFFER_STORE_DATA_CB) || defined(WOLFSSL_SNIFFER_CHAIN_INPUT) + +static inline unsigned int min(unsigned int a, unsigned int b) +{ + return a > b ? b : a; +} + +#endif + + #ifdef WOLFSSL_SNIFFER_WATCH const byte rsaHash[] = { @@ -228,8 +257,7 @@ static int myStoreDataCb(const unsigned char* decryptBuf, if (decryptBufSz < decryptBufOffset) return -1; - qty = (decryptBufSz - decryptBufOffset) < 32 ? - (decryptBufSz - decryptBufOffset) : 32; + qty = min(decryptBufSz - decryptBufOffset, STORE_DATA_BLOCK_SZ); if (*data == NULL) { byte* tmpData; @@ -265,6 +293,10 @@ int main(int argc, char** argv) struct bpf_program fp; pcap_if_t *d; pcap_addr_t *a; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + struct iovec chain[CHAIN_INPUT_COUNT]; + int chainSz; +#endif signal(SIGINT, sig_handler); @@ -443,13 +475,38 @@ int main(int argc, char** argv) } else continue; +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT + { + unsigned int j = 0; + unsigned int remainder = header.caplen; -#ifndef WOLFSSL_SNIFFER_STORE_DATA_CB - ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data, - &sslInfo, err); -#else + chainSz = 0; + do { + unsigned int chunkSz; + + chunkSz = min(remainder, CHAIN_INPUT_CHUNK_SIZE); + chain[chainSz].iov_base = (void*)(packet + j); + chain[chainSz].iov_len = chunkSz; + j += chunkSz; + remainder -= chunkSz; + chainSz++; + } while (j < header.caplen); + } +#endif + +#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ + defined(WOLFSSL_SNIFFER_STORE_DATA_CB) + ret = ssl_DecodePacketWithChainSessionInfoStoreData(chain, chainSz, + &data, &sslInfo, err); +#elif defined(WOLFSSL_SNIFFER_CHAIN_INPUT) + (void)sslInfo; + ret = ssl_DecodePacketWithChain(chain, chainSz, &data, err); +#elif defined(WOLFSSL_SNIFFER_STORE_DATA_CB) ret = ssl_DecodePacketWithSessionInfoStoreData(packet, header.caplen, &data, &sslInfo, err); +#else + ret = ssl_DecodePacketWithSessionInfo(packet, header.caplen, &data, + &sslInfo, err); #endif if (ret < 0) { printf("ssl_Decode ret = %d, %s\n", ret, err); diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index 28e26ba4e..7d11a7517 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -205,6 +205,17 @@ SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData( const unsigned char* packet, int length, void* ctx, SSLInfo* sslInfo, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithChain(void* vChain, + unsigned int chainSz, unsigned char** data, char* error); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithChainSessionInfoStoreData( + void* vChain, unsigned int chainSz, void* ctx, SSLInfo* sslInfo, + char* error); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/sniffer_error.h b/wolfssl/sniffer_error.h index f3fe93ca4..a63e1d015 100644 --- a/wolfssl/sniffer_error.h +++ b/wolfssl/sniffer_error.h @@ -129,6 +129,7 @@ #define NO_DATA_DEST_STR 91 #define STORE_DATA_FAIL_STR 92 +#define CHAIN_INPUT_STR 93 /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ diff --git a/wolfssl/sniffer_error.rc b/wolfssl/sniffer_error.rc index 31e1317cc..72fe36e9e 100644 --- a/wolfssl/sniffer_error.rc +++ b/wolfssl/sniffer_error.rc @@ -111,5 +111,6 @@ STRINGTABLE 91, "No data destination Error" 92, "Store Data callback failed" + 93, "Loading chain input" } From b6ca72549c1ecc933eda2e7d52860384efdabade Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 26 Aug 2019 11:24:09 -0700 Subject: [PATCH 12/30] Sniffer Fixes Added a flag to disable the normally enabled session stats, WOLFSSL_NO_SESSION_STATS. --- wolfssl/wolfcrypt/settings.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index f4c689530..550e60c03 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1779,11 +1779,17 @@ extern void uITRON4_free(void *p) ; #ifndef WOLFSSL_STATIC_RSA #define WOLFSSL_STATIC_RSA #endif - #ifndef WOLFSSL_SESSION_STATS - #define WOLFSSL_SESSION_STATS + #ifndef WOLFSSL_STATIC_DH + #define WOLFSSL_STATIC_DH #endif - #ifndef WOLFSSL_PEAK_SESSIONS - #define WOLFSSL_PEAK_SESSIONS + /* Allow option to be disabled. */ + #ifndef WOLFSSL_NO_SESSION_STATS + #ifndef WOLFSSL_SESSION_STATS + #define WOLFSSL_SESSION_STATS + #endif + #ifndef WOLFSSL_PEAK_SESSIONS + #define WOLFSSL_PEAK_SESSIONS + #endif #endif #endif From 53c7f864b245e30256ff0b7ef9f76354b01790c9 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 28 Aug 2019 13:54:29 -0700 Subject: [PATCH 13/30] Add midding function prototype. --- wolfssl/sniffer.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index 7d11a7517..6d6e155f8 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -180,6 +180,10 @@ typedef int (*SSLWatchCb)(void* vSniffer, WOLFSSL_API SSL_SNIFFER_API int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error); +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, + char* error); + WOLFSSL_API SSL_SNIFFER_API int ssl_SetWatchKeyCtx(void* ctx, char* error); From 3256fef7f90804e6f458ff9ac87fa9f3bf758884 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 29 Aug 2019 12:45:01 -0700 Subject: [PATCH 14/30] Sniffer Chain Buffers 1. Fixed an issue when a TLS record is split across two chain buffers. The second buffer was being treated as a new record. 2. Fixed an issue with STARTTLS_ALLOWED where the input buffer isn't getting cleared and the skipped data just builds up blocking TLS records. --- src/sniffer.c | 58 ++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index a4da757cd..efe2d9bbc 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3606,8 +3606,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, /* if current partial data, add to end of partial */ /* if skipping, the data is already at the end of partial */ - if ( !skipPartial && !vChain && - (length = ssl->buffers.inputBuffer.length) ) { + if ( !skipPartial && (length = ssl->buffers.inputBuffer.length) ) { Trace(PARTIAL_ADD_STR); if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { @@ -3616,49 +3615,54 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, return -1; } } - XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes); - *sslBytes += length; - ssl->buffers.inputBuffer.length = *sslBytes; - *sslFrame = ssl->buffers.inputBuffer.buffer; - *end = *sslFrame + *sslBytes; + if (vChain == NULL) { + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], + *sslFrame, *sslBytes); + *sslBytes += length; + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + } } if (vChain != NULL) { #ifdef WOLFSSL_SNIFFER_CHAIN_INPUT struct iovec* chain = (struct iovec*)vChain; - word32 i, offset, headerOffset, qty; + word32 i, offset, headerSz, qty, remainder; Trace(CHAIN_INPUT_STR); - headerOffset = (word32)*sslFrame - (word32)chain[0].iov_base; - length = *sslBytes + headerOffset; - if (length > ssl->buffers.inputBuffer.bufferSize) { - if (GrowInputBuffer(ssl, length, 0) < 0) { + headerSz = (word32)*sslFrame - (word32)chain[0].iov_base; + remainder = *sslBytes; + + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); return -1; } } - offset = 0; - for (i = 0; i < chainSz; i++) { - /* In case there is extra data in the chain that isn't covered - * by the sizes in the TCP headers, don't copy too much. This - * case has been seen where there are 4 extra bytes in the - * packet capture than the TCP header indicates. */ - if (offset + chain[i].iov_len > length) - qty = length - offset; + qty = min(*sslBytes, (word32)chain[0].iov_len - headerSz); + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], + (byte*)chain[0].iov_base + headerSz, qty); + offset = length; + for (i = 1; i < chainSz; i++) { + offset += qty; + remainder -= qty; + + if (chain[i].iov_len > remainder) + qty = remainder; else qty = (word32)chain[i].iov_len; XMEMCPY(ssl->buffers.inputBuffer.buffer + offset, chain[i].iov_base, qty); - offset += qty; } - ssl->buffers.inputBuffer.length = length; - *sslFrame = ssl->buffers.inputBuffer.buffer + headerOffset; + *sslBytes += length; + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; *end = *sslFrame + *sslBytes; -#else - (void)chainSz; #endif + (void)chainSz; } if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { @@ -3677,8 +3681,10 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, } else { #ifdef STARTTLS_ALLOWED - if (ssl->buffers.inputBuffer.dynamicFlag) + if (ssl->buffers.inputBuffer.dynamicFlag) { + ssl->buffers.inputBuffer.length = 0; ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } return 1; #endif } From b2fb6d1a8182f22ff14be3697a7550fe89ebc0ee Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 29 Aug 2019 13:42:24 -0700 Subject: [PATCH 15/30] Move some stats captures to a different location. --- src/sniffer.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index efe2d9bbc..2a72d30cb 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3832,18 +3832,24 @@ doMessage: SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } -#ifdef WOLFSSL_SNIFFER_STATS - LOCK_STAT(); - NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); - NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); - UNLOCK_STAT(); -#endif sslFrame = DecryptMessage(ssl, sslFrame, rhSize, ssl->buffers.outputBuffer.buffer, &errCode, &ivAdvance); recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so should recordEnd */ decrypted = 1; + +#ifdef WOLFSSL_SNIFFER_STATS + if (errCode != 0) { + INC_STAT(SnifferStats.sslKeyFails); + } + else { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); + UNLOCK_STAT(); + } +#endif if (errCode != 0) { SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE); return -1; From 725243b132a1887084492edcc8a2a038b6fb5c1c Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 29 Aug 2019 17:36:34 -0700 Subject: [PATCH 16/30] Changed how the sniffer calculates the sslFrame size, sslBytes, and the end of packet pointer. The end of packet pointer is based on sslFrame and sslBytes. sslBytes is calculated from the total length in the IP header, rather than the caplen. The caplen may include things like Ethernet's FCS, which throws packet processing off. --- src/sniffer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 2a72d30cb..20a342036 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3052,7 +3052,9 @@ static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet, SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); return -1; } - *sslBytes = (int)(packet + length - *sslFrame); + /* We only care about the data in the TCP/IP record. There may be extra + * data after the IP record for the FCS for Ethernet. */ + *sslBytes = (int)(packet + ipInfo->total - *sslFrame); return 0; } @@ -4069,7 +4071,7 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, TcpInfo tcpInfo; IpInfo ipInfo; const byte* sslFrame; - const byte* end = packet + length; + const byte* end; int sslBytes; /* ssl bytes unconsumed */ int ret; SnifferSession* session = 0; @@ -4090,6 +4092,8 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, error) != 0) return -1; + end = sslFrame + sslBytes; + ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; else if (ret == -1) return -1; From 841e469340e11c6f0907e7eef71947acdbbac423 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 30 Aug 2019 17:09:11 -0700 Subject: [PATCH 17/30] Convert the data the snifftest is about to print into printable text. Anything that isprint() or isspace() is kept, anything else is changed to a period. --- sslSniffer/sslSnifferTest/snifftest.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 71781e160..07adf2c2a 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -54,6 +54,7 @@ int main(void) #include /* EXIT_SUCCESS */ #include /* strcmp */ #include /* signal */ +#include /* isprint */ #include @@ -513,6 +514,12 @@ int main(int argc, char** argv) hadBadPacket = 1; } if (ret > 0) { + int j; + /* Convert non-printable data to periods. */ + for (j = 0; j < ret; j++) { + if (isprint(data[j]) || isspace(data[j])) continue; + data[j] = '.'; + } data[ret] = 0; printf("SSL App Data(%d:%d):%s\n", packetNumber, ret, data); ssl_FreeZeroDecodeBuffer(&data, ret, err); From 1b057df6108f86385c84951f2edb6a5b1d9ad806 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 30 Aug 2019 17:13:08 -0700 Subject: [PATCH 18/30] When enabling SHOW_SECRETS one of the array counter variables for a secret had a type mismatch. Changed the index to a word32 to match the boundary variable's type. --- src/sniffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sniffer.c b/src/sniffer.c index 20a342036..8fcc537e6 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1870,7 +1870,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, #ifdef SHOW_SECRETS { - int i; + word32 i; printf("pre master secret: "); for (i = 0; i < session->sslServer->arrays->preMasterSz; i++) printf("%02x", session->sslServer->arrays->preMasterSecret[i]); From 8b21082abea16296c9333ce0053f5ff35347ef97 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Sep 2019 12:47:41 -0700 Subject: [PATCH 19/30] Use wrapper macros for all touches of the sniffer statistics mutex. --- src/sniffer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 8fcc537e6..60cbb1791 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -4358,9 +4358,9 @@ int ssl_ReadStatistics(SSLStats* stats) if (stats == NULL) return -1; - wc_LockMutex(&StatsMutex); + LOCK_STAT(); XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); - wc_UnLockMutex(&StatsMutex); + UNLOCK_STAT(); return 0; } @@ -4372,10 +4372,10 @@ int ssl_ReadResetStatistics(SSLStats* stats) if (stats == NULL) return -1; - wc_LockMutex(&StatsMutex); + LOCK_STAT(); XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); - wc_UnLockMutex(&StatsMutex); + UNLOCK_STAT(); return 0; } From d1d2eb0edd21b4fcb272e9c921981db9946b8489 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Sep 2019 17:05:11 -0700 Subject: [PATCH 20/30] Add IPv6 to the sniffer. --- src/sniffer.c | 257 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 186 insertions(+), 71 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 60cbb1791..8fd3531e0 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -78,6 +78,7 @@ enum { IP_HDR_SZ = 20, /* IP header length, min */ TCP_HDR_SZ = 20, /* TCP header length, min */ IPV4 = 4, /* IP version 4 */ + IPV6 = 6, /* IP version 6 */ TCP_PROTOCOL = 6, /* TCP Protocol id */ TRACE_MSG_SZ = 80, /* Trace Message buffer size */ HASH_SIZE = 499, /* Session Hash Table Rows */ @@ -316,11 +317,18 @@ typedef struct NamedKey { #endif +typedef union IpAddrInfo { + word32 ip4; + word32 ip6[4]; +} IpAddrInfo; + + /* Sniffer Server holds info for each server/port monitored */ typedef struct SnifferServer { SSL_CTX* ctx; /* SSL context */ char address[MAX_SERVER_ADDRESS]; /* passed in server address */ - word32 server; /* netowrk order address */ + IpAddrInfo server; /* network order address */ + int version; /* IP version */ int port; /* server port */ #ifdef HAVE_SNI NamedKey* namedKeys; /* mapping of names and keys */ @@ -382,8 +390,9 @@ typedef struct SnifferSession { SnifferServer* context; /* server context */ SSL* sslServer; /* SSL server side decode */ SSL* sslClient; /* SSL client side decode */ - word32 server; /* server address in network byte order */ - word32 client; /* client address in network byte order */ + IpAddrInfo server; /* server address in network byte order */ + IpAddrInfo client; /* client address in network byte order */ + int version; word16 srvPort; /* server port */ word16 cliPort; /* client port */ word32 cliSeqStart; /* client start sequence */ @@ -744,85 +753,40 @@ static int HashCopy(HS_Hashes* d, HsHashes* s) /* Initialize a SnifferServer */ static void InitSnifferServer(SnifferServer* sniffer) { - sniffer->ctx = 0; - XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS); - sniffer->server = 0; - sniffer->port = 0; -#ifdef HAVE_SNI - sniffer->namedKeys = 0; - wc_InitMutex(&sniffer->namedKeysMutex); -#endif - sniffer->next = 0; + XMEMSET(sniffer, 0, sizeof(SnifferServer)); } /* Initialize session flags */ static void InitFlags(Flags* flags) { - flags->side = 0; - flags->serverCipherOn = 0; - flags->clientCipherOn = 0; - flags->resuming = 0; - flags->cached = 0; - flags->clientHello = 0; - flags->finCount = 0; - flags->fatalError = 0; - flags->cliAckFault = 0; - flags->srvAckFault = 0; - flags->cliSkipPartial = 0; - flags->srvSkipPartial = 0; -#ifdef HAVE_EXTENDED_MASTER - flags->expectEms = 0; -#endif + XMEMSET(flags, 0, sizeof(Flags)); } /* Initialize FIN Capture */ static void InitFinCapture(FinCaputre* cap) { - cap->cliFinSeq = 0; - cap->srvFinSeq = 0; - cap->cliCounted = 0; - cap->srvCounted = 0; + XMEMSET(cap, 0, sizeof(FinCaputre)); } /* Initialize a Sniffer Session */ static void InitSession(SnifferSession* session) { - session->context = 0; - session->sslServer = 0; - session->sslClient = 0; - session->server = 0; - session->client = 0; - session->srvPort = 0; - session->cliPort = 0; - session->cliSeqStart = 0; - session->srvSeqStart = 0; - session->cliExpected = 0; - session->srvExpected = 0; - session->lastUsed = 0; - session->cliReassemblyList = 0; - session->srvReassemblyList = 0; - session->cliReassemblyMemory = 0; - session->srvReassemblyMemory = 0; - session->next = 0; - session->ticketID = 0; - + XMEMSET(session, 0, sizeof(SnifferSession)); InitFlags(&session->flags); InitFinCapture(&session->finCaputre); -#ifdef HAVE_EXTENDED_MASTER - session->hash = 0; -#endif } /* IP Info from IP Header */ typedef struct IpInfo { + int version; /* IP version */ int length; /* length of this header */ int total; /* total length of fragment */ - word32 src; /* network order source address */ - word32 dst; /* network order destination address */ + IpAddrInfo src; /* network order source address */ + IpAddrInfo dst; /* network order destination address */ } IpInfo; @@ -868,7 +832,7 @@ typedef struct EthernetHdr { } EthernetHdr; -/* IP Header */ +/* IPv4 Header */ typedef struct IpHdr { byte ver_hl; /* version/header length */ byte tos; /* type of service */ @@ -883,6 +847,19 @@ typedef struct IpHdr { } IpHdr; +/* IPv6 Header */ +typedef struct Ip6Hdr { + byte ver_hl; /* version/traffic class high */ + byte tc_fl; /* traffic class low/flow label high */ + word16 fl; /* flow label low */ + word16 length; /* payload length */ + byte next_header; /* next header (6 for TCP, any other skip) */ + byte hl; /* hop limit */ + word32 src[4]; /* source address */ + word32 dst[4]; /* destination address */ +} Ip6Hdr; + + #define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4) #define IP_V(ip) ( ((ip)->ver_hl) >> 4) @@ -982,6 +959,18 @@ static char* IpToS(word32 addr, char* str) } +/* Convert network byte order address into human readable */ +static char* Ip6ToS(word32* addr, char* str) +{ + byte* p = (byte*)addr; + + /* Very incorrect. XXX */ + SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[127]); + + return str; +} + + /* Show destination and source address from Ip Hdr for packet Trace */ static void TraceIP(IpHdr* iphdr) { @@ -994,6 +983,18 @@ static void TraceIP(IpHdr* iphdr) } +/* Show destination and source address from Ip6Hdr for packet Trace */ +static void TraceIP6(Ip6Hdr* iphdr) +{ + if (TraceOn) { + char src[TRACE_MSG_SZ]; + char dst[TRACE_MSG_SZ]; + fprintf(TraceFile, "\tdst:%s src:%s\n", Ip6ToS(iphdr->dst, dst), + Ip6ToS(iphdr->src, src)); + } +} + + /* Show destination and source port from Tcp Hdr for packet Trace */ static void TraceTcp(TcpHdr* tcphdr) { @@ -1178,7 +1179,32 @@ static int IsServerRegistered(word32 addr) sniffer = ServerList; while (sniffer) { - if (sniffer->server == addr) { + if (sniffer->server.ip4 == addr) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + wc_UnLockMutex(&ServerListMutex); + + return ret; +} + + +/* See if this port has been registered to watch */ +/* See if this IPV4 network order address has been registered */ +/* return 1 is true, 0 is false */ +static int IsServerRegistered6(word32* addr) +{ + int ret = 0; /* false */ + SnifferServer* sniffer; + + wc_LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) { ret = 1; break; } @@ -1228,10 +1254,25 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) #ifndef WOLFSSL_SNIFFER_WATCH while (sniffer) { - if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) - break; - if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst) - break; + if (ipInfo->version == IPV4) { + if (sniffer->port == tcpInfo->srcPort && + sniffer->server.ip4 == ipInfo->src.ip4) + break; + if (sniffer->port == tcpInfo->dstPort && + sniffer->server.ip4 == ipInfo->dst.ip4) + break; + } + else if (ipInfo->version == IPV6) { + if (sniffer->port == tcpInfo->srcPort && + XMEMCMP(sniffer->server.ip6, ipInfo->src.ip6, + sizeof(sniffer->server.ip6)) == 0) + break; + if (sniffer->port == tcpInfo->dstPort && + XMEMCMP(sniffer->server.ip6, ipInfo->dst.ip6, + sizeof(sniffer->server.ip6)) == 0) + break; + } + sniffer = sniffer->next; } #else @@ -1248,13 +1289,35 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) /* Hash the Session Info, return hash row */ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { - word32 hash = ipInfo->src * ipInfo->dst; + word32 hash = 1; + + if (ipInfo->version == IPV4) { + hash *= ipInfo->src.ip4 * ipInfo->dst.ip4; + } + else if (ipInfo->version == IPV6) { + word32 x; + x = ipInfo->src.ip6[0] ^ ipInfo->src.ip6[1] ^ + ipInfo->src.ip6[2] ^ ipInfo->src.ip6[3]; + hash *= x; + x = ipInfo->dst.ip6[0] ^ ipInfo->dst.ip6[1] ^ + ipInfo->dst.ip6[2] ^ ipInfo->dst.ip6[3]; + hash *= x; + } hash *= tcpInfo->srcPort * tcpInfo->dstPort; return hash % HASH_SIZE; } +static inline int MatchAddr(int version, IpAddrInfo l, IpAddrInfo r) +{ + if (version == IPV4) + return (l.ip4 == r.ip4); + else + return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6))); +} + + /* Get Exisiting SnifferSession from IP and Port */ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) { @@ -1268,11 +1331,14 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session = SessionTable[row]; while (session) { - if (session->server == ipInfo->src && session->client == ipInfo->dst && + if (MatchAddr(session->version, session->server, ipInfo->src) && + MatchAddr(session->version, session->client, ipInfo->dst) && session->srvPort == tcpInfo->srcPort && session->cliPort == tcpInfo->dstPort) break; - if (session->client == ipInfo->src && session->server == ipInfo->dst && + + if (MatchAddr(session->version, session->client, ipInfo->src) && + MatchAddr(session->version, session->server, ipInfo->dst) && session->cliPort == tcpInfo->srcPort && session->srvPort == tcpInfo->dstPort) break; @@ -1287,11 +1353,14 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) /* determine side */ if (session) { - if (ipInfo->dst == session->server && - tcpInfo->dstPort == session->srvPort) + if (MatchAddr(ipInfo->version, ipInfo->dst, session->server) && + tcpInfo->dstPort == session->srvPort) { + session->flags.side = WOLFSSL_SERVER_END; - else + } + else { session->flags.side = WOLFSSL_CLIENT_END; + } } return session; @@ -1449,7 +1518,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, serverIp = inet_addr(address); sniffer = ServerList; while (sniffer != NULL && - (sniffer->server != serverIp || sniffer->port != port)) { + (sniffer->server.ip4 != serverIp || sniffer->port != port)) { sniffer = sniffer->next; } @@ -1468,7 +1537,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1); sniffer->address[MAX_SERVER_ADDRESS-1] = '\0'; - sniffer->server = serverIp; + sniffer->server.ip4 = serverIp; sniffer->port = port; sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); @@ -1569,7 +1638,49 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, } +/* Check IP Header for IPV6, TCP, and a registered server address */ +/* returns 0 on success, -1 on error */ +static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) +{ + int version = IP_V(iphdr); + + TraceIP6(iphdr); + Trace(IP_CHECK_STR); + + if (version != IPV6) { + SetError(BAD_IPVER_STR, error, NULL, 0); + return -1; + } + + /* Here, we need to move onto next header if not TCP. */ + if (iphdr->next_header != TCP_PROTOCOL) { + SetError(BAD_PROTO_STR, error, NULL, 0); + return -1; + } + +#ifndef WOLFSSL_SNIFFER_WATCH + if (!IsServerRegistered6(iphdr->src) && !IsServerRegistered6(iphdr->dst)) { + SetError(SERVER_NOT_REG_STR, error, NULL, 0); + return -1; + } +#endif + + info->total = ntohs(iphdr->length); + info->version = IPV6; + XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6)); + XMEMCPY(info->dst.ip6, iphdr->src, sizeof(info->dst.ip6)); + + /* This needs to massage the length and size to match what the sniffer + * expects. IPv4 and IPv6 treat the length parameter differently. */ + if (info->total == 0) + info->total = length; /* reassembled may be off */ + + return 0; +} + + /* Check IP Header for IPV4, TCP, and a registered server address */ +/* If header IPv6, pass to CheckIp6Hdr(). */ /* returns 0 on success, -1 on error */ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) { @@ -1578,6 +1689,9 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) TraceIP(iphdr); Trace(IP_CHECK_STR); + if (version == IPV6) + return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error); + if (version != IPV4) { SetError(BAD_IPVER_STR, error, NULL, 0); return -1; @@ -1597,8 +1711,9 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) info->length = IP_HL(iphdr); info->total = ntohs(iphdr->length); - info->src = iphdr->src; - info->dst = iphdr->dst; + info->version = IPV4; + info->src.ip4 = iphdr->src; + info->dst.ip4 = iphdr->dst; if (info->total == 0) info->total = length; /* reassembled may be off */ From a5bfb8a18b31d19a868cc418aeef7730454905f8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 6 Sep 2019 16:12:09 -0700 Subject: [PATCH 21/30] Change the IP address wrappers to include the version. Makes comparing easier. Hard-coded some IPv6 localhost tests. --- src/sniffer.c | 139 ++++++++++++++------------ sslSniffer/sslSnifferTest/snifftest.c | 44 +++++--- 2 files changed, 103 insertions(+), 80 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 8fd3531e0..25629d14a 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -317,9 +317,12 @@ typedef struct NamedKey { #endif -typedef union IpAddrInfo { - word32 ip4; - word32 ip6[4]; +typedef struct IpAddrInfo { + int version; + union { + word32 ip4; + byte ip6[16]; + }; } IpAddrInfo; @@ -328,7 +331,6 @@ typedef struct SnifferServer { SSL_CTX* ctx; /* SSL context */ char address[MAX_SERVER_ADDRESS]; /* passed in server address */ IpAddrInfo server; /* network order address */ - int version; /* IP version */ int port; /* server port */ #ifdef HAVE_SNI NamedKey* namedKeys; /* mapping of names and keys */ @@ -392,7 +394,6 @@ typedef struct SnifferSession { SSL* sslClient; /* SSL client side decode */ IpAddrInfo server; /* server address in network byte order */ IpAddrInfo client; /* client address in network byte order */ - int version; word16 srvPort; /* server port */ word16 cliPort; /* client port */ word32 cliSeqStart; /* client start sequence */ @@ -782,7 +783,6 @@ static void InitSession(SnifferSession* session) /* IP Info from IP Header */ typedef struct IpInfo { - int version; /* IP version */ int length; /* length of this header */ int total; /* total length of fragment */ IpAddrInfo src; /* network order source address */ @@ -855,8 +855,8 @@ typedef struct Ip6Hdr { word16 length; /* payload length */ byte next_header; /* next header (6 for TCP, any other skip) */ byte hl; /* hop limit */ - word32 src[4]; /* source address */ - word32 dst[4]; /* destination address */ + byte src[16]; /* source address */ + byte dst[16]; /* destination address */ } Ip6Hdr; @@ -960,12 +960,12 @@ static char* IpToS(word32 addr, char* str) /* Convert network byte order address into human readable */ -static char* Ip6ToS(word32* addr, char* str) +static char* Ip6ToS(byte* addr, char* str) { byte* p = (byte*)addr; /* Very incorrect. XXX */ - SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[127]); + SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[15]); return str; } @@ -989,7 +989,7 @@ static void TraceIP6(Ip6Hdr* iphdr) if (TraceOn) { char src[TRACE_MSG_SZ]; char dst[TRACE_MSG_SZ]; - fprintf(TraceFile, "\tdst:%s src:%s\n", Ip6ToS(iphdr->dst, dst), + fprintf(TraceFile, "\tdst: %s src: %s\n", Ip6ToS(iphdr->dst, dst), Ip6ToS(iphdr->src, src)); } } @@ -1166,6 +1166,19 @@ static void SetError(int idx, char* error, SnifferSession* session, int fatal) } +/* Compare IpAddrInfo structs */ +static inline int MatchAddr(IpAddrInfo l, IpAddrInfo r) +{ + if (l.version == r.version) { + if (l.version == IPV4) + return (l.ip4 == r.ip4); + else if (l.version == IPV6) + return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6))); + } + return 0; +} + + #ifndef WOLFSSL_SNIFFER_WATCH /* See if this IPV4 network order address has been registered */ @@ -1195,7 +1208,7 @@ static int IsServerRegistered(word32 addr) /* See if this port has been registered to watch */ /* See if this IPV4 network order address has been registered */ /* return 1 is true, 0 is false */ -static int IsServerRegistered6(word32* addr) +static int IsServerRegistered6(byte* addr) { int ret = 0; /* false */ SnifferServer* sniffer; @@ -1204,7 +1217,8 @@ static int IsServerRegistered6(word32* addr) sniffer = ServerList; while (sniffer) { - if (XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) { + if (sniffer->server.version == IPV6 && + 0 == XMEMCMP(sniffer->server.ip6, addr, sizeof(sniffer->server.ip6))) { ret = 1; break; } @@ -1254,24 +1268,12 @@ static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) #ifndef WOLFSSL_SNIFFER_WATCH while (sniffer) { - if (ipInfo->version == IPV4) { - if (sniffer->port == tcpInfo->srcPort && - sniffer->server.ip4 == ipInfo->src.ip4) - break; - if (sniffer->port == tcpInfo->dstPort && - sniffer->server.ip4 == ipInfo->dst.ip4) - break; - } - else if (ipInfo->version == IPV6) { - if (sniffer->port == tcpInfo->srcPort && - XMEMCMP(sniffer->server.ip6, ipInfo->src.ip6, - sizeof(sniffer->server.ip6)) == 0) - break; - if (sniffer->port == tcpInfo->dstPort && - XMEMCMP(sniffer->server.ip6, ipInfo->dst.ip6, - sizeof(sniffer->server.ip6)) == 0) - break; - } + if (sniffer->port == tcpInfo->srcPort && + MatchAddr(sniffer->server, ipInfo->src)) + break; + if (sniffer->port == tcpInfo->dstPort && + MatchAddr(sniffer->server, ipInfo->dst)) + break; sniffer = sniffer->next; } @@ -1291,17 +1293,18 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) { word32 hash = 1; - if (ipInfo->version == IPV4) { + if (ipInfo->src.version == IPV4) { hash *= ipInfo->src.ip4 * ipInfo->dst.ip4; } - else if (ipInfo->version == IPV6) { - word32 x; - x = ipInfo->src.ip6[0] ^ ipInfo->src.ip6[1] ^ - ipInfo->src.ip6[2] ^ ipInfo->src.ip6[3]; - hash *= x; - x = ipInfo->dst.ip6[0] ^ ipInfo->dst.ip6[1] ^ - ipInfo->dst.ip6[2] ^ ipInfo->dst.ip6[3]; - hash *= x; + else if (ipInfo->src.version == IPV6) { + word32* x; + word32 y; + x = (word32*)ipInfo->src.ip6; + y = x[0] ^ x[1] ^ x[2] ^ x[3]; + hash *= y; + x = (word32*)ipInfo->dst.ip6; + y = x[0] ^ x[1] ^ x[2] ^ x[3]; + hash *= y; } hash *= tcpInfo->srcPort * tcpInfo->dstPort; @@ -1309,15 +1312,6 @@ static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) } -static inline int MatchAddr(int version, IpAddrInfo l, IpAddrInfo r) -{ - if (version == IPV4) - return (l.ip4 == r.ip4); - else - return (0 == XMEMCMP(l.ip6, r.ip6, sizeof(l.ip6))); -} - - /* Get Exisiting SnifferSession from IP and Port */ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) { @@ -1331,14 +1325,14 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) session = SessionTable[row]; while (session) { - if (MatchAddr(session->version, session->server, ipInfo->src) && - MatchAddr(session->version, session->client, ipInfo->dst) && + if (MatchAddr(session->server, ipInfo->src) && + MatchAddr(session->client, ipInfo->dst) && session->srvPort == tcpInfo->srcPort && session->cliPort == tcpInfo->dstPort) break; - if (MatchAddr(session->version, session->client, ipInfo->src) && - MatchAddr(session->version, session->server, ipInfo->dst) && + if (MatchAddr(session->client, ipInfo->src) && + MatchAddr(session->server, ipInfo->dst) && session->cliPort == tcpInfo->srcPort && session->srvPort == tcpInfo->dstPort) break; @@ -1353,7 +1347,7 @@ static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) /* determine side */ if (session) { - if (MatchAddr(ipInfo->version, ipInfo->dst, session->server) && + if (MatchAddr(ipInfo->dst, session->server) && tcpInfo->dstPort == session->srvPort) { session->flags.side = WOLFSSL_SERVER_END; @@ -1451,7 +1445,8 @@ static int CreateWatchSnifferServer(char* error) { SnifferServer* sniffer; - sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL, DYNAMIC_TYPE_SNIFFER_SERVER); + sniffer = (SnifferServer*)XMALLOC(sizeof(SnifferServer), NULL, + DYNAMIC_TYPE_SNIFFER_SERVER); if (sniffer == NULL) { SetError(MEMORY_STR, error, NULL, 0); return -1; @@ -1482,7 +1477,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : WOLFSSL_FILETYPE_ASN1; int isNew = 0; - word32 serverIp; + IpAddrInfo serverIp; #ifdef HAVE_SNI NamedKey* namedKey = NULL; @@ -1515,10 +1510,18 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, } #endif - serverIp = inet_addr(address); + serverIp.version = IPV4; + serverIp.ip4 = inet_addr(address); + if (serverIp.ip4 == INADDR_NONE) { + if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) { + serverIp.version = IPV6; + serverIp.ip6[0] = 0; + serverIp.ip6[1] = 0; + } + } sniffer = ServerList; while (sniffer != NULL && - (sniffer->server.ip4 != serverIp || sniffer->port != port)) { + (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) { sniffer = sniffer->next; } @@ -1537,7 +1540,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1); sniffer->address[MAX_SERVER_ADDRESS-1] = '\0'; - sniffer->server.ip4 = serverIp; + sniffer->server = serverIp; sniffer->port = port; sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); @@ -1665,10 +1668,13 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) } #endif - info->total = ntohs(iphdr->length); - info->version = IPV6; + info->length = 40; + info->total = ntohs(iphdr->length) + info->length; + /* IPv6 doesn't include its own header size in the length like v4. */ + info->src.version = IPV6; XMEMCPY(info->src.ip6, iphdr->src, sizeof(info->src.ip6)); - XMEMCPY(info->dst.ip6, iphdr->src, sizeof(info->dst.ip6)); + info->dst.version = IPV6; + XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6)); /* This needs to massage the length and size to match what the sniffer * expects. IPv4 and IPv6 treat the length parameter differently. */ @@ -1686,12 +1692,12 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) { int version = IP_V(iphdr); - TraceIP(iphdr); - Trace(IP_CHECK_STR); - if (version == IPV6) return CheckIp6Hdr((Ip6Hdr*)iphdr, info, length, error); + TraceIP(iphdr); + Trace(IP_CHECK_STR); + if (version != IPV4) { SetError(BAD_IPVER_STR, error, NULL, 0); return -1; @@ -1711,8 +1717,9 @@ static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) info->length = IP_HL(iphdr); info->total = ntohs(iphdr->length); - info->version = IPV4; + info->src.version = IPV4; info->src.ip4 = iphdr->src; + info->dst.version = IPV4; info->dst.ip4 = iphdr->dst; if (info->total == 0) diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 07adf2c2a..d367de836 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -184,7 +184,23 @@ static char* iptos(unsigned int addr) static char output[32]; byte *p = (byte*)&addr; - SNPRINTF(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + + return output; +} + + +static char* ip6tos(const unsigned char* addr) +{ + static char output[42]; + + snprintf(output, sizeof(output), + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], + addr[8], addr[9], addr[10], addr[11], + addr[12], addr[13], addr[14], addr[15]); return output; } @@ -347,22 +363,21 @@ int main(int argc, char** argv) if (pcap == NULL) printf("pcap_create failed %s\n", err); - /* get an IPv4 address */ + /* get an IPv4 or IPv6 address */ for (a = d->addresses; a; a = a->next) { - switch(a->addr->sa_family) - { - case AF_INET: - server = - iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); - printf("server = %s\n", server); - break; - - default: - break; - } + if (a->addr->sa_family == AF_INET) + server = + iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); + else if (a->addr->sa_family == AF_INET6) + server = + ip6tos(((struct sockaddr_in6 *)a->addr)->sin6_addr.s6_addr); + else + server = NULL; } if (server == NULL) - err_sys("Unable to get device IPv4 address"); + err_sys("Unable to get device IPv4 or IPv6 address"); + else + printf("server = %s\n", server); ret = pcap_set_snaplen(pcap, 65536); if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); @@ -395,6 +410,7 @@ int main(int argc, char** argv) if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); #ifndef WOLFSSL_SNIFFER_WATCH + server = "::1"; ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem", FILETYPE_PEM, NULL, err); if (ret != 0) { From ebd435ae467bb163796b564a20dc6ea4c2a8d368 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Sep 2019 10:22:47 -0700 Subject: [PATCH 22/30] skip IPv6 extended headers --- src/sniffer.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 25629d14a..97b40c807 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -75,11 +75,13 @@ enum { ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */ LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */ TCP_PROTO = 6, /* TCP_PROTOCOL */ - IP_HDR_SZ = 20, /* IP header length, min */ + IP_HDR_SZ = 20, /* IPv4 header length, min */ + IP6_HDR_SZ = 40, /* IPv6 header length, min */ TCP_HDR_SZ = 20, /* TCP header length, min */ IPV4 = 4, /* IP version 4 */ IPV6 = 6, /* IP version 6 */ TCP_PROTOCOL = 6, /* TCP Protocol id */ + NO_NEXT_HEADER = 59, /* IPv6 no headers follow */ TRACE_MSG_SZ = 80, /* Trace Message buffer size */ HASH_SIZE = 499, /* Session Hash Table Rows */ PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */ @@ -860,6 +862,14 @@ typedef struct Ip6Hdr { } Ip6Hdr; +/* IPv6 extension header */ +typedef struct Ip6ExtHdr { + byte next_header; /* next header (6 for TCP, any other skip) */ + byte length; /* length in 8-octet units - 1 */ + byte reserved[6]; +} Ip6ExtHdr; + + #define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4) #define IP_V(ip) ( ((ip)->ver_hl) >> 4) @@ -1645,7 +1655,8 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, /* returns 0 on success, -1 on error */ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) { - int version = IP_V(iphdr); + int version = IP_V(iphdr); + int exthdrsz = 0; TraceIP6(iphdr); Trace(IP_CHECK_STR); @@ -1657,8 +1668,14 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) /* Here, we need to move onto next header if not TCP. */ if (iphdr->next_header != TCP_PROTOCOL) { - SetError(BAD_PROTO_STR, error, NULL, 0); - return -1; + Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ); + do { + int hdrsz = (exthdr->length + 1) * 8; + exthdrsz += hdrsz; + exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz); + } + while (exthdr->next_header != TCP_PROTOCOL && + exthdr->next_header != NO_NEXT_HEADER); } #ifndef WOLFSSL_SNIFFER_WATCH @@ -1668,7 +1685,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) } #endif - info->length = 40; + info->length = IP6_HDR_SZ + exthdrsz; info->total = ntohs(iphdr->length) + info->length; /* IPv6 doesn't include its own header size in the length like v4. */ info->src.version = IPV6; From 89ff909d7363fc46de28e3f52c4ff9f6436a04ba Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Sep 2019 11:55:56 -0700 Subject: [PATCH 23/30] Sniffer IPv6 1. Sorted out IPv6 configuration for sniff test. 2. Tests the sniffer using an IPv6 file. --- scripts/sniffer-testsuite.test | 6 ++ src/sniffer.c | 2 - sslSniffer/sslSnifferTest/snifftest.c | 102 ++++++++++++++------------ 3 files changed, 60 insertions(+), 50 deletions(-) diff --git a/scripts/sniffer-testsuite.test b/scripts/sniffer-testsuite.test index c68040301..6224c781b 100755 --- a/scripts/sniffer-testsuite.test +++ b/scripts/sniffer-testsuite.test @@ -8,6 +8,12 @@ echo -e "\nStaring snifftest on testsuite.pcap...\n" RESULT=$? [ $RESULT -ne 0 ] && echo -e "\nsnifftest failed\n" && exit 1 +echo -e "\nStaring snifftest on sniffer-ipv6.pcap...\n" +./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-ipv6.pcap ./certs/server-key.pem ::1 11111 + +RESULT=$? +[ $RESULT -ne 0 ] && echo -e "\nsnifftest (ipv6) failed\n" && exit 1 + echo -e "\nSuccess!\n" exit 0 diff --git a/src/sniffer.c b/src/sniffer.c index 97b40c807..1258ec350 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1525,8 +1525,6 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, if (serverIp.ip4 == INADDR_NONE) { if (inet_pton(AF_INET6, address, serverIp.ip6) == 1) { serverIp.version = IPV6; - serverIp.ip6[0] = 0; - serverIp.ip6[1] = 0; } } sniffer = ServerList; diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index d367de836..6438d7ced 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -179,10 +179,10 @@ static void err_sys(const char* msg) #endif -static char* iptos(unsigned int addr) +static char* iptos(const struct in_addr* addr) { static char output[32]; - byte *p = (byte*)&addr; + byte *p = (byte*)&addr->s_addr; snprintf(output, sizeof(output), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); @@ -190,19 +190,10 @@ static char* iptos(unsigned int addr) } -static char* ip6tos(const unsigned char* addr) +static const char* ip6tos(const struct in6_addr* addr) { static char output[42]; - - snprintf(output, sizeof(output), - "%02x%02x:%02x%02x:%02x%02x:%02x%02x:" - "%02x%02x:%02x%02x:%02x%02x:%02x%02x", - addr[0], addr[1], addr[2], addr[3], - addr[4], addr[5], addr[6], addr[7], - addr[8], addr[9], addr[10], addr[11], - addr[12], addr[13], addr[14], addr[15]); - - return output; + return inet_ntop(AF_INET6, addr, output, 42); } @@ -363,21 +354,21 @@ int main(int argc, char** argv) if (pcap == NULL) printf("pcap_create failed %s\n", err); - /* get an IPv4 or IPv6 address */ + /* print out addresses for selected interface */ for (a = d->addresses; a; a = a->next) { - if (a->addr->sa_family == AF_INET) + if (a->addr->sa_family == AF_INET) { server = - iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr); - else if (a->addr->sa_family == AF_INET6) + iptos(&((struct sockaddr_in *)a->addr)->sin_addr); + printf("server = %s\n", server); + } + else if (a->addr->sa_family == AF_INET6) { server = - ip6tos(((struct sockaddr_in6 *)a->addr)->sin6_addr.s6_addr); - else - server = NULL; + ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr); + printf("server = %s\n", server); + } } if (server == NULL) err_sys("Unable to get device IPv4 or IPv6 address"); - else - printf("server = %s\n", server); ret = pcap_set_snaplen(pcap, 65536); if (ret != 0) printf("pcap_set_snaplen failed %s\n", pcap_geterr(pcap)); @@ -409,33 +400,48 @@ int main(int argc, char** argv) ret = pcap_setfilter(pcap, &fp); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); -#ifndef WOLFSSL_SNIFFER_WATCH - server = "::1"; - ret = ssl_SetPrivateKey(server, port, "../../certs/server-key.pem", - FILETYPE_PEM, NULL, err); - if (ret != 0) { - printf("Please run directly from sslSniffer/sslSnifferTest dir\n"); - } - -#ifdef HAVE_SNI - { - char altName[128]; - - printf("Enter alternate SNI: "); - ret = scanf("%s", altName); - - if (strnlen(altName, 128) > 0) { - ret = ssl_SetNamedPrivateKey(altName, - server, port, "../../certs/server-key.pem", - FILETYPE_PEM, NULL, err); - if (ret != 0) { - printf("Please run directly from " - "sslSniffer/sslSnifferTest dir\n"); - } + /* get IPv4 or IPv6 addresses for selected interface */ + for (a = d->addresses; a; a = a->next) { + server = NULL; + if (a->addr->sa_family == AF_INET) { + server = + iptos(&((struct sockaddr_in *)a->addr)->sin_addr); } - } -#endif -#endif + else if (a->addr->sa_family == AF_INET6) { + server = + ip6tos(&((struct sockaddr_in6 *)a->addr)->sin6_addr); + } + + if (server) { + #ifndef WOLFSSL_SNIFFER_WATCH + ret = ssl_SetPrivateKey(server, port, + "../../certs/server-key.pem", + FILETYPE_PEM, NULL, err); + if (ret != 0) { + printf("Please run directly from sslSniffer/sslSnifferTest" + "dir\n"); + } + #ifdef HAVE_SNI + { + char altName[128]; + + printf("Enter alternate SNI: "); + ret = scanf("%s", altName); + + if (strnlen(altName, 128) > 0) { + ret = ssl_SetNamedPrivateKey(altName, + server, port, "../../certs/server-key.pem", + FILETYPE_PEM, NULL, err); + if (ret != 0) { + printf("Please run directly from " + "sslSniffer/sslSnifferTest dir\n"); + } + } + } + #endif + #endif + } + } } else if (argc >= 3) { saveFile = 1; From b6b57154e5f186deb9c4cac0bbdf01569ff7ac9d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Sep 2019 12:34:23 -0700 Subject: [PATCH 24/30] Add the new IPv6 sniffer test file to the automake list. --- scripts/include.am | 1 + scripts/sniffer-ipv6.pcap | Bin 0 -> 9484 bytes 2 files changed, 1 insertion(+) create mode 100644 scripts/sniffer-ipv6.pcap diff --git a/scripts/include.am b/scripts/include.am index f1ce84b2b..3a3d7995a 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -84,6 +84,7 @@ endif endif EXTRA_DIST += scripts/testsuite.pcap \ + scripts/sniffer-ipv6.pcap \ scripts/ping.test # leave openssl.test as extra until non bash works diff --git a/scripts/sniffer-ipv6.pcap b/scripts/sniffer-ipv6.pcap new file mode 100644 index 0000000000000000000000000000000000000000..6d8ac43430d0b276ab03394048ddfcf47c0c8c79 GIT binary patch literal 9484 zcmd^FdpuOz+uw6>opCAmP$NQQ>=~CxMdDPB`;c2HArwYqq)?26D3?x3DJ4#bP?Qq7 zkXtySB6TVvx=0c##k&^r!|9@*_mA^_-u3ycnYH$wy}!@%eJ*P~dk;4c4|fHEAVy0S z=U~A1@L0nl>c|>Trn9@e`9ji4I>TAs!e}AMZLyNZVl{L%X{D(pNryxwQ_)qc{Ydh@ zZcJAaji#?krY=Mf9HN96IXIF`Xe4VA1tn8d$?A(pn|$2dok$doRhnufc|8Y)ubU^B zkr$Iua0!A(sED4AhnJ&+7fIgAjp6L=>cH5#kfcIJ$tooI?IYhxsFI61MFriYN!^4x zJF3GAL4)!`+1J6zNaIAXKniy{ig1B5?BE#jzmN&u3f>c5zXMJ{lRn6XJTs1?T7xm{ zb3xz8`!)nw#I6H|6B`t1V#CxD6#824t97LQAH3eUb_^7!?9y9oZRBL+;{LC z9y^LR6<5+^3NELw*K}|dU22KXgs&+BY+BCjZ{tGjiMZ}i5YV8$G62^QjA0+wmo#mC zX#g7y;un2}$OAi#=?U>52GnsPmcmplsN*!S#&krXjz7Yx19-4Oy(|G%78t`mu2=9c z>Lm*FikPgIFb;>T2iCX2;R27<9bNoN^pn+X>|BEcl}80J+k{VX-B^C}t}b^~f!h(_ z0Eja9DH-7bF3Qc0VZ-1tI1Cnp5D@Tza3lN(FCvDBA|i+oB7pFNVE6bTLR2VD0%QcWZ(Fo8xdN-|VaLDx(q$ zmP*FFSA5i&lP?tA_~PXk1JQxgt z4MAClCvQax^zEh4+l@mER+xahMUMq zbMR%-=}cFO06GgEA`rP((mlO>+?j5kE)-Ez7#_qC`FwqS$-Z>=&EDSbWJkIOWgaRy zE(RAynBUEFGhJuG574i$EGMN=GVm@Q;nO*0g-4l z!>_6lh#WK@FE2WSITMkCG4m&qi(x}>!5BUS4aRU|gE1K7dK_nq)rxo9Jo4-HSIA+U z%k;C}70RHO<7$%!WI8#tDbBk&Q=E2XgLb1B&jOPcM@O?rf|K^Sm6!jNSf`qsg`9G{)gMT(aoyp4 zX1{1U)+4(_3`4%m|E#Q9C(kYUHx;)q&(fvTKIdKNuPk-(%VslTkwtEc#|DW) zY41B+xP5~4{8yYx6zY-=8x*$Oonu#i>iP}G9ejF=QR?9!s&rhEZ-GGl5%1RZ3o5tp zlxS{D$;)xm)#ZB8#9639%C(-KdiGUm%X5c4x9Sf+c~EC^t`UpFAedyI2)(wI z(j zQ6FOir3_eQT{SgLvm>q-1l#$Xvv?K|v?Y`5PBJbw3Qk=mu zvFF6?;iYX#R$I;-e$sHm^;vz{p5KqOmQi_&OL12?BJ3`Q6x`C(matB>YeZr)2SH#rgdlu(_EGJ%j|Z0H&YTtwT;r#(PoDeXwF>W-tm_rg3kg; z>MTf72S=0C1oHk5CM#5PQnCWmf2os##Ps8Yb&Xi1BzR$Nh^}3Y#yo>}Mn3#Km()%^ zsoI5$Z^(R%+x$kMrzvNbCx-=rKVHfx==N+gJWjXddA44^Qo0H-Xh_Q!BY35@Gns-?jmTBPYOe26NcI?i~@$>F&2Hy1womkrn^kZwvAups>J9 zDnB4J#D_XhtbKWa9G2i1?BjAQoUR;|?BjA!{wW8Z7u*yyh&PpMu^Dq+$^Ij*C)S`6 zGsoil5tbp_h?*mIjibd;7lJwLBYcAT1OMgceEz5YsN@56R3RIBRrk-RU*Mod)fKq;mzC%x-es-+qU3ry(&cKBPlfs-gL?6S$b!FkK6bzEVa@eV zz^yuV&AB?zS;p;5r{F%jHr0V!If8%mx%e;f+tGqqyEgWWfbN0%r8>tAyYGZPS!^aw zOw#J>Nj6YxYpFf_M11!(<0EzaooSpXE1N`EDR_(Nl1B}u9|*k}u5(m_d-FnOBDw7?$4I z`F>kNsE(*Wj^jm!FgBvfgwa-+~d;PtG&&vxyDNd*m~OK>oT18i1s6RHN4CjHHg zu3@6PEqJ`-V#{S4_c~ukSq)=V!)=sR5hVDn-z2e8Qdmjow0;OOw{TGK z4Wj9#2YKiZ^DNjkCtCUs8dGgH{VkdFvMb2ZE&Mq#X$|@`_@OJ`?vTvkVSn9EyOl4P zpRC_$uQppwz3|ClYrVsk6$Xc}8w^f7YFIMhkr}zu^K)^uwDp#VJ`HZ&{&;3Mjf~B1 z;Vq_DGgSg!=iN?S;}NWD^2&Q*2^CQk`Vj6H?LiXHa^7&OF5*tBlSgvekW)*#-Sax> z`&fqUYg|;Ai`ap-w4*{dmc_0sYs-OhZfLdpthGg3sY}+B?(5L=j@))0-iC-xIQss*`f9dL}}INXa~qK4A`> zx<-_OTne92!alw>P2*Y4=<}6IzT9k;gCK9$PFRm&F71VD!^k=a9=^c_pXIPw#!;=n z9QLny8>2YgysdKZneb@d#;8on+r1!fW7zo-_ymwF%h@YqoB2+lLTKy9bGgA*_v;QZ zA0B}x4d5zef*!|vdZ$E@zP$zKF<@~)IL;tRfVo-WpK8DoPcycOS6FELe zp2w3EU#8FzC~n{%uNT$MnTT9$*MGJ1%*Xd3(Fe(way6L?*e{uxIe+;WxAN*Kxt$Ns zIo*q%C5VLHmgOyuZ&_5pc-7RF?i2JID^qF1p`gJ#*CQ@@8090^p5_~61Usx;chJ>A z>FjGUn`OfUr$O^i%LAp(Y{MvQEznB9yfoE$h))$-)lrji{t%%nuWg;0o;u|SPD8Fp zK~l@8LY7(0r6a|{*50sVohn~m^f1YO7jO0g9xrRsC1eNScB+lZfcKf%SoH+3an<*1 z95BJgKAYpHHee3>xQ&&jYh%?D<2F_sxA6e&wsvoyJ9lwZbZzU6RjT?>ll7U45dHb-n9ud-E&7coo}O32J)VLZoAC z_Or!Zju6C}8}6^nw|X7ae7>OFy8gV!lFMaw&5xvI@>cXOm|v`nxginbe)7cflZkAJ zLJ5}Cs!v_d_hzewJ;cW77#pqIHczbX!G#mOpW=m|=Bn|j2zh$Z=m%n#^IP%tH%c*! zm-=>JQgi=QSx_J{Cz(60lUSE~TuP*ByV;>i*SmXDXZ>lt!(q;gox+DnsD#3&d(q2` zb?if=_t_E>(`Z(odTR}N*q%$Zel*Doi+O?DpZ2EMK%90>>v4kVtoIU=DAMsHTW)L8ou_QbwjNW?7?qM@wI^;`5Fo^ zC;1x0oQAKBVG8ADk6}*swSf^|vlnEmt$AE^UZ$Gx#>~Rjur0z#E_AN$x(!>Z3T+OA zt6y}eyGiA<@~?RIdr_KJgjsHJk#+1MS~uS^ZAL5fvYoVW|U&t7^|P73y#S-I0S&kCgh} zt8_YiA#PLnf>_hwYs_~?u|xsZxA=O|f2m>l`_e|+)Ph4#a)K!3=AHMiENY$O(I1-r zVZTpViBWu7d6$XF8AJOFr{T;V%leQH`D^^!jU-PepmUUcA8W4Wxq~kf7dDklF2&Rl zCh(O4#<0O$#tC#_fidhOHitS`{@mtcI%JRV1$9_I+2%sP=4esIZx)&1qRX3C7%>)S z2D}CRwIpp04F5vSbrTJ8yv3od}d|s!hd#jFaN+*KFE0 zBIB&@+jL@Xr%c8ArPx+C05Oma{O8K|{AVJT+RU-qri-OHbFB6sVNLX@bpUIUPeBf+ z;Zvi}az;382YKYmH+@R)&!o38%&yGtm{^4+zE;Jirs8OnJFfz}?ah5RqqmwipAL;h zx0@|Bxr5U_$%=`b;8PpH7&hql3?QQp7{flE>jZ!9_hT{!0z0>x3IZ7=!2e#rJ)qCR zZ`k1deg4b)kHu9xypJg!e2m>6lzEf>A96gqn2G@>SJHjJzmpi=BrgViyPK1<6KT^< nlGErPh_DFfh%Ec=nNe|L Date: Fri, 4 Oct 2019 14:56:42 -0700 Subject: [PATCH 25/30] Change the GPL version back to v2 for the quickassist_sync files. --- wolfcrypt/src/port/intel/quickassist_sync.c | 2 +- wolfssl/wolfcrypt/port/intel/quickassist_sync.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/port/intel/quickassist_sync.c b/wolfcrypt/src/port/intel/quickassist_sync.c index 79e250f76..19a576000 100644 --- a/wolfcrypt/src/port/intel/quickassist_sync.c +++ b/wolfcrypt/src/port/intel/quickassist_sync.c @@ -6,7 +6,7 @@ * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, diff --git a/wolfssl/wolfcrypt/port/intel/quickassist_sync.h b/wolfssl/wolfcrypt/port/intel/quickassist_sync.h index 5b21ad4d9..974d2b500 100644 --- a/wolfssl/wolfcrypt/port/intel/quickassist_sync.h +++ b/wolfssl/wolfcrypt/port/intel/quickassist_sync.h @@ -6,7 +6,7 @@ * * wolfSSL is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or + * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * wolfSSL is distributed in the hope that it will be useful, From f025f083150b68744d995d755034bb03c9bc269a Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 4 Oct 2019 17:06:35 -0700 Subject: [PATCH 26/30] Sniffer touches for Windows. --- src/sniffer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sniffer.c b/src/sniffer.c index 1258ec350..a358f5f2e 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -34,6 +34,8 @@ #ifndef _WIN32 #include +#else + #include #endif #ifdef _WIN32 @@ -1177,7 +1179,7 @@ static void SetError(int idx, char* error, SnifferSession* session, int fatal) /* Compare IpAddrInfo structs */ -static inline int MatchAddr(IpAddrInfo l, IpAddrInfo r) +static WC_INLINE int MatchAddr(IpAddrInfo l, IpAddrInfo r) { if (l.version == r.version) { if (l.version == IPV4) From 8ec90339d941fd6ae0f5ffde6752728a18f4422e Mon Sep 17 00:00:00 2001 From: John Safranek Date: Sat, 5 Oct 2019 19:26:41 -0700 Subject: [PATCH 27/30] Change the sniffer testsuite to do the IPv6 test when the "-6" option is on the command line. --- scripts/sniffer-testsuite.test | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/sniffer-testsuite.test b/scripts/sniffer-testsuite.test index 6224c781b..491c1197e 100755 --- a/scripts/sniffer-testsuite.test +++ b/scripts/sniffer-testsuite.test @@ -8,11 +8,15 @@ echo -e "\nStaring snifftest on testsuite.pcap...\n" RESULT=$? [ $RESULT -ne 0 ] && echo -e "\nsnifftest failed\n" && exit 1 -echo -e "\nStaring snifftest on sniffer-ipv6.pcap...\n" -./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-ipv6.pcap ./certs/server-key.pem ::1 11111 -RESULT=$? -[ $RESULT -ne 0 ] && echo -e "\nsnifftest (ipv6) failed\n" && exit 1 +if test $# -ne 0 && test "x$1" = "x-6"; +then + echo -e "\nStaring snifftest on sniffer-ipv6.pcap...\n" + ./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-ipv6.pcap ./certs/server-key.pem ::1 11111 + + RESULT=$? + [ $RESULT -ne 0 ] && echo -e "\nsnifftest (ipv6) failed\n" && exit 1 +fi echo -e "\nSuccess!\n" From ff15b3cfaa8a7e93cf33bc3559251cf1715e288f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 8 Oct 2019 11:32:57 -0700 Subject: [PATCH 28/30] better display of the IPv6 addresses in the sniffer --- src/sniffer.c | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index a358f5f2e..5cc51802d 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -961,25 +961,9 @@ static void TracePacket(void) /* Convert network byte order address into human readable */ -static char* IpToS(word32 addr, char* str) +static const char* IpToS(int version, void* src, char* dst) { - byte* p = (byte*)&addr; - - SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); - - return str; -} - - -/* Convert network byte order address into human readable */ -static char* Ip6ToS(byte* addr, char* str) -{ - byte* p = (byte*)addr; - - /* Very incorrect. XXX */ - SNPRINTF(str, TRACE_MSG_SZ, "::%d", p[15]); - - return str; + return inet_ntop(version, src, dst, TRACE_MSG_SZ); } @@ -989,8 +973,9 @@ static void TraceIP(IpHdr* iphdr) if (TraceOn) { char src[TRACE_MSG_SZ]; char dst[TRACE_MSG_SZ]; - fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst), - IpToS(iphdr->src, src)); + fprintf(TraceFile, "\tdst:%s src:%s\n", + IpToS(AF_INET, &iphdr->dst, dst), + IpToS(AF_INET, &iphdr->src, src)); } } @@ -1001,8 +986,9 @@ static void TraceIP6(Ip6Hdr* iphdr) if (TraceOn) { char src[TRACE_MSG_SZ]; char dst[TRACE_MSG_SZ]; - fprintf(TraceFile, "\tdst: %s src: %s\n", Ip6ToS(iphdr->dst, dst), - Ip6ToS(iphdr->src, src)); + fprintf(TraceFile, "\tdst: %s src: %s\n", + IpToS(AF_INET6, iphdr->dst, dst), + IpToS(AF_INET6, iphdr->src, src)); } } From 89db0da0aa20d7f8b141d1e212ba1b7779c87722 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 8 Oct 2019 16:49:38 -0700 Subject: [PATCH 29/30] Synchronous Quick Assist Support for Sniffer 1. Fixed a compiler warnings. 2. Fixed a memory issue when using the storage callback with QAT. --- scripts/include.am | 2 +- src/sniffer.c | 2 +- sslSniffer/sslSnifferTest/snifftest.c | 9 +++++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/scripts/include.am b/scripts/include.am index 3a3d7995a..268e3ec00 100644 --- a/scripts/include.am +++ b/scripts/include.am @@ -84,7 +84,7 @@ endif endif EXTRA_DIST += scripts/testsuite.pcap \ - scripts/sniffer-ipv6.pcap \ + scripts/sniffer-ipv6.pcap \ scripts/ping.test # leave openssl.test as extra until non bash works diff --git a/src/sniffer.c b/src/sniffer.c index 5cc51802d..2754dcade 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3758,7 +3758,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, word32 i, offset, headerSz, qty, remainder; Trace(CHAIN_INPUT_STR); - headerSz = (word32)*sslFrame - (word32)chain[0].iov_base; + headerSz = (word64)*sslFrame - (word64)chain[0].iov_base; remainder = *sslBytes; if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 6438d7ced..f6e6866ca 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -26,6 +26,10 @@ #include +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB + #include +#endif + #ifdef _WIN32 #define WOLFSSL_SNIFFER #endif @@ -269,9 +273,10 @@ static int myStoreDataCb(const unsigned char* decryptBuf, if (*data == NULL) { byte* tmpData; - tmpData = (byte*)realloc(*data, decryptBufSz + 1); + tmpData = (byte*)XREALLOC(*data, decryptBufSz + 1, + NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmpData == NULL) { - free(*data); + XFREE(*data, NULL, DYNAMIC_TYPE_TMP_BUFFER); *data = NULL; return -1; } From f0dfe5355b620fe3b29ecb00c234cdc5559175fc Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 14 Oct 2019 10:17:37 -0700 Subject: [PATCH 30/30] Sniffer for IPv6 1. Better length checking on the IPv6 extension headers. 2. Removed the default size update analogous to the IPv4 header check function. It cannot ever be 0, so the update was unnecessary. --- src/sniffer.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 2754dcade..bad212021 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1642,7 +1642,7 @@ int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) { int version = IP_V(iphdr); - int exthdrsz = 0; + int exthdrsz = IP6_HDR_SZ; TraceIP6(iphdr); Trace(IP_CHECK_STR); @@ -1657,6 +1657,10 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) Ip6ExtHdr* exthdr = (Ip6ExtHdr*)((byte*)iphdr + IP6_HDR_SZ); do { int hdrsz = (exthdr->length + 1) * 8; + if (hdrsz > length - exthdrsz) { + SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); + return -1; + } exthdrsz += hdrsz; exthdr = (Ip6ExtHdr*)((byte*)exthdr + hdrsz); } @@ -1671,7 +1675,7 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) } #endif - info->length = IP6_HDR_SZ + exthdrsz; + info->length = exthdrsz; info->total = ntohs(iphdr->length) + info->length; /* IPv6 doesn't include its own header size in the length like v4. */ info->src.version = IPV6; @@ -1679,11 +1683,6 @@ static int CheckIp6Hdr(Ip6Hdr* iphdr, IpInfo* info, int length, char* error) info->dst.version = IPV6; XMEMCPY(info->dst.ip6, iphdr->dst, sizeof(info->dst.ip6)); - /* This needs to massage the length and size to match what the sniffer - * expects. IPv4 and IPv6 treat the length parameter differently. */ - if (info->total == 0) - info->total = length; /* reassembled may be off */ - return 0; }