diff --git a/src/internal.c b/src/internal.c index 09c6d23f7..5c9ede255 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5267,8 +5267,8 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_ENTER("DoHandShakeMsg()"); - /* If there is a pending fragmented handshake message, pending message size - * will be non-zero. */ + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ if (ssl->arrays->pendingMsgSz == 0) { byte type; word32 size; @@ -5276,8 +5276,16 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) return PARSE_ERROR; + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + /* size is the size of the certificate message payload */ - if (totalSz - HANDSHAKE_HEADER_SZ < size) { + if (ssl->curSize < size) { ssl->arrays->pendingMsgType = type; ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, @@ -5286,25 +5294,25 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ssl->arrays->pendingMsg == NULL) return MEMORY_E; XMEMCPY(ssl->arrays->pendingMsg, - input + *inOutIdx - HANDSHAKE_HEADER_SZ, totalSz); - ssl->arrays->pendingMsgOffset = totalSz; - *inOutIdx += totalSz - HANDSHAKE_HEADER_SZ; + input + *inOutIdx - HANDSHAKE_HEADER_SZ, ssl->curSize); + ssl->arrays->pendingMsgOffset = ssl->curSize; + *inOutIdx += ssl->curSize - HANDSHAKE_HEADER_SZ; return 0; } ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); } else { - if (totalSz + ssl->arrays->pendingMsgOffset + if (ssl->curSize + ssl->arrays->pendingMsgOffset > ssl->arrays->pendingMsgSz) { return BUFFER_ERROR; } else { XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, - input + *inOutIdx, totalSz); - ssl->arrays->pendingMsgOffset += totalSz; - *inOutIdx += totalSz; + input + *inOutIdx, ssl->curSize); + ssl->arrays->pendingMsgOffset += ssl->curSize; + *inOutIdx += ssl->curSize; } if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) @@ -8553,6 +8561,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case RSA_SIGN_FAULT: return "RSA Signature Fault Error"; + case HANDSHAKE_SIZE_ERROR: + return "Handshake message too large Error"; + default : return "unknown error number"; } diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 309be9eca..c3ff047fc 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -136,6 +136,7 @@ enum wolfSSL_ErrorCodes { DH_KEY_SIZE_E = -401, /* DH Key too small */ SNI_ABSENT_ERROR = -402, /* No SNI request. */ RSA_SIGN_FAULT = -403, /* RSA Sign fault */ + HANDSHAKE_SIZE_ERROR = -404, /* Handshake message too large */ /* add strings to SetErrorString !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 420c0f677..85afad61c 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1016,6 +1016,19 @@ enum Misc { #define MAX_CHAIN_DEPTH 9 #endif +/* max size of a certificate message payload */ +/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */ +#ifndef MAX_CERTIFICATE_SZ + #define MAX_CERTIFICATE_SZ \ + CERT_HEADER_SZ + \ + (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH +#endif + +/* max size of a handshake message, currently set to the certificate */ +#ifndef MAX_HANDSHAKE_SZ + #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ +#endif + #ifndef SESSION_TICKET_LEN #define SESSION_TICKET_LEN 256 #endif