Keep a separate drop counter for each epoch

This commit is contained in:
Juliusz Sosinowicz
2022-09-15 15:49:05 +02:00
parent 67473bac28
commit 1941fb2b35
5 changed files with 27 additions and 36 deletions

View File

@ -2012,15 +2012,6 @@ int Dtls13NewEpoch(WOLFSSL* ssl, w64wrapper epochNumber, int side)
return BAD_STATE_E; return BAD_STATE_E;
} }
#ifndef WOLFSSL_TLS13_IGNORE_AEAD_LIMITS
/* We are updating the receiving keys for this connection. We can restart
* the failed decryption counter if we haven't reached the key update
* limit. */
if ((side == ENCRYPT_AND_DECRYPT_SIDE || side == DECRYPT_SIDE_ONLY) &&
w64IsZero(ssl->dtls13InvalidateBefore))
w64Zero(&ssl->macDropCount);
#endif
Dtls13EpochCopyKeys(ssl, e, &ssl->keys, side); Dtls13EpochCopyKeys(ssl, e, &ssl->keys, side);
if (!e->isValid) { if (!e->isValid) {
@ -2691,13 +2682,20 @@ int Dtls13CheckAEADFailLimit(WOLFSSL* ssl)
WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR); WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR);
return DECRYPT_ERROR; return DECRYPT_ERROR;
} }
if (w64GT(ssl->macDropCount, hardLimit)) { if (ssl->dtls13DecryptEpoch == NULL) {
WOLFSSL_MSG("Dtls13CheckAEADFailLimit: ssl->dtls13DecryptEpoch should "
"not be NULL");
WOLFSSL_ERROR_VERBOSE(BAD_STATE_E);
return BAD_STATE_E;
}
w64Increment(&ssl->dtls13DecryptEpoch->dropCount);
if (w64GT(ssl->dtls13DecryptEpoch->dropCount, hardLimit)) {
/* We have reached the hard limit for failed decryptions. */ /* We have reached the hard limit for failed decryptions. */
WOLFSSL_MSG("Connection exceeded hard AEAD limit"); WOLFSSL_MSG("Connection exceeded hard AEAD limit");
WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR); WOLFSSL_ERROR_VERBOSE(DECRYPT_ERROR);
return DECRYPT_ERROR; return DECRYPT_ERROR;
} }
else if (w64GT(ssl->macDropCount, keyUpdateLimit)) { else if (w64GT(ssl->dtls13DecryptEpoch->dropCount, keyUpdateLimit)) {
WOLFSSL_MSG("Connection exceeded key update limit. Issuing key update"); WOLFSSL_MSG("Connection exceeded key update limit. Issuing key update");
/* If not waiting for a response then request a key update. */ /* If not waiting for a response then request a key update. */
if (!ssl->keys.updateResponseReq) { if (!ssl->keys.updateResponseReq) {

View File

@ -18206,7 +18206,6 @@ int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx, int sniff)
Dtls13SetOlderEpochSide(ssl, ssl->dtls13InvalidateBefore, Dtls13SetOlderEpochSide(ssl, ssl->dtls13InvalidateBefore,
ENCRYPT_SIDE_ONLY); ENCRYPT_SIDE_ONLY);
w64Zero(&ssl->dtls13InvalidateBefore); w64Zero(&ssl->dtls13InvalidateBefore);
w64Zero(&ssl->macDropCount);
} }
} }
#endif #endif
@ -18799,15 +18798,14 @@ static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz,
static int HandleDTLSDecryptFailed(WOLFSSL* ssl) static int HandleDTLSDecryptFailed(WOLFSSL* ssl)
{ {
int ret = 0; int ret = 0;
#if defined(WOLFSSL_DTLS_DROP_STATS) || \ #ifdef WOLFSSL_DTLS_DROP_STATS
(defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)) ssl->macDropCount++;
w64Increment(&ssl->macDropCount); #endif
#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS) #if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_TLS13_IGNORE_AEAD_LIMITS)
/* Handle AEAD limits specified by the RFC for failed decryption */ /* Handle AEAD limits specified by the RFC for failed decryption */
if (IsAtLeastTLSv1_3(ssl->version)) if (IsAtLeastTLSv1_3(ssl->version))
ret = Dtls13CheckAEADFailLimit(ssl); ret = Dtls13CheckAEADFailLimit(ssl);
#endif
#endif #endif
(void)ssl; (void)ssl;

View File

@ -1534,7 +1534,7 @@ int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl,
else { else {
ret = WOLFSSL_SUCCESS; ret = WOLFSSL_SUCCESS;
if (macDropCount != NULL) if (macDropCount != NULL)
*macDropCount = w64GetLow32(ssl->macDropCount); *macDropCount = ssl->macDropCount;
if (replayDropCount != NULL) if (replayDropCount != NULL)
*replayDropCount = ssl->replayDropCount; *replayDropCount = ssl->replayDropCount;
} }
@ -3284,11 +3284,6 @@ int wolfSSL_Rehandshake(WOLFSSL* ssl)
/* CLIENT/SERVER: Reset peer authentication for full secure handshake. */ /* CLIENT/SERVER: Reset peer authentication for full secure handshake. */
ssl->options.peerAuthGood = 0; ssl->options.peerAuthGood = 0;
#ifdef WOLFSSL_DTLS_DROP_STATS
if (ssl->options.dtls)
w64Zero(&ssl->macDropCount);
#endif
#ifdef HAVE_SESSION_TICKET #ifdef HAVE_SESSION_TICKET
if (ret == WOLFSSL_SUCCESS) if (ret == WOLFSSL_SUCCESS)
#endif #endif

View File

@ -55381,7 +55381,7 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
test_AEAD_get_limits(ssl, &hardLimit, &keyUpdateLimit, &sendLimit); test_AEAD_get_limits(ssl, &hardLimit, &keyUpdateLimit, &sendLimit);
w64Zero(&counter); w64Zero(&counter);
AssertTrue(w64Equal(ssl->macDropCount, counter)); AssertTrue(w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->dropCount, counter));
wolfSSL_SSLSetIORecv(ssl, test_AEAD_cbiorecv); wolfSSL_SSLSetIORecv(ssl, test_AEAD_cbiorecv);
@ -55392,12 +55392,12 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf));
/* Should succeed since decryption failures are dropped */ /* Should succeed since decryption failures are dropped */
AssertIntGT(ret, 0); AssertIntGT(ret, 0);
AssertTrue(w64Equal(ssl->macDropCount, counter)); AssertTrue(w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount, counter));
} }
test_AEAD_fail_decryption = 1; test_AEAD_fail_decryption = 1;
ssl->macDropCount = keyUpdateLimit; Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount = keyUpdateLimit;
w64Increment(&ssl->macDropCount); w64Increment(&Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount);
/* 100 read calls should be enough to complete the key update */ /* 100 read calls should be enough to complete the key update */
w64Zero(&counter); w64Zero(&counter);
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
@ -55406,7 +55406,7 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
AssertIntGT(ret, 0); AssertIntGT(ret, 0);
/* Epoch after one key update is 4 */ /* Epoch after one key update is 4 */
if (w64Equal(ssl->dtls13PeerEpoch, w64From32(0, 4)) && if (w64Equal(ssl->dtls13PeerEpoch, w64From32(0, 4)) &&
w64Equal(ssl->macDropCount, counter)) { w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount, counter)) {
didReKey = 1; didReKey = 1;
break; break;
} }
@ -55415,9 +55415,7 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
if (!w64IsZero(sendLimit)) { if (!w64IsZero(sendLimit)) {
/* Test the sending limit for AEAD ciphers */ /* Test the sending limit for AEAD ciphers */
Dtls13Epoch* e = Dtls13GetEpoch(ssl, ssl->dtls13Epoch); Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->nextSeqNumber = sendLimit;
AssertNotNull(e);
e->nextSeqNumber = sendLimit;
test_AEAD_seq_num = 1; test_AEAD_seq_num = 1;
ret = wolfSSL_write(ssl, msgBuf, sizeof(msgBuf)); ret = wolfSSL_write(ssl, msgBuf, sizeof(msgBuf));
AssertIntGT(ret, 0); AssertIntGT(ret, 0);
@ -55430,7 +55428,7 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
AssertIntGT(ret, 0); AssertIntGT(ret, 0);
/* Epoch after another key update is 5 */ /* Epoch after another key update is 5 */
if (w64Equal(ssl->dtls13Epoch, w64From32(0, 5)) && if (w64Equal(ssl->dtls13Epoch, w64From32(0, 5)) &&
w64Equal(ssl->macDropCount, counter)) { w64Equal(Dtls13GetEpoch(ssl, ssl->dtls13Epoch)->dropCount, counter)) {
didReKey = 1; didReKey = 1;
break; break;
} }
@ -55439,8 +55437,8 @@ static void test_AEAD_limit_client(WOLFSSL* ssl)
} }
test_AEAD_fail_decryption = 2; test_AEAD_fail_decryption = 2;
ssl->macDropCount = hardLimit; Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount = hardLimit;
w64Decrement(&ssl->macDropCount); w64Decrement(&Dtls13GetEpoch(ssl, ssl->dtls13PeerEpoch)->dropCount);
/* Connection should fail with a DECRYPT_ERROR */ /* Connection should fail with a DECRYPT_ERROR */
ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf)); ret = wolfSSL_read(ssl, msgBuf, sizeof(msgBuf));
AssertIntEQ(ret, WOLFSSL_FATAL_ERROR); AssertIntEQ(ret, WOLFSSL_FATAL_ERROR);

View File

@ -4651,6 +4651,10 @@ typedef struct Dtls13Epoch {
w64wrapper nextSeqNumber; w64wrapper nextSeqNumber;
w64wrapper nextPeerSeqNumber; w64wrapper nextPeerSeqNumber;
#ifndef WOLFSSL_TLS13_IGNORE_AEAD_LIMITS
w64wrapper dropCount; /* Amount of records that failed decryption */
#endif
word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; word32 window[WOLFSSL_DTLS_WINDOW_WORDS];
/* key material for the epoch */ /* key material for the epoch */
@ -4912,10 +4916,8 @@ struct WOLFSSL {
#ifdef WOLFSSL_MULTICAST #ifdef WOLFSSL_MULTICAST
void* mcastHwCbCtx; /* Multicast highwater callback ctx */ void* mcastHwCbCtx; /* Multicast highwater callback ctx */
#endif /* WOLFSSL_MULTICAST */ #endif /* WOLFSSL_MULTICAST */
#if defined(WOLFSSL_DTLS_DROP_STATS) || defined(WOLFSSL_DTLS13)
w64wrapper macDropCount;
#endif
#ifdef WOLFSSL_DTLS_DROP_STATS #ifdef WOLFSSL_DTLS_DROP_STATS
word32 macDropCount;
word32 replayDropCount; word32 replayDropCount;
#endif /* WOLFSSL_DTLS_DROP_STATS */ #endif /* WOLFSSL_DTLS_DROP_STATS */
#ifdef WOLFSSL_SRTP #ifdef WOLFSSL_SRTP