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 <Gilles.Peskine@arm.com>
diff --git a/include/mbedtls/cipher.h b/include/mbedtls/cipher.h
index 1dc31c9..6ef703d 100644
--- a/include/mbedtls/cipher.h
+++ b/include/mbedtls/cipher.h
@@ -881,7 +881,7 @@
* 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 @@
* 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 @@
* 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 @@
* 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 @@
* \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 2ae01dd..f3e2f91 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -1124,6 +1124,23 @@
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 dd8bf71..4298b1d 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -1590,6 +1590,114 @@
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 7f9f4af..2de31ed 100644
--- a/tests/suites/test_suite_cipher.constant_time.data
+++ b/tests/suites/test_suite_cipher.constant_time.data
@@ -13,6 +13,114 @@
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 8ae2234..fbc48b7 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -946,6 +946,179 @@
}
/* 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,