forked from wolfSSL/wolfssl
Merge pull request #7029 from julek-wolfssl/zd/17108-fix
Additional TLS checks
This commit is contained in:
15
src/dtls13.c
15
src/dtls13.c
@@ -363,6 +363,14 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
|
|||||||
if (!msg->ready)
|
if (!msg->ready)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||||
|
ret = MsgCheckEncryption(ssl, msg->type, msg->encrypted);
|
||||||
|
if (ret != 0) {
|
||||||
|
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* We may have DTLS <=1.2 msgs stored from before we knew which version
|
/* We may have DTLS <=1.2 msgs stored from before we knew which version
|
||||||
* we were going to use. Interpret correctly. */
|
* we were going to use. Interpret correctly. */
|
||||||
if (IsAtLeastTLSv1_3(ssl->version)) {
|
if (IsAtLeastTLSv1_3(ssl->version)) {
|
||||||
@@ -1622,6 +1630,13 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
|
|||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
|
|
||||||
|
/* Need idx + fragLength as we don't advance the inputBuffer idx value */
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, handshakeType, idx + fragLength);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (ssl->options.side == WOLFSSL_SERVER_END &&
|
if (ssl->options.side == WOLFSSL_SERVER_END &&
|
||||||
ssl->options.acceptState < TLS13_ACCEPT_FIRST_REPLY_DONE) {
|
ssl->options.acceptState < TLS13_ACCEPT_FIRST_REPLY_DONE) {
|
||||||
if (handshakeType != client_hello) {
|
if (handshakeType != client_hello) {
|
||||||
|
353
src/internal.c
353
src/internal.c
@@ -547,7 +547,7 @@ int IsAtLeastTLSv1_3(const ProtocolVersion pv)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsEncryptionOn(WOLFSSL* ssl, int isSend)
|
int IsEncryptionOn(const WOLFSSL* ssl, int isSend)
|
||||||
{
|
{
|
||||||
#ifdef WOLFSSL_DTLS
|
#ifdef WOLFSSL_DTLS
|
||||||
/* For DTLS, epoch 0 is always not encrypted. */
|
/* For DTLS, epoch 0 is always not encrypted. */
|
||||||
@@ -4688,7 +4688,7 @@ static void SetDigest(WOLFSSL* ssl, int hashAlgo)
|
|||||||
#endif /* !NO_CERTS */
|
#endif /* !NO_CERTS */
|
||||||
|
|
||||||
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||||
static word32 MacSize(WOLFSSL* ssl)
|
static word32 MacSize(const WOLFSSL* ssl)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_TRUNCATED_HMAC
|
#ifdef HAVE_TRUNCATED_HMAC
|
||||||
word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
|
word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ
|
||||||
@@ -8972,7 +8972,8 @@ static void DtlsMsgAssembleCompleteMessage(DtlsMsg* msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte type,
|
int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte type,
|
||||||
word32 fragOffset, word32 fragSz, void* heap, word32 totalLen)
|
word32 fragOffset, word32 fragSz, void* heap, word32 totalLen,
|
||||||
|
byte encrypted)
|
||||||
{
|
{
|
||||||
word32 fragOffsetEnd = fragOffset + fragSz;
|
word32 fragOffsetEnd = fragOffset + fragSz;
|
||||||
|
|
||||||
@@ -8993,11 +8994,13 @@ int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch, const byte* data, byte ty
|
|||||||
WOLFSSL_ERROR_VERBOSE(SEQUENCE_ERROR);
|
WOLFSSL_ERROR_VERBOSE(SEQUENCE_ERROR);
|
||||||
return SEQUENCE_ERROR;
|
return SEQUENCE_ERROR;
|
||||||
}
|
}
|
||||||
|
msg->encrypted = msg->encrypted && encrypted;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
msg->type = type;
|
msg->type = type;
|
||||||
msg->epoch = epoch;
|
msg->epoch = epoch;
|
||||||
msg->seq = seq;
|
msg->seq = seq;
|
||||||
|
msg->encrypted = encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg->fragBucketList == NULL) {
|
if (msg->fragBucketList == NULL) {
|
||||||
@@ -9118,6 +9121,7 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DtlsMsg* head = ssl->dtls_rx_msg_list;
|
DtlsMsg* head = ssl->dtls_rx_msg_list;
|
||||||
|
byte encrypted = ssl->keys.decryptedCur == 1;
|
||||||
WOLFSSL_ENTER("DtlsMsgStore");
|
WOLFSSL_ENTER("DtlsMsgStore");
|
||||||
|
|
||||||
if (head != NULL) {
|
if (head != NULL) {
|
||||||
@@ -9126,7 +9130,7 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data,
|
|||||||
cur = DtlsMsgNew(dataSz, 0, heap);
|
cur = DtlsMsgNew(dataSz, 0, heap);
|
||||||
if (cur != NULL) {
|
if (cur != NULL) {
|
||||||
if (DtlsMsgSet(cur, seq, epoch, data, type,
|
if (DtlsMsgSet(cur, seq, epoch, data, type,
|
||||||
fragOffset, fragSz, heap, dataSz) < 0) {
|
fragOffset, fragSz, heap, dataSz, encrypted) < 0) {
|
||||||
DtlsMsgDelete(cur, heap);
|
DtlsMsgDelete(cur, heap);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -9138,13 +9142,13 @@ void DtlsMsgStore(WOLFSSL* ssl, word16 epoch, word32 seq, const byte* data,
|
|||||||
else {
|
else {
|
||||||
/* If this fails, the data is just dropped. */
|
/* If this fails, the data is just dropped. */
|
||||||
DtlsMsgSet(cur, seq, epoch, data, type, fragOffset,
|
DtlsMsgSet(cur, seq, epoch, data, type, fragOffset,
|
||||||
fragSz, heap, dataSz);
|
fragSz, heap, dataSz, encrypted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
head = DtlsMsgNew(dataSz, 0, heap);
|
head = DtlsMsgNew(dataSz, 0, heap);
|
||||||
if (DtlsMsgSet(head, seq, epoch, data, type, fragOffset,
|
if (DtlsMsgSet(head, seq, epoch, data, type, fragOffset,
|
||||||
fragSz, heap, dataSz) < 0) {
|
fragSz, heap, dataSz, encrypted) < 0) {
|
||||||
DtlsMsgDelete(head, heap);
|
DtlsMsgDelete(head, heap);
|
||||||
head = NULL;
|
head = NULL;
|
||||||
}
|
}
|
||||||
@@ -10714,6 +10718,297 @@ int CheckAvailableSize(WOLFSSL *ssl, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||||
|
|
||||||
|
int MsgCheckEncryption(WOLFSSL* ssl, byte type, byte encrypted)
|
||||||
|
{
|
||||||
|
#ifdef WOLFSSL_QUIC
|
||||||
|
/* QUIC protects messages outside of the TLS scope */
|
||||||
|
if (WOLFSSL_IS_QUIC(ssl) && IsAtLeastTLSv1_3(ssl->version))
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
/* Verify which messages always have to be encrypted */
|
||||||
|
if (IsAtLeastTLSv1_3(ssl->version)) {
|
||||||
|
switch ((enum HandShakeType)type) {
|
||||||
|
case client_hello:
|
||||||
|
case server_hello:
|
||||||
|
case hello_verify_request:
|
||||||
|
case hello_retry_request:
|
||||||
|
case change_cipher_hs:
|
||||||
|
if (encrypted) {
|
||||||
|
WOLFSSL_MSG("Message can not be encrypted");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hello_request:
|
||||||
|
case session_ticket:
|
||||||
|
case end_of_early_data:
|
||||||
|
case encrypted_extensions:
|
||||||
|
case certificate:
|
||||||
|
case server_key_exchange:
|
||||||
|
case certificate_request:
|
||||||
|
case server_hello_done:
|
||||||
|
case certificate_verify:
|
||||||
|
case client_key_exchange:
|
||||||
|
case finished:
|
||||||
|
case certificate_status:
|
||||||
|
case key_update:
|
||||||
|
if (!encrypted) {
|
||||||
|
WOLFSSL_MSG("Message always has to be encrypted");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case message_hash:
|
||||||
|
case no_shake:
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Unknown message type");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||||
|
return SANITY_MSG_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ((enum HandShakeType)type) {
|
||||||
|
case client_hello:
|
||||||
|
if ((IsSCR(ssl) || ssl->options.handShakeDone) && !encrypted) {
|
||||||
|
WOLFSSL_MSG("Message has to be encrypted for SCR");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case server_hello:
|
||||||
|
case hello_verify_request:
|
||||||
|
case hello_retry_request:
|
||||||
|
case certificate:
|
||||||
|
case server_key_exchange:
|
||||||
|
case certificate_request:
|
||||||
|
case server_hello_done:
|
||||||
|
case certificate_verify:
|
||||||
|
case client_key_exchange:
|
||||||
|
case certificate_status:
|
||||||
|
case session_ticket:
|
||||||
|
case change_cipher_hs:
|
||||||
|
if (IsSCR(ssl)) {
|
||||||
|
if (!encrypted) {
|
||||||
|
WOLFSSL_MSG("Message has to be encrypted during SCR");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (encrypted) {
|
||||||
|
WOLFSSL_MSG("Message can not be encrypted in regular "
|
||||||
|
"handshake");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hello_request:
|
||||||
|
case finished:
|
||||||
|
if (!encrypted) {
|
||||||
|
WOLFSSL_MSG("Message always has to be encrypted");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case key_update:
|
||||||
|
case encrypted_extensions:
|
||||||
|
case end_of_early_data:
|
||||||
|
case message_hash:
|
||||||
|
case no_shake:
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Unknown message type");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||||
|
return SANITY_MSG_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static WC_INLINE int isLastMsg(const WOLFSSL* ssl, word32 msgSz)
|
||||||
|
{
|
||||||
|
word32 extra = 0;
|
||||||
|
if (IsEncryptionOn(ssl, 0)) {
|
||||||
|
extra = ssl->keys.padSz;
|
||||||
|
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
|
||||||
|
if (ssl->options.startedETMRead)
|
||||||
|
extra += MacSize(ssl);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return (ssl->buffers.inputBuffer.idx - ssl->curStartIdx) + msgSz + extra
|
||||||
|
== ssl->curSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the msg is the last msg in a record. This is also an easy way
|
||||||
|
* to check that a record doesn't span different key boundaries. */
|
||||||
|
static int MsgCheckBoundary(const WOLFSSL* ssl, byte type,
|
||||||
|
byte version_negotiated, word32 msgSz)
|
||||||
|
{
|
||||||
|
if (version_negotiated) {
|
||||||
|
if (IsAtLeastTLSv1_3(ssl->version)) {
|
||||||
|
switch ((enum HandShakeType)type) {
|
||||||
|
case hello_request:
|
||||||
|
case client_hello:
|
||||||
|
case server_hello:
|
||||||
|
case hello_verify_request:
|
||||||
|
case hello_retry_request:
|
||||||
|
case finished:
|
||||||
|
case end_of_early_data:
|
||||||
|
if (!isLastMsg(ssl, msgSz)) {
|
||||||
|
WOLFSSL_MSG("Message type is not last in record");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case session_ticket:
|
||||||
|
case encrypted_extensions:
|
||||||
|
case certificate:
|
||||||
|
case server_key_exchange:
|
||||||
|
case certificate_request:
|
||||||
|
case certificate_verify:
|
||||||
|
case client_key_exchange:
|
||||||
|
case certificate_status:
|
||||||
|
case key_update:
|
||||||
|
case change_cipher_hs:
|
||||||
|
break;
|
||||||
|
case server_hello_done:
|
||||||
|
case message_hash:
|
||||||
|
case no_shake:
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Unknown message type");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||||
|
return SANITY_MSG_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ((enum HandShakeType)type) {
|
||||||
|
case hello_request:
|
||||||
|
case client_hello:
|
||||||
|
case hello_verify_request:
|
||||||
|
if (!isLastMsg(ssl, msgSz)) {
|
||||||
|
WOLFSSL_MSG("Message type is not last in record");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case server_hello:
|
||||||
|
case session_ticket:
|
||||||
|
case end_of_early_data:
|
||||||
|
case certificate:
|
||||||
|
case server_key_exchange:
|
||||||
|
case certificate_request:
|
||||||
|
case server_hello_done:
|
||||||
|
case certificate_verify:
|
||||||
|
case client_key_exchange:
|
||||||
|
case finished:
|
||||||
|
case certificate_status:
|
||||||
|
case change_cipher_hs:
|
||||||
|
break;
|
||||||
|
case hello_retry_request:
|
||||||
|
case encrypted_extensions:
|
||||||
|
case key_update:
|
||||||
|
case message_hash:
|
||||||
|
case no_shake:
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Unknown message type");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||||
|
return SANITY_MSG_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch ((enum HandShakeType)type) {
|
||||||
|
case hello_request:
|
||||||
|
case client_hello:
|
||||||
|
case hello_verify_request:
|
||||||
|
if (!isLastMsg(ssl, msgSz)) {
|
||||||
|
WOLFSSL_MSG("Message type is not last in record");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(OUT_OF_ORDER_E);
|
||||||
|
return OUT_OF_ORDER_E;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case server_hello:
|
||||||
|
case session_ticket:
|
||||||
|
case end_of_early_data:
|
||||||
|
case hello_retry_request:
|
||||||
|
case encrypted_extensions:
|
||||||
|
case certificate:
|
||||||
|
case server_key_exchange:
|
||||||
|
case certificate_request:
|
||||||
|
case server_hello_done:
|
||||||
|
case certificate_verify:
|
||||||
|
case client_key_exchange:
|
||||||
|
case finished:
|
||||||
|
case certificate_status:
|
||||||
|
case key_update:
|
||||||
|
case change_cipher_hs:
|
||||||
|
break;
|
||||||
|
case message_hash:
|
||||||
|
case no_shake:
|
||||||
|
default:
|
||||||
|
WOLFSSL_MSG("Unknown message type");
|
||||||
|
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
|
||||||
|
return SANITY_MSG_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSL_DISABLE_EARLY_SANITY_CHECKS */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This check is performed as soon as the handshake message type becomes known.
|
||||||
|
* These checks can not be delayed and need to be performed when the msg is
|
||||||
|
* received and not when it is processed (fragmentation may cause messages to
|
||||||
|
* be processed at a later time). This function CAN NOT be called on stored
|
||||||
|
* messages as it relies on the state of the WOLFSSL object right after
|
||||||
|
* receiving the message.
|
||||||
|
*
|
||||||
|
* @param ssl The current connection
|
||||||
|
* @param type The enum HandShakeType of the current message
|
||||||
|
* @param msgSz Size of the current message
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type, word32 msgSz)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||||
|
byte version_negotiated = 0;
|
||||||
|
|
||||||
|
WOLFSSL_ENTER("EarlySanityCheckMsgReceived");
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
/* Version has only been negotiated after we either send or process a
|
||||||
|
* ServerHello message */
|
||||||
|
if (ssl->options.dtls)
|
||||||
|
version_negotiated = ssl->options.serverState >= SERVER_HELLO_COMPLETE;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
version_negotiated = 1;
|
||||||
|
|
||||||
|
if (version_negotiated)
|
||||||
|
ret = MsgCheckEncryption(ssl, type, ssl->keys.decryptedCur == 1);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = MsgCheckBoundary(ssl, type, version_negotiated, msgSz);
|
||||||
|
|
||||||
|
if (ret != 0
|
||||||
|
#ifdef WOLFSSL_DTLS
|
||||||
|
&& ssl->options.dtls && ssl->options.dtlsStateful
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||||
|
|
||||||
|
WOLFSSL_LEAVE("EarlySanityCheckMsgReceived", ret);
|
||||||
|
#else
|
||||||
|
(void)ssl;
|
||||||
|
(void)type;
|
||||||
|
(void)msgSz;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
static int GetInputData(WOLFSSL *ssl, word32 size);
|
static int GetInputData(WOLFSSL *ssl, word32 size);
|
||||||
static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
|
static int GetDtls13RecordHeader(WOLFSSL* ssl, word32* inOutIdx,
|
||||||
@@ -15785,7 +16080,6 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
|
/* Make sure no duplicates, no fast forward, or other problems; 0 on success */
|
||||||
static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
|
static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
|
||||||
{
|
{
|
||||||
@@ -16650,6 +16944,12 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, type, size);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (size > MAX_HANDSHAKE_SZ) {
|
if (size > MAX_HANDSHAKE_SZ) {
|
||||||
WOLFSSL_MSG("Handshake message too large");
|
WOLFSSL_MSG("Handshake message too large");
|
||||||
WOLFSSL_ERROR_VERBOSE(HANDSHAKE_SIZE_ERROR);
|
WOLFSSL_ERROR_VERBOSE(HANDSHAKE_SIZE_ERROR);
|
||||||
@@ -16673,6 +16973,13 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, type,
|
||||||
|
min(inputLength - HANDSHAKE_HEADER_SZ, size));
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cap the maximum size of a handshake message to something reasonable.
|
/* Cap the maximum size of a handshake message to something reasonable.
|
||||||
* By default is the maximum size of a certificate message assuming
|
* By default is the maximum size of a certificate message assuming
|
||||||
* nine 2048-bit RSA certificates in the chain. */
|
* nine 2048-bit RSA certificates in the chain. */
|
||||||
@@ -16711,6 +17018,13 @@ static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
if (inputLength > pendSz)
|
if (inputLength > pendSz)
|
||||||
inputLength = pendSz;
|
inputLength = pendSz;
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, ssl->arrays->pendingMsgType,
|
||||||
|
inputLength);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
if (ssl->error != WC_PENDING_E)
|
if (ssl->error != WC_PENDING_E)
|
||||||
#endif
|
#endif
|
||||||
@@ -17265,6 +17579,14 @@ int DtlsMsgDrain(WOLFSSL* ssl)
|
|||||||
item->ready && ret == 0) {
|
item->ready && ret == 0) {
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
|
|
||||||
|
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||||
|
ret = MsgCheckEncryption(ssl, item->type, item->encrypted);
|
||||||
|
if (ret != 0) {
|
||||||
|
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef WOLFSSL_NO_TLS12
|
#ifdef WOLFSSL_NO_TLS12
|
||||||
ret = DoTls13HandShakeMsgType(ssl, item->fullMsg, &idx, item->type,
|
ret = DoTls13HandShakeMsgType(ssl, item->fullMsg, &idx, item->type,
|
||||||
item->sz, item->sz);
|
item->sz, item->sz);
|
||||||
@@ -17314,6 +17636,12 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, type, fragSz);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cap the maximum size of a handshake message to something reasonable.
|
/* Cap the maximum size of a handshake message to something reasonable.
|
||||||
* By default is the maximum size of a certificate message assuming
|
* By default is the maximum size of a certificate message assuming
|
||||||
* nine 2048-bit RSA certificates in the chain. */
|
* nine 2048-bit RSA certificates in the chain. */
|
||||||
@@ -20271,7 +20599,6 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr)
|
|||||||
{
|
{
|
||||||
int ret = 0, type = internal_error, readSz;
|
int ret = 0, type = internal_error, readSz;
|
||||||
int atomicUser = 0;
|
int atomicUser = 0;
|
||||||
word32 startIdx = 0;
|
|
||||||
#if defined(WOLFSSL_DTLS)
|
#if defined(WOLFSSL_DTLS)
|
||||||
int used;
|
int used;
|
||||||
#endif
|
#endif
|
||||||
@@ -20563,7 +20890,8 @@ default:
|
|||||||
ssl->keys.padSz = 0;
|
ssl->keys.padSz = 0;
|
||||||
|
|
||||||
ssl->options.processReply = verifyEncryptedMessage;
|
ssl->options.processReply = verifyEncryptedMessage;
|
||||||
startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */
|
/* in case > 1 msg per record */
|
||||||
|
ssl->curStartIdx = ssl->buffers.inputBuffer.idx;
|
||||||
FALL_THROUGH;
|
FALL_THROUGH;
|
||||||
|
|
||||||
/* verify digest of encrypted message */
|
/* verify digest of encrypted message */
|
||||||
@@ -20907,7 +21235,7 @@ default:
|
|||||||
/* For TLS v1.1 the block size and explicit IV are added to idx,
|
/* For TLS v1.1 the block size and explicit IV are added to idx,
|
||||||
* so it needs to be included in this limit check */
|
* so it needs to be included in this limit check */
|
||||||
if ((ssl->curSize - ssl->keys.padSz -
|
if ((ssl->curSize - ssl->keys.padSz -
|
||||||
(ssl->buffers.inputBuffer.idx - startIdx) -
|
(ssl->buffers.inputBuffer.idx - ssl->curStartIdx) -
|
||||||
MacSize(ssl) > MAX_PLAINTEXT_SZ)
|
MacSize(ssl) > MAX_PLAINTEXT_SZ)
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
&& ssl->buffers.inputBuffer.length !=
|
&& ssl->buffers.inputBuffer.length !=
|
||||||
@@ -20929,7 +21257,7 @@ default:
|
|||||||
* so it needs to be included in this limit check */
|
* so it needs to be included in this limit check */
|
||||||
if (!IsAtLeastTLSv1_3(ssl->version)
|
if (!IsAtLeastTLSv1_3(ssl->version)
|
||||||
&& ssl->curSize - ssl->keys.padSz -
|
&& ssl->curSize - ssl->keys.padSz -
|
||||||
(ssl->buffers.inputBuffer.idx - startIdx)
|
(ssl->buffers.inputBuffer.idx - ssl->curStartIdx)
|
||||||
> MAX_PLAINTEXT_SZ
|
> MAX_PLAINTEXT_SZ
|
||||||
#ifdef WOLFSSL_ASYNC_CRYPT
|
#ifdef WOLFSSL_ASYNC_CRYPT
|
||||||
&& ssl->buffers.inputBuffer.length !=
|
&& ssl->buffers.inputBuffer.length !=
|
||||||
@@ -21333,7 +21661,8 @@ default:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/* more messages per record */
|
/* more messages per record */
|
||||||
else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) {
|
else if ((ssl->buffers.inputBuffer.idx - ssl->curStartIdx)
|
||||||
|
< ssl->curSize) {
|
||||||
WOLFSSL_MSG("More messages in record");
|
WOLFSSL_MSG("More messages in record");
|
||||||
|
|
||||||
ssl->options.processReply = runProcessingOneMessage;
|
ssl->options.processReply = runProcessingOneMessage;
|
||||||
|
23
src/tls13.c
23
src/tls13.c
@@ -11787,8 +11787,6 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
WOLFSSL_ENTER("DoTls13HandShakeMsg");
|
WOLFSSL_ENTER("DoTls13HandShakeMsg");
|
||||||
|
|
||||||
if (ssl->arrays == NULL) {
|
if (ssl->arrays == NULL) {
|
||||||
|
|
||||||
|
|
||||||
if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
|
if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size,
|
||||||
totalSz) != 0) {
|
totalSz) != 0) {
|
||||||
SendAlert(ssl, alert_fatal, unexpected_message);
|
SendAlert(ssl, alert_fatal, unexpected_message);
|
||||||
@@ -11796,6 +11794,12 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, type, size);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
|
return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size,
|
||||||
totalSz);
|
totalSz);
|
||||||
}
|
}
|
||||||
@@ -11812,6 +11816,13 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
return PARSE_ERROR;
|
return PARSE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, type,
|
||||||
|
min(inputLength - HANDSHAKE_HEADER_SZ, size));
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Cap the maximum size of a handshake message to something reasonable.
|
/* Cap the maximum size of a handshake message to something reasonable.
|
||||||
* By default is the maximum size of a certificate message assuming
|
* By default is the maximum size of a certificate message assuming
|
||||||
* nine 2048-bit RSA certificates in the chain. */
|
* nine 2048-bit RSA certificates in the chain. */
|
||||||
@@ -11847,6 +11858,14 @@ int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx,
|
|||||||
inputLength = ssl->arrays->pendingMsgSz -
|
inputLength = ssl->arrays->pendingMsgSz -
|
||||||
ssl->arrays->pendingMsgOffset;
|
ssl->arrays->pendingMsgOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = EarlySanityCheckMsgReceived(ssl, ssl->arrays->pendingMsgType,
|
||||||
|
inputLength);
|
||||||
|
if (ret != 0) {
|
||||||
|
WOLFSSL_ERROR(ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
|
XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset,
|
||||||
input + *inOutIdx, inputLength);
|
input + *inOutIdx, inputLength);
|
||||||
ssl->arrays->pendingMsgOffset += inputLength;
|
ssl->arrays->pendingMsgOffset += inputLength;
|
||||||
|
@@ -61806,6 +61806,7 @@ static word32 test_wolfSSL_dtls_stateless_HashWOLFSSL(const WOLFSSL* ssl)
|
|||||||
sslCopy.buffers.outputBuffer.offset = 0;
|
sslCopy.buffers.outputBuffer.offset = 0;
|
||||||
sslCopy.error = 0;
|
sslCopy.error = 0;
|
||||||
sslCopy.curSize = 0;
|
sslCopy.curSize = 0;
|
||||||
|
sslCopy.curStartIdx = 0;
|
||||||
sslCopy.keys.curSeq_lo = 0;
|
sslCopy.keys.curSeq_lo = 0;
|
||||||
XMEMSET(&sslCopy.curRL, 0, sizeof(sslCopy.curRL));
|
XMEMSET(&sslCopy.curRL, 0, sizeof(sslCopy.curRL));
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
@@ -67470,7 +67471,11 @@ static int test_TLSX_CA_NAMES_bad_extension(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
|
||||||
|
#ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS
|
||||||
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), OUT_OF_ORDER_E);
|
||||||
|
#else
|
||||||
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), BUFFER_ERROR);
|
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), BUFFER_ERROR);
|
||||||
|
#endif
|
||||||
|
|
||||||
wolfSSL_free(ssl_c);
|
wolfSSL_free(ssl_c);
|
||||||
ssl_c = NULL;
|
ssl_c = NULL;
|
||||||
|
@@ -5146,6 +5146,7 @@ typedef struct DtlsMsg {
|
|||||||
byte type;
|
byte type;
|
||||||
byte fragBucketListCount;
|
byte fragBucketListCount;
|
||||||
byte ready:1;
|
byte ready:1;
|
||||||
|
byte encrypted:1;
|
||||||
} DtlsMsg;
|
} DtlsMsg;
|
||||||
|
|
||||||
|
|
||||||
@@ -5475,6 +5476,7 @@ struct WOLFSSL {
|
|||||||
word32 timeout; /* session timeout */
|
word32 timeout; /* session timeout */
|
||||||
word32 fragOffset; /* fragment offset */
|
word32 fragOffset; /* fragment offset */
|
||||||
word16 curSize;
|
word16 curSize;
|
||||||
|
word32 curStartIdx;
|
||||||
byte verifyDepth;
|
byte verifyDepth;
|
||||||
RecordLayerHeader curRL;
|
RecordLayerHeader curRL;
|
||||||
MsgsReceived msgsReceived; /* peer messages received */
|
MsgsReceived msgsReceived; /* peer messages received */
|
||||||
@@ -6110,7 +6112,7 @@ WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side);
|
|||||||
WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl);
|
WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl);
|
WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL int IsAtLeastTLSv1_3(ProtocolVersion pv);
|
WOLFSSL_LOCAL int IsAtLeastTLSv1_3(ProtocolVersion pv);
|
||||||
WOLFSSL_LOCAL int IsEncryptionOn(WOLFSSL* ssl, int isSend);
|
WOLFSSL_LOCAL int IsEncryptionOn(const WOLFSSL* ssl, int isSend);
|
||||||
WOLFSSL_LOCAL int TLSv1_3_Capable(WOLFSSL* ssl);
|
WOLFSSL_LOCAL int TLSv1_3_Capable(WOLFSSL* ssl);
|
||||||
|
|
||||||
WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl);
|
WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl);
|
||||||
@@ -6232,6 +6234,9 @@ WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes,
|
|||||||
WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
|
WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep);
|
||||||
WOLFSSL_LOCAL int CheckAvailableSize(WOLFSSL *ssl, int size);
|
WOLFSSL_LOCAL int CheckAvailableSize(WOLFSSL *ssl, int size);
|
||||||
WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
|
WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength);
|
||||||
|
WOLFSSL_LOCAL int MsgCheckEncryption(WOLFSSL* ssl, byte type, byte encrypted);
|
||||||
|
WOLFSSL_LOCAL int EarlySanityCheckMsgReceived(WOLFSSL* ssl, byte type,
|
||||||
|
word32 msgSz);
|
||||||
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
|
#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH)
|
||||||
WOLFSSL_LOCAL void DoCertFatalAlert(WOLFSSL* ssl, int ret);
|
WOLFSSL_LOCAL void DoCertFatalAlert(WOLFSSL* ssl, int ret);
|
||||||
#endif
|
#endif
|
||||||
@@ -6271,7 +6276,7 @@ WOLFSSL_LOCAL int cipherExtraData(WOLFSSL* ssl);
|
|||||||
WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch,
|
WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg* msg, word32 seq, word16 epoch,
|
||||||
const byte* data, byte type,
|
const byte* data, byte type,
|
||||||
word32 fragOffset, word32 fragSz, void* heap,
|
word32 fragOffset, word32 fragSz, void* heap,
|
||||||
word32 totalLen);
|
word32 totalLen, byte encrypted);
|
||||||
/* Use WOLFSSL_API to enable src/api.c testing */
|
/* Use WOLFSSL_API to enable src/api.c testing */
|
||||||
WOLFSSL_API DtlsMsg* DtlsMsgFind(DtlsMsg* head, word16 epoch, word32 seq);
|
WOLFSSL_API DtlsMsg* DtlsMsgFind(DtlsMsg* head, word16 epoch, word32 seq);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user