Merge pull request #6700 from julek-wolfssl/dtls13-downgrade-acks

DTLS 1.3: do not send ACKs until we negotiate 1.3 (through SH)
This commit is contained in:
JacobBarthelmeh
2023-08-25 09:34:53 -06:00
committed by GitHub
9 changed files with 318 additions and 19 deletions

View File

@ -91,7 +91,7 @@ set -e
if [ -d ./async ];
then
echo "\n\nUsing existing async repo\n\n"
echo "Using existing async repo"
else
# make a clone of the wolfAsyncCrypt repository
git clone --depth 1 $ASYNC_REPO async

View File

@ -75,6 +75,7 @@ void DtlsResetState(WOLFSSL* ssl)
ssl->options.connectState = CONNECT_BEGIN;
ssl->options.acceptState = ACCEPT_BEGIN;
ssl->options.handShakeState = NULL_STATE;
ssl->options.seenUnifiedHdr = 0;
ssl->msgsReceived.got_client_hello = 0;
ssl->keys.dtls_handshake_number = 0;
ssl->keys.dtls_expected_peer_handshake_number = 0;

View File

@ -352,6 +352,7 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
WOLFSSL_ENTER("Dtls13ProcessBufferedMessages");
while (msg != NULL) {
int downgraded = 0;
idx = 0;
/* message not in order */
@ -362,8 +363,18 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
if (!msg->ready)
break;
ret = DoTls13HandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
msg->sz, msg->sz);
/* We may have DTLS <=1.2 msgs stored from before we knew which version
* we were going to use. Interpret correctly. */
if (IsAtLeastTLSv1_3(ssl->version)) {
ret = DoTls13HandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
msg->sz, msg->sz);
if (!IsAtLeastTLSv1_3(ssl->version))
downgraded = 1;
}
else {
ret = DoHandShakeMsgType(ssl, msg->fullMsg, &idx, msg->type,
msg->sz, msg->sz);
}
/* processing certificate_request triggers a connect. The error came
* from there, the message can be considered processed successfully.
@ -371,7 +382,13 @@ int Dtls13ProcessBufferedMessages(WOLFSSL* ssl)
* waiting to flush the output buffer. */
if ((ret == 0 || ret == WANT_WRITE) || (msg->type == certificate_request &&
ssl->options.handShakeDone && ret == WC_PENDING_E)) {
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);
if (IsAtLeastTLSv1_3(ssl->version))
Dtls13MsgWasProcessed(ssl, (enum HandShakeType)msg->type);
else if (downgraded)
/* DoHandShakeMsgType normally handles the hs number but if
* DoTls13HandShakeMsgType processed 1.2 msgs then this wasn't
* incremented. */
ssl->keys.dtls_expected_peer_handshake_number++;
ssl->dtls_rx_msg_list = msg->next;
DtlsMsgDelete(msg, ssl->heap);
@ -625,7 +642,7 @@ static void Dtls13RtxRecordUnlink(WOLFSSL* ssl, Dtls13RtxRecord** prevNext,
*prevNext = r->next;
}
static void Dtls13RtxFlushBuffered(WOLFSSL* ssl, byte keepNewSessionTicket)
void Dtls13RtxFlushBuffered(WOLFSSL* ssl, byte keepNewSessionTicket)
{
Dtls13RtxRecord *r, **prevNext;
@ -806,10 +823,16 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
Dtls13MaybeSaveClientHello(ssl);
/* In the handshake, receiving part of the next flight, acknowledge the
sent flight. The only exception is, on the server side, receiving the
last client flight does not ACK any sent new_session_ticket
messages. */
Dtls13RtxFlushBuffered(ssl, 1);
* sent flight. */
/* On the server side, receiving the last client flight does not ACK any
* sent new_session_ticket messages. */
/* We don't want to clear the buffer until we have done version
* negotiation in the SH or have received a unified header in the
* DTLS record. */
if (ssl->options.serverState >= SERVER_HELLO_COMPLETE ||
ssl->options.seenUnifiedHdr)
/* Use 1.2 API to clear 1.2 buffers too */
DtlsMsgPoolReset(ssl);
}
if (ssl->keys.dtls_peer_handshake_number <
@ -853,6 +876,8 @@ static int Dtls13RtxMsgRecvd(WOLFSSL* ssl, enum HandShakeType hs,
void Dtls13FreeFsmResources(WOLFSSL* ssl)
{
Dtls13RtxFlushAcks(ssl);
/* Use 1.2 API to clear 1.2 buffers too */
DtlsMsgPoolReset(ssl);
Dtls13RtxFlushBuffered(ssl, 0);
}
@ -2471,7 +2496,12 @@ int Dtls13RtxTimeout(WOLFSSL* ssl)
{
int ret = 0;
if (ssl->dtls13Rtx.seenRecords != NULL) {
/* We don't want to send acks until we have done version
* negotiation in the SH or have received a unified header in the
* DTLS record. */
if (ssl->dtls13Rtx.seenRecords != NULL &&
(ssl->options.serverState >= SERVER_HELLO_COMPLETE ||
ssl->options.seenUnifiedHdr)) {
ssl->dtls13Rtx.sendAcks = 0;
/* reset fast timeout as we are sending ACKs */
ssl->dtls13FastTimeout = 0;

View File

@ -9185,6 +9185,10 @@ void DtlsMsgPoolReset(WOLFSSL* ssl)
ssl->dtls_tx_msg = NULL;
ssl->dtls_tx_msg_list_sz = 0;
}
#ifdef WOLFSSL_DTLS13
/* Clear DTLS 1.3 buffer too */
Dtls13RtxFlushBuffered(ssl, 1);
#endif
}
@ -10740,6 +10744,7 @@ static int GetDtlsRecordHeader(WOLFSSL* ssl, word32* inOutIdx,
int ret;
if (Dtls13IsUnifiedHeader(*(ssl->buffers.inputBuffer.buffer + *inOutIdx))) {
ssl->options.seenUnifiedHdr = 1; /* We can send ACKs to the peer */
/* version 1.3 already negotiated */
if (ssl->options.tls1_3) {
@ -15678,6 +15683,12 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
WOLFSSL_ERROR_VERBOSE(DUPLICATE_MSG_E);
return DUPLICATE_MSG_E;
}
if (ssl->msgsReceived.got_hello_retry_request) {
WOLFSSL_MSG("Received HelloVerifyRequest after a "
"HelloRetryRequest");
WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
return VERSION_ERROR;
}
ssl->msgsReceived.got_hello_verify_request = 1;
break;
@ -16050,7 +16061,7 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type)
}
static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
byte type, word32 size, word32 totalSz)
{
int ret = 0;

View File

@ -12447,7 +12447,7 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
return WOLFSSL_FATAL_ERROR;
}
/* if resumption failed, reset needed state */
else if (neededState == SERVER_FINISHED_COMPLETE)
else if (neededState == SERVER_FINISHED_COMPLETE) {
if (!ssl->options.resuming) {
#ifdef WOLFSSL_DTLS
if (IsDtlsNotSctpMode(ssl))
@ -12456,17 +12456,19 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#endif
neededState = SERVER_HELLODONE_COMPLETE;
}
#ifdef WOLFSSL_DTLS13
}
#ifdef WOLFSSL_DTLS13
if (ssl->options.dtls && IsAtLeastTLSv1_3(ssl->version)
&& ssl->dtls13Rtx.sendAcks == 1) {
ssl->dtls13Rtx.sendAcks = 0;
&& ssl->dtls13Rtx.sendAcks == 1
&& ssl->options.seenUnifiedHdr) {
/* we aren't negotiated the version yet, so we aren't sure
* the other end can speak v1.3. On the other side we have
* received a unified records, assuming that the
* ServerHello got lost, we will send an empty ACK. In case
* the server is a DTLS with version less than 1.3, it
* should just ignore the message */
ssl->dtls13Rtx.sendAcks = 0;
if ((ssl->error = SendDtls13Ack(ssl)) < 0) {
if (ssl->error == WANT_WRITE)
ssl->dtls13SendingAckOrRtx = 1;
@ -12474,8 +12476,6 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
return WOLFSSL_FATAL_ERROR;
}
}
#endif /* WOLFSSL_DTLS13 */
}

View File

@ -5088,6 +5088,13 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
WOLFSSL_MSG("HelloRetryRequest format");
*extMsgType = hello_retry_request;
if (ssl->msgsReceived.got_hello_verify_request) {
WOLFSSL_MSG("Received HelloRetryRequest after a "
"HelloVerifyRequest");
WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
return VERSION_ERROR;
}
/* A HelloRetryRequest comes in as an ServerHello for MiddleBox compat.
* Found message to be a HelloRetryRequest.
* Don't allow more than one HelloRetryRequest or ServerHello.

View File

@ -5597,7 +5597,7 @@ static WC_INLINE int test_ssl_memio_write_cb(WOLFSSL *ssl, char *data, int sz,
}
if ((unsigned)(*len + sz) > TEST_SSL_MEMIO_BUF_SZ)
return WOLFSSL_CBIO_ERR_WANT_READ;
return WOLFSSL_CBIO_ERR_WANT_WRITE;
XMEMCPY(buf + *len, data, sz);
*len += sz;
@ -64662,6 +64662,237 @@ static int test_dtls_downgrade_scr(void)
}
#endif
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
static int test_dtls_client_hello_timeout_downgrade_read_cb(WOLFSSL *ssl,
char *data, int sz, void *ctx)
{
static int call_counter = 0;
call_counter++;
(void)ssl;
(void)data;
(void)sz;
(void)ctx;
switch (call_counter) {
case 1:
case 2:
return WOLFSSL_CBIO_ERR_TIMEOUT;
case 3:
return WOLFSSL_CBIO_ERR_WANT_READ;
default:
AssertIntLE(call_counter, 3);
return -1;
}
}
#endif
/* Make sure we don't send acks before getting a server hello */
static int test_dtls_client_hello_timeout_downgrade(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
DtlsRecordLayerHeader* dtlsRH;
size_t len;
byte sequence_number[8];
int i;
for (i = 0; i < 2; i++) {
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLS_client_method, wolfDTLSv1_2_server_method), 0);
if (i == 0) {
/* First time simulate timeout in IO layer */
/* CH1 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* HVR */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* CH2 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* SH flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* Drop the SH */
dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.c_buff);
len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]);
XMEMMOVE(test_ctx.c_buff, test_ctx.c_buff +
sizeof(DtlsRecordLayerHeader) + len, test_ctx.c_len -
(sizeof(DtlsRecordLayerHeader) + len));
test_ctx.c_len -= sizeof(DtlsRecordLayerHeader) + len;
/* Read the remainder of the flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_SSLSetIORecv(ssl_c,
test_dtls_client_hello_timeout_downgrade_read_cb);
/* CH3 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
wolfSSL_SSLSetIORecv(ssl_c, test_memio_read_cb);
}
else {
/* Second time call wolfSSL_dtls_got_timeout */
/* CH1 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* HVR */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* CH2 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* SH flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
/* Drop the SH */
dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.c_buff);
len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]);
XMEMMOVE(test_ctx.c_buff, test_ctx.c_buff +
sizeof(DtlsRecordLayerHeader) + len, test_ctx.c_len -
(sizeof(DtlsRecordLayerHeader) + len));
test_ctx.c_len -= sizeof(DtlsRecordLayerHeader) + len;
/* Read the remainder of the flight */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
/* Quick timeout should be set as we received at least one msg */
ExpectIntEQ(wolfSSL_dtls13_use_quick_timeout(ssl_c), 1);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
/* Quick timeout should be cleared after a quick timeout */
/* CH3 */
ExpectIntEQ(wolfSSL_dtls13_use_quick_timeout(ssl_c), 0);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
}
/* Parse out to make sure we got exactly one ClientHello message */
XMEMSET(&sequence_number, 0, sizeof(sequence_number));
/* Second ClientHello after HVR */
sequence_number[7] = 2;
dtlsRH = (DtlsRecordLayerHeader*)test_ctx.s_buff;
ExpectIntEQ(dtlsRH->type, handshake);
ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR);
ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR);
ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number,
sizeof(sequence_number)), 0);
len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]);
ExpectIntEQ(sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len);
/* Connection should be able to continue */
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
ssl_c = NULL;
ssl_s = NULL;
ctx_c = NULL;
ctx_s = NULL;
if (!EXPECT_SUCCESS())
break;
}
#endif
return EXPECT_RESULT();
}
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
static int test_dtls_client_hello_timeout_read_cb(WOLFSSL *ssl, char *data,
int sz, void *ctx)
{
static int call_counter = 0;
call_counter++;
(void)ssl;
(void)data;
(void)sz;
(void)ctx;
switch (call_counter) {
case 1:
return WOLFSSL_CBIO_ERR_TIMEOUT;
case 2:
return WOLFSSL_CBIO_ERR_WANT_READ;
default:
AssertIntLE(call_counter, 2);
return -1;
}
}
#endif
/* Make sure we don't send acks before getting a server hello */
static int test_dtls_client_hello_timeout(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13)
WOLFSSL *ssl_c = NULL;
WOLFSSL_CTX *ctx_c = NULL;
struct test_memio_ctx test_ctx;
DtlsRecordLayerHeader* dtlsRH;
size_t idx;
size_t len;
byte sequence_number[8];
int i;
for (i = 0; i < 2; i++) {
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, NULL, &ssl_c, NULL,
wolfDTLSv1_3_client_method, NULL), 0);
if (i == 0) {
/* First time simulate timeout in IO layer */
wolfSSL_SSLSetIORecv(ssl_c, test_dtls_client_hello_timeout_read_cb);
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
}
else {
/* Second time call wolfSSL_dtls_got_timeout */
ExpectIntEQ(wolfSSL_connect(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS);
}
/* Parse out to make sure we got exactly two ClientHello messages */
idx = 0;
XMEMSET(&sequence_number, 0, sizeof(sequence_number));
/* First ClientHello */
dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.s_buff + idx);
ExpectIntEQ(dtlsRH->type, handshake);
ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR);
ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR);
ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number,
sizeof(sequence_number)), 0);
len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]);
ExpectIntLT(idx + sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len);
idx += sizeof(DtlsRecordLayerHeader) + len;
/* Second ClientHello */
sequence_number[7] = 1;
dtlsRH = (DtlsRecordLayerHeader*)(test_ctx.s_buff + idx);
ExpectIntEQ(dtlsRH->type, handshake);
ExpectIntEQ(dtlsRH->pvMajor, DTLS_MAJOR);
ExpectIntEQ(dtlsRH->pvMinor, DTLSv1_2_MINOR);
ExpectIntEQ(XMEMCMP(sequence_number, dtlsRH->sequence_number,
sizeof(sequence_number)), 0);
len = (size_t)((dtlsRH->length[0] << 8) | dtlsRH->length[1]);
ExpectIntEQ(idx + sizeof(DtlsRecordLayerHeader) + len, test_ctx.s_len);
wolfSSL_free(ssl_c);
wolfSSL_CTX_free(ctx_c);
ssl_c = NULL;
ctx_c = NULL;
if (!EXPECT_SUCCESS())
break;
}
#endif
return EXPECT_RESULT();
}
/*----------------------------------------------------------------------------*
| Main
*----------------------------------------------------------------------------*/
@ -65922,6 +66153,8 @@ TEST_CASE testCases[] = {
TEST_DECL(test_session_ticket_hs_update),
TEST_DECL(test_dtls_downgrade_scr_server),
TEST_DECL(test_dtls_downgrade_scr),
TEST_DECL(test_dtls_client_hello_timeout_downgrade),
TEST_DECL(test_dtls_client_hello_timeout),
/* This test needs to stay at the end to clean up any caches allocated. */
TEST_DECL(test_wolfSSL_Cleanup)
};

View File

@ -119,6 +119,17 @@ cleanup:
/* This set of memio functions allows for more fine tuned control of the TLS
* connection operations. For new tests, try to use ssl_memio first. */
/* To dump the memory in gdb use
* dump memory client.bin test_ctx.c_buff test_ctx.c_buff+test_ctx.c_len
* dump memory server.bin test_ctx.s_buff test_ctx.s_buff+test_ctx.s_len
* This can be imported into Wireshark by transforming the file with
* od -Ax -tx1 -v client.bin > client.bin.hex
* od -Ax -tx1 -v server.bin > server.bin.hex
* And then loading test_output.dump.hex into Wireshark using the
* "Import from Hex Dump..." option ion and selecting the TCP
* encapsulation option.
*/
#define HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES
#define TEST_MEMIO_BUF_SZ (64 * 1024)
@ -157,7 +168,7 @@ static WC_INLINE int test_memio_write_cb(WOLFSSL *ssl, char *data, int sz,
}
if ((unsigned)(*len + sz) > TEST_MEMIO_BUF_SZ)
return WOLFSSL_CBIO_ERR_WANT_READ;
return WOLFSSL_CBIO_ERR_WANT_WRITE;
XMEMCPY(buf + *len, data, sz);
*len += sz;

View File

@ -2135,6 +2135,9 @@ WOLFSSL_LOCAL void InitSSL_CTX_Suites(WOLFSSL_CTX* ctx);
WOLFSSL_LOCAL int InitSSL_Suites(WOLFSSL* ssl);
WOLFSSL_LOCAL int InitSSL_Side(WOLFSSL* ssl, word16 side);
WOLFSSL_LOCAL int DoHandShakeMsgType(WOLFSSL* ssl, byte* input,
word32* inOutIdx, byte type, word32 size, word32 totalSz);
/* for sniffer */
WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
word32 size, word32 totalSz, int sniff);
@ -4607,6 +4610,7 @@ struct Options {
word16 tls:1; /* using TLS ? */
word16 tls1_1:1; /* using TLSv1.1+ ? */
word16 tls1_3:1; /* using TLSv1.3+ ? */
word16 seenUnifiedHdr:1; /* received msg with unified header */
word16 dtls:1; /* using datagrams ? */
word16 dtlsStateful:1; /* allow stateful processing ? */
word16 connReset:1; /* has the peer reset */
@ -6532,6 +6536,8 @@ WOLFSSL_LOCAL int Dtls13HashHandshake(WOLFSSL* ssl, const byte* input,
WOLFSSL_LOCAL int Dtls13HashClientHello(const WOLFSSL* ssl, byte* hash,
int* hashSz, const byte* body, word32 length, CipherSpecs* specs);
WOLFSSL_LOCAL void Dtls13FreeFsmResources(WOLFSSL* ssl);
WOLFSSL_LOCAL void Dtls13RtxFlushBuffered(WOLFSSL* ssl,
byte keepNewSessionTicket);
WOLFSSL_LOCAL int Dtls13RtxTimeout(WOLFSSL* ssl);
WOLFSSL_LOCAL int Dtls13ProcessBufferedMessages(WOLFSSL* ssl);
WOLFSSL_LOCAL int Dtls13CheckAEADFailLimit(WOLFSSL* ssl);