diff --git a/src/sniffer.c b/src/sniffer.c index 9f56f4f62..bcc6cd6ba 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -3733,7 +3733,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, #endif #ifdef WOLFSSL_ASYNC_CRYPT - if (session->sslServer->error != WC_PENDING_E) + if (session->sslServer->error != WC_PENDING_E && session->pendSeq == 0) #endif { /* hash server_hello */ @@ -4412,7 +4412,7 @@ static int DoHandShake(const byte* input, int* sslBytes, #ifdef WOLFSSL_TLS13 if (type != client_hello && type != server_hello #ifdef WOLFSSL_ASYNC_CRYPT - && session->sslServer->error != WC_PENDING_E + && session->sslServer->error != WC_PENDING_E && session->pendSeq == 0 #endif ) { /* For resumption the hash is before / after client_hello PSK binder */ @@ -4492,11 +4492,10 @@ static int DoHandShake(const byte* input, int* sslBytes, case client_key_exchange: Trace(GOT_CLIENT_KEY_EX_STR); #ifdef HAVE_EXTENDED_MASTER - #ifdef WOLFSSL_ASYNC_CRYPT - if (session->sslServer->error != WC_PENDING_E) - #endif - { - if (session->flags.expectEms && session->hash != NULL) { + if (session->flags.expectEms) { + /* on async reentry the session->hash is already copied + * and free'd */ + if (session->hash != NULL) { if (HashCopy(session->sslServer->hsHashes, session->hash) == 0 && HashCopy(session->sslClient->hsHashes, @@ -4514,10 +4513,10 @@ static int DoHandShake(const byte* input, int* sslBytes, XFREE(session->hash, NULL, DYNAMIC_TYPE_HASHES); session->hash = NULL; } - else { - session->sslServer->options.haveEMS = 0; - session->sslClient->options.haveEMS = 0; - } + } + else { + session->sslServer->options.haveEMS = 0; + session->sslClient->options.haveEMS = 0; } #endif if (ret == 0) { @@ -4937,7 +4936,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); if (session == NULL) { SetError(MEMORY_STR, error, NULL, 0); - return 0; + return NULL; } InitSession(session); #ifdef HAVE_EXTENDED_MASTER @@ -4947,12 +4946,12 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, if (newHash == NULL) { SetError(MEMORY_STR, error, NULL, 0); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); - return 0; + return NULL; } if (HashInit(newHash) != 0) { SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); - return 0; + return NULL; } session->hash = newHash; } @@ -4973,14 +4972,14 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, if (session->context == NULL) { SetError(SERVER_NOT_REG_STR, error, NULL, 0); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); - return 0; + return NULL; } session->sslServer = wolfSSL_new(session->context->ctx); if (session->sslServer == NULL) { SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); - return 0; + return NULL; } session->sslClient = wolfSSL_new(session->context->ctx); if (session->sslClient == NULL) { @@ -4989,7 +4988,7 @@ static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); XFREE(session, NULL, DYNAMIC_TYPE_SNIFFER_SESSION); - return 0; + return NULL; } /* put server back into server mode */ session->sslServer->options.side = WOLFSSL_SERVER_END; @@ -5178,6 +5177,16 @@ static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, { /* create a new SnifferSession on client SYN */ if (tcpInfo->syn && !tcpInfo->ack) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* if session already exists and is pending do not create another */ + *session = GetSnifferSession(ipInfo, tcpInfo); + if (*session != NULL) { + if ((*session)->pendSeq != 0) { + return WC_PENDING_E; + } + } + #endif + TraceClientSyn(tcpInfo->sequence); #ifdef WOLFSSL_SNIFFER_STATS INC_STAT(SnifferStats.sslEncryptedConns); @@ -5437,7 +5446,11 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, if (real < *expected) { if (real + *sslBytes > *expected) { - if (session->sslServer->error != WC_PENDING_E) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (session->sslServer->error != WC_PENDING_E && + session->pendSeq != tcpInfo->sequence) + #endif + { Trace(OVERLAP_DUPLICATE_STR); } @@ -5488,7 +5501,11 @@ static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, if (*sslBytes > 0) { /* If packet has data attempt to process packet, if hasn't * already been ack'd during handshake */ - if (session->sslServer->error != WC_PENDING_E && + if ( + #ifdef WOLFSSL_ASYNC_CRYPT + session->sslServer->error != WC_PENDING_E && + session->pendSeq != tcpInfo->sequence && + #endif FindPrevAck(session, real)) { Trace(DUPLICATE_STR); ret = 1; @@ -5717,6 +5734,17 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, &session->flags.cliAckFault : &session->flags.srvAckFault; +#ifdef WOLFSSL_ASYNC_CRYPT + if (session->sslServer->error == 0 && session->pendSeq != 0 && + session->pendSeq == tcpInfo->sequence) { + return 0; /* ready to process, but skip sequence checking below (already done) */ + } + /* check if this session is pending */ + else if (session->pendSeq != 0 && session->pendSeq != tcpInfo->sequence) { + return WC_PENDING_E; + } +#endif + /* init SEQ from server to client - if not ack fault */ if (tcpInfo->syn && tcpInfo->ack && !*ackFault) { session->srvSeqStart = tcpInfo->sequence; @@ -5731,15 +5759,6 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, *sslBytes = actualLen; } -#ifdef WOLFSSL_ASYNC_CRYPT - /* check if this session is pending */ - if (session->sslServer->error == WC_PENDING_E && - session->pendSeq != tcpInfo->sequence) { - /* this stream is processing, queue packet */ - return WC_PENDING_E; - } -#endif - TraceSequence(tcpInfo->sequence, *sslBytes); if (CheckAck(tcpInfo, session) < 0) { if (!RecoveryEnabled) { @@ -5769,38 +5788,56 @@ static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, /* Check Status before record processing */ /* returns 0 on success (continue), -1 on error, 1 on success (end) */ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, - const byte** sslFrame, SnifferSession** session, + const byte** sslFrame, SnifferSession** pSession, int* sslBytes, const byte** end, void* vChain, word32 chainSz, char* error) { word32 length; - WOLFSSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? - (*session)->sslServer : (*session)->sslClient; - byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? - (*session)->flags.srvSkipPartial : - (*session)->flags.cliSkipPartial; + SnifferSession* session = *pSession; + WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : session->sslClient; + byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? + session->flags.srvSkipPartial : + session->flags.cliSkipPartial; + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if this is a pending async packet do not "grow" on partial (we already did) */ + if (session->pendSeq == tcpInfo->sequence) { + if (session->sslServer->error == WC_PENDING_E) { + return 0; /* don't check pre-record again */ + } + /* if record check already done then restore, otherwise process normal */ + if (ssl->buffers.inputBuffer.length > 0) { + *sslBytes = ssl->buffers.inputBuffer.length; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + return 0; + } + } +#endif + /* remove SnifferSession on 2nd FIN or RST */ if (tcpInfo->fin || tcpInfo->rst) { /* flag FIN and RST */ if (tcpInfo->fin) - (*session)->flags.finCount += 1; + session->flags.finCount += 1; else if (tcpInfo->rst) - (*session)->flags.finCount += 2; + session->flags.finCount += 2; - if ((*session)->flags.finCount >= 2) { - RemoveSession(*session, ipInfo, tcpInfo, 0); - *session = NULL; + if (session->flags.finCount >= 2) { + RemoveSession(session, ipInfo, tcpInfo, 0); + *pSession = NULL; return 1; } } - if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { + if (session->flags.fatalError == FATAL_ERROR_STATE) { SetError(FATAL_ERROR_STR, error, NULL, 0); return -1; } if (skipPartial) { - if (FindNextRecordInAssembly(*session, + if (FindNextRecordInAssembly(session, sslFrame, sslBytes, end, error) < 0) { return -1; } @@ -5819,7 +5856,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { - SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } } @@ -5842,7 +5879,7 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { - SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); return -1; } } @@ -5872,14 +5909,14 @@ static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, } } - if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { + 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]); if ((rhSize <= (*sslBytes - 2)) && (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) { #ifdef OLD_HELLO_ALLOWED - int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error); + int ret = DoOldHello(session, *sslFrame, &rhSize, sslBytes, error); if (ret < 0) return -1; /* error already set */ if (*sslBytes <= 0) @@ -5978,7 +6015,7 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, const byte* recordEnd; /* end of record indicator */ const byte* inRecordEnd; /* indicator from input stream not decrypt */ RecordLayerHeader rh; - int rhSize = 0; + int rhSize; int ret; int errCode = 0; int decoded = 0; /* bytes stored for user in data */ @@ -5987,7 +6024,9 @@ static int ProcessMessage(const byte* sslFrame, SnifferSession* session, WOLFSSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? session->sslServer : session->sslClient; doMessage: + notEnough = 0; + rhSize = 0; if (sslBytes < 0) { SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE); return -1; @@ -5999,8 +6038,9 @@ doMessage: return 0; } } - else + else { notEnough = 1; + } if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { /* don't have enough input yet to process full SSL record */ @@ -6027,7 +6067,7 @@ doMessage: inRecordEnd = recordEnd; /* Make sure cipher is on for client, if we get an application data packet - * and handhsake is done for server. This workaround is required if client + * and handshake is done for server. This workaround is required if client * handshake packets were missed, retransmitted or sent out of order. */ if ((enum ContentType)rh.type == application_data && ssl->options.handShakeDone && session->flags.serverCipherOn) { @@ -6348,6 +6388,9 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return WOLFSSL_SNIFFER_FATAL_ERROR; +#ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) return WC_PENDING_E; +#endif else if (ret == -1) return WOLFSSL_SNIFFER_ERROR; else if (ret == 1) { #ifdef WOLFSSL_SNIFFER_STATS @@ -6427,10 +6470,9 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, session->sslServer->error = ret; #ifdef WOLFSSL_ASYNC_CRYPT /* capture the seq pending for this session */ - session->pendSeq = tcpInfo.sequence; - if (ret == WC_PENDING_E) { session->flags.wasPolled = 0; + session->pendSeq = tcpInfo.sequence; if (!asyncOkay || CryptoDeviceId == INVALID_DEVID) { /* If devId has not been set then we need to block here by * polling and looping */ @@ -6440,6 +6482,9 @@ static int ssl_DecodePacketInternal(const byte* packet, int length, int isChain, return ret; /* return to caller */ } } + else { + session->pendSeq = 0; + } } while (ret == WC_PENDING_E); #else (void)asyncOkay; @@ -6888,6 +6933,7 @@ int ssl_PollSniffer(WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, SnifferSession* session = FindSession(ssl); if (session) { session->flags.wasPolled = 1; + session->sslServer->error = events[i]->ret; } } wc_UnLockMutex(&SessionMutex); diff --git a/sslSniffer/sslSnifferTest/snifftest.c b/sslSniffer/sslSnifferTest/snifftest.c index 0fe03966c..92b7fc6ee 100644 --- a/sslSniffer/sslSnifferTest/snifftest.c +++ b/sslSniffer/sslSnifferTest/snifftest.c @@ -545,7 +545,7 @@ static int SnifferAsyncPollQueue(byte** data, char* err, SSLInfo* sslInfo, if (ret == 0) { /* attempt to reprocess pending packet */ #ifdef DEBUG_SNIFFER - printf("Retrying packet %d\n", asyncQueue[i].packetNumber); + printf("Packet Number: %d (retry)\n", asyncQueue[i].packetNumber); #endif ret = ssl_DecodePacketAsync(asyncQueue[i].packet, asyncQueue[i].length, 0, data, err, sslInfo, NULL); @@ -828,7 +828,7 @@ int main(int argc, char** argv) /* grab next pcap packet */ packetNumber++; packet = pcap_next(pcap, &header); - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(DEBUG_SNIFFER) + #ifdef DEBUG_SNIFFER printf("Packet Number: %d\n", packetNumber); #endif } @@ -904,6 +904,11 @@ int main(int argc, char** argv) /* check if we are done reading file */ if (packet == NULL && data == NULL && saveFile) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* if items pending still then keep processing */ + if (queueSz > 0) + continue; + #endif break; }