Skip to content

Commit 74232f5

Browse files
authored
Merge pull request #8631 from julek-wolfssl/gh/8579-2
dtls13: additional epoch checks
2 parents 8c0b931 + e709cb4 commit 74232f5

6 files changed

Lines changed: 167 additions & 1 deletion

File tree

src/dtls13.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,102 @@ static int Dtls13AcceptFragmented(WOLFSSL *ssl, enum HandShakeType type)
16371637
#endif
16381638
return 0;
16391639
}
1640+
1641+
int Dtls13CheckEpoch(WOLFSSL* ssl, enum HandShakeType type)
1642+
{
1643+
w64wrapper plainEpoch = w64From32(0x0, 0x0);
1644+
w64wrapper hsEpoch = w64From32(0x0, DTLS13_EPOCH_HANDSHAKE);
1645+
w64wrapper t0Epoch = w64From32(0x0, DTLS13_EPOCH_TRAFFIC0);
1646+
1647+
if (IsAtLeastTLSv1_3(ssl->version)) {
1648+
switch (type) {
1649+
case client_hello:
1650+
case server_hello:
1651+
case hello_verify_request:
1652+
case hello_retry_request:
1653+
case hello_request:
1654+
if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
1655+
WOLFSSL_MSG("Msg should be epoch 0");
1656+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1657+
return SANITY_MSG_E;
1658+
}
1659+
break;
1660+
case encrypted_extensions:
1661+
case server_key_exchange:
1662+
case server_hello_done:
1663+
case client_key_exchange:
1664+
if (!w64Equal(ssl->keys.curEpoch64, hsEpoch)) {
1665+
if (ssl->options.side == WOLFSSL_CLIENT_END &&
1666+
ssl->options.serverState < SERVER_HELLO_COMPLETE) {
1667+
/* before processing SH we don't know which version
1668+
* will be negotiated. */
1669+
if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
1670+
WOLFSSL_MSG("Msg should be epoch 2 or 0");
1671+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1672+
return SANITY_MSG_E;
1673+
}
1674+
}
1675+
else {
1676+
WOLFSSL_MSG("Msg should be epoch 2");
1677+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1678+
return SANITY_MSG_E;
1679+
}
1680+
}
1681+
break;
1682+
case certificate_request:
1683+
case certificate:
1684+
case certificate_verify:
1685+
case finished:
1686+
if (!ssl->options.handShakeDone) {
1687+
if (!w64Equal(ssl->keys.curEpoch64, hsEpoch)) {
1688+
if (ssl->options.side == WOLFSSL_CLIENT_END &&
1689+
ssl->options.serverState < SERVER_HELLO_COMPLETE) {
1690+
/* before processing SH we don't know which version
1691+
* will be negotiated. */
1692+
if (!w64Equal(ssl->keys.curEpoch64, plainEpoch)) {
1693+
WOLFSSL_MSG("Msg should be epoch 2 or 0");
1694+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1695+
return SANITY_MSG_E;
1696+
}
1697+
}
1698+
else {
1699+
WOLFSSL_MSG("Msg should be epoch 2");
1700+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1701+
return SANITY_MSG_E;
1702+
}
1703+
}
1704+
}
1705+
else {
1706+
/* Allow epoch 2 in case of rtx */
1707+
if (!w64GTE(ssl->keys.curEpoch64, hsEpoch)) {
1708+
WOLFSSL_MSG("Msg should be epoch 2+");
1709+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1710+
return SANITY_MSG_E;
1711+
}
1712+
}
1713+
break;
1714+
case certificate_status:
1715+
case change_cipher_hs:
1716+
case key_update:
1717+
case session_ticket:
1718+
if (!w64GTE(ssl->keys.curEpoch64, t0Epoch)) {
1719+
WOLFSSL_MSG("Msg should be epoch 3+");
1720+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1721+
return SANITY_MSG_E;
1722+
}
1723+
break;
1724+
case end_of_early_data:
1725+
case message_hash:
1726+
case no_shake:
1727+
default:
1728+
WOLFSSL_MSG("Unknown message type");
1729+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
1730+
return SANITY_MSG_E;
1731+
}
1732+
}
1733+
return 0;
1734+
}
1735+
16401736
/**
16411737
* Dtls13HandshakeRecv() - process an handshake message. Deal with
16421738
fragmentation if needed
@@ -1672,6 +1768,12 @@ static int _Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input, word32 size,
16721768
return ret;
16731769
}
16741770

1771+
ret = Dtls13CheckEpoch(ssl, (enum HandShakeType)handshakeType);
1772+
if (ret != 0) {
1773+
WOLFSSL_ERROR(ret);
1774+
return ret;
1775+
}
1776+
16751777
if (ssl->options.side == WOLFSSL_SERVER_END &&
16761778
ssl->options.acceptState < TLS13_ACCEPT_FIRST_REPLY_DONE) {
16771779
if (handshakeType != client_hello) {

src/internal.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21013,6 +21013,16 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
2101321013
isEarlyData = isEarlyData && w64Equal(ssl->keys.curEpoch64,
2101421014
w64From32(0x0, DTLS13_EPOCH_EARLYDATA));
2101521015
#endif
21016+
#ifdef WOLFSSL_DTLS13
21017+
/* Application data should never appear in epoch 0 or 2 */
21018+
if (ssl->options.tls1_3 && ssl->options.dtls &&
21019+
(w64Equal(ssl->keys.curEpoch64, w64From32(0x0, DTLS13_EPOCH_HANDSHAKE))
21020+
|| w64Equal(ssl->keys.curEpoch64, w64From32(0x0, 0x0))))
21021+
{
21022+
WOLFSSL_ERROR_VERBOSE(SANITY_MSG_E);
21023+
return SANITY_MSG_E;
21024+
}
21025+
#endif
2101621026

2101721027
#ifdef WOLFSSL_EARLY_DATA
2101821028
if (isEarlyData && acceptEarlyData) {

tests/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67811,6 +67811,7 @@ TEST_CASE testCases[] = {
6781167811
TEST_DECL(test_wolfSSL_SSLDisableRead),
6781267812
TEST_DECL(test_wolfSSL_inject),
6781367813
TEST_DECL(test_wolfSSL_dtls_cid_parse),
67814+
TEST_DECL(test_dtls13_epochs),
6781467815
TEST_DECL(test_ocsp_status_callback),
6781567816
TEST_DECL(test_ocsp_basic_verify),
6781667817
TEST_DECL(test_ocsp_response_parsing),

tests/api/test_dtls.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,3 +595,54 @@ int test_wolfSSL_dtls_cid_parse(void)
595595
#endif
596596
return EXPECT_RESULT();
597597
}
598+
599+
int test_dtls13_epochs(void) {
600+
EXPECT_DECLS;
601+
#if defined(WOLFSSL_DTLS13) && !defined(NO_WOLFSSL_CLIENT)
602+
WOLFSSL_CTX* ctx = NULL;
603+
WOLFSSL* ssl = NULL;
604+
byte input[20];
605+
word32 inOutIdx = 0;
606+
607+
XMEMSET(input, 0, sizeof(input));
608+
609+
ExpectNotNull(ctx = wolfSSL_CTX_new(wolfDTLSv1_3_client_method()));
610+
ExpectNotNull(ssl = wolfSSL_new(ctx));
611+
/* Some manual setup to enter the epoch check */
612+
ExpectTrue(ssl->options.tls1_3 = 1);
613+
614+
inOutIdx = 0;
615+
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x0);
616+
ExpectIntEQ(DoApplicationData(ssl, input, &inOutIdx, 0), SANITY_MSG_E);
617+
inOutIdx = 0;
618+
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x2);
619+
ExpectIntEQ(DoApplicationData(ssl, input, &inOutIdx, 0), SANITY_MSG_E);
620+
621+
if (ssl != NULL) ssl->keys.curEpoch64 = w64From32(0x0, 0x1);
622+
ExpectIntEQ(Dtls13CheckEpoch(ssl, client_hello), SANITY_MSG_E);
623+
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_hello), SANITY_MSG_E);
624+
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_verify_request), SANITY_MSG_E);
625+
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_retry_request), SANITY_MSG_E);
626+
ExpectIntEQ(Dtls13CheckEpoch(ssl, hello_request), SANITY_MSG_E);
627+
ExpectIntEQ(Dtls13CheckEpoch(ssl, encrypted_extensions), SANITY_MSG_E);
628+
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_key_exchange), SANITY_MSG_E);
629+
ExpectIntEQ(Dtls13CheckEpoch(ssl, server_hello_done), SANITY_MSG_E);
630+
ExpectIntEQ(Dtls13CheckEpoch(ssl, client_key_exchange), SANITY_MSG_E);
631+
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_request), SANITY_MSG_E);
632+
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate), SANITY_MSG_E);
633+
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_verify), SANITY_MSG_E);
634+
ExpectIntEQ(Dtls13CheckEpoch(ssl, finished), SANITY_MSG_E);
635+
ExpectIntEQ(Dtls13CheckEpoch(ssl, certificate_status), SANITY_MSG_E);
636+
ExpectIntEQ(Dtls13CheckEpoch(ssl, change_cipher_hs), SANITY_MSG_E);
637+
ExpectIntEQ(Dtls13CheckEpoch(ssl, key_update), SANITY_MSG_E);
638+
ExpectIntEQ(Dtls13CheckEpoch(ssl, session_ticket), SANITY_MSG_E);
639+
ExpectIntEQ(Dtls13CheckEpoch(ssl, end_of_early_data), SANITY_MSG_E);
640+
ExpectIntEQ(Dtls13CheckEpoch(ssl, message_hash), SANITY_MSG_E);
641+
ExpectIntEQ(Dtls13CheckEpoch(ssl, no_shake), SANITY_MSG_E);
642+
643+
wolfSSL_CTX_free(ctx);
644+
wolfSSL_free(ssl);
645+
#endif
646+
return EXPECT_RESULT();
647+
}
648+

tests/api/test_dtls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@
2525
int test_dtls12_basic_connection_id(void);
2626
int test_dtls13_basic_connection_id(void);
2727
int test_wolfSSL_dtls_cid_parse(void);
28+
int test_dtls13_epochs(void);
2829

2930
#endif /* TESTS_API_DTLS_H */

wolfssl/internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2222,7 +2222,7 @@ WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
22222222
WOLFSSL_LOCAL int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
22232223
word32 size, word32 totalSz, int sniff);
22242224
#endif
2225-
WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx,
2225+
WOLFSSL_TEST_VIS int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx,
22262226
int sniff);
22272227
/* TLS v1.3 needs these */
22282228
WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, Suites* clSuites);
@@ -7052,6 +7052,7 @@ WOLFSSL_LOCAL int Dtls13HandshakeSend(WOLFSSL* ssl, byte* output,
70527052
word16 output_size, word16 length, enum HandShakeType handshake_type,
70537053
int hash_output);
70547054
WOLFSSL_LOCAL int Dtls13RecordRecvd(WOLFSSL* ssl);
7055+
WOLFSSL_TEST_VIS int Dtls13CheckEpoch(WOLFSSL* ssl, enum HandShakeType type);
70557056
WOLFSSL_LOCAL int Dtls13HandshakeRecv(WOLFSSL* ssl, byte* input,
70567057
word32* inOutIdx, word32 totalSz);
70577058
WOLFSSL_LOCAL int Dtls13HandshakeAddHeader(WOLFSSL* ssl, byte* output,

0 commit comments

Comments
 (0)