add messages received framework, disallow duplicates

This commit is contained in:
toddouska 2014-11-17 12:55:07 -08:00
parent de388bf37f
commit 5318b243ba
4 changed files with 182 additions and 23 deletions

View File

@ -124,6 +124,7 @@ enum CyaSSL_ErrorCodes {
SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */
SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */
NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */
SANITY_MSG_E = -394, /* Sanity check on msg order error */
/* add strings to SetErrorString !!!!! */ /* add strings to SetErrorString !!!!! */

View File

@ -1956,6 +1956,24 @@ typedef struct DtlsMsg {
#endif #endif
/* Handshake messages recevied from peer (plus change cipher */
typedef struct MsgsReceived {
word16 got_hello_request:1;
word16 got_client_hello:1;
word16 got_server_hello:1;
word16 got_hello_verify_request:1;
word16 got_session_ticket:1;
word16 got_certificate:1;
word16 got_server_key_exchange:1;
word16 got_certificate_request:1;
word16 got_server_hello_done:1;
word16 got_certificate_verify:1;
word16 got_client_key_exchange:1;
word16 got_finished:1;
word16 got_change_cipher:1;
} MsgsReceived;
/* CyaSSL ssl type */ /* CyaSSL ssl type */
struct CYASSL { struct CYASSL {
CYASSL_CTX* ctx; CYASSL_CTX* ctx;
@ -1970,6 +1988,7 @@ struct CYASSL {
#endif #endif
CipherSpecs specs; CipherSpecs specs;
Keys keys; Keys keys;
MsgsReceived msgsReceived; /* peer messages received */
int rfd; /* read file descriptor */ int rfd; /* read file descriptor */
int wfd; /* write file descriptor */ int wfd; /* write file descriptor */
int rflags; /* user read flags */ int rflags; /* user read flags */

View File

@ -1580,29 +1580,8 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
ssl->keys.dtls_state.nextSeq = 0; ssl->keys.dtls_state.nextSeq = 0;
#endif #endif
#ifndef NO_OLD_TLS XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
#ifndef NO_MD5
InitMd5(&ssl->hashMd5);
#endif
#ifndef NO_SHA
ret = InitSha(&ssl->hashSha);
if (ret != 0) {
return ret;
}
#endif
#endif
#ifndef NO_SHA256
ret = InitSha256(&ssl->hashSha256);
if (ret != 0) {
return ret;
}
#endif
#ifdef CYASSL_SHA384
ret = InitSha384(&ssl->hashSha384);
if (ret != 0) {
return ret;
}
#endif
#ifndef NO_RSA #ifndef NO_RSA
ssl->peerRsaKey = NULL; ssl->peerRsaKey = NULL;
ssl->peerRsaKeyPresent = 0; ssl->peerRsaKeyPresent = 0;
@ -1800,6 +1779,30 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
/* all done with init, now can return errors, call other stuff */ /* all done with init, now can return errors, call other stuff */
#ifndef NO_OLD_TLS
#ifndef NO_MD5
InitMd5(&ssl->hashMd5);
#endif
#ifndef NO_SHA
ret = InitSha(&ssl->hashSha);
if (ret != 0) {
return ret;
}
#endif
#endif
#ifndef NO_SHA256
ret = InitSha256(&ssl->hashSha256);
if (ret != 0) {
return ret;
}
#endif
#ifdef CYASSL_SHA384
ret = InitSha384(&ssl->hashSha384);
if (ret != 0) {
return ret;
}
#endif
/* increment CTX reference count */ /* increment CTX reference count */
if (LockMutex(&ctx->countMutex) != 0) { if (LockMutex(&ctx->countMutex) != 0) {
CYASSL_MSG("Couldn't lock CTX count mutex"); CYASSL_MSG("Couldn't lock CTX count mutex");
@ -4686,6 +4689,129 @@ int DoFinished(CYASSL* ssl, const byte* input, word32* inOutIdx, word32 size,
} }
/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
static int SanityCheckMsgReceived(CYASSL* ssl, byte type)
{
/* verify not a duplicate, mark received, check state */
switch (type) {
case hello_request:
if (ssl->msgsReceived.got_hello_request) {
CYASSL_MSG("Duplicate HelloRequest received");
return -1;
}
ssl->msgsReceived.got_hello_request = 1;
break;
case client_hello:
if (ssl->msgsReceived.got_client_hello) {
CYASSL_MSG("Duplicate ClientHello received");
return -1;
}
ssl->msgsReceived.got_client_hello = 1;
break;
case server_hello:
if (ssl->msgsReceived.got_server_hello) {
CYASSL_MSG("Duplicate ServerHello received");
return -1;
}
ssl->msgsReceived.got_server_hello = 1;
break;
case hello_verify_request:
if (ssl->msgsReceived.got_hello_verify_request) {
CYASSL_MSG("Duplicate HelloVerifyRequest received");
return -1;
}
ssl->msgsReceived.got_hello_verify_request = 1;
break;
case session_ticket:
if (ssl->msgsReceived.got_session_ticket) {
CYASSL_MSG("Duplicate SessionTicket received");
return -1;
}
ssl->msgsReceived.got_session_ticket = 1;
break;
case certificate:
if (ssl->msgsReceived.got_certificate) {
CYASSL_MSG("Duplicate Certificate received");
return -1;
}
ssl->msgsReceived.got_certificate = 1;
break;
case server_key_exchange:
if (ssl->msgsReceived.got_server_key_exchange) {
CYASSL_MSG("Duplicate ServerKeyExchange received");
return -1;
}
ssl->msgsReceived.got_server_key_exchange = 1;
break;
case certificate_request:
if (ssl->msgsReceived.got_certificate_request) {
CYASSL_MSG("Duplicate CertificateRequest received");
return -1;
}
ssl->msgsReceived.got_certificate_request = 1;
break;
case server_hello_done:
if (ssl->msgsReceived.got_server_hello_done) {
CYASSL_MSG("Duplicate ServerHelloDone received");
return -1;
}
ssl->msgsReceived.got_server_hello_done = 1;
break;
case certificate_verify:
if (ssl->msgsReceived.got_certificate_verify) {
CYASSL_MSG("Duplicate CertificateVerify received");
return -1;
}
ssl->msgsReceived.got_certificate_verify = 1;
break;
case client_key_exchange:
if (ssl->msgsReceived.got_client_key_exchange) {
CYASSL_MSG("Duplicate ClientKeyExchange received");
return -1;
}
ssl->msgsReceived.got_client_key_exchange = 1;
break;
case finished:
if (ssl->msgsReceived.got_finished) {
CYASSL_MSG("Duplicate Finished received");
return -1;
}
ssl->msgsReceived.got_finished = 1;
break;
default:
CYASSL_MSG("Unknown message type");
return -1;
}
return 0;
}
static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx, static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
byte type, word32 size, word32 totalSz) byte type, word32 size, word32 totalSz)
{ {
@ -4698,6 +4824,12 @@ static int DoHandShakeMsgType(CYASSL* ssl, byte* input, word32* inOutIdx,
if (*inOutIdx + size > totalSz) if (*inOutIdx + size > totalSz)
return INCOMPLETE_DATA; return INCOMPLETE_DATA;
/* sanity check msg received */
if (SanityCheckMsgReceived(ssl, type) != 0) {
CYASSL_MSG("Sanity Check on handshake message type received failed");
return SANITY_MSG_E;
}
/* hello_request not hashed */ /* hello_request not hashed */
if (type != hello_request) { if (type != hello_request) {
ret = HashInput(ssl, input + *inOutIdx, size); ret = HashInput(ssl, input + *inOutIdx, size);
@ -7898,6 +8030,9 @@ const char* CyaSSL_ERR_reason_error_string(unsigned long e)
case NO_CHANGE_CIPHER_E: case NO_CHANGE_CIPHER_E:
return "Finished received from peer before Change Cipher Error"; return "Finished received from peer before Change Cipher Error";
case SANITY_MSG_E:
return "Sanity Check on message order Error";
default : default :
return "unknown error number"; return "unknown error number";
} }

View File

@ -779,6 +779,8 @@ int CyaSSL_Rehandshake(CYASSL* ssl)
ssl->options.processReply = 0; /* TODO, move states in internal.h */ ssl->options.processReply = 0; /* TODO, move states in internal.h */
ssl->options.gotChangeCipher = 0; ssl->options.gotChangeCipher = 0;
XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED;
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS
@ -5313,6 +5315,8 @@ int CyaSSL_dtls_got_timeout(CYASSL* ssl)
#ifdef CYASSL_DTLS #ifdef CYASSL_DTLS
if (ssl->options.dtls) { if (ssl->options.dtls) {
ssl->options.clientState = NULL_STATE; /* get again */ ssl->options.clientState = NULL_STATE; /* get again */
/* reset messages received */
XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived));
/* re-init hashes, exclude first hello and verify request */ /* re-init hashes, exclude first hello and verify request */
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS
InitMd5(&ssl->hashMd5); InitMd5(&ssl->hashMd5);