From 1781a9fd76bd8ebf4f26c6d014acda2ff03df7bd Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 16 May 2019 10:56:10 -0700 Subject: [PATCH 1/3] Sniffer Logging 1. Capture the SNI in the SSLInfo. 2. Save the private key length and capture it in the SSLInfo. --- src/sniffer.c | 37 ++++++++++++++++++++++++++++++++----- wolfssl/sniffer.h | 2 ++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 78279f552..70bccedde 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -374,12 +374,16 @@ typedef struct SnifferSession { FinCaputre finCaputre; /* retain out of order FIN s */ Flags flags; /* session flags */ time_t lastUsed; /* last used ticks */ + word32 keySz; /* size of the private key */ PacketBuffer* cliReassemblyList; /* client out of order packets */ PacketBuffer* srvReassemblyList; /* server out of order packets */ word32 cliReassemblyMemory; /* client packet memory used */ word32 srvReassemblyMemory; /* server packet memory used */ struct SnifferSession* next; /* for hash table list */ byte* ticketID; /* mac ID of session ticket */ +#ifdef HAVE_SNI + const char* sni; /* server name indication */ +#endif #ifdef HAVE_EXTENDED_MASTER HsHashes* hash; #endif @@ -1025,12 +1029,20 @@ static void TraceSessionInfo(SSLInfo* sslInfo) if (TraceOn) { if (sslInfo != NULL && sslInfo->isValid) { fprintf(TraceFile, - "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s)\n", + "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) " + #ifdef HAVE_SNI + "sni:(%s) " + #endif + "keySize:(%u)\n", sslInfo->protocolVersionMajor, sslInfo->protocolVersionMinor, sslInfo->serverCipherSuite0, sslInfo->serverCipherSuite, - sslInfo->serverCipherSuiteName); + sslInfo->serverCipherSuiteName, + #ifdef HAVE_SNI + sslInfo->serverNameIndication, + #endif + sslInfo->keySize); } } } @@ -1537,6 +1549,10 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } if (ret == 0) { + session->keySz = length * 8; + /* length is the key size in bytes */ + session->sslServer->arrays->preMasterSz = SECRET_LEN; + do { #ifdef WOLFSSL_ASYNC_CRYPT ret = wc_AsyncWait(ret, &key.asyncDev, @@ -1545,7 +1561,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, if (ret >= 0) { ret = wc_RsaPrivateDecrypt(input, length, session->sslServer->arrays->preMasterSecret, - SECRET_LEN, &key); + session->sslServer->arrays->preMasterSz, &key); } } while (ret == WC_PENDING_E); @@ -1554,8 +1570,6 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } } - session->sslServer->arrays->preMasterSz = SECRET_LEN; - wc_FreeRsaKey(&key); } @@ -1604,6 +1618,9 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } if (ret == 0) { + session->keySz = (length - 1) * 4; + /* The length is the key size in bytes, times 2 for the (x,y) + * coordinates, plus 1 for the type. */ session->sslServer->arrays->preMasterSz = ENCRYPT_LEN; do { @@ -1953,6 +1970,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, FATAL_ERROR_STATE); return -1; } + session->sni = namedKey->name; break; } else @@ -3608,6 +3626,15 @@ static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) sslInfo->serverCipherSuiteName [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; } + sslInfo->keySize = session->keySz; + #ifdef HAVE_SNI + if (NULL != session->sni) { + XSTRNCPY((char*)sslInfo->serverNameIndication, + session->sni, sizeof(sslInfo->serverNameIndication)); + sslInfo->serverNameIndication + [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; + } + #endif TraceSessionInfo(sslInfo); } } diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index 28ca51a01..aef4d4b0d 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -115,6 +115,8 @@ typedef struct SSLInfo unsigned char serverCipherSuite; /* second byte, actual suite */ unsigned char serverCipherSuiteName[256]; /* cipher name, e.g., "TLS_RSA_..." */ + unsigned char serverNameIndication[128]; + unsigned int keySize; } WOLFSSL_PACK SSLInfo; From 245db5d5ce97bf2409dbb723de3904ac571e129b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 16 May 2019 14:07:44 -0700 Subject: [PATCH 2/3] Expand Sniffer Logging 1. Moved the CopySessionInfo function to a better location for the additions. 2. Added accessors for a callback and application context data. 3. Added a callback that is called from ProcessClientKeyExchange when everything is known about the start of the current session. 4. Added the private key size and the server name indication to the SSLInfo record. --- src/sniffer.c | 119 ++++++++++++++++++++++++++++++---------------- wolfssl/sniffer.h | 8 ++++ 2 files changed, 86 insertions(+), 41 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 70bccedde..ca33f19df 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -406,6 +406,10 @@ static int RecoveryEnabled = 0; /* global switch */ static int MaxRecoveryMemory = -1; /* per session max recovery memory */ static word32 MissedDataSessions = 0; /* # of sessions with missed data */ +/* Connection Info Callback */ +static SSLConnCb ConnectionCb; +static void* ConnectionCbCtx = NULL; + static void UpdateMissedDataSessions(void) { @@ -1490,6 +1494,58 @@ static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size) } +/* Copies the session's infomation to the provided sslInfo. Skip copy if + * SSLInfo is not provided. */ +static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) +{ + if (NULL != sslInfo) { + XMEMSET(sslInfo, 0, sizeof(SSLInfo)); + + /* Pass back Session Info after we have processed the Server Hello. */ + if (0 != session->sslServer->options.cipherSuite) { + const char* pCipher; + + sslInfo->isValid = 1; + sslInfo->protocolVersionMajor = session->sslServer->version.major; + sslInfo->protocolVersionMinor = session->sslServer->version.minor; + sslInfo->serverCipherSuite0 = + session->sslServer->options.cipherSuite0; + sslInfo->serverCipherSuite = + session->sslServer->options.cipherSuite; + + pCipher = wolfSSL_get_cipher(session->sslServer); + if (NULL != pCipher) { + XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher, + sizeof(sslInfo->serverCipherSuiteName)); + sslInfo->serverCipherSuiteName + [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; + } + sslInfo->keySize = session->keySz; + #ifdef HAVE_SNI + if (NULL != session->sni) { + XSTRNCPY((char*)sslInfo->serverNameIndication, + session->sni, sizeof(sslInfo->serverNameIndication)); + sslInfo->serverNameIndication + [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; + } + #endif + TraceSessionInfo(sslInfo); + } + } +} + + +/* Call the session connection start callback. */ +static void CallConnectionCb(SnifferSession* session) +{ + if (ConnectionCb != NULL) { + SSLInfo info; + CopySessionInfo(session, &info); + ConnectionCb((const void*)session, &info, ConnectionCbCtx); + } +} + + /* Process Client Key Exchange, RSA or static ECDH */ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, SnifferSession* session, char* error) @@ -1698,6 +1754,8 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } #endif + CallConnectionCb(session); + return ret; } @@ -2521,6 +2579,10 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, session->cliSeqStart = tcpInfo->sequence; session->cliExpected = 1; /* relative */ session->lastUsed= time(NULL); + session->keySz = 0; +#ifdef HAVE_SNI + session->sni = NULL; +#endif session->context = GetSnifferServer(ipInfo, tcpInfo); if (session->context == NULL) { @@ -3600,47 +3662,6 @@ static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, } -/* Copies the session's infomation to the provided sslInfo. Skip copy if - * SSLInfo is not provided. */ -static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) -{ - if (NULL != sslInfo) { - XMEMSET(sslInfo, 0, sizeof(SSLInfo)); - - /* Pass back Session Info after we have processed the Server Hello. */ - if (0 != session->sslServer->options.cipherSuite) { - const char* pCipher; - - sslInfo->isValid = 1; - sslInfo->protocolVersionMajor = session->sslServer->version.major; - sslInfo->protocolVersionMinor = session->sslServer->version.minor; - sslInfo->serverCipherSuite0 = - session->sslServer->options.cipherSuite0; - sslInfo->serverCipherSuite = - session->sslServer->options.cipherSuite; - - pCipher = wolfSSL_get_cipher(session->sslServer); - if (NULL != pCipher) { - XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher, - sizeof(sslInfo->serverCipherSuiteName)); - sslInfo->serverCipherSuiteName - [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; - } - sslInfo->keySize = session->keySz; - #ifdef HAVE_SNI - if (NULL != session->sni) { - XSTRNCPY((char*)sslInfo->serverNameIndication, - session->sni, sizeof(sslInfo->serverNameIndication)); - sslInfo->serverNameIndication - [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; - } - #endif - TraceSessionInfo(sslInfo); - } - } -} - - /* 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, @@ -3808,5 +3829,21 @@ int ssl_GetSessionStats(unsigned int* active, unsigned int* total, +int ssl_SetConnectionCb(SSLConnCb cb) +{ + ConnectionCb = cb; + return 0; +} + + + +int ssl_SetConnectionCtx(void* ctx) +{ + ConnectionCbCtx = ctx; + return 0; +} + + + #endif /* WOLFSSL_SNIFFER */ #endif /* WOLFCRYPT_ONLY */ diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index aef4d4b0d..33b26da87 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -125,6 +125,14 @@ SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfo( const unsigned char* packet, int length, unsigned char** data, SSLInfo* sslInfo, char* error); +typedef void (*SSLConnCb)(const void* session, SSLInfo* info, void* ctx); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCb(SSLConnCb cb); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCtx(void* ctx); + #ifdef __cplusplus } /* extern "C" */ From 86b558300bac533ff43cf499694b2adf4b346d65 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 23 May 2019 13:02:52 -0700 Subject: [PATCH 3/3] Sniffer Logging 1. When collecting the key size to log it, use the constant WOLFSSL_BIT_SIZE for the bytes->bits multiply. 2. When converting the size of the ECC key, break the steps out more explicitly. Also update the comment to be more accurate. --- src/sniffer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index ca33f19df..db78c2c9e 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1605,7 +1605,7 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } if (ret == 0) { - session->keySz = length * 8; + session->keySz = length * WOLFSSL_BIT_SIZE; /* length is the key size in bytes */ session->sslServer->arrays->preMasterSz = SECRET_LEN; @@ -1674,9 +1674,10 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, } if (ret == 0) { - session->keySz = (length - 1) * 4; - /* The length is the key size in bytes, times 2 for the (x,y) - * coordinates, plus 1 for the type. */ + session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE; + /* Length is in bytes. Subtract 1 for the ECC key type. Divide + * by two as the key is in (x,y) coordinates, where x and y are + * the same size, the key size. Convert from bytes to bits. */ session->sslServer->arrays->preMasterSz = ENCRYPT_LEN; do {