diff --git a/tests/suites/test_suite_psa_crypto_constant_time.function b/tests/suites/test_suite_psa_crypto_constant_time.function index c212ec7250..740b8d7d18 100644 --- a/tests/suites/test_suite_psa_crypto_constant_time.function +++ b/tests/suites/test_suite_psa_crypto_constant_time.function @@ -115,6 +115,8 @@ void ct_cipher_encrypt(int alg_arg, { psa_key_type_t key_type = key_type_arg; psa_algorithm_t alg = alg_arg; + size_t sufficient_output_size = + PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext->len); 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; @@ -129,9 +131,51 @@ void ct_cipher_encrypt(int alg_arg, psa_set_key_type(&attributes, key_type); PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len, &key)); + /* Output buffer too small for the actual output */ + mbedtls_test_set_step(1); PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg)); if (!ct_cipher_multipart(&operation, iv, plaintext, - PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(plaintext->len), + expected_ciphertext->len - 1, + expected_ciphertext, + PSA_ERROR_BUFFER_TOO_SMALL)) { + goto exit; + } + + if (expected_ciphertext->len < sufficient_output_size) { + /* For a buffer of intermediate size (between the actual output length + * and the guaranteed sufficient size), either PSA_SUCCESS or + * PSA_ERROR_BUFFER_TOO_SMALL is acceptable. Require what the our + * built-in implementation currently does. */ + psa_status_t intermediate_size_status = PSA_SUCCESS; + + /* Output buffer size just large enough for the actual output + * but less than the guaranteed sufficient size */ + mbedtls_test_set_step(2); + PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, plaintext, + expected_ciphertext->len, + expected_ciphertext, + intermediate_size_status)) { + goto exit; + } + + /* Output buffer size large enough for the actual output + * but one less than the guaranteed sufficient size */ + mbedtls_test_set_step(3); + PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, plaintext, + sufficient_output_size - 1, + expected_ciphertext, + intermediate_size_status)) { + goto exit; + } + } + + /* Guaranteed sufficient output buffer size */ + mbedtls_test_set_step(4); + PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, plaintext, + sufficient_output_size, expected_ciphertext, PSA_SUCCESS)) { goto exit; @@ -170,22 +214,86 @@ void ct_cipher_decrypt(int alg_arg, TEST_CF_SECRET(ciphertext->x, ciphertext->len); //TEST_ASSERT(key_data->x[0] != 42); // uncomment to trip constant-flow test + TEST_CALLOC(input.x, input.len); + memcpy(input.x, iv->x, iv->len); + memcpy(input.x + iv->len, ciphertext->x, ciphertext->len); + 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)); + /* Output buffer too small for the actual output */ + mbedtls_test_set_step(1); PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg)); if (!ct_cipher_multipart(&operation, iv, ciphertext, - PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(ciphertext->len), + expected_plaintext->len - 1, + expected_plaintext, + PSA_ERROR_BUFFER_TOO_SMALL)) { + goto exit; + } + if (!ct_cipher_decrypt_oneshot(key, alg, &input, + expected_plaintext->len - 1, + expected_plaintext, + PSA_ERROR_BUFFER_TOO_SMALL)) { + goto exit; + } + + if (expected_plaintext->len < sufficient_output_size) { + /* For a buffer of intermediate size (between the actual output length + * and the guaranteed sufficient size), either PSA_SUCCESS (or + * PSA_ERROR_INVALID_PADDING if the padding is invalid) or + * PSA_ERROR_BUFFER_TOO_SMALL is acceptable. Require what the our + * built-in implementation currently does. */ + psa_status_t intermediate_size_status = expected_status; + if (alg == PSA_ALG_CBC_PKCS7) { + intermediate_size_status = PSA_ERROR_BUFFER_TOO_SMALL; + } + + /* Output buffer size just large enough for the actual output + * but less than the guaranteed sufficient size */ + mbedtls_test_set_step(2); + PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, ciphertext, + expected_plaintext->len, + expected_plaintext, + intermediate_size_status)) { + goto exit; + } + if (!ct_cipher_decrypt_oneshot(key, alg, &input, + expected_plaintext->len - 1, + expected_plaintext, + intermediate_size_status)) { + goto exit; + } + + /* Output buffer size large enough for the actual output + * but one less than the guaranteed sufficient size */ + mbedtls_test_set_step(3); + PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, ciphertext, + sufficient_output_size - 1, + expected_plaintext, + intermediate_size_status)) { + goto exit; + } + if (!ct_cipher_decrypt_oneshot(key, alg, &input, + sufficient_output_size - 1, + expected_plaintext, + intermediate_size_status)) { + goto exit; + } + } + + /* Guaranteed sufficient output buffer size */ + mbedtls_test_set_step(4); + PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg)); + if (!ct_cipher_multipart(&operation, iv, ciphertext, + sufficient_output_size, expected_plaintext, expected_status)) { goto exit; } - - TEST_CALLOC(input.x, input.len); - memcpy(input.x, iv->x, iv->len); - memcpy(input.x + iv->len, ciphertext->x, ciphertext->len); if (!ct_cipher_decrypt_oneshot(key, alg, &input, sufficient_output_size, expected_plaintext,