From 46ebc3a758c061312855b7faec4bff785509e792 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sun, 27 Jul 2025 21:20:47 +0200 Subject: [PATCH] Note that the decrypted length is sensitive when there was padding The decrypted length reveals the amount of padding that was eliminated, and thus reveals partial information about the last ciphertext block. Signed-off-by: Gilles Peskine --- include/mbedtls/cipher.h | 9 +++++++++ tests/suites/test_suite_cipher.function | 3 +++ 2 files changed, 12 insertions(+) diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 3778f44551..616c5543c9 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -991,6 +991,11 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, * buffer of at least block_size Bytes. * \param olen The length of the data written to the \p output buffer. * This may not be \c NULL. + * Note that when decrypting in a mode with padding, + * the actual output length is sensitive and may be + * used to mount a padding oracle attack (see warning + * above), although less efficiently than through + * the invalid-padding condition. * * \return \c 0 on success. * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on @@ -1025,6 +1030,10 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, * buffer of at least block_size Bytes. * \param[out] olen The length of the data written to the \p output buffer. * This may not be \c NULL. + * Note that when decrypting in a mode with padding, + * the actual output length is sensitive and may be + * used to mount a padding oracle attack (see warning + * on mbedtls_cipher_finish()). * \param[out] invalid_padding * If this function returns \c 0 on decryption, * \p *invalid_padding is \c 0 if the ciphertext was diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 9e3e026834..ac0264e3d9 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -921,6 +921,7 @@ void decrypt_test_vec_cf(int cipher_id, int pad_mode, data_t *key, total_len += outlen; int actual_finish_result = mbedtls_cipher_finish(&ctx, output + outlen, &outlen); + TEST_CF_PUBLIC(&outlen, sizeof(outlen)); TEST_EQUAL(actual_finish_result, expected_finish_result); if (0 != expected_finish_result) { /* Check output parameter is set to the least-harmful value on error */ @@ -1083,6 +1084,7 @@ void decrypt_padded_test_vec_cf(int cipher_id, int pad_mode, data_t *key, int actual_finish_result = mbedtls_cipher_finish_padded(&ctx, output + outlen, &outlen, &invalid_padding); + TEST_CF_PUBLIC(&outlen, sizeof(outlen)); switch (expected_finish_result) { case 0: TEST_EQUAL(actual_finish_result, 0); @@ -1439,6 +1441,7 @@ void test_vec_crypt_cf(int cipher_id, int pad_mode, int operation, data_t *key, mbedtls_cipher_crypt(&ctx, iv->len ? iv->x : NULL, iv->len, input->x, input->len, output, &outlen); + TEST_CF_PUBLIC(&outlen, sizeof(outlen)); TEST_EQUAL(expected_finish_result, actual_finish_result); /* check plaintext only if everything went fine */