mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-05-04 17:12:51 +02:00
Add constant-time AES-CBC encrypt and decrypt tests through PSA
The main goal is to validate that unpadding is constant-time, including error reporting. Use a separate test function, not annotations in the existing function, so that the functional tests can run on any platform, and we know from test outcomes where we have run the constant-time tests. The tests can only be actually constant-time if AES is constant time, since AES computations are part of what is checked. Thus this requires hardware-accelerated AES. We can't run our AESNI (or AESCE?) code under Msan (it doesn't detect when memory is written from assembly code), so these tests can only be run with Valgrind. Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
This commit is contained in:
39
tests/suites/test_suite_psa_crypto_constant_time.data
Normal file
39
tests/suites/test_suite_psa_crypto_constant_time.data
Normal file
@@ -0,0 +1,39 @@
|
||||
CT encrypt CHACHA20
|
||||
depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
|
||||
ct_cipher_encrypt:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"000000000000004a00000000":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":"af051e40bba0354981329a806a140eafd258a22a6dcb4bb9f6569cb3efe2deaf837bd87ca20b5ba12081a306af0eb35c41a239d20dfc74c81771560d9c9c1e4b224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cba40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a832c89c167eacd901d7e2bf363"
|
||||
|
||||
CT encrypt AES-CTR
|
||||
depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_encrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"dd3b5e5319b7591daab1e1a92687feb2":"396ee84fb75fdbb5c2b13c7fe5a654aa"
|
||||
|
||||
CT encrypt AES-CBC-nopad
|
||||
depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_encrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"49e4e66c89a86b67758df89db9ad6955":"396ee84fb75fdbb5c2b13c7fe5a654aa"
|
||||
|
||||
CT encrypt AES-CBC-PKCS7
|
||||
depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_encrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"6bc1bee22e409f96e93d7e117393172a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3"
|
||||
|
||||
CT decrypt CHACHA20
|
||||
depends_on:PSA_WANT_ALG_STREAM_CIPHER:PSA_WANT_KEY_TYPE_CHACHA20
|
||||
ct_cipher_decrypt:PSA_ALG_STREAM_CIPHER:PSA_KEY_TYPE_CHACHA20:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f":"000000000000004a00000000":"af051e40bba0354981329a806a140eafd258a22a6dcb4bb9f6569cb3efe2deaf837bd87ca20b5ba12081a306af0eb35c41a239d20dfc74c81771560d9c9c1e4b224f51f3401bd9e12fde276fb8631ded8c131f823d2c06e27e4fcaec9ef3cf788a3b0aa372600a92b57974cded2b9334794cba40c63e34cdea212c4cf07d41b769a6749f3f630f4122cafe28ec4dc47e26d4346d70b98c73f3e9c53ac40c5945398b6eda1a832c89c167eacd901d7e2bf363":"00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000":0
|
||||
|
||||
CT decrypt AES-CTR
|
||||
depends_on:PSA_WANT_ALG_CTR:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_decrypt:PSA_ALG_CTR:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"dd3b5e5319b7591daab1e1a92687feb2":0
|
||||
|
||||
CT decrypt AES-CBC-nopad
|
||||
depends_on:PSA_WANT_ALG_CBC_NO_PADDING:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_decrypt:PSA_ALG_CBC_NO_PADDING:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"396ee84fb75fdbb5c2b13c7fe5a654aa":"49e4e66c89a86b67758df89db9ad6955":0
|
||||
|
||||
CT decrypt AES-CBC-PKCS7 good
|
||||
depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743bca7e8a15dc3c776436314293031cd4f3":"6bc1bee22e409f96e93d7e117393172a":0
|
||||
|
||||
CT decrypt AES-CBC-PKCS7 invalid padding @0
|
||||
depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743bf42ddf64c420325affb343d5d5f5d5dc":"6bc1bee22e409f96e93d7e117393172a":1
|
||||
|
||||
CT decrypt AES-CBC-PKCS7 invalid padding @16
|
||||
depends_on:PSA_WANT_ALG_CBC_PKCS7:PSA_WANT_KEY_TYPE_AES:HAVE_CONSTANT_TIME_AES
|
||||
ct_cipher_decrypt:PSA_ALG_CBC_PKCS7:PSA_KEY_TYPE_AES:"2b7e151628aed2a6abf7158809cf4f3c":"2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a":"a076ec9dfbe47d52afc357336f20743ba3d6a86d0a9d172eeb1b754512d04416":"6bc1bee22e409f96e93d7e117393172a":1
|
||||
161
tests/suites/test_suite_psa_crypto_constant_time.function
Normal file
161
tests/suites/test_suite_psa_crypto_constant_time.function
Normal file
@@ -0,0 +1,161 @@
|
||||
/* BEGIN_HEADER */
|
||||
/* Positive test cases for PSA crypto APIs that assert constant-time
|
||||
* (more accurately constant-flow) behavior. */
|
||||
|
||||
#include <psa/crypto.h>
|
||||
#include <test/constant_flow.h>
|
||||
|
||||
/* Our software AES implementation is not constant-time. For constant-time
|
||||
* testing involving AES, require a hardware-assisted AES that is
|
||||
* constant-time.
|
||||
*
|
||||
* We assume that if the hardware-assisted version is available in the build,
|
||||
* it will be available at runtime. The AES tests will fail if run on a
|
||||
* processor without AESNI/AESCE.
|
||||
*/
|
||||
#include "aesce.h"
|
||||
#include "aesni.h"
|
||||
#if defined(MBEDTLS_AESCE_HAVE_CODE) || defined(MBEDTLS_AESNI_HAVE_CODE)
|
||||
#define HAVE_CONSTANT_TIME_AES
|
||||
#endif
|
||||
|
||||
/* END_HEADER */
|
||||
|
||||
/* BEGIN_DEPENDENCIES
|
||||
* depends_on:MBEDTLS_PSA_CRYPTO_C
|
||||
* END_DEPENDENCIES
|
||||
*/
|
||||
|
||||
/* BEGIN_CASE */
|
||||
/* Known answer test for cipher multipart encryption.
|
||||
* There is no known answer test for one-shot encryption because that
|
||||
* uses a random IV. */
|
||||
void ct_cipher_encrypt(int alg_arg,
|
||||
int key_type_arg, const data_t *key_data,
|
||||
const data_t *iv,
|
||||
const data_t *plaintext,
|
||||
const data_t *expected_ciphertext)
|
||||
{
|
||||
psa_key_type_t key_type = key_type_arg;
|
||||
psa_algorithm_t alg = alg_arg;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||
unsigned char *output = NULL;
|
||||
size_t output_size = PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(plaintext->len);
|
||||
size_t update_length = SIZE_MAX;
|
||||
size_t finish_length = SIZE_MAX;
|
||||
|
||||
PSA_INIT();
|
||||
TEST_CALLOC(output, output_size);
|
||||
TEST_CF_SECRET(key_data->x, key_data->len);
|
||||
TEST_CF_SECRET(plaintext->x, plaintext->len);
|
||||
//TEST_ASSERT(key_data->x[0] != 42); // uncomment to trip constant-flow test
|
||||
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
|
||||
psa_set_key_algorithm(&attributes, alg);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key));
|
||||
|
||||
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
|
||||
PSA_ASSERT(psa_cipher_set_iv(&operation, iv->x, iv->len));
|
||||
PSA_ASSERT(psa_cipher_update(&operation,
|
||||
plaintext->x, plaintext->len,
|
||||
output, output_size, &update_length));
|
||||
TEST_LE_U(update_length, output_size);
|
||||
PSA_ASSERT(psa_cipher_finish(&operation,
|
||||
output + update_length,
|
||||
output_size - update_length,
|
||||
&finish_length));
|
||||
|
||||
TEST_CF_PUBLIC(output, output_size);
|
||||
TEST_MEMORY_COMPARE(expected_ciphertext->x, expected_ciphertext->len,
|
||||
output, update_length + finish_length);
|
||||
|
||||
exit:
|
||||
mbedtls_free(output);
|
||||
psa_cipher_abort(&operation);
|
||||
psa_destroy_key(key);
|
||||
PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
/* Known answer for cipher decryption (one-shot and multipart).
|
||||
* Supports good cases and invalid padding cases. */
|
||||
void ct_cipher_decrypt(int alg_arg,
|
||||
int key_type_arg, const data_t *key_data,
|
||||
const data_t *iv,
|
||||
const data_t *ciphertext,
|
||||
const data_t *expected_plaintext,
|
||||
int expect_invalid_padding)
|
||||
{
|
||||
psa_key_type_t key_type = key_type_arg;
|
||||
psa_algorithm_t alg = alg_arg;
|
||||
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
|
||||
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
|
||||
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
|
||||
unsigned char *input = NULL;
|
||||
unsigned char *output = NULL;
|
||||
size_t output_size = PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(ciphertext->len);
|
||||
size_t update_length = SIZE_MAX;
|
||||
size_t finish_length = SIZE_MAX;
|
||||
size_t output_length = SIZE_MAX;
|
||||
psa_status_t status;
|
||||
|
||||
PSA_INIT();
|
||||
TEST_CALLOC(output, output_size);
|
||||
TEST_CF_SECRET(key_data->x, key_data->len);
|
||||
TEST_CF_SECRET(ciphertext->x, ciphertext->len);
|
||||
//TEST_ASSERT(key_data->x[0] != 42); // uncomment to trip constant-flow test
|
||||
|
||||
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
|
||||
psa_set_key_algorithm(&attributes, alg);
|
||||
psa_set_key_type(&attributes, key_type);
|
||||
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key));
|
||||
|
||||
PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
|
||||
PSA_ASSERT(psa_cipher_set_iv(&operation, iv->x, iv->len));
|
||||
PSA_ASSERT(psa_cipher_update(&operation,
|
||||
ciphertext->x, ciphertext->len,
|
||||
output, output_size, &update_length));
|
||||
TEST_LE_U(update_length, output_size);
|
||||
status = psa_cipher_finish(&operation,
|
||||
output + update_length,
|
||||
output_size - update_length,
|
||||
&finish_length);
|
||||
TEST_CF_PUBLIC(output, output_size);
|
||||
|
||||
if (expect_invalid_padding) {
|
||||
TEST_EQUAL(status, PSA_ERROR_INVALID_PADDING);
|
||||
} else {
|
||||
TEST_EQUAL(status, PSA_SUCCESS);
|
||||
TEST_MEMORY_COMPARE(expected_plaintext->x, expected_plaintext->len,
|
||||
output, update_length + finish_length);
|
||||
}
|
||||
|
||||
memset(output, 0, output_size);
|
||||
TEST_CALLOC(input, iv->len + ciphertext->len);
|
||||
memcpy(input, iv->x, iv->len);
|
||||
memcpy(input + iv->len, ciphertext->x, ciphertext->len);
|
||||
status = psa_cipher_decrypt(key, alg,
|
||||
input, iv->len + ciphertext->len,
|
||||
output, output_size, &output_length);
|
||||
TEST_CF_PUBLIC(output, output_size);
|
||||
|
||||
if (expect_invalid_padding) {
|
||||
TEST_EQUAL(status, PSA_ERROR_INVALID_PADDING);
|
||||
} else {
|
||||
TEST_EQUAL(status, PSA_SUCCESS);
|
||||
TEST_MEMORY_COMPARE(expected_plaintext->x, expected_plaintext->len,
|
||||
output, output_length);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_free(input);
|
||||
mbedtls_free(output);
|
||||
psa_cipher_abort(&operation);
|
||||
psa_destroy_key(key);
|
||||
PSA_DONE();
|
||||
}
|
||||
/* END_CASE */
|
||||
Reference in New Issue
Block a user