diff --git a/cyassl/internal.h b/cyassl/internal.h index fa86cd16b..a9809cb8c 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -820,7 +820,7 @@ CYASSL_LOCAL void InitSSL_Method(CYASSL_METHOD*, ProtocolVersion); /* for sniffer */ CYASSL_LOCAL int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, - int sniff); + word32 size, word32 totalSz, int sniff); CYASSL_LOCAL int DoApplicationData(CYASSL* ssl, byte* input, word32* inOutIdx); diff --git a/src/internal.c b/src/internal.c index 5a54f7d2b..ec765e6c9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3664,28 +3664,36 @@ static int DoHelloRequest(CYASSL* ssl, const byte* input, word32* inOutIdx) } -int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) +int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 size, + word32 totalSz, int sniff) { - int finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ; - word32 idx = *inOutIdx; + if ((ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ) != size) + return BUFFER_ERROR; #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName("Finished", &ssl->handShakeInfo); if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); #endif + if (sniff == NO_SNIFF) { - if (XMEMCMP(input + idx, &ssl->verifyHashes, finishedSz) != 0) { + if (XMEMCMP(input + *inOutIdx, &ssl->verifyHashes, size) != 0) { CYASSL_MSG("Verify finished error on hashes"); return VERIFY_FINISHED_ERROR; } } - idx += finishedSz; - idx += ssl->keys.padSz; - + + /* increment beyond input + size should be checked against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return INCOMPLETE_DATA; + + /* force input exhaustion at ProcessReply consuming padSz */ + *inOutIdx += size + ssl->keys.padSz; + if (ssl->options.side == CYASSL_CLIENT_END) { ssl->options.serverState = SERVER_FINISHED_COMPLETE; if (!ssl->options.resuming) { ssl->options.handShakeState = HANDSHAKE_DONE; + #ifdef CYASSL_DTLS if (ssl->options.dtls) { /* Other side has received our Finished, go to next epoch */ @@ -3699,6 +3707,7 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) ssl->options.clientState = CLIENT_FINISHED_COMPLETE; if (ssl->options.resuming) { ssl->options.handShakeState = HANDSHAKE_DONE; + #ifdef CYASSL_DTLS if (ssl->options.dtls) { /* Other side has received our Finished, go to next epoch */ @@ -3709,7 +3718,6 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, int sniff) } } - *inOutIdx = idx; return 0; } @@ -3818,7 +3826,7 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, case finished: CYASSL_MSG("processing finished"); - ret = DoFinished(ssl, input, inOutIdx, NO_SNIFF); + ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); break; #ifndef NO_CYASSL_SERVER diff --git a/src/sniffer.c b/src/sniffer.c index 53d4b9948..4f6d7c21d 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1444,7 +1444,7 @@ static int ProcessClientHello(const byte* input, int* sslBytes, /* Process Finished */ -static int ProcessFinished(const byte* input, int* sslBytes, +static int ProcessFinished(const byte* input, int size, int* sslBytes, SnifferSession* session, char* error) { SSL* ssl; @@ -1455,7 +1455,9 @@ static int ProcessFinished(const byte* input, int* sslBytes, ssl = session->sslServer; else ssl = session->sslClient; - ret = DoFinished(ssl, input, &inOutIdx, SNIFF); + + ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes, + SNIFF); *sslBytes -= (int)inOutIdx; if (ret < 0) { @@ -1533,7 +1535,7 @@ static int DoHandShake(const byte* input, int* sslBytes, break; case finished: Trace(GOT_FINISHED_STR); - ret = ProcessFinished(input, sslBytes, session, error); + ret = ProcessFinished(input, size, sslBytes, session, error); break; case client_hello: Trace(GOT_CLIENT_HELLO_STR);