diff --git a/src/dtls13.c b/src/dtls13.c index 56904a5c3..3f50dae18 100644 --- a/src/dtls13.c +++ b/src/dtls13.c @@ -351,7 +351,7 @@ static void Dtls13MsgWasProcessed(WOLFSSL* ssl, enum HandShakeType hs) ssl->dtls13Rtx.sendAcks = Dtls13RtxMsgNeedsAck(ssl, hs); } -static int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) +int Dtls13ProcessBufferedMessages(WOLFSSL* ssl) { DtlsMsg* msg = ssl->dtls_rx_msg_list; word32 idx = 0; @@ -1419,6 +1419,7 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, { word32 fragOff, fragLength; byte isComplete, isFirst; + byte usingAsyncCrypto; word32 messageLength; byte handshakeType; word32 idx; @@ -1470,9 +1471,17 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size, isFirst = fragOff == 0; isComplete = isFirst && fragLength == messageLength; + usingAsyncCrypto = ssl->devId != INVALID_DEVID; - if (!isComplete || ssl->keys.dtls_peer_handshake_number > - ssl->keys.dtls_expected_peer_handshake_number) { + /* store the message if any of the following: (a) incomplete message, (b) + * out of order message or (c) if using async crypto. In (c) the processing + * of the message can return WC_PENDING_E, it's easier to handle this error + * if the message is stored in the buffer. + */ + if (!isComplete || + ssl->keys.dtls_peer_handshake_number > + ssl->keys.dtls_expected_peer_handshake_number || + usingAsyncCrypto) { DtlsMsgStore(ssl, w64GetLow32(ssl->keys.curEpoch64), ssl->keys.dtls_peer_handshake_number, input + DTLS_HANDSHAKE_HEADER_SZ, messageLength, handshakeType, diff --git a/src/internal.c b/src/internal.c index f57457492..c0f7a9fa1 100644 --- a/src/internal.c +++ b/src/internal.c @@ -18113,11 +18113,25 @@ int ProcessReplyEx(WOLFSSL* ssl, int allowSocketErr) #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_ASYNC_CRYPT) /* process any pending DTLS messages - this flow can happen with async */ if (ssl->dtls_rx_msg_list != NULL) { - ret = DtlsMsgDrain(ssl); + word32 pendingMsg = ssl->dtls_rx_msg_list_sz; + if(IsAtLeastTLSv1_3(ssl->version)) { +#ifdef WOLFSSL_DTLS13 + ret = Dtls13ProcessBufferedMessages(ssl); +#elif + ret = NOT_COMPILED_IN; +#endif /* WOLFSSL_DTLS13 */ + } + else { + ret = DtlsMsgDrain(ssl); + } if (ret != 0) { WOLFSSL_ERROR(ret); return ret; } + /* we processed some messages, return so connect/accept can make + progress */ + if (ssl->dtls_rx_msg_list_sz != pendingMsg) + return ret; } #endif diff --git a/src/tls13.c b/src/tls13.c index 4353ddc3d..716685ae5 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -9475,8 +9475,11 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_ASYNC_IO) /* if async, offset index so this msg will be processed again */ - /* NOTE: check this now before other calls can overwirte ret */ + /* NOTE: check this now before other calls can overwrite ret */ if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { + /* DTLS always stores a message in a buffer when async is enable, so we + * don't need to adjust for the extra bytes here (*inOutIdx is always + * == 0) */ *inOutIdx -= HANDSHAKE_HEADER_SZ; } #endif diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 33daeaa7c..567b08a23 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -5479,6 +5479,7 @@ WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* output, word16 length); WOLFSSL_LOCAL void Dtls13FreeFsmResources(WOLFSSL* ssl); WOLFSSL_LOCAL int Dtls13RtxTimeout(WOLFSSL* ssl); +WOLFSSL_LOCAL int Dtls13ProcessBufferedMessages(WOLFSSL* ssl); #endif /* WOLFSSL_DTLS13 */ #ifdef WOLFSSL_STATIC_EPHEMERAL