diff --git a/library/chachapoly.c b/library/chachapoly.c index a1314eab6d..a6fbebe10e 100644 --- a/library/chachapoly.c +++ b/library/chachapoly.c @@ -165,6 +165,11 @@ int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx, return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE; } + ret = mbedtls_chacha20_check_counter_wrap(&ctx->chacha20_ctx, len); + if (ret != 0) { + return ret; + } + if (ctx->state == CHACHAPOLY_STATE_AAD) { ctx->state = CHACHAPOLY_STATE_CIPHERTEXT; diff --git a/tests/suites/test_suite_chachapoly.data b/tests/suites/test_suite_chachapoly.data index 02c7bf3d21..1c4c670953 100644 --- a/tests/suites/test_suite_chachapoly.data +++ b/tests/suites/test_suite_chachapoly.data @@ -19,6 +19,9 @@ mbedtls_chachapoly_dec:"1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc ChaCha20-Poly1305 State Flow chachapoly_state: +ChaCha20-Poly1305 overlong update preserves state +chachapoly_update_too_long_preserves_state: + ChaCha20-Poly1305 Selftest depends_on:MBEDTLS_SELF_TEST chachapoly_selftest: diff --git a/tests/suites/test_suite_chachapoly.function b/tests/suites/test_suite_chachapoly.function index 4f1a34e047..594eb09101 100644 --- a/tests/suites/test_suite_chachapoly.function +++ b/tests/suites/test_suite_chachapoly.function @@ -76,6 +76,35 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void chachapoly_update_too_long_preserves_state() +{ + unsigned char key[32] = { 0 }; + unsigned char nonce[12] = { 0 }; + unsigned char input[65] = { 0 }; + unsigned char output[65] = { 0 }; + unsigned char aad[1] = { 0 }; + mbedtls_chachapoly_context ctx; + + mbedtls_chachapoly_init(&ctx); + + TEST_EQUAL(mbedtls_chachapoly_setkey(&ctx, key), 0); + TEST_EQUAL(mbedtls_chachapoly_starts(&ctx, nonce, + MBEDTLS_CHACHAPOLY_ENCRYPT), 0); + + /* Force the next update to be too long without processing a huge buffer. */ + ctx.chacha20_ctx.state[12] = UINT32_MAX; + TEST_EQUAL(mbedtls_chachapoly_update(&ctx, sizeof(input), input, output), + MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA); + TEST_EQUAL(ctx.ciphertext_len, 0); + + TEST_EQUAL(mbedtls_chachapoly_update_aad(&ctx, aad, sizeof(aad)), 0); + +exit: + mbedtls_chachapoly_free(&ctx); +} +/* END_CASE */ + /* BEGIN_CASE */ void chachapoly_state() {