From 2dd169f9a17763c8351dc31f1420dfd02c0b40af Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 30 Jun 2021 15:19:48 -0700 Subject: [PATCH 01/10] Added new sniffer API for callback for key use `ssl_SetKeyCallback`. Support indicated by `WOLFSSL_SNIFFER_KEY_CALLBACK`. Trace cleanup for custom error. --- src/sniffer.c | 107 +++++++++++++++++++++++++++++++++++-------- sslSniffer/README.md | 28 ++++++++++- wolfssl/sniffer.h | 29 ++++++++++-- 3 files changed, 140 insertions(+), 24 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 2d915d9c2..dd8f6e32c 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -349,6 +349,9 @@ static const char* const msgTable[] = /* *nix version uses table above */ static void GetError(int idx, char* str) { + if (str == NULL || + idx < 0 || idx > (int)(sizeof(msgTable)/sizeof(const char* const))) + return; XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1); str[MAX_ERROR_LEN-1] = '\0'; } @@ -360,6 +363,8 @@ static void GetError(int idx, char* str) /* Windows version uses .rc table */ static void GetError(int idx, char* buffer) { + if (buffer == NULL) + return; if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN)) buffer[0] = 0; } @@ -517,10 +522,9 @@ typedef struct SnifferSession { /* Sniffer Server List and mutex */ -static WOLFSSL_GLOBAL SnifferServer* ServerList = 0; +static WOLFSSL_GLOBAL SnifferServer* ServerList = NULL; static WOLFSSL_GLOBAL wolfSSL_Mutex ServerListMutex; - /* Session Hash Table, mutex, and count */ static WOLFSSL_GLOBAL SnifferSession* SessionTable[HASH_SIZE]; static WOLFSSL_GLOBAL wolfSSL_Mutex SessionMutex; @@ -536,7 +540,7 @@ static WOLFSSL_GLOBAL word32 MissedDataSessions = 0; /* Connection Info Callback */ static WOLFSSL_GLOBAL SSLConnCb ConnectionCb; -static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL; +static WOLFSSL_GLOBAL void* ConnectionCbCtx = NULL; #ifdef WOLFSSL_SNIFFER_STATS /* Sessions Statistics */ @@ -544,10 +548,15 @@ static WOLFSSL_GLOBAL SSLStats SnifferStats; static WOLFSSL_GLOBAL wolfSSL_Mutex StatsMutex; #endif +#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK +static WOLFSSL_GLOBAL SSLKeyCb KeyCb; +static WOLFSSL_GLOBAL void* KeyCbCtx = NULL; +#endif + #ifdef WOLFSSL_SNIFFER_WATCH /* Watch Key Callback */ static WOLFSSL_GLOBAL SSLWatchCb WatchCb; -static WOLFSSL_GLOBAL void* WatchCbCtx = NULL; +static WOLFSSL_GLOBAL void* WatchCbCtx = NULL; #endif #ifdef WOLFSSL_SNIFFER_STORE_DATA_CB @@ -993,18 +1002,26 @@ typedef struct TcpHdr { /* Use platform specific GetError to write to trace file if tracing */ -static void Trace(int idx) +static void TraceError(int idx, char* error) { if (TraceOn) { char myBuffer[MAX_ERROR_LEN]; - GetError(idx, myBuffer); - XFPRINTF(TraceFile, "\t%s\n", myBuffer); + if (error == NULL) { + error = myBuffer; + GetError(idx, myBuffer); + } + XFPRINTF(TraceFile, "\t%s\n", error); #ifdef DEBUG_SNIFFER - XFPRINTF(stderr, "\t%s\n", myBuffer); + XFPRINTF(stderr, "\t%s\n", error); #endif } } +static void Trace(int idx) +{ + TraceError(idx, NULL); +} + /* Show TimeStamp for beginning of packet Trace */ static void TraceHeader(void) @@ -1255,7 +1272,7 @@ static void TraceStat(const char* name, int add) static void SetError(int idx, char* error, SnifferSession* session, int fatal) { GetError(idx, error); - Trace(idx); + TraceError(idx, error); if (session && fatal == FATAL_ERROR_STATE) session->flags.fatalError = 1; } @@ -1563,7 +1580,7 @@ static int CreateWatchSnifferServer(char* error) return -1; } InitSnifferServer(sniffer); - sniffer->ctx = wolfSSL_CTX_new(SSLv23_client_method()); + sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); FreeSnifferServer(sniffer); @@ -1573,7 +1590,12 @@ static int CreateWatchSnifferServer(char* error) if (CryptoDeviceId != INVALID_DEVID) wolfSSL_CTX_SetDevId(sniffer->ctx, CryptoDeviceId); #endif + + /* add to server list */ + wc_LockMutex(&ServerListMutex); + sniffer->next = ServerList; ServerList = sniffer; + wc_UnLockMutex(&ServerListMutex); return 0; } @@ -1659,7 +1681,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, sniffer->server = serverIp; sniffer->port = port; - sniffer->ctx = wolfSSL_CTX_new(SSLv23_client_method()); + sniffer->ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); if (!sniffer->ctx) { SetError(MEMORY_STR, error, NULL, 0); #ifdef HAVE_SNI @@ -2140,6 +2162,10 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, if (ksInfo && ksInfo->curve_id != 0) useEccCurveId = ksInfo->curve_id; #endif + int devId = INVALID_DEVID; +#ifdef WOLF_CRYPTO_CB + devId = CryptoDeviceId; +#endif #ifndef NO_RSA /* Static RSA */ @@ -2149,7 +2175,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, keyBuf = keys->rsaKey; - ret = wc_InitRsaKey(&key, 0); + ret = wc_InitRsaKey_ex(&key, NULL, devId); if (ret == 0) { ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length); if (ret != 0) { @@ -2227,6 +2253,19 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, keyBuf = keys->dhKey; +#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK + if (KeyCb != NULL) { + ret = KeyCb(session, ksInfo->named_group, + session->srvKs.key, session->srvKs.key_len, + session->cliKs.key, session->cliKs.key_len, + keyBuf, KeyCbCtx, error); + if (ret != 0) { + SetError(-1, error, session, FATAL_ERROR_STATE); + return ret; + } + } +#endif + /* get DH params */ switch (ksInfo->named_group) { #ifdef HAVE_FFDHE_2048 @@ -2263,7 +2302,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, return BAD_FUNC_ARG; } - ret = wc_InitDhKey(&dhKey); + ret = wc_InitDhKey_ex(&dhKey, NULL, devId); if (ret == 0) { ret = wc_DhSetKey(&dhKey, (byte*)params->p, params->p_len, @@ -2315,8 +2354,22 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, int length, keyInit = 0, pubKeyInit = 0; keyBuf = keys->ecKey; + +#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK + if (KeyCb != NULL && ksInfo) { + ret = KeyCb(session, ksInfo->named_group, + session->srvKs.key, session->srvKs.key_len, + session->cliKs.key, session->cliKs.key_len, + keyBuf, KeyCbCtx, error); + if (ret != 0) { + SetError(-1, error, session, FATAL_ERROR_STATE); + return ret; + } + } +#endif + idx = 0; - ret = wc_ecc_init(&key); + ret = wc_ecc_init_ex(&key, NULL, devId); if (ret == 0) { keyInit = 1; ret = wc_ecc_init(&pubKey); @@ -3100,6 +3153,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, keys.ecKey = session->sslServer->staticKE.ecKey; #endif #endif + ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len, session, error, &session->cliKs, &keys); if (ret != 0) { @@ -3507,7 +3561,7 @@ static int ProcessCertificate(const byte* input, int* sslBytes, return KeyWatchCall(session, input, certSz, error); } -#endif +#endif /* WOLFSSL_SNIFFER_WATCH */ /* Process Finished */ @@ -3813,8 +3867,11 @@ static int DoHandShake(const byte* input, int* sslBytes, session->sslClient->options.haveEMS = 0; } #endif - if (ret == 0) + if (ret == 0) { ret = ProcessClientKeyExchange(input, sslBytes, session, error); + if (ret != 0) + SetError(GOT_CLIENT_KEY_EX_STR, error, session, FATAL_ERROR_STATE); + } break; case certificate_verify: Trace(GOT_CERT_VER_STR); @@ -5676,19 +5733,22 @@ int ssl_ReadResetStatistics(SSLStats* stats) int ssl_SetWatchKeyCallback_ex(SSLWatchCb cb, int devId, char* error) { +#ifdef WOLF_CRYPTO_CB + if (CryptoDeviceId == INVALID_DEVID) + CryptoDeviceId = devId; +#else (void)devId; +#endif WatchCb = cb; return CreateWatchSnifferServer(error); } - int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error) { WatchCb = cb; return CreateWatchSnifferServer(error); } - int ssl_SetWatchKeyCtx(void* ctx, char* error) { (void)error; @@ -5696,7 +5756,6 @@ int ssl_SetWatchKeyCtx(void* ctx, char* error) return 0; } - int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz, int keyType, char* error) { @@ -5739,7 +5798,6 @@ int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz, return 0; } - int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, const char* password, char* error) { @@ -5786,5 +5844,14 @@ int ssl_SetStoreDataCallback(SSLStoreDataCb cb) #endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */ +#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK +int ssl_SetKeyCallback(SSLKeyCb cb, void* cbCtx) +{ + KeyCb = cb; + KeyCbCtx = cbCtx; + return 0; +} +#endif + #endif /* WOLFSSL_SNIFFER */ #endif /* WOLFCRYPT_ONLY */ diff --git a/sslSniffer/README.md b/sslSniffer/README.md index ad5bade76..c687fa5be 100644 --- a/sslSniffer/README.md +++ b/sslSniffer/README.md @@ -369,6 +369,32 @@ Return Values: * -1 if a problem occurred +### ssl_SetKeyCallback + +This feature is enabled by default and will be called when a key is required for a session using static ephemeral keys with TLS v1.3. + +The public key being used will be provided allowing lookup of the corresponding private key. + +The `privKey` buffer is a dynamic buffer assigned via a call to setup a static ephemeral key via `ssl_SetNamedEphemeralKey` or `ssl_SetEphemeralKey`. + +```c +typedef int (*SSLKeyCb)(void* vSniffer, int namedGroup, + const unsigned char* srvPub, unsigned int srvPubSz, + const unsigned char* cliPub, unsigned int cliPubSz, + unsigned char* privKey, unsigned int* privKeySz, + void* ctx, char* error); + +int ssl_SetKeyCallback(SSLKeyCb cb, void* ctx, char* error); +``` + +The parameter `vSniffer` is a typeless pointer to the current sniffer session (`SnifferSession`). The `namedGroup` is the TLS defined named groups like `WOLFSSL_ECC_SECP256R1` or `WOLFSSL_FFDHE_2048`. The server and client public key information are provided to lookup the private key to be used for this session. The loaded private key to be used will be passed in `key`. If a different key should be used it can optionally be returned in `privKey` and `privKeySz`. + +Return Values: + +* 0 on success +* -1 if a problem occurred, the string error will hold a message describing the problem + + ## API Usage: SSL Statistics options For an example on the use of the sniffer stats option, search the source `snifftest.c` for `WOLFSSL_SNIFFER_STATS`. @@ -460,7 +486,7 @@ typedef int (*SSLWatchCb)(void* vSniffer, void* ctx, char* error); ``` -The parameter `vSniffer` is a typeless pointer to the current sniffer session and is meant to be passed directly to the function `ssl_SetWatchKey`. `certHash` is a SHA-256 hash of the certificate sent by the server, and its size is `certHashSz`. A pointer to certificate message’s payload is provided in the parameter `certChain`, and the certificate chain’s size in `certChainSz`. This will be a list of pairs of 24-bit certificate sizes and raw DER certificates in network order from the wire. The application space callback context data is provided in parameter ctx and is set by the function `ssl_SetWatchKeyCtx`. Any error string is copied into parameter error. Your callback function can use these values to locate the appropriate private key and load it into the sniffer session with the function `ssl_SetWatchKey`. +The parameter `vSniffer` is a typeless pointer to the current sniffer session and is meant to be passed directly to the function `ssl_SetWatchKey_file` or `ssl_SetWatchKey_buffer`. The `certHash` is a SHA-256 hash of the certificate sent by the server, and its size is `certHashSz`. A pointer to certificate message’s payload is provided in the parameter `certChain`, and the certificate chain’s size in `certChainSz`. This will be a list of pairs of 24-bit certificate sizes and raw DER certificates in network order from the wire. The application space callback context data is provided in parameter ctx and is set by the function `ssl_SetWatchKeyCtx`. Any error string is copied into parameter error. Your callback function can use these values to locate the appropriate private key and load it into the sniffer session with the function `ssl_SetWatchKey_file` or `ssl_SetWatchKey_buffer`. Return Values: diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index fb48498a4..a68ef21a6 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -25,6 +25,7 @@ #define WOLFSSL_SNIFFER_H #include +#include #ifdef _WIN32 #ifdef SSL_SNIFFER_EXPORTS @@ -199,7 +200,21 @@ SSL_SNIFFER_API int ssl_ReadStatistics(SSLStats* stats); WOLFSSL_API SSL_SNIFFER_API int ssl_ReadResetStatistics(SSLStats* stats); +typedef int (*SSLKeyCb)(void* vSniffer, int namedGroup, + const unsigned char* srvPub, unsigned int srvPubSz, + const unsigned char* cliPub, unsigned int cliPubSz, + DerBuffer* privKey, void* cbCtx, char* error); +#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_TLS13) +/* macro indicating support for key callback */ +#undef WOLFSSL_SNIFFER_KEY_CALLBACK +#define WOLFSSL_SNIFFER_KEY_CALLBACK +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetKeyCallback(SSLKeyCb cb, void* cbCtx); +#endif + + +#ifdef WOLFSSL_SNIFFER_WATCH typedef int (*SSLWatchCb)(void* vSniffer, const unsigned char* certHash, unsigned int certHashSz, @@ -226,29 +241,37 @@ WOLFSSL_API SSL_SNIFFER_API int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, const char* password, char* error); +#endif - +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB 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); +#endif +#ifdef WOLFSSL_SNIFFER_STORE_DATA_CB WOLFSSL_API SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfoStoreData( const unsigned char* packet, int length, void* ctx, SSLInfo* sslInfo, char* error); +#endif - +#ifdef WOLFSSL_SNIFFER_CHAIN_INPUT WOLFSSL_API SSL_SNIFFER_API int ssl_DecodePacketWithChain(void* vChain, unsigned int chainSz, unsigned char** data, char* error); +#endif - +#if defined(WOLFSSL_SNIFFER_CHAIN_INPUT) && \ + defined(WOLFSSL_SNIFFER_STORE_DATA_CB) WOLFSSL_API SSL_SNIFFER_API int ssl_DecodePacketWithChainSessionInfoStoreData( void* vChain, unsigned int chainSz, void* ctx, SSLInfo* sslInfo, char* error); +#endif + #ifdef __cplusplus } /* extern "C" */ From 26789ef877064e6840f5232ceb9a76202d028ad0 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 2 Jul 2021 13:24:25 -0700 Subject: [PATCH 02/10] Fix variable declaration mid-code. --- src/sniffer.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sniffer.c b/src/sniffer.c index dd8f6e32c..11a496119 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -25,6 +25,7 @@ #endif #include +#include #include /* xctime */ @@ -2159,10 +2160,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, DerBuffer* keyBuf; #ifdef HAVE_ECC int useEccCurveId = ECC_CURVE_DEF; +#endif + int devId = INVALID_DEVID; + +#ifdef HAVE_ECC if (ksInfo && ksInfo->curve_id != 0) useEccCurveId = ksInfo->curve_id; #endif - int devId = INVALID_DEVID; #ifdef WOLF_CRYPTO_CB devId = CryptoDeviceId; #endif From ddbe0e6daba198f53104813c7387c221a2491381 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Jul 2021 09:31:59 -0700 Subject: [PATCH 03/10] Fix for sniffer stats on resume miss. The logic for `hello_retry_request` will no longer try and do resume, so restore `BAD_SESSION_RESUME_STR` error. --- src/sniffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 11a496119..8ea894460 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2797,11 +2797,11 @@ static int DoResume(SnifferSession* session, char* error) session->sslServer->arrays->masterSecret, 0); } if (resume == NULL) { - /* a session id without resume is okay with hello_retry_request */ #ifdef WOLFSSL_SNIFFER_STATS - INC_STAT(SnifferStats.sslStandardConns); + INC_STAT(SnifferStats.sslResumeMisses); #endif - return 0; + SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); + return -1; } /* make sure client has master secret too */ From 4cb076f22be60b7e8d1e0b1d1cc9c4873afa44dc Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Jul 2021 09:49:13 -0700 Subject: [PATCH 04/10] Cleanup to remove duplicate stat `sslResumptionValid`. Add print of `sslResumptionInserts`. --- src/sniffer.c | 5 ++--- sslSniffer/sslSnifferTest/snifftest.c | 2 ++ wolfssl/sniffer.h | 2 -- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 8ea894460..a798c52c7 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2821,7 +2821,6 @@ static int DoResume(SnifferSession* session, char* error) 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); @@ -3607,9 +3606,9 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); if (sess == NULL) { AddSession(session->sslServer); /* don't re add */ -#ifdef WOLFSSL_SNIFFER_STATS + #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslResumptionInserts); -#endif + #endif } session->flags.cached = 1; } diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 2816b179f..a8d2db930 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -170,6 +170,8 @@ static void DumpStats(void) sslStats.sslResumedConns); printf("SSL Stats (sslEphemeralMisses):%lu\n", sslStats.sslEphemeralMisses); + printf("SSL Stats (sslResumptionInserts):%lu\n", + sslStats.sslResumptionInserts); printf("SSL Stats (sslResumeMisses):%lu\n", sslStats.sslResumeMisses); printf("SSL Stats (sslCiphersUnsupported):%lu\n", diff --git a/wolfssl/sniffer.h b/wolfssl/sniffer.h index a68ef21a6..447a149b8 100644 --- a/wolfssl/sniffer.h +++ b/wolfssl/sniffer.h @@ -183,8 +183,6 @@ 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 4f055653c7b76ce29feb90b17dc39cca7ef90270 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Jul 2021 13:50:08 -0700 Subject: [PATCH 05/10] Restore TLS v1.3 `hello_retry` behavior with session id. Fix for SNI with default (no name) putting newline due to fgets. --- src/sniffer.c | 19 ++++++++++++------- sslSniffer/sslSnifferTest/snifftest.c | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index a798c52c7..db85bfea9 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2789,19 +2789,24 @@ static int DoResume(SnifferSession* session, char* error) if (IsAtLeastTLSv1_3(session->sslServer->version)) { resume = GetSession(session->sslServer, session->sslServer->session.masterSecret, 0); + if (resume == NULL) { + /* TLS v1.3 with hello_retry uses session_id even for new session, + so ignore error here */ + return 0; + } } else #endif { 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; + if (resume == NULL) { + #ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumeMisses); + #endif + SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); + return -1; + } } /* make sure client has master secret too */ diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index a8d2db930..e95d5dd68 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -366,6 +366,15 @@ static int load_key(const char* name, const char* server, int port, return ret; } +static void TrimNewLine(char* str) +{ + word32 strSz = 0; + if (str) + strSz = (word32)XSTRLEN(str); + if (strSz > 0 && (str[strSz-1] == '\n' || str[strSz-1] == '\r')) + str[strSz-1] = '\0'; +} + int main(int argc, char** argv) { int ret = 0; @@ -504,13 +513,10 @@ int main(int argc, char** argv) XMEMSET(keyFilesBuf, 0, sizeof(keyFilesBuf)); XMEMSET(keyFilesUser, 0, sizeof(keyFilesUser)); if (XFGETS(keyFilesUser, sizeof(keyFilesUser), stdin)) { - word32 strSz; - if (keyFilesUser[0] != '\r' && keyFilesUser[0] != '\n') { + TrimNewLine(keyFilesUser); + if (XSTRLEN(keyFilesUser) > 0) { keyFilesSrc = keyFilesUser; } - strSz = (word32)XSTRLEN(keyFilesUser); - if (keyFilesUser[strSz-1] == '\n') - keyFilesUser[strSz-1] = '\0'; } XSTRNCPY(keyFilesBuf, keyFilesSrc, sizeof(keyFilesBuf)); @@ -519,6 +525,7 @@ int main(int argc, char** argv) printf("Enter alternate SNI [default: none]: "); XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg)); if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) { + TrimNewLine(cmdLineArg); if (XSTRLEN(cmdLineArg) > 0) { sniName = cmdLineArg; } From e1b487ab9f659abdd79e104eb061fa45d6c89a92 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 8 Jul 2021 14:36:36 -0700 Subject: [PATCH 06/10] Fix for `wc_export_int` with `WC_TYPE_HEX_STR`, which was not returning the correct length. --- tests/api.c | 34 +++++++++++++++++++++++----------- wolfcrypt/src/wolfmath.c | 33 ++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/tests/api.c b/tests/api.c index ad2c4849c..b1e8b564a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -42068,42 +42068,54 @@ static int test_get_digit (void) /* * Testing wc_export_int */ -static int test_wc_export_int (void) +static int test_wc_export_int(void) { int ret = 0; #if defined(WOLFSSL_PUBLIC_MP) mp_int mp; - byte buf[256]; + byte buf[32]; word32 keySz = (word32)sizeof(buf); word32 len = (word32)sizeof(buf); - - int encType = WC_TYPE_UNSIGNED_BIN; - printf(testingFmt, "wc_export_int()"); if (mp_init(&mp) != MP_OKAY) { ret = -1; } if (ret == 0) { - ret = wc_export_int(NULL, buf, &len, keySz, encType); + ret = mp_set_int(&mp, 1234); + } + if (ret == 0) { + ret = wc_export_int(NULL, buf, &len, keySz, WC_TYPE_UNSIGNED_BIN); if (ret == BAD_FUNC_ARG) { ret = 0; } } - len = sizeof(buf)-1; if (ret == 0) { - ret = wc_export_int(&mp, buf, &len, keySz, encType); + len = sizeof(buf)-1; + ret = wc_export_int(&mp, buf, &len, keySz, WC_TYPE_UNSIGNED_BIN); if (ret == BUFFER_E) { ret = 0; } } - len = sizeof(buf); if (ret == 0) { - ret = wc_export_int(&mp, buf, &len, keySz, WC_TYPE_HEX_STR); + len = sizeof(buf); + ret = wc_export_int(&mp, buf, &len, keySz, WC_TYPE_UNSIGNED_BIN); } if (ret == 0) { - ret = wc_export_int(&mp, buf, &len, keySz, encType); + len = 4; /* test input too small */ + ret = wc_export_int(&mp, buf, &len, 0, WC_TYPE_HEX_STR); + if (ret == BUFFER_E) { + ret = 0; + } + } + if (ret == 0) { + len = sizeof(buf); + ret = wc_export_int(&mp, buf, &len, 0, WC_TYPE_HEX_STR); + /* hex version of 1234 is 04D2 and should be 4 digits + 1 null */ + if (ret == 0 && len != 5) { + ret = BAD_FUNC_ARG; + } } printf(resultFmt, ret == 0 ? passed : failed); diff --git a/wolfcrypt/src/wolfmath.c b/wolfcrypt/src/wolfmath.c index 0a587baef..9ed023468 100644 --- a/wolfcrypt/src/wolfmath.c +++ b/wolfcrypt/src/wolfmath.c @@ -210,26 +210,37 @@ int wc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, { int err; - if (mp == NULL) + if (mp == NULL || buf == NULL || len == NULL) return BAD_FUNC_ARG; - /* check buffer size */ - if (*len < keySz) { - *len = keySz; - return BUFFER_E; - } - - *len = keySz; - XMEMSET(buf, 0, *len); - if (encType == WC_TYPE_HEX_STR) { + /* for WC_TYPE_HEX_STR the keySz is not used. + * The size is computed via mp_radix_size and checked with len input */ #ifdef WC_MP_TO_RADIX - err = mp_tohex(mp, (char*)buf); + int size = 0; + err = mp_radix_size(mp, MP_RADIX_HEX, &size); + if (err == MP_OKAY) { + /* make sure we can fit result */ + if (*len < (word32)size) { + *len = (word32)size; + return BUFFER_E; + } + *len = (word32)size; + err = mp_tohex(mp, (char*)buf); + } #else err = NOT_COMPILED_IN; #endif } else { + /* for WC_TYPE_UNSIGNED_BIN keySz is used to zero pad. + * The key size is always returned as the size */ + if (*len < keySz) { + *len = keySz; + return BUFFER_E; + } + *len = keySz; + XMEMSET(buf, 0, *len); err = mp_to_unsigned_bin(mp, buf + (keySz - mp_unsigned_bin_size(mp))); } From db32570ab3476fb3ac94eb1aee7477f02d8621f6 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 12 Jul 2021 13:40:55 -0700 Subject: [PATCH 07/10] Fix for missing `sp_radix_size` with `WC_MP_TO_RADIX`. --- wolfcrypt/benchmark/benchmark.c | 2 +- wolfcrypt/src/sp_int.c | 10 ++++++---- wolfssl/wolfcrypt/sp_int.h | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index cc5a01e13..e92573278 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1295,7 +1295,7 @@ static void bench_stats_sym_finish(const char* desc, int doAsync, int count, } } - /* caclulcate blocks per second */ + /* calculate blocks per second */ if (total > 0) { persec = (1 / total) * blocks; } diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 99cd6c627..08b65eee4 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -12722,7 +12722,8 @@ int sp_todecimal(sp_int* a, char* str) } #endif /* WOLFSSL_SP_MATH_ALL || WOLFSSL_KEY_GEN || HAVE_COMP_KEY */ -#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + defined(WC_MP_TO_RADIX) /* Put the string version, big-endian, of a in str using the given radix. * * @param [in] a SP integer to convert. @@ -12755,9 +12756,10 @@ int sp_toradix(sp_int* a, char* str, int radix) return err; } -#endif /* WOLFSSL_SP_MATH_ALL */ +#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || WC_MP_TO_RADIX */ -#if defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + defined(WC_MP_TO_RADIX) /* Calculate the length of the string version, big-endian, of a using the given * radix. * @@ -12848,7 +12850,7 @@ int sp_radix_size(sp_int* a, int radix, int* size) return err; } -#endif /* WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY */ +#endif /* (WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY) || WC_MP_TO_RADIX */ /*************************************** * Prime number generation and checking. diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index fd5ec9b9b..a48d5ad5d 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -881,7 +881,7 @@ MP_API int sp_to_unsigned_bin_at_pos(int o, sp_int* a, unsigned char* out); MP_API int sp_read_radix(sp_int* a, const char* in, int radix); MP_API int sp_tohex(sp_int* a, char* str); MP_API int sp_todecimal(mp_int* a, char* str); -#ifdef WOLFSSL_SP_MATH_ALL +#if defined(WOLFSSL_SP_MATH_ALL) || defined(WC_MP_TO_RADIX) MP_API int sp_toradix(mp_int* a, char* str, int radix); MP_API int sp_radix_size(mp_int* a, int radix, int* size); #endif From 3ff21171cbd3189db9c0492c7a9f853d2f60d0a4 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 13 Jul 2021 13:56:00 -0700 Subject: [PATCH 08/10] Fix for secure renegotiation, which was not keeping handshake resources. Added NULL checks for case where handshake resources might be free'd to prevent possible use of NULL. Refactor the SNI client hello processing to not assume TLS header is in prior buffer (not there for decrypted handshake packets). --- src/sniffer.c | 180 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 114 insertions(+), 66 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index db85bfea9..90fdffe3e 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1603,7 +1603,7 @@ static int CreateWatchSnifferServer(char* error) #endif - +/* Caller locks ServerListMutex */ static int SetNamedPrivateKey(const char* name, const char* address, int port, const char* keyFile, int keySz, int typeKey, const char* password, char* error, int isEphemeralKey) @@ -1658,6 +1658,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port, serverIp.version = IPV6; } } + sniffer = ServerList; while (sniffer != NULL && (!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) { @@ -2171,6 +2172,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, devId = CryptoDeviceId; #endif + if (session->sslServer->arrays == NULL || session->sslClient->arrays == NULL) { + /* secret's have already been established and released */ + /* this can happen with secure renegotiation */ + return 0; + } + #ifndef NO_RSA /* Static RSA */ if (ksInfo == NULL && keys->rsaKey) { @@ -2773,8 +2780,10 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes, } /* store session with macID as sessionID */ session->sslServer->options.haveSessionId = 1; - XMEMCPY(session->sslServer->arrays->sessionID, - input + len - ID_LEN, ID_LEN); + if (session->sslServer->arrays) { + XMEMCPY(session->sslServer->arrays->sessionID, + input + len - ID_LEN, ID_LEN); + } } return 0; @@ -3011,6 +3020,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, FATAL_ERROR_STATE); return -1; } + #ifdef DEBUG_SNIFFER + printf("\tserver_hello ext: 0x%02x (len %d)\n", extType, extLen); + #endif switch (extType) { #ifdef WOLFSSL_TLS13 @@ -3070,7 +3082,14 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, session->flags.expectEms = 1; #endif break; - } + case EXT_RENEGOTIATION_INFO: + #if defined(HAVE_SECURE_RENEGOTIATION) || \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + session->sslServer->secure_renegotiation->enabled = 1; + session->sslClient->secure_renegotiation->enabled = 1; + #endif + break; + } /* switch (extType) */ input += extLen; *sslBytes -= extLen; @@ -3179,6 +3198,48 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, return 0; } +#ifdef HAVE_SNI +static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz) +{ + int ret = 0; + WOLFSSL* ssl = session->sslServer; + NamedKey* namedKey; + + wc_LockMutex(&session->context->namedKeysMutex); + namedKey = session->context->namedKeys; + while (namedKey != NULL) { + if (nameSz == namedKey->nameSz && + XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { + #ifdef WOLFSSL_STATIC_EPHEMERAL + if (namedKey->isEphemeralKey) { + /* auto detect key type with WC_PK_TYPE_NONE */ + ret = wolfSSL_set_ephemeral_key(ssl, + WC_PK_TYPE_NONE, (const char*)namedKey->key, + namedKey->keySz, WOLFSSL_FILETYPE_ASN1); + if (ret == 0) + ret = WOLFSSL_SUCCESS; + } + else + #endif + { + ret = wolfSSL_use_PrivateKey_buffer(ssl, + namedKey->key, namedKey->keySz, + WOLFSSL_FILETYPE_ASN1); + } + if (ret != WOLFSSL_SUCCESS) { + ret = -1; + break; + } + session->sni = namedKey->name; + break; + } + else + namedKey = namedKey->next; + } + wc_UnLockMutex(&session->context->namedKeysMutex); + return ret; +} +#endif /* Process normal Client Hello */ static int ProcessClientHello(const byte* input, int* sslBytes, @@ -3193,65 +3254,6 @@ static int ProcessClientHello(const byte* input, int* sslBytes, WOLFSSL* ssl = session->sslServer; int didHash = 0; -#ifdef HAVE_SNI - { - byte name[MAX_SERVER_NAME]; - word32 nameSz = sizeof(name); - - ret = wolfSSL_SNI_GetFromBuffer( - input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ, - *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ, - WOLFSSL_SNI_HOST_NAME, name, &nameSz); - - if (ret == WOLFSSL_SUCCESS) { - NamedKey* namedKey; - - if (nameSz > sizeof(name) - 1) - nameSz = sizeof(name) - 1; - name[nameSz] = 0; - wc_LockMutex(&session->context->namedKeysMutex); - namedKey = session->context->namedKeys; - while (namedKey != NULL) { - if (nameSz == namedKey->nameSz && - XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { - #ifdef WOLFSSL_STATIC_EPHEMERAL - if (namedKey->isEphemeralKey) { - /* auto detect key type with WC_PK_TYPE_NONE */ - ret = wolfSSL_set_ephemeral_key(ssl, - WC_PK_TYPE_NONE, (const char*)namedKey->key, - namedKey->keySz, WOLFSSL_FILETYPE_ASN1); - if (ret == 0) - ret = WOLFSSL_SUCCESS; - } - else - #endif - { - ret = wolfSSL_use_PrivateKey_buffer(ssl, - namedKey->key, namedKey->keySz, - WOLFSSL_FILETYPE_ASN1); - } - if (ret != WOLFSSL_SUCCESS) { - wc_UnLockMutex(&session->context->namedKeysMutex); - SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, - FATAL_ERROR_STATE); - return -1; - } - session->sni = namedKey->name; - break; - } - else - namedKey = namedKey->next; - } - wc_UnLockMutex(&session->context->namedKeysMutex); - } - /* SSLv3 does not support the SNI TLS Extension and may return SNI_UNSUPPORTED */ - if (ret > 0 || ret == SNI_UNSUPPORTED) { - /* make sure WOLFSSL_SUCCESS is converted to zero error code */ - ret = 0; - } - } -#endif - session->flags.clientHello = 1; /* don't process again */ /* make sure can read up to session len */ @@ -3264,8 +3266,11 @@ static int ProcessClientHello(const byte* input, int* sslBytes, input += VERSION_SZ; *sslBytes -= VERSION_SZ; - XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN); - XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN); + /* for secure renegotiation server arrays can be NULL */ + if (session->sslServer->arrays) + XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN); + if (session->sslClient->arrays) + XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN); input += RAN_LEN; *sslBytes -= RAN_LEN; @@ -3287,7 +3292,8 @@ static int ProcessClientHello(const byte* input, int* sslBytes, } #ifdef SHOW_SECRETS - PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN); + if (ssl->arrays) + PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN); #endif input += bLen; @@ -3359,7 +3365,46 @@ static int ProcessClientHello(const byte* input, int* sslBytes, return -1; } + #ifdef DEBUG_SNIFFER + printf("\tclient_hello ext: 0x%02x (len %d)\n", extType, extLen); + #endif + switch (extType) { + #ifdef HAVE_SNI + case EXT_SERVER_NAME: + { + word16 listLen = 0, offset = 0; + + ato16(input + offset, &listLen); + offset += OPAQUE16_LEN; + + if (extLen < offset + listLen) + return BUFFER_ERROR; + + while (listLen > ENUM_LEN + OPAQUE16_LEN) { + byte sniType = input[offset++]; + word16 sniLen; + + ato16(input + offset, &sniLen); + offset += OPAQUE16_LEN; + + if (extLen < offset + sniLen) + return BUFFER_ERROR; + + if (sniType == WOLFSSL_SNI_HOST_NAME) { + ret = LoadNamedKey(session, input + offset, sniLen); + if (ret < 0) { + /* don't treat this as fatal error */ + SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, 0); + break; + } + } + offset += sniLen; + listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen); + } + break; + } + #endif #ifdef WOLFSSL_TLS13 case EXT_KEY_SHARE: { @@ -3675,6 +3720,9 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, } #endif + + /* TODO: Do not free yet if Extension: renegotiation_info (len=1) provided - secure reneg */ + /* If receiving a finished message from one side, free the resources * from the other side's tracker. */ if (session->flags.side == WOLFSSL_SERVER_END) From fe77e29ba0fb13a3fedfd6f8976ac6af2f655fad Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 16 Jul 2021 11:23:20 -0700 Subject: [PATCH 09/10] Fix for SNI refactor handling of return codes. Fix for possible use of NULL on client array. --- src/sniffer.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 90fdffe3e..5535542db 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3199,6 +3199,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, } #ifdef HAVE_SNI +/* Function return value must be 0 for success */ static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz) { int ret = 0; @@ -3216,8 +3217,6 @@ static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz ret = wolfSSL_set_ephemeral_key(ssl, WC_PK_TYPE_NONE, (const char*)namedKey->key, namedKey->keySz, WOLFSSL_FILETYPE_ASN1); - if (ret == 0) - ret = WOLFSSL_SUCCESS; } else #endif @@ -3225,16 +3224,15 @@ static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz ret = wolfSSL_use_PrivateKey_buffer(ssl, namedKey->key, namedKey->keySz, WOLFSSL_FILETYPE_ASN1); + /* translate return code */ + ret = (ret == WOLFSSL_SUCCESS) ? 0 : -1; } - if (ret != WOLFSSL_SUCCESS) { - ret = -1; - break; + if (ret == 0) { + session->sni = namedKey->name; } - session->sni = namedKey->name; break; } - else - namedKey = namedKey->next; + namedKey = namedKey->next; } wc_UnLockMutex(&session->context->namedKeysMutex); return ret; @@ -3287,7 +3285,8 @@ static int ProcessClientHello(const byte* input, int* sslBytes, #ifdef WOLFSSL_TLS13 XMEMCPY(session->sslClient->session.sessionID, input, ID_LEN); #endif - XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); + if (session->sslClient->arrays) + XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); session->sslClient->options.haveSessionId = 1; } From 070ca6c34dd112ab850ddd656e6ca63d09e61168 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 16 Jul 2021 14:48:22 -0700 Subject: [PATCH 10/10] Fixes to properly support sniffer with secure renegotiation. --- src/sniffer.c | 52 +++++++++++++++++++++++---------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/sniffer.c b/src/sniffer.c index 5535542db..20eebb71f 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -439,6 +439,7 @@ typedef struct Flags { byte expectEms; /* expect extended master secret */ #endif byte gotFinished; /* processed finished */ + byte secRenegEn; /* secure renegotiation enabled */ } Flags; @@ -3083,11 +3084,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, #endif break; case EXT_RENEGOTIATION_INFO: - #if defined(HAVE_SECURE_RENEGOTIATION) || \ - defined(HAVE_SERVER_RENEGOTIATION_INFO) - session->sslServer->secure_renegotiation->enabled = 1; - session->sslClient->secure_renegotiation->enabled = 1; - #endif + session->flags.secRenegEn = 1; break; } /* switch (extType) */ @@ -3719,15 +3716,15 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes, } #endif - - /* TODO: Do not free yet if Extension: renegotiation_info (len=1) provided - secure reneg */ - - /* If receiving a finished message from one side, free the resources - * from the other side's tracker. */ - if (session->flags.side == WOLFSSL_SERVER_END) - FreeHandshakeResources(session->sslClient); - else - FreeHandshakeResources(session->sslServer); + /* Do not free handshake resources yet if secure renegotiation */ + if (session->flags.secRenegEn == 0) { + /* If receiving a finished message from one side, free the resources + * from the other side's tracker. */ + if (session->flags.side == WOLFSSL_SERVER_END) + FreeHandshakeResources(session->sslClient); + else + FreeHandshakeResources(session->sslServer); + } return ret; } @@ -3784,18 +3781,6 @@ static int DoHandShake(const byte* input, int* sslBytes, else ssl = session->sslClient; -#ifdef HAVE_SECURE_RENEGOTIATION - if (!IsAtLeastTLSv1_3(ssl->version)) { - /* A session's arrays are released when the handshake is completed. */ - if (session->sslServer->arrays == NULL && - session->sslClient->arrays == NULL) { - - SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); - return -1; - } - } -#endif - #ifdef HAVE_MAX_FRAGMENT if (rhSize < size) { /* partial fragment, let's reassemble */ @@ -4083,6 +4068,7 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, *error = ret; return NULL; } + ssl->keys.encryptSz = sz; if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) { output += ssl->specs.block_size; /* go past TLSv1.1 IV */ @@ -4097,8 +4083,15 @@ static const byte* DecryptMessage(WOLFSSL* ssl, const byte* input, word32 sz, else ssl->keys.padSz = ssl->specs.hash_size; - if (ssl->specs.cipher_type == block) - ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; + if (ssl->specs.cipher_type == block) { + /* last pad bytes indicates length */ + word32 pad = 0; + if ((int)sz > ivExtra) { + /* get value of last pad byte */ + pad = *(output + sz - ivExtra - 1) + 1; + } + ssl->keys.padSz += pad; + } #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version)) { @@ -5345,7 +5338,8 @@ doPart: } } else { - SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE); + /* set error, but do not treat fatal */ + SetError(BAD_APP_DATA_STR, error,session, 0); return -1; } if (ssl->buffers.outputBuffer.dynamicFlag)