From 155de2ab775e77ab6fa81bf2b1e6e63768123bc1 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Sun, 27 Jul 2025 18:53:57 +0200 Subject: [PATCH] New function mbedtls_cipher_finish_padded New function `mbedtls_cipher_finish_padded()`, similar to `mbedtls_cipher_finish()`, but reporting padding errors through a separate output parameter. This makes it easier to avoid leaking the presence of a padding error, especially through timing. Thus the new function is recommended to defend against padding oracle attacks. In this commit, implement this function naively, with timing that depends on whether an error happened. A subsequent commit will make this function constant-time. Copy the test decrypt_test_vec and decrypt_test_vec_cf test cases into variants that call `mbedtls_cipher_finish_padded()`. Signed-off-by: Gilles Peskine --- include/mbedtls/cipher.h | 66 ++++++- library/cipher.c | 17 ++ tests/suites/test_suite_cipher.aes.data | 108 +++++++++++ .../test_suite_cipher.constant_time.data | 108 +++++++++++ tests/suites/test_suite_cipher.function | 173 ++++++++++++++++++ 5 files changed, 468 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h index 1dc31c9c24..6ef703ddab 100644 --- a/include/mbedtls/cipher.h +++ b/include/mbedtls/cipher.h @@ -881,7 +881,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update() one or more times - * 4. mbedtls_cipher_finish() + * 4. mbedtls_cipher_finish() or mbedtls_cipher_finish_padded() * . * This sequence can be repeated to encrypt or decrypt multiple * messages with the same key. @@ -892,7 +892,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, * 2. mbedtls_cipher_reset() * 3. mbedtls_cipher_update_ad() * 4. mbedtls_cipher_update() one or more times - * 5. mbedtls_cipher_finish() + * 5. mbedtls_cipher_finish() or mbedtls_cipher_finish_padded() * 6. mbedtls_cipher_check_tag() (for decryption) or * mbedtls_cipher_write_tag() (for encryption). * . @@ -930,7 +930,8 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, * many block-sized blocks of data as possible to output. * Any data that cannot be written immediately is either * added to the next block, or flushed when - * mbedtls_cipher_finish() is called. + * mbedtls_cipher_finish() or mbedtls_cipher_finish_padded() + * is called. * Exception: For MBEDTLS_MODE_ECB, expects a single block * in size. For example, 16 Bytes for AES. * @@ -964,6 +965,19 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, * contained in it is padded to the size of * the last block, and written to the \p output buffer. * + * \warning This function reports invalid padding through an error + * code. Adversaries may be able to decrypt encrypted + * data if they can submit chosen ciphertexts and + * detect whether it has valid padding or not, + * either through direct observation or through a side + * channel such as timing. This is known as a + * padding oracle attack. + * Therefore applications that call this function for + * decryption with a cipher that involves padding + * should take care around error handling. Preferably, + * such applicatios should use + * mbedtls_cipher_finish_padded() instead of this function. + * * \param ctx The generic cipher context. This must be initialized and * bound to a key. * \param output The buffer to write data to. This needs to be a writable @@ -977,12 +991,56 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption * expecting a full block but not receiving one. * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding - * while decrypting. + * while decrypting. Note that invalid-padding errors + * should be handled carefully; see the warning above. * \return A cipher-specific error code on failure. */ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, unsigned char *output, size_t *olen); +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \note This function is similar to mbedtls_cipher_finish(). + * The only difference is that it reports invalid padding + * decryption differently, through the \p invalid_padding + * parameter rather than an error code. + * For encryption, and in modes without padding (including + * all authenticated modes), this function is identical + * to mbedtls_cipher_finish(). + * + * \param[in,out] ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param[out] output The buffer to write data to. This needs to be a writable + * 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. + * \param[out] invalid_padding + * If this function returns \c 0 on decryption, + * \p *invalid_padding is \c 0 if the ciphertext was + * valid, and all-bits-one if the ciphertext had invalid + * padding. + * On encryption, or in a mode without padding (including + * all authenticated modes), \p *invalid_padding is \c 0 + * on success. + * The value in \p *invalid_padding is unspecified if + * this function returns a nonzero status. + * + * \return \c 0 on success. + * Also \c 0 for decryption with invalid padding. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen, + size_t *invalid_padding); + #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) /** * \brief This function writes a tag for AEAD ciphers. diff --git a/library/cipher.c b/library/cipher.c index 2ae01dd84d..f3e2f91f82 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -1124,6 +1124,23 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; } +int mbedtls_cipher_finish_padded(mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen, + size_t *invalid_padding) +{ + *invalid_padding = 0; + int ret = mbedtls_cipher_finish(ctx, output, olen); +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) || \ + defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) || \ + defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) { + ret = 0; + *invalid_padding = SIZE_MAX; + } +#endif + return ret; +} + #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode) diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data index dd8bf719e0..4298b1d595 100644 --- a/tests/suites/test_suite_cipher.aes.data +++ b/tests/suites/test_suite_cipher.aes.data @@ -1590,6 +1590,114 @@ AES-256-CBC Decrypt test vector, PKCS7 (short, bad pad 17) depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 decrypt_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"3e536c7917a695485ef046bda7c6a3e6":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 +AES-128-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_NONE:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":0:0 + +AES-192-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_NONE:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"fffffffff80000000000000000000000":"":"":0:0 + +AES-256-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_NONE:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"ff000000000000000000000000000000":"":"":0:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"6dbd04d1579f6a7bee0842b9ae491588":"000000000000000000000000000000":"":"":0:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"593ebdf9a785f414cbed5d8a9eee1e4d":"fffffffff800000000000000000000":"":"":0:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"f1b27ac78b93f6b0ab9787d8827176e6":"ff0000000000000000000000000000":"":"":0:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"175334ced3166a22437861f4bcced178":"0000000000000000000000000000":"":"":0:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"5d9ee7bc7066e438582c86c165604f2e":"fffffffff8000000000000000000":"":"":0:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"cc71abea78b8e82c3791b52d3dba55e2":"ff00000000000000000000000000":"":"":0:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"7d340c60b9067883962c69766cf9ec35":"2a":"":"":0:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"48fef8aaa78c4a148f241aaf14866772":"2a":"":"":0:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"6ad50ca266a3e32024818f11839afb2f":"2a":"":"":0:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"e9844992c4b55bcaf8199d5df842adad":"":"":"":0:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"02bb292527e726fd51eb29894d6f0aad":"":"":"":0:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"1f788fe6d86c317549697fbf0c07fa43":"":"":"":0:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"e651289760d35177eade56eae724f8fd":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"f5b599490354e71a3b3fb5f1419fb971":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"6852d318a0884a289a725c558e761e25":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"9c336551cc31074ffcefc161bac686b7afa572c3b53bd14a1b98d201229ddd03":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"33a31ec7605c85893872a467777f3ddb5c4271870e51a0c618f20a0efccc2bfc":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"3e536c7917a695485ef046bda7c6a3e64f439d87aa0deb338029253bea0ba54f":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-128-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"9c336551cc31074ffcefc161bac686b7":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-192-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"33a31ec7605c85893872a467777f3ddb":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +AES-256-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7 +decrypt_padded_test_vec:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"3e536c7917a695485ef046bda7c6a3e6":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + AES-128-CFB Decrypt test vector depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CFB decrypt_test_vec:MBEDTLS_CIPHER_AES_128_CFB128:-1:"fffffffe000000000000000000000000":"00000000000000000000000000000000":"1114bc2028009b923f0b01915ce5e7c4":"00000000000000000000000000000000":"":"":0:0: diff --git a/tests/suites/test_suite_cipher.constant_time.data b/tests/suites/test_suite_cipher.constant_time.data index 7f9f4af6ff..2de31ed15c 100644 --- a/tests/suites/test_suite_cipher.constant_time.data +++ b/tests/suites/test_suite_cipher.constant_time.data @@ -13,6 +13,114 @@ get_pkcs_padding:"00112233445566778899AABBCCDDEE00":MBEDTLS_ERR_CIPHER_INVALID_P Constant-time PKCS7 padding, invalid > 16 get_pkcs_padding:"00112233445566778899AABBCCDDEE11":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 +CF AES-128-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_NONE:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":0:0 + +CF AES-192-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_NONE:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"fffffffff80000000000000000000000":"":"":0:0 + +CF AES-256-CBC Decrypt with finish_padded, no padding +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_NONE:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"ff000000000000000000000000000000":"":"":0:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"6dbd04d1579f6a7bee0842b9ae491588":"000000000000000000000000000000":"":"":0:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"593ebdf9a785f414cbed5d8a9eee1e4d":"fffffffff800000000000000000000":"":"":0:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 1) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"f1b27ac78b93f6b0ab9787d8827176e6":"ff0000000000000000000000000000":"":"":0:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"175334ced3166a22437861f4bcced178":"0000000000000000000000000000":"":"":0:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"5d9ee7bc7066e438582c86c165604f2e":"fffffffff8000000000000000000":"":"":0:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 2) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"cc71abea78b8e82c3791b52d3dba55e2":"ff00000000000000000000000000":"":"":0:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"7d340c60b9067883962c69766cf9ec35":"2a":"":"":0:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"48fef8aaa78c4a148f241aaf14866772":"2a":"":"":0:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 15) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"6ad50ca266a3e32024818f11839afb2f":"2a":"":"":0:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"e9844992c4b55bcaf8199d5df842adad":"":"":"":0:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"02bb292527e726fd51eb29894d6f0aad":"":"":"":0:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (good pad 16) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"1f788fe6d86c317549697fbf0c07fa43":"":"":"":0:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (bad pad 0) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"e651289760d35177eade56eae724f8fd":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"f5b599490354e71a3b3fb5f1419fb971":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (bad pad 0102) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"6852d318a0884a289a725c558e761e25":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"9c336551cc31074ffcefc161bac686b7afa572c3b53bd14a1b98d201229ddd03":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"33a31ec7605c85893872a467777f3ddb5c4271870e51a0c618f20a0efccc2bfc":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (long, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"3e536c7917a695485ef046bda7c6a3e64f439d87aa0deb338029253bea0ba54f":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-128-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"9c336551cc31074ffcefc161bac686b7":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-192-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_192_CBC:MBEDTLS_PADDING_PKCS7:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"33a31ec7605c85893872a467777f3ddb":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + +CF AES-256-CBC Decrypt with finish_padded, PKCS7 (short, bad pad 17) +depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:!MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH:MBEDTLS_CIPHER_PADDING_PKCS7:HAVE_CONSTANT_TIME_AES +decrypt_padded_test_vec_cf:MBEDTLS_CIPHER_AES_256_CBC:MBEDTLS_PADDING_PKCS7:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"3e536c7917a695485ef046bda7c6a3e6":"":"":"":MBEDTLS_ERR_CIPHER_INVALID_PADDING:0 + CF AES-128-CBC Decrypt test vector, no padding depends_on:MBEDTLS_AES_C:MBEDTLS_CIPHER_MODE_CBC:HAVE_CONSTANT_TIME_AES decrypt_test_vec_cf:MBEDTLS_CIPHER_AES_128_CBC:MBEDTLS_PADDING_NONE:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":0:0 diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function index 8ae2234d4c..fbc48b7974 100644 --- a/tests/suites/test_suite_cipher.function +++ b/tests/suites/test_suite_cipher.function @@ -946,6 +946,179 @@ exit: } /* END_CASE */ +/* BEGIN_CASE */ +void decrypt_padded_test_vec(int cipher_id, int pad_mode, data_t *key, + data_t *iv, data_t *cipher, + data_t *clear, data_t *ad, data_t *tag, + int expected_finish_result, int tag_result) +{ + unsigned char output[265]; + mbedtls_cipher_context_t ctx; + size_t outlen, total_len; + + mbedtls_cipher_init(&ctx); + + memset(output, 0x00, sizeof(output)); + +#if !defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CHACHAPOLY_C) + ((void) ad); + ((void) tag); +#endif + + /* Prepare context */ + TEST_ASSERT(0 == mbedtls_cipher_setup(&ctx, + mbedtls_cipher_info_from_type(cipher_id))); + TEST_ASSERT(0 == mbedtls_cipher_setkey(&ctx, key->x, 8 * key->len, MBEDTLS_DECRYPT)); +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + if (pad_mode != -1) { + TEST_ASSERT(0 == mbedtls_cipher_set_padding_mode(&ctx, pad_mode)); + } +#else + (void) pad_mode; +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + TEST_ASSERT(0 == mbedtls_cipher_set_iv(&ctx, iv->x, iv->len)); + TEST_ASSERT(0 == mbedtls_cipher_reset(&ctx)); +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) + int expected = (ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL(expected, mbedtls_cipher_update_ad(&ctx, ad->x, ad->len)); +#endif + + /* decode buffer and check tag->x */ + total_len = 0; + TEST_ASSERT(0 == mbedtls_cipher_update(&ctx, cipher->x, cipher->len, output, &outlen)); + total_len += outlen; + + size_t invalid_padding = 42; + int actual_finish_result = + mbedtls_cipher_finish_padded(&ctx, output + outlen, &outlen, + &invalid_padding); + switch (expected_finish_result) { + case 0: + TEST_EQUAL(actual_finish_result, 0); + TEST_EQUAL(invalid_padding, 0); + break; + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + TEST_EQUAL(actual_finish_result, 0); + TEST_EQUAL(invalid_padding, SIZE_MAX); + break; + default: + TEST_EQUAL(actual_finish_result, expected_finish_result); + /* Check output parameter is set to the least-harmful value on error */ + TEST_EQUAL(0, outlen); + break; + } + total_len += outlen; + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) + int tag_expected = (ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) ? + tag_result : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL(tag_expected, mbedtls_cipher_check_tag(&ctx, tag->x, tag->len)); +#endif + + /* check plaintext only if everything went fine */ + if (0 == expected_finish_result && 0 == tag_result) { + TEST_ASSERT(total_len == clear->len); + TEST_ASSERT(0 == memcmp(output, clear->x, clear->len)); + } + +exit: + mbedtls_cipher_free(&ctx); +} +/* END_CASE */ + +/* BEGIN_CASE */ +void decrypt_padded_test_vec_cf(int cipher_id, int pad_mode, data_t *key, + data_t *iv, data_t *cipher, + data_t *clear, data_t *ad, data_t *tag, + int expected_finish_result, int tag_result) +{ + unsigned char output[265]; + mbedtls_cipher_context_t ctx; + size_t outlen, total_len; + + mbedtls_cipher_init(&ctx); + + memset(output, 0x00, sizeof(output)); + +#if !defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CHACHAPOLY_C) + ((void) ad); + ((void) tag); +#endif + + TEST_CF_SECRET(key->x, key->len); + TEST_CF_SECRET(cipher->x, cipher->len); + + /* Prepare context */ + TEST_ASSERT(0 == mbedtls_cipher_setup(&ctx, + mbedtls_cipher_info_from_type(cipher_id))); + TEST_ASSERT(0 == mbedtls_cipher_setkey(&ctx, key->x, 8 * key->len, MBEDTLS_DECRYPT)); +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + if (pad_mode != -1) { + TEST_ASSERT(0 == mbedtls_cipher_set_padding_mode(&ctx, pad_mode)); + } +#else + (void) pad_mode; +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + TEST_ASSERT(0 == mbedtls_cipher_set_iv(&ctx, iv->x, iv->len)); + TEST_ASSERT(0 == mbedtls_cipher_reset(&ctx)); +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) + int expected = (ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) ? + 0 : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL(expected, mbedtls_cipher_update_ad(&ctx, ad->x, ad->len)); +#endif + + /* decode buffer and check tag->x */ + total_len = 0; + TEST_ASSERT(0 == mbedtls_cipher_update(&ctx, cipher->x, cipher->len, output, &outlen)); + total_len += outlen; + + size_t invalid_padding = 42; + int actual_finish_result = + mbedtls_cipher_finish_padded(&ctx, output + outlen, &outlen, + &invalid_padding); + switch (expected_finish_result) { + case 0: + TEST_EQUAL(actual_finish_result, 0); + TEST_EQUAL(invalid_padding, 0); + break; + case MBEDTLS_ERR_CIPHER_INVALID_PADDING: + TEST_EQUAL(actual_finish_result, 0); + TEST_EQUAL(invalid_padding, SIZE_MAX); + break; + default: + TEST_EQUAL(actual_finish_result, expected_finish_result); + /* Check output parameter is set to the least-harmful value on error */ + TEST_EQUAL(0, outlen); + break; + } + total_len += outlen; + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) + int tag_expected = (ctx.cipher_info->mode == MBEDTLS_MODE_GCM || + ctx.cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) ? + tag_result : MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + + TEST_EQUAL(tag_expected, mbedtls_cipher_check_tag(&ctx, tag->x, tag->len)); +#endif + + /* check plaintext only if everything went fine */ + if (0 == expected_finish_result && 0 == tag_result) { + TEST_CF_PUBLIC(output, sizeof(output)); + TEST_MEMORY_COMPARE(output, total_len, clear->x, clear->len); + } + +exit: + mbedtls_cipher_free(&ctx); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_CIPHER_MODE_AEAD */ void auth_crypt_tv(int cipher_id, data_t *key, data_t *iv, data_t *ad, data_t *cipher, data_t *tag,