diff --git a/cyassl/error-ssl.h b/cyassl/error-ssl.h index e0dae860d..94dec7e2f 100644 --- a/cyassl/error-ssl.h +++ b/cyassl/error-ssl.h @@ -123,6 +123,7 @@ enum CyaSSL_ErrorCodes { SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ + NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ /* add strings to SetErrorString !!!!! */ diff --git a/cyassl/internal.h b/cyassl/internal.h index d909ec109..5373b3c98 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1788,6 +1788,7 @@ typedef struct Options { byte quietShutdown; /* don't send close notify */ byte certOnly; /* stop once we get cert */ byte groupMessages; /* group handshake messages */ + byte gotChangeCipher; /* received change cipher from peer */ byte usingNonblock; /* set when using nonblocking socket */ byte saveArrays; /* save array Memory for user get keys or psk */ diff --git a/src/internal.c b/src/internal.c index 31c726572..464d62e65 100644 --- a/src/internal.c +++ b/src/internal.c @@ -1685,6 +1685,7 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->options.quietShutdown = ctx->quietShutdown; ssl->options.certOnly = 0; ssl->options.groupMessages = ctx->groupMessages; + ssl->options.gotChangeCipher = 0; ssl->options.usingNonblock = 0; ssl->options.saveArrays = 0; #ifdef HAVE_POLY1305 @@ -4601,6 +4602,11 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 size, if (finishedSz != size) return BUFFER_ERROR; + if (ssl->options.gotChangeCipher == 0) { + CYASSL_MSG("Finished received from peer before change cipher"); + return NO_CHANGE_CIPHER_E; + } + /* check against totalSz */ if (*inOutIdx + size + ssl->keys.padSz > totalSz) return BUFFER_E; @@ -6457,6 +6463,7 @@ int ProcessReply(CYASSL* ssl) break; case change_cipher_spec: + ssl->options.gotChangeCipher = 1; CYASSL_MSG("got CHANGE CIPHER SPEC"); #ifdef CYASSL_CALLBACKS if (ssl->hsInfoOn) @@ -7861,6 +7868,9 @@ const char* CyaSSL_ERR_reason_error_string(unsigned long e) case SESSION_SECRET_CB_E: return "Session Secret Callback Error"; + case NO_CHANGE_CIPHER_E: + return "Finished received from peer before Change Cipher Error"; + default : return "unknown error number"; } diff --git a/src/ssl.c b/src/ssl.c index 89fe952d1..e7d12d75e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -775,6 +775,7 @@ int CyaSSL_Rehandshake(CYASSL* ssl) ssl->options.acceptState = ACCEPT_BEGIN; ssl->options.handShakeState = NULL_STATE; ssl->options.processReply = 0; /* TODO, move states in internal.h */ + ssl->options.gotChangeCipher = 0; ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;