mbedtls/tests/suites/test_suite_psa_crypto.function
Ryan Everett 50619991c8 Add test function for concurrently using the same persistent key
The thread functions can also be used in future tests for other key types
and other test scenarios

Signed-off-by: Ryan Everett <ryan.everett@arm.com>
2024-03-13 14:31:11 +00:00

10791 lines
400 KiB
C

/* BEGIN_HEADER */
#include <stdint.h>
#include "mbedtls/asn1.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
#include "common.h"
#include "mbedtls/psa_util.h"
/* For MBEDTLS_CTR_DRBG_MAX_REQUEST, knowing that psa_generate_random()
* uses mbedtls_ctr_drbg internally. */
#include "mbedtls/ctr_drbg.h"
#include "psa/crypto.h"
#include "psa_crypto_slot_management.h"
/* For psa_can_do_hash() */
#include "psa_crypto_core.h"
#include "test/asn1_helpers.h"
#include "test/psa_crypto_helpers.h"
#include "test/psa_exercise_key.h"
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test/drivers/test_driver.h"
#define TEST_DRIVER_LOCATION PSA_CRYPTO_TEST_DRIVER_LOCATION
#else
#define TEST_DRIVER_LOCATION 0x7fffff
#endif
#if defined(MBEDTLS_THREADING_PTHREAD)
#include "mbedtls/threading.h"
#endif
/* If this comes up, it's a bug in the test code or in the test data. */
#define UNUSED 0xdeadbeef
/* Assert that an operation is (not) active.
* This serves as a proxy for checking if the operation is aborted. */
#define ASSERT_OPERATION_IS_ACTIVE(operation) TEST_ASSERT(operation.id != 0)
#define ASSERT_OPERATION_IS_INACTIVE(operation) TEST_ASSERT(operation.id == 0)
#if defined(PSA_WANT_ALG_JPAKE)
int ecjpake_operation_setup(psa_pake_operation_t *operation,
psa_pake_cipher_suite_t *cipher_suite,
psa_pake_role_t role,
mbedtls_svc_key_id_t key,
size_t key_available)
{
PSA_ASSERT(psa_pake_abort(operation));
PSA_ASSERT(psa_pake_setup(operation, cipher_suite));
PSA_ASSERT(psa_pake_set_role(operation, role));
if (key_available) {
PSA_ASSERT(psa_pake_set_password_key(operation, key));
}
return 0;
exit:
return 1;
}
#endif
/** An invalid export length that will never be set by psa_export_key(). */
static const size_t INVALID_EXPORT_LENGTH = ~0U;
/** Test if a buffer contains a constant byte value.
*
* `mem_is_char(buffer, c, size)` is true after `memset(buffer, c, size)`.
*
* \param buffer Pointer to the beginning of the buffer.
* \param c Expected value of every byte.
* \param size Size of the buffer in bytes.
*
* \return 1 if the buffer is all-bits-zero.
* \return 0 if there is at least one nonzero byte.
*/
static int mem_is_char(void *buffer, unsigned char c, size_t size)
{
size_t i;
for (i = 0; i < size; i++) {
if (((unsigned char *) buffer)[i] != c) {
return 0;
}
}
return 1;
}
#if defined(MBEDTLS_ASN1_WRITE_C)
/* Write the ASN.1 INTEGER with the value 2^(bits-1)+x backwards from *p. */
static int asn1_write_10x(unsigned char **p,
unsigned char *start,
size_t bits,
unsigned char x)
{
int ret;
int len = bits / 8 + 1;
if (bits == 0) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
if (bits <= 8 && x >= 1 << (bits - 1)) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
if (*p < start || *p - start < (ptrdiff_t) len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= len;
(*p)[len-1] = x;
if (bits % 8 == 0) {
(*p)[1] |= 1;
} else {
(*p)[0] |= 1 << (bits % 8);
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
MBEDTLS_ASN1_INTEGER));
return len;
}
static int construct_fake_rsa_key(unsigned char *buffer,
size_t buffer_size,
unsigned char **p,
size_t bits,
int keypair)
{
size_t half_bits = (bits + 1) / 2;
int ret;
int len = 0;
/* Construct something that looks like a DER encoding of
* as defined by PKCS#1 v2.2 (RFC 8017) section A.1.2:
* RSAPrivateKey ::= SEQUENCE {
* version Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL
* }
* Or, for a public key, the same structure with only
* version, modulus and publicExponent.
*/
*p = buffer + buffer_size;
if (keypair) {
MBEDTLS_ASN1_CHK_ADD(len, /* pq */
asn1_write_10x(p, buffer, half_bits, 1));
MBEDTLS_ASN1_CHK_ADD(len, /* dq */
asn1_write_10x(p, buffer, half_bits, 1));
MBEDTLS_ASN1_CHK_ADD(len, /* dp */
asn1_write_10x(p, buffer, half_bits, 1));
MBEDTLS_ASN1_CHK_ADD(len, /* q */
asn1_write_10x(p, buffer, half_bits, 1));
MBEDTLS_ASN1_CHK_ADD(len, /* p != q to pass mbedtls sanity checks */
asn1_write_10x(p, buffer, half_bits, 3));
MBEDTLS_ASN1_CHK_ADD(len, /* d */
asn1_write_10x(p, buffer, bits, 1));
}
MBEDTLS_ASN1_CHK_ADD(len, /* e = 65537 */
asn1_write_10x(p, buffer, 17, 1));
MBEDTLS_ASN1_CHK_ADD(len, /* n */
asn1_write_10x(p, buffer, bits, 1));
if (keypair) {
MBEDTLS_ASN1_CHK_ADD(len, /* version = 0 */
mbedtls_asn1_write_int(p, buffer, 0));
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buffer, len));
{
const unsigned char tag =
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buffer, tag));
}
return len;
}
#endif /* MBEDTLS_ASN1_WRITE_C */
int exercise_mac_setup(psa_key_type_t key_type,
const unsigned char *key_bytes,
size_t key_length,
psa_algorithm_t alg,
psa_mac_operation_t *operation,
psa_status_t *status)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_bytes, key_length, &key));
*status = psa_mac_sign_setup(operation, key, alg);
/* Whether setup succeeded or failed, abort must succeed. */
PSA_ASSERT(psa_mac_abort(operation));
/* If setup failed, reproduce the failure, so that the caller can
* test the resulting state of the operation object. */
if (*status != PSA_SUCCESS) {
TEST_EQUAL(psa_mac_sign_setup(operation, key, alg), *status);
}
psa_destroy_key(key);
return 1;
exit:
psa_destroy_key(key);
return 0;
}
int exercise_cipher_setup(psa_key_type_t key_type,
const unsigned char *key_bytes,
size_t key_length,
psa_algorithm_t alg,
psa_cipher_operation_t *operation,
psa_status_t *status)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
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_bytes, key_length, &key));
*status = psa_cipher_encrypt_setup(operation, key, alg);
/* Whether setup succeeded or failed, abort must succeed. */
PSA_ASSERT(psa_cipher_abort(operation));
/* If setup failed, reproduce the failure, so that the caller can
* test the resulting state of the operation object. */
if (*status != PSA_SUCCESS) {
TEST_EQUAL(psa_cipher_encrypt_setup(operation, key, alg),
*status);
}
psa_destroy_key(key);
return 1;
exit:
psa_destroy_key(key);
return 0;
}
static int test_operations_on_invalid_key(mbedtls_svc_key_id_t key)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, 0x6964);
uint8_t buffer[1];
size_t length;
int ok = 0;
psa_set_key_id(&attributes, key_id);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
TEST_EQUAL(psa_get_key_attributes(key, &attributes),
PSA_ERROR_INVALID_HANDLE);
TEST_EQUAL(
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(psa_get_key_id(&attributes)), 0);
TEST_EQUAL(
MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(psa_get_key_id(&attributes)), 0);
TEST_EQUAL(psa_get_key_lifetime(&attributes), 0);
TEST_EQUAL(psa_get_key_usage_flags(&attributes), 0);
TEST_EQUAL(psa_get_key_algorithm(&attributes), 0);
TEST_EQUAL(psa_get_key_type(&attributes), 0);
TEST_EQUAL(psa_get_key_bits(&attributes), 0);
TEST_EQUAL(psa_export_key(key, buffer, sizeof(buffer), &length),
PSA_ERROR_INVALID_HANDLE);
TEST_EQUAL(psa_export_public_key(key,
buffer, sizeof(buffer), &length),
PSA_ERROR_INVALID_HANDLE);
ok = 1;
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
return ok;
}
/* Assert that a key isn't reported as having a slot number. */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
#define ASSERT_NO_SLOT_NUMBER(attributes) \
do \
{ \
psa_key_slot_number_t ASSERT_NO_SLOT_NUMBER_slot_number; \
TEST_EQUAL(psa_get_key_slot_number( \
attributes, \
&ASSERT_NO_SLOT_NUMBER_slot_number), \
PSA_ERROR_INVALID_ARGUMENT); \
} \
while (0)
#else /* MBEDTLS_PSA_CRYPTO_SE_C */
#define ASSERT_NO_SLOT_NUMBER(attributes) \
((void) 0)
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#define INPUT_INTEGER 0x10000 /* Out of range of psa_key_type_t */
/* An overapproximation of the amount of storage needed for a key of the
* given type and with the given content. The API doesn't make it easy
* to find a good value for the size. The current implementation doesn't
* care about the value anyway. */
#define KEY_BITS_FROM_DATA(type, data) \
(data)->len
typedef enum {
IMPORT_KEY = 0,
GENERATE_KEY = 1,
DERIVE_KEY = 2
} generate_method;
typedef enum {
DO_NOT_SET_LENGTHS = 0,
SET_LENGTHS_BEFORE_NONCE = 1,
SET_LENGTHS_AFTER_NONCE = 2
} set_lengths_method_t;
typedef enum {
USE_NULL_TAG = 0,
USE_GIVEN_TAG = 1,
} tag_usage_method_t;
/*!
* \brief Internal Function for AEAD multipart tests.
* \param key_type_arg Type of key passed in
* \param key_data The encryption / decryption key data
* \param alg_arg The type of algorithm used
* \param nonce Nonce data
* \param additional_data Additional data
* \param ad_part_len_arg If not -1, the length of chunks to
* feed additional data in to be encrypted /
* decrypted. If -1, no chunking.
* \param input_data Data to encrypt / decrypt
* \param data_part_len_arg If not -1, the length of chunks to feed
* the data in to be encrypted / decrypted. If
* -1, no chunking
* \param set_lengths_method A member of the set_lengths_method_t enum is
* expected here, this controls whether or not
* to set lengths, and in what order with
* respect to set nonce.
* \param expected_output Expected output
* \param is_encrypt If non-zero this is an encryption operation.
* \param do_zero_parts If non-zero, interleave zero length chunks
* with normal length chunks.
* \return int Zero on failure, non-zero on success.
*/
static int aead_multipart_internal_func(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
int ad_part_len_arg,
data_t *input_data,
int data_part_len_arg,
set_lengths_method_t set_lengths_method,
data_t *expected_output,
int is_encrypt,
int do_zero_parts)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
unsigned char *output_data = NULL;
unsigned char *part_data = NULL;
unsigned char *final_data = NULL;
size_t data_true_size = 0;
size_t part_data_size = 0;
size_t output_size = 0;
size_t final_output_size = 0;
size_t output_length = 0;
size_t key_bits = 0;
size_t tag_length = 0;
size_t part_offset = 0;
size_t part_length = 0;
size_t output_part_length = 0;
size_t tag_size = 0;
size_t ad_part_len = 0;
size_t data_part_len = 0;
uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
int test_ok = 0;
size_t part_count = 0;
PSA_ASSERT(psa_crypto_init());
if (is_encrypt) {
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
} else {
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
tag_length = PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg);
if (is_encrypt) {
/* Tag gets written at end of buffer. */
output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg,
(input_data->len +
tag_length));
data_true_size = input_data->len;
} else {
output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg,
(input_data->len -
tag_length));
/* Do not want to attempt to decrypt tag. */
data_true_size = input_data->len - tag_length;
}
TEST_CALLOC(output_data, output_size);
if (is_encrypt) {
final_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(final_output_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
} else {
final_output_size = PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(final_output_size, PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE);
}
TEST_CALLOC(final_data, final_output_size);
if (is_encrypt) {
status = psa_aead_encrypt_setup(&operation, key, alg);
} else {
status = psa_aead_decrypt_setup(&operation, key, alg);
}
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
PSA_ASSERT(status);
if (set_lengths_method == DO_NOT_SET_LENGTHS) {
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
} else if (set_lengths_method == SET_LENGTHS_BEFORE_NONCE) {
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
data_true_size));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
} else if (set_lengths_method == SET_LENGTHS_AFTER_NONCE) {
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
data_true_size));
}
if (ad_part_len_arg != -1) {
/* Pass additional data in parts */
ad_part_len = (size_t) ad_part_len_arg;
for (part_offset = 0, part_count = 0;
part_offset < additional_data->len;
part_offset += part_length, part_count++) {
if (do_zero_parts && (part_count & 0x01)) {
part_length = 0;
} else if (additional_data->len - part_offset < ad_part_len) {
part_length = additional_data->len - part_offset;
} else {
part_length = ad_part_len;
}
PSA_ASSERT(psa_aead_update_ad(&operation,
additional_data->x + part_offset,
part_length));
}
} else {
/* Pass additional data in one go. */
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
}
if (data_part_len_arg != -1) {
/* Pass data in parts */
data_part_len = (size_t) data_part_len_arg;
part_data_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg,
(size_t) data_part_len);
TEST_CALLOC(part_data, part_data_size);
for (part_offset = 0, part_count = 0;
part_offset < data_true_size;
part_offset += part_length, part_count++) {
if (do_zero_parts && (part_count & 0x01)) {
part_length = 0;
} else if ((data_true_size - part_offset) < data_part_len) {
part_length = (data_true_size - part_offset);
} else {
part_length = data_part_len;
}
PSA_ASSERT(psa_aead_update(&operation,
(input_data->x + part_offset),
part_length, part_data,
part_data_size,
&output_part_length));
if (output_data && output_part_length) {
memcpy((output_data + output_length), part_data,
output_part_length);
}
output_length += output_part_length;
}
} else {
/* Pass all data in one go. */
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
data_true_size, output_data,
output_size, &output_length));
}
if (is_encrypt) {
PSA_ASSERT(psa_aead_finish(&operation, final_data,
final_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size));
} else {
PSA_ASSERT(psa_aead_verify(&operation, final_data,
final_output_size,
&output_part_length,
(input_data->x + data_true_size),
tag_length));
}
if (output_data && output_part_length) {
memcpy((output_data + output_length), final_data,
output_part_length);
}
output_length += output_part_length;
/* For all currently defined algorithms, PSA_AEAD_xxx_OUTPUT_SIZE
* should be exact.*/
if (is_encrypt) {
TEST_EQUAL(tag_length, tag_size);
if (output_data && tag_length) {
memcpy((output_data + output_length), tag_buffer,
tag_length);
}
output_length += tag_length;
TEST_EQUAL(output_length,
PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg,
input_data->len));
TEST_LE_U(output_length,
PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(input_data->len));
} else {
TEST_EQUAL(output_length,
PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg,
input_data->len));
TEST_LE_U(output_length,
PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(input_data->len));
}
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
output_data, output_length);
test_ok = 1;
exit:
psa_destroy_key(key);
psa_aead_abort(&operation);
mbedtls_free(output_data);
mbedtls_free(part_data);
mbedtls_free(final_data);
PSA_DONE();
return test_ok;
}
/*!
* \brief Internal Function for MAC multipart tests.
* \param key_type_arg Type of key passed in
* \param key_data The encryption / decryption key data
* \param alg_arg The type of algorithm used
* \param input_data Data to encrypt / decrypt
* \param data_part_len_arg If not -1, the length of chunks to feed
* the data in to be encrypted / decrypted. If
* -1, no chunking
* \param expected_output Expected output
* \param is_verify If non-zero this is a verify operation.
* \param do_zero_parts If non-zero, interleave zero length chunks
* with normal length chunks.
* \return int Zero on failure, non-zero on success.
*/
static int mac_multipart_internal_func(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *input_data,
int data_part_len_arg,
data_t *expected_output,
int is_verify,
int do_zero_parts)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
unsigned char mac[PSA_MAC_MAX_SIZE];
size_t part_offset = 0;
size_t part_length = 0;
size_t data_part_len = 0;
size_t mac_len = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
int test_ok = 0;
size_t part_count = 0;
PSA_INIT();
if (is_verify) {
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
} else {
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
}
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));
if (is_verify) {
status = psa_mac_verify_setup(&operation, key, alg);
} else {
status = psa_mac_sign_setup(&operation, key, alg);
}
PSA_ASSERT(status);
if (data_part_len_arg != -1) {
/* Pass data in parts */
data_part_len = (size_t) data_part_len_arg;
for (part_offset = 0, part_count = 0;
part_offset < input_data->len;
part_offset += part_length, part_count++) {
if (do_zero_parts && (part_count & 0x01)) {
part_length = 0;
} else if ((input_data->len - part_offset) < data_part_len) {
part_length = (input_data->len - part_offset);
} else {
part_length = data_part_len;
}
PSA_ASSERT(psa_mac_update(&operation,
(input_data->x + part_offset),
part_length));
}
} else {
/* Pass all data in one go. */
PSA_ASSERT(psa_mac_update(&operation, input_data->x,
input_data->len));
}
if (is_verify) {
PSA_ASSERT(psa_mac_verify_finish(&operation, expected_output->x,
expected_output->len));
} else {
PSA_ASSERT(psa_mac_sign_finish(&operation, mac,
PSA_MAC_MAX_SIZE, &mac_len));
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
mac, mac_len);
}
test_ok = 1;
exit:
psa_destroy_key(key);
psa_mac_abort(&operation);
PSA_DONE();
return test_ok;
}
#if defined(PSA_WANT_ALG_JPAKE)
static void ecjpake_do_round(psa_algorithm_t alg, unsigned int primitive,
psa_pake_operation_t *server,
psa_pake_operation_t *client,
int client_input_first,
int round, int inject_error)
{
unsigned char *buffer0 = NULL, *buffer1 = NULL;
size_t buffer_length = (
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_KEY_SHARE) +
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PUBLIC) +
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PROOF)) * 2;
/* The output should be exactly this size according to the spec */
const size_t expected_size_key_share =
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_KEY_SHARE);
/* The output should be exactly this size according to the spec */
const size_t expected_size_zk_public =
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PUBLIC);
/* The output can be smaller: the spec allows stripping leading zeroes */
const size_t max_expected_size_zk_proof =
PSA_PAKE_OUTPUT_SIZE(alg, primitive, PSA_PAKE_STEP_ZK_PROOF);
size_t buffer0_off = 0;
size_t buffer1_off = 0;
size_t s_g1_len, s_g2_len, s_a_len;
size_t s_g1_off, s_g2_off, s_a_off;
size_t s_x1_pk_len, s_x2_pk_len, s_x2s_pk_len;
size_t s_x1_pk_off, s_x2_pk_off, s_x2s_pk_off;
size_t s_x1_pr_len, s_x2_pr_len, s_x2s_pr_len;
size_t s_x1_pr_off, s_x2_pr_off, s_x2s_pr_off;
size_t c_g1_len, c_g2_len, c_a_len;
size_t c_g1_off, c_g2_off, c_a_off;
size_t c_x1_pk_len, c_x2_pk_len, c_x2s_pk_len;
size_t c_x1_pk_off, c_x2_pk_off, c_x2s_pk_off;
size_t c_x1_pr_len, c_x2_pr_len, c_x2s_pr_len;
size_t c_x1_pr_off, c_x2_pr_off, c_x2s_pr_off;
psa_status_t expected_status = PSA_SUCCESS;
psa_status_t status;
TEST_CALLOC(buffer0, buffer_length);
TEST_CALLOC(buffer1, buffer_length);
switch (round) {
case 1:
/* Server first round Output */
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + buffer0_off,
512 - buffer0_off, &s_g1_len));
TEST_EQUAL(s_g1_len, expected_size_key_share);
s_g1_off = buffer0_off;
buffer0_off += s_g1_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x1_pk_len));
TEST_EQUAL(s_x1_pk_len, expected_size_zk_public);
s_x1_pk_off = buffer0_off;
buffer0_off += s_x1_pk_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x1_pr_len));
TEST_LE_U(s_x1_pr_len, max_expected_size_zk_proof);
s_x1_pr_off = buffer0_off;
buffer0_off += s_x1_pr_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + buffer0_off,
512 - buffer0_off, &s_g2_len));
TEST_EQUAL(s_g2_len, expected_size_key_share);
s_g2_off = buffer0_off;
buffer0_off += s_g2_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x2_pk_len));
TEST_EQUAL(s_x2_pk_len, expected_size_zk_public);
s_x2_pk_off = buffer0_off;
buffer0_off += s_x2_pk_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x2_pr_len));
TEST_LE_U(s_x2_pr_len, max_expected_size_zk_proof);
s_x2_pr_off = buffer0_off;
buffer0_off += s_x2_pr_len;
if (inject_error == 1) {
buffer0[s_x1_pr_off + 8] ^= 1;
buffer0[s_x2_pr_off + 7] ^= 1;
expected_status = PSA_ERROR_DATA_INVALID;
}
/*
* When injecting errors in inputs, the implementation is
* free to detect it right away of with a delay.
* This permits delaying the error until the end of the input
* sequence, if no error appears then, this will be treated
* as an error.
*/
if (client_input_first == 1) {
/* Client first round Input */
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_g1_off, s_g1_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x1_pk_off,
s_x1_pk_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x1_pr_off,
s_x1_pr_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_g2_off,
s_g2_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x2_pk_off,
s_x2_pk_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x2_pr_off,
s_x2_pr_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 1) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
}
/* Client first round Output */
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + buffer1_off,
512 - buffer1_off, &c_g1_len));
TEST_EQUAL(c_g1_len, expected_size_key_share);
c_g1_off = buffer1_off;
buffer1_off += c_g1_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x1_pk_len));
TEST_EQUAL(c_x1_pk_len, expected_size_zk_public);
c_x1_pk_off = buffer1_off;
buffer1_off += c_x1_pk_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x1_pr_len));
TEST_LE_U(c_x1_pr_len, max_expected_size_zk_proof);
c_x1_pr_off = buffer1_off;
buffer1_off += c_x1_pr_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + buffer1_off,
512 - buffer1_off, &c_g2_len));
TEST_EQUAL(c_g2_len, expected_size_key_share);
c_g2_off = buffer1_off;
buffer1_off += c_g2_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x2_pk_len));
TEST_EQUAL(c_x2_pk_len, expected_size_zk_public);
c_x2_pk_off = buffer1_off;
buffer1_off += c_x2_pk_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x2_pr_len));
TEST_LE_U(c_x2_pr_len, max_expected_size_zk_proof);
c_x2_pr_off = buffer1_off;
buffer1_off += c_x2_pr_len;
if (client_input_first == 0) {
/* Client first round Input */
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_g1_off, s_g1_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x1_pk_off,
s_x1_pk_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x1_pr_off,
s_x1_pr_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_g2_off,
s_g2_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x2_pk_off,
s_x2_pk_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x2_pr_off,
s_x2_pr_len);
if (inject_error == 1 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 1) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
}
if (inject_error == 2) {
buffer1[c_x1_pr_off + 12] ^= 1;
buffer1[c_x2_pr_off + 7] ^= 1;
expected_status = PSA_ERROR_DATA_INVALID;
}
/* Server first round Input */
status = psa_pake_input(server, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + c_g1_off, c_g1_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + c_x1_pk_off, c_x1_pk_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + c_x1_pr_off, c_x1_pr_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + c_g2_off, c_g2_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + c_x2_pk_off, c_x2_pk_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + c_x2_pr_off, c_x2_pr_len);
if (inject_error == 2 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 2) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
break;
case 2:
/* Server second round Output */
buffer0_off = 0;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + buffer0_off,
512 - buffer0_off, &s_a_len));
TEST_EQUAL(s_a_len, expected_size_key_share);
s_a_off = buffer0_off;
buffer0_off += s_a_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x2s_pk_len));
TEST_EQUAL(s_x2s_pk_len, expected_size_zk_public);
s_x2s_pk_off = buffer0_off;
buffer0_off += s_x2s_pk_len;
PSA_ASSERT(psa_pake_output(server, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + buffer0_off,
512 - buffer0_off, &s_x2s_pr_len));
TEST_LE_U(s_x2s_pr_len, max_expected_size_zk_proof);
s_x2s_pr_off = buffer0_off;
buffer0_off += s_x2s_pr_len;
if (inject_error == 3) {
buffer0[s_x2s_pk_off + 12] += 0x33;
expected_status = PSA_ERROR_DATA_INVALID;
}
if (client_input_first == 1) {
/* Client second round Input */
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_a_off, s_a_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x2s_pk_off,
s_x2s_pk_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x2s_pr_off,
s_x2s_pr_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 3) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
}
/* Client second round Output */
buffer1_off = 0;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + buffer1_off,
512 - buffer1_off, &c_a_len));
TEST_EQUAL(c_a_len, expected_size_key_share);
c_a_off = buffer1_off;
buffer1_off += c_a_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x2s_pk_len));
TEST_EQUAL(c_x2s_pk_len, expected_size_zk_public);
c_x2s_pk_off = buffer1_off;
buffer1_off += c_x2s_pk_len;
PSA_ASSERT(psa_pake_output(client, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + buffer1_off,
512 - buffer1_off, &c_x2s_pr_len));
TEST_LE_U(c_x2s_pr_len, max_expected_size_zk_proof);
c_x2s_pr_off = buffer1_off;
buffer1_off += c_x2s_pr_len;
if (client_input_first == 0) {
/* Client second round Input */
status = psa_pake_input(client, PSA_PAKE_STEP_KEY_SHARE,
buffer0 + s_a_off, s_a_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PUBLIC,
buffer0 + s_x2s_pk_off,
s_x2s_pk_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(client, PSA_PAKE_STEP_ZK_PROOF,
buffer0 + s_x2s_pr_off,
s_x2s_pr_len);
if (inject_error == 3 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 3) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
}
if (inject_error == 4) {
buffer1[c_x2s_pk_off + 7] += 0x28;
expected_status = PSA_ERROR_DATA_INVALID;
}
/* Server second round Input */
status = psa_pake_input(server, PSA_PAKE_STEP_KEY_SHARE,
buffer1 + c_a_off, c_a_len);
if (inject_error == 4 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PUBLIC,
buffer1 + c_x2s_pk_off, c_x2s_pk_len);
if (inject_error == 4 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
status = psa_pake_input(server, PSA_PAKE_STEP_ZK_PROOF,
buffer1 + c_x2s_pr_off, c_x2s_pr_len);
if (inject_error == 4 && status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
break;
} else {
TEST_EQUAL(status, PSA_SUCCESS);
}
/* Error didn't trigger, make test fail */
if (inject_error == 4) {
TEST_ASSERT(
!"One of the last psa_pake_input() calls should have returned the expected error.");
}
break;
}
exit:
mbedtls_free(buffer0);
mbedtls_free(buffer1);
}
#endif /* PSA_WANT_ALG_JPAKE */
typedef enum {
INJECT_ERR_NONE = 0,
INJECT_ERR_UNINITIALIZED_ACCESS,
INJECT_ERR_DUPLICATE_SETUP,
INJECT_ERR_INVALID_USER,
INJECT_ERR_INVALID_PEER,
INJECT_ERR_SET_USER,
INJECT_ERR_SET_PEER,
INJECT_EMPTY_IO_BUFFER,
INJECT_UNKNOWN_STEP,
INJECT_INVALID_FIRST_STEP,
INJECT_WRONG_BUFFER_SIZE,
INJECT_VALID_OPERATION_AFTER_FAILURE,
INJECT_ANTICIPATE_KEY_DERIVATION_1,
INJECT_ANTICIPATE_KEY_DERIVATION_2,
} ecjpake_injected_failure_t;
#if defined(MBEDTLS_ECP_RESTARTABLE)
static void interruptible_signverify_get_minmax_completes(uint32_t max_ops,
psa_status_t expected_status,
size_t *min_completes,
size_t *max_completes)
{
/* This is slightly contrived, but we only really know that with a minimum
value of max_ops that a successful operation should take more than one op
to complete, and likewise that with a max_ops of
PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, it should complete in one go. */
if (max_ops == 0 || max_ops == 1) {
if (expected_status == PSA_SUCCESS) {
*min_completes = 2;
} else {
*min_completes = 1;
}
*max_completes = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
} else {
*min_completes = 1;
*max_completes = 1;
}
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
static int rsa_test_e(mbedtls_svc_key_id_t key,
size_t bits,
const data_t *e_arg)
{
uint8_t *exported = NULL;
size_t exported_size =
PSA_EXPORT_KEY_OUTPUT_SIZE(PSA_KEY_TYPE_RSA_PUBLIC_KEY, bits);
size_t exported_length = SIZE_MAX;
int ok = 0;
TEST_CALLOC(exported, exported_size);
PSA_ASSERT(psa_export_public_key(key,
exported, exported_size,
&exported_length));
uint8_t *p = exported;
uint8_t *end = exported + exported_length;
size_t len;
/* RSAPublicKey ::= SEQUENCE {
* modulus INTEGER, -- n
* publicExponent INTEGER } -- e
*/
TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_SEQUENCE |
MBEDTLS_ASN1_CONSTRUCTED));
TEST_ASSERT(mbedtls_test_asn1_skip_integer(&p, end, bits, bits, 1));
TEST_EQUAL(0, mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_INTEGER));
if (len >= 1 && p[0] == 0) {
++p;
--len;
}
if (e_arg->len == 0) {
TEST_EQUAL(len, 3);
TEST_EQUAL(p[0], 1);
TEST_EQUAL(p[1], 0);
TEST_EQUAL(p[2], 1);
} else {
const uint8_t *expected = e_arg->x;
size_t expected_len = e_arg->len;
while (expected_len > 0 && *expected == 0) {
++expected;
--expected_len;
}
TEST_MEMORY_COMPARE(p, len, expected, expected_len);
}
ok = 1;
exit:
mbedtls_free(exported);
return ok;
}
#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */
static int setup_key_production_parameters(
psa_key_production_parameters_t **params, size_t *params_data_length,
int flags_arg, const data_t *params_data)
{
*params_data_length = params_data->len;
/* If there are N bytes of padding at the end of
* psa_key_production_parameters_t, then it's enough to allocate
* MIN(sizeof(psa_key_production_parameters_t),
* offsetof(psa_key_production_parameters_t, data) + params_data_length).
*
* For simplicity, here, we allocate up to N more bytes than necessary.
* In practice, the current layout of psa_key_production_parameters_t
* makes padding extremely unlikely, so we don't worry about testing
* that the library code doesn't try to access these extra N bytes.
*/
*params = mbedtls_calloc(1, sizeof(**params) + *params_data_length);
TEST_ASSERT(*params != NULL);
(*params)->flags = (uint32_t) flags_arg;
memcpy((*params)->data, params_data->x, params_data->len);
return 1;
exit:
return 0;
}
#if defined(MBEDTLS_THREADING_PTHREAD)
typedef struct same_key_context {
data_t *data;
mbedtls_svc_key_id_t key;
psa_key_attributes_t *attributes;
int type;
int bits;
/* The following two parameters are used to ensure that when multiple
* threads attempt to load/destroy the key, exactly one thread succeeds. */
int key_loaded;
mbedtls_threading_mutex_t MBEDTLS_PRIVATE(key_loaded_mutex);
}
same_key_context;
/* Attempt to import the key in ctx. This handles any valid error codes
* and reports an error for any invalid codes. This function also insures
* that once imported by some thread, all threads can use the key. */
void *thread_import_key(void *ctx)
{
mbedtls_svc_key_id_t returned_key_id;
same_key_context *skc = (struct same_key_context *) ctx;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
/* Import the key, exactly one thread must succceed. */
psa_status_t status = psa_import_key(skc->attributes, skc->data->x,
skc->data->len, &returned_key_id);
switch (status) {
case PSA_SUCCESS:
if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) {
if (skc->key_loaded) {
mbedtls_mutex_unlock(&skc->key_loaded_mutex);
/* More than one thread has succeeded, report a failure. */
TEST_EQUAL(skc->key_loaded, 0);
}
skc->key_loaded = 1;
mbedtls_mutex_unlock(&skc->key_loaded_mutex);
}
break;
case PSA_ERROR_INSUFFICIENT_MEMORY:
/* If all of the key slots are reserved when a thread
* locks the mutex to reserve a new slot, it will return
* PSA_ERROR_INSUFFICIENT_MEMORY; this is correct behaviour.
* There is a chance for this to occur here when the number of
* threads running this function is larger than the number of
* free key slots. Each thread reserves an empty key slot,
* unlocks the mutex, then relocks it to finalize key creation.
* It is at that point where the thread sees that the key
* already exists, releases the reserved slot,
* and returns PSA_ERROR_ALREADY_EXISTS.
* There is no guarantee that the key is loaded upon this return
* code, so we can't test the key information. Just stop this
* thread from executing, note that this is not an error. */
goto exit;
break;
case PSA_ERROR_ALREADY_EXISTS:
/* The key has been loaded by a different thread. */
break;
default:
PSA_ASSERT(status);
}
/* At this point the key must exist, test the key information. */
status = psa_get_key_attributes(skc->key, &got_attributes);
if (status == PSA_ERROR_INSUFFICIENT_MEMORY) {
/* This is not a test failure. The following sequence of events
* causes this to occur:
* 1: This thread successfuly imports a persistent key skc->key.
* 2: N threads reserve an empty key slot in psa_import_key,
* where N is equal to the number of free key slots.
* 3: A final thread attempts to reserve an empty key slot, kicking
* skc->key (which has no registered readers) out of its slot.
* 4: This thread calls psa_get_key_attributes(skc->key,...):
* it sees that skc->key is not in a slot, attempts to load it and
* finds that there are no free slots.
* This thread returns PSA_ERROR_INSUFFICIENT_MEMORY.
*
* The PSA spec allows this behaviour, it is an unavoidable consequence
* of allowing persistent keys to be kicked out of the key store while
* they are still valid. */
goto exit;
}
PSA_ASSERT(status);
TEST_EQUAL(psa_get_key_type(&got_attributes), skc->type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), skc->bits);
exit:
/* Key attributes may have been returned by psa_get_key_attributes(),
* reset them as required. */
psa_reset_key_attributes(&got_attributes);
return NULL;
}
void *thread_use_and_destroy_key(void *ctx)
{
same_key_context *skc = (struct same_key_context *) ctx;
/* Do something with the key according
* to its type and permitted usage. */
TEST_ASSERT(mbedtls_test_psa_exercise_key(skc->key,
skc->attributes->policy.usage,
skc->attributes->policy.alg, 1));
psa_status_t status = psa_destroy_key(skc->key);
if (status == PSA_SUCCESS) {
if (mbedtls_mutex_lock(&skc->key_loaded_mutex) == 0) {
/* Ensure that we are the only thread to succeed. */
if (skc->key_loaded != 1) {
mbedtls_mutex_unlock(&skc->key_loaded_mutex);
//Will always fail
TEST_EQUAL(skc->key_loaded, 1);
}
skc->key_loaded = 0;
mbedtls_mutex_unlock(&skc->key_loaded_mutex);
}
} else {
TEST_EQUAL(status, PSA_ERROR_INVALID_HANDLE);
}
exit:
return NULL;
}
typedef struct generate_key_context {
psa_key_type_t type;
psa_key_usage_t usage;
size_t bits;
psa_algorithm_t alg;
psa_status_t expected_status;
psa_key_attributes_t *attributes;
int is_large_key;
int reps;
}
generate_key_context;
void *thread_generate_key(void *ctx)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
generate_key_context *gkc = (struct generate_key_context *) ctx;
/* If there are race conditions, it is likely the case that they do not
* arise every time the code runs. We repeat the code to increase the
* chance that any race conditions will be hit. */
for (int n = 0; n < gkc->reps; n++) {
/* Generate a key */
psa_status_t status = psa_generate_key(gkc->attributes, &key);
if (gkc->is_large_key > 0) {
TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
}
TEST_EQUAL(status, gkc->expected_status);
if (gkc->expected_status != PSA_SUCCESS) {
PSA_ASSERT(psa_destroy_key(key));
goto exit;
}
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), gkc->type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), gkc->bits);
/* Do something with the key according
* to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, gkc->usage, gkc->alg, 0)) {
psa_destroy_key(key);
goto exit;
}
psa_reset_key_attributes(&got_attributes);
PSA_ASSERT(psa_destroy_key(key));
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
return NULL;
}
#endif /* MBEDTLS_THREADING_PTHREAD */
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_PSA_CRYPTO_C
* END_DEPENDENCIES
*/
/* BEGIN_CASE */
void psa_can_do_hash()
{
/* We can't test that this is specific to drivers until partial init has
* been implemented, but we can at least test before/after full init. */
TEST_EQUAL(0, psa_can_do_hash(PSA_ALG_NONE));
PSA_INIT();
TEST_EQUAL(1, psa_can_do_hash(PSA_ALG_NONE));
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void static_checks()
{
size_t max_truncated_mac_size =
PSA_ALG_MAC_TRUNCATION_MASK >> PSA_MAC_TRUNCATION_OFFSET;
/* Check that the length for a truncated MAC always fits in the algorithm
* encoding. The shifted mask is the maximum truncated value. The
* untruncated algorithm may be one byte larger. */
TEST_LE_U(PSA_MAC_MAX_SIZE, 1 + max_truncated_mac_size);
}
/* END_CASE */
/* BEGIN_CASE */
void import_with_policy(int type_arg,
int usage_arg, int alg_arg,
int expected_status_arg)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
psa_key_usage_t usage = usage_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
const uint8_t key_material[16] = { 0 };
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_type(&attributes, type);
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
status = psa_import_key(&attributes,
key_material, sizeof(key_material),
&key);
TEST_EQUAL(status, expected_status);
if (status != PSA_SUCCESS) {
goto exit;
}
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
TEST_EQUAL(psa_get_key_usage_flags(&got_attributes),
mbedtls_test_update_key_usage_flags(usage));
TEST_EQUAL(psa_get_key_algorithm(&got_attributes), alg);
ASSERT_NO_SLOT_NUMBER(&got_attributes);
PSA_ASSERT(psa_destroy_key(key));
test_operations_on_invalid_key(key);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void import_with_data(data_t *data, int type_arg,
int attr_bits_arg,
int expected_status_arg)
{
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
size_t attr_bits = attr_bits_arg;
psa_status_t expected_status = expected_status_arg;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, attr_bits);
status = psa_import_key(&attributes, data->x, data->len, &key);
/* When expecting INVALID_ARGUMENT, also accept NOT_SUPPORTED.
*
* This can happen with a type supported only by a driver:
* - the driver sees the invalid data (for example wrong size) and thinks
* "well perhaps this is a key size I don't support" so it returns
* NOT_SUPPORTED which is correct at this point;
* - we fallback to built-ins, which don't support this type, so return
* NOT_SUPPORTED which again is correct at this point.
*/
if (expected_status == PSA_ERROR_INVALID_ARGUMENT &&
status == PSA_ERROR_NOT_SUPPORTED) {
; // OK
} else {
TEST_EQUAL(status, expected_status);
}
if (status != PSA_SUCCESS) {
goto exit;
}
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
if (attr_bits != 0) {
TEST_EQUAL(attr_bits, psa_get_key_bits(&got_attributes));
}
ASSERT_NO_SLOT_NUMBER(&got_attributes);
PSA_ASSERT(psa_destroy_key(key));
test_operations_on_invalid_key(key);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
/* Construct and attempt to import a large unstructured key. */
void import_large_key(int type_arg, int byte_size_arg,
int expected_status_arg)
{
psa_key_type_t type = type_arg;
size_t byte_size = byte_size_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t expected_status = expected_status_arg;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
uint8_t *buffer = NULL;
size_t buffer_size = byte_size + 1;
size_t n;
/* Skip the test case if the target running the test cannot
* accommodate large keys due to heap size constraints */
TEST_CALLOC_OR_SKIP(buffer, buffer_size);
memset(buffer, 'K', byte_size);
PSA_ASSERT(psa_crypto_init());
/* Try importing the key */
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_type(&attributes, type);
status = psa_import_key(&attributes, buffer, byte_size, &key);
TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
TEST_EQUAL(status, expected_status);
if (status == PSA_SUCCESS) {
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
TEST_EQUAL(psa_get_key_type(&attributes), type);
TEST_EQUAL(psa_get_key_bits(&attributes),
PSA_BYTES_TO_BITS(byte_size));
ASSERT_NO_SLOT_NUMBER(&attributes);
memset(buffer, 0, byte_size + 1);
PSA_ASSERT(psa_export_key(key, buffer, byte_size, &n));
for (n = 0; n < byte_size; n++) {
TEST_EQUAL(buffer[n], 'K');
}
for (n = byte_size; n < buffer_size; n++) {
TEST_EQUAL(buffer[n], 0);
}
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
mbedtls_free(buffer);
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ASN1_WRITE_C */
/* Import an RSA key with a valid structure (but not valid numbers
* inside, beyond having sensible size and parity). This is expected to
* fail for large keys. */
void import_rsa_made_up(int bits_arg, int keypair, int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
size_t bits = bits_arg;
psa_status_t expected_status = expected_status_arg;
psa_status_t status;
psa_key_type_t type =
keypair ? PSA_KEY_TYPE_RSA_KEY_PAIR : PSA_KEY_TYPE_RSA_PUBLIC_KEY;
size_t buffer_size = /* Slight overapproximations */
keypair ? bits * 9 / 16 + 80 : bits / 8 + 20;
unsigned char *buffer = NULL;
unsigned char *p;
int ret;
size_t length;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
TEST_CALLOC(buffer, buffer_size);
TEST_ASSERT((ret = construct_fake_rsa_key(buffer, buffer_size, &p,
bits, keypair)) >= 0);
length = ret;
/* Try importing the key */
psa_set_key_type(&attributes, type);
status = psa_import_key(&attributes, p, length, &key);
TEST_EQUAL(status, expected_status);
if (status == PSA_SUCCESS) {
PSA_ASSERT(psa_destroy_key(key));
}
exit:
mbedtls_free(buffer);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void import_export(data_t *data,
int type_arg,
int usage_arg, int alg_arg,
int lifetime_arg,
int expected_bits,
int export_size_delta,
int expected_export_status_arg,
/*whether reexport must give the original input exactly*/
int canonical_input)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_export_status = expected_export_status_arg;
psa_status_t status;
psa_key_lifetime_t lifetime = lifetime_arg;
unsigned char *exported = NULL;
unsigned char *reexported = NULL;
size_t export_size;
size_t exported_length = INVALID_EXPORT_LENGTH;
size_t reexported_length;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
export_size = (ptrdiff_t) data->len + export_size_delta;
TEST_CALLOC(exported, export_size);
if (!canonical_input) {
TEST_CALLOC(reexported, export_size);
}
PSA_ASSERT(psa_crypto_init());
psa_set_key_lifetime(&attributes, lifetime);
psa_set_key_usage_flags(&attributes, usage_arg);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
if (PSA_KEY_TYPE_IS_DH(type) &&
expected_export_status == PSA_ERROR_BUFFER_TOO_SMALL) {
/* Simulate that buffer is too small, by decreasing its size by 1 byte. */
export_size -= 1;
}
/* Import the key */
TEST_EQUAL(psa_import_key(&attributes, data->x, data->len, &key),
PSA_SUCCESS);
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), (size_t) expected_bits);
ASSERT_NO_SLOT_NUMBER(&got_attributes);
/* Export the key */
status = psa_export_key(key, exported, export_size, &exported_length);
TEST_EQUAL(status, expected_export_status);
/* The exported length must be set by psa_export_key() to a value between 0
* and export_size. On errors, the exported length must be 0. */
TEST_ASSERT(exported_length != INVALID_EXPORT_LENGTH);
TEST_ASSERT(status == PSA_SUCCESS || exported_length == 0);
TEST_LE_U(exported_length, export_size);
TEST_ASSERT(mem_is_char(exported + exported_length, 0,
export_size - exported_length));
if (status != PSA_SUCCESS) {
TEST_EQUAL(exported_length, 0);
goto destroy;
}
/* Run sanity checks on the exported key. For non-canonical inputs,
* this validates the canonical representations. For canonical inputs,
* this doesn't directly validate the implementation, but it still helps
* by cross-validating the test data with the sanity check code. */
if (!psa_key_lifetime_is_external(lifetime)) {
if (!mbedtls_test_psa_exercise_key(key, usage_arg, 0, 0)) {
goto exit;
}
}
if (canonical_input) {
TEST_MEMORY_COMPARE(data->x, data->len, exported, exported_length);
} else {
mbedtls_svc_key_id_t key2 = MBEDTLS_SVC_KEY_ID_INIT;
PSA_ASSERT(psa_import_key(&attributes, exported, exported_length,
&key2));
PSA_ASSERT(psa_export_key(key2,
reexported,
export_size,
&reexported_length));
TEST_MEMORY_COMPARE(exported, exported_length,
reexported, reexported_length);
PSA_ASSERT(psa_destroy_key(key2));
}
TEST_LE_U(exported_length,
PSA_EXPORT_KEY_OUTPUT_SIZE(type,
psa_get_key_bits(&got_attributes)));
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
TEST_LE_U(exported_length, PSA_EXPORT_KEY_PAIR_MAX_SIZE);
} else if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
TEST_LE_U(exported_length, PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
}
destroy:
/* Destroy the key */
PSA_ASSERT(psa_destroy_key(key));
test_operations_on_invalid_key(key);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_destroy_key(key);
mbedtls_free(exported);
mbedtls_free(reexported);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void import_export_public_key(data_t *data,
int type_arg, // key pair or public key
int alg_arg,
int lifetime_arg,
int export_size_delta,
int expected_export_status_arg,
data_t *expected_public_key)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_export_status = expected_export_status_arg;
psa_status_t status;
psa_key_lifetime_t lifetime = lifetime_arg;
unsigned char *exported = NULL;
size_t export_size = expected_public_key->len + export_size_delta;
size_t exported_length = INVALID_EXPORT_LENGTH;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_lifetime(&attributes, lifetime);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
/* Import the key */
PSA_ASSERT(psa_import_key(&attributes, data->x, data->len, &key));
/* Export the public key */
TEST_CALLOC(exported, export_size);
status = psa_export_public_key(key,
exported, export_size,
&exported_length);
TEST_EQUAL(status, expected_export_status);
if (status == PSA_SUCCESS) {
psa_key_type_t public_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type);
size_t bits;
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
bits = psa_get_key_bits(&attributes);
TEST_LE_U(expected_public_key->len,
PSA_EXPORT_KEY_OUTPUT_SIZE(public_type, bits));
TEST_LE_U(expected_public_key->len,
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(public_type, bits));
TEST_LE_U(expected_public_key->len,
PSA_EXPORT_PUBLIC_KEY_MAX_SIZE);
TEST_MEMORY_COMPARE(expected_public_key->x, expected_public_key->len,
exported, exported_length);
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
mbedtls_free(exported);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
#if defined(MBEDTLS_THREADING_PTHREAD)
/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD:MBEDTLS_PSA_CRYPTO_STORAGE_C */
void concurrently_use_same_persistent_key(data_t *data,
int type_arg,
int bits_arg,
int alg_arg,
int thread_count_arg)
{
size_t thread_count = (size_t) thread_count_arg;
mbedtls_test_thread_t *threads = NULL;
mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, 1);
same_key_context skc;
skc.data = data;
skc.key = key_id;
skc.type = type_arg;
skc.bits = bits_arg;
skc.key_loaded = 0;
mbedtls_mutex_init(&skc.key_loaded_mutex);
psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise(skc.type, alg_arg);
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_id(&attributes, key_id);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg_arg);
psa_set_key_type(&attributes, type_arg);
psa_set_key_bits(&attributes, bits_arg);
skc.attributes = &attributes;
TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
/* Test that when multiple threads import the same key,
* exactly one thread succeeds and the rest fail with valid errors.
* Also test that all threads can use the key as soon as it has been
* imported. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(
mbedtls_test_thread_create(&threads[i], thread_import_key,
(void *) &skc), 0);
}
/* Join threads. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
}
/* Test that when multiple threads use and destroy a key no corruption
* occurs, and exactly one thread succeeds when destroying the key. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(
mbedtls_test_thread_create(&threads[i], thread_use_and_destroy_key,
(void *) &skc), 0);
}
/* Join threads. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
}
/* Ensure that one thread succeeded in destroying the key. */
TEST_ASSERT(!skc.key_loaded);
exit:
psa_reset_key_attributes(&attributes);
mbedtls_mutex_free(&skc.key_loaded_mutex);
mbedtls_free(threads);
PSA_DONE();
}
/* END_CASE */
#endif
/* BEGIN_CASE */
void import_and_exercise_key(data_t *data,
int type_arg,
int bits_arg,
int alg_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
size_t bits = bits_arg;
psa_algorithm_t alg = alg_arg;
psa_key_usage_t usage = mbedtls_test_psa_usage_to_exercise(type, alg);
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
/* Import the key */
PSA_ASSERT(psa_import_key(&attributes, data->x, data->len, &key));
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
/* Do something with the key according to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
goto exit;
}
PSA_ASSERT(psa_destroy_key(key));
test_operations_on_invalid_key(key);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void effective_key_attributes(int type_arg, int expected_type_arg,
int bits_arg, int expected_bits_arg,
int usage_arg, int expected_usage_arg,
int alg_arg, int expected_alg_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = type_arg;
psa_key_type_t expected_key_type = expected_type_arg;
size_t bits = bits_arg;
size_t expected_bits = expected_bits_arg;
psa_algorithm_t alg = alg_arg;
psa_algorithm_t expected_alg = expected_alg_arg;
psa_key_usage_t usage = usage_arg;
psa_key_usage_t expected_usage = expected_usage_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
psa_set_key_bits(&attributes, bits);
PSA_ASSERT(psa_generate_key(&attributes, &key));
psa_reset_key_attributes(&attributes);
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
TEST_EQUAL(psa_get_key_type(&attributes), expected_key_type);
TEST_EQUAL(psa_get_key_bits(&attributes), expected_bits);
TEST_EQUAL(psa_get_key_usage_flags(&attributes), expected_usage);
TEST_EQUAL(psa_get_key_algorithm(&attributes), expected_alg);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void check_key_policy(int type_arg, int bits_arg,
int usage_arg, int alg_arg)
{
test_effective_key_attributes(type_arg, type_arg, bits_arg, bits_arg,
usage_arg,
mbedtls_test_update_key_usage_flags(usage_arg),
alg_arg, alg_arg);
goto exit;
}
/* END_CASE */
/* BEGIN_CASE */
void key_attributes_init()
{
/* Test each valid way of initializing the object, except for `= {0}`, as
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
* though it's OK by the C standard. We could test for this, but we'd need
* to suppress the Clang warning for the test. */
psa_key_attributes_t func = psa_key_attributes_init();
psa_key_attributes_t init = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t zero;
memset(&zero, 0, sizeof(zero));
TEST_EQUAL(psa_get_key_lifetime(&func), PSA_KEY_LIFETIME_VOLATILE);
TEST_EQUAL(psa_get_key_lifetime(&init), PSA_KEY_LIFETIME_VOLATILE);
TEST_EQUAL(psa_get_key_lifetime(&zero), PSA_KEY_LIFETIME_VOLATILE);
TEST_EQUAL(psa_get_key_type(&func), 0);
TEST_EQUAL(psa_get_key_type(&init), 0);
TEST_EQUAL(psa_get_key_type(&zero), 0);
TEST_EQUAL(psa_get_key_bits(&func), 0);
TEST_EQUAL(psa_get_key_bits(&init), 0);
TEST_EQUAL(psa_get_key_bits(&zero), 0);
TEST_EQUAL(psa_get_key_usage_flags(&func), 0);
TEST_EQUAL(psa_get_key_usage_flags(&init), 0);
TEST_EQUAL(psa_get_key_usage_flags(&zero), 0);
TEST_EQUAL(psa_get_key_algorithm(&func), 0);
TEST_EQUAL(psa_get_key_algorithm(&init), 0);
TEST_EQUAL(psa_get_key_algorithm(&zero), 0);
}
/* END_CASE */
/* BEGIN_CASE */
void mac_key_policy(int policy_usage_arg,
int policy_alg_arg,
int key_type_arg,
data_t *key_data,
int exercise_alg_arg,
int expected_status_sign_arg,
int expected_status_verify_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t policy_alg = policy_alg_arg;
psa_algorithm_t exercise_alg = exercise_alg_arg;
psa_key_usage_t policy_usage = policy_usage_arg;
psa_status_t status;
psa_status_t expected_status_sign = expected_status_sign_arg;
psa_status_t expected_status_verify = expected_status_verify_arg;
unsigned char mac[PSA_MAC_MAX_SIZE];
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
TEST_EQUAL(psa_get_key_usage_flags(&attributes),
mbedtls_test_update_key_usage_flags(policy_usage));
status = psa_mac_sign_setup(&operation, key, exercise_alg);
TEST_EQUAL(status, expected_status_sign);
/* Calculate the MAC, one-shot case. */
uint8_t input[128] = { 0 };
size_t mac_len;
TEST_EQUAL(psa_mac_compute(key, exercise_alg,
input, 128,
mac, PSA_MAC_MAX_SIZE, &mac_len),
expected_status_sign);
/* Calculate the MAC, multi-part case. */
PSA_ASSERT(psa_mac_abort(&operation));
status = psa_mac_sign_setup(&operation, key, exercise_alg);
if (status == PSA_SUCCESS) {
status = psa_mac_update(&operation, input, 128);
if (status == PSA_SUCCESS) {
TEST_EQUAL(psa_mac_sign_finish(&operation, mac, PSA_MAC_MAX_SIZE,
&mac_len),
expected_status_sign);
} else {
TEST_EQUAL(status, expected_status_sign);
}
} else {
TEST_EQUAL(status, expected_status_sign);
}
PSA_ASSERT(psa_mac_abort(&operation));
/* Verify correct MAC, one-shot case. */
status = psa_mac_verify(key, exercise_alg, input, 128,
mac, mac_len);
if (expected_status_sign != PSA_SUCCESS && expected_status_verify == PSA_SUCCESS) {
TEST_EQUAL(status, PSA_ERROR_INVALID_SIGNATURE);
} else {
TEST_EQUAL(status, expected_status_verify);
}
/* Verify correct MAC, multi-part case. */
status = psa_mac_verify_setup(&operation, key, exercise_alg);
if (status == PSA_SUCCESS) {
status = psa_mac_update(&operation, input, 128);
if (status == PSA_SUCCESS) {
status = psa_mac_verify_finish(&operation, mac, mac_len);
if (expected_status_sign != PSA_SUCCESS && expected_status_verify == PSA_SUCCESS) {
TEST_EQUAL(status, PSA_ERROR_INVALID_SIGNATURE);
} else {
TEST_EQUAL(status, expected_status_verify);
}
} else {
TEST_EQUAL(status, expected_status_verify);
}
} else {
TEST_EQUAL(status, expected_status_verify);
}
psa_mac_abort(&operation);
memset(mac, 0, sizeof(mac));
status = psa_mac_verify_setup(&operation, key, exercise_alg);
TEST_EQUAL(status, expected_status_verify);
exit:
psa_mac_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_key_policy(int policy_usage_arg,
int policy_alg,
int key_type,
data_t *key_data,
int exercise_alg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_usage_t policy_usage = policy_usage_arg;
size_t output_buffer_size = 0;
size_t input_buffer_size = 0;
size_t output_length = 0;
uint8_t *output = NULL;
uint8_t *input = NULL;
psa_status_t status;
input_buffer_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(exercise_alg);
output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, exercise_alg,
input_buffer_size);
TEST_CALLOC(input, input_buffer_size);
TEST_CALLOC(output, output_buffer_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* Check if no key usage flag implication is done */
TEST_EQUAL(policy_usage,
mbedtls_test_update_key_usage_flags(policy_usage));
/* Encrypt check, one-shot */
status = psa_cipher_encrypt(key, exercise_alg, input, input_buffer_size,
output, output_buffer_size,
&output_length);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_ENCRYPT) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
/* Encrypt check, multi-part */
status = psa_cipher_encrypt_setup(&operation, key, exercise_alg);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_ENCRYPT) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
psa_cipher_abort(&operation);
/* Decrypt check, one-shot */
status = psa_cipher_decrypt(key, exercise_alg, output, output_buffer_size,
input, input_buffer_size,
&output_length);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_DECRYPT) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
/* Decrypt check, multi-part */
status = psa_cipher_decrypt_setup(&operation, key, exercise_alg);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_DECRYPT) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
exit:
psa_cipher_abort(&operation);
mbedtls_free(input);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_key_policy(int policy_usage_arg,
int policy_alg,
int key_type,
data_t *key_data,
int nonce_length_arg,
int tag_length_arg,
int exercise_alg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_key_usage_t policy_usage = policy_usage_arg;
psa_status_t status;
psa_status_t expected_status = expected_status_arg;
unsigned char nonce[16] = { 0 };
size_t nonce_length = nonce_length_arg;
unsigned char tag[16];
size_t tag_length = tag_length_arg;
size_t output_length;
TEST_LE_U(nonce_length, sizeof(nonce));
TEST_LE_U(tag_length, sizeof(tag));
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* Check if no key usage implication is done */
TEST_EQUAL(policy_usage,
mbedtls_test_update_key_usage_flags(policy_usage));
/* Encrypt check, one-shot */
status = psa_aead_encrypt(key, exercise_alg,
nonce, nonce_length,
NULL, 0,
NULL, 0,
tag, tag_length,
&output_length);
if ((policy_usage & PSA_KEY_USAGE_ENCRYPT) != 0) {
TEST_EQUAL(status, expected_status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
/* Encrypt check, multi-part */
status = psa_aead_encrypt_setup(&operation, key, exercise_alg);
if ((policy_usage & PSA_KEY_USAGE_ENCRYPT) != 0) {
TEST_EQUAL(status, expected_status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
/* Decrypt check, one-shot */
memset(tag, 0, sizeof(tag));
status = psa_aead_decrypt(key, exercise_alg,
nonce, nonce_length,
NULL, 0,
tag, tag_length,
NULL, 0,
&output_length);
if ((policy_usage & PSA_KEY_USAGE_DECRYPT) == 0) {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
} else if (expected_status == PSA_SUCCESS) {
TEST_EQUAL(status, PSA_ERROR_INVALID_SIGNATURE);
} else {
TEST_EQUAL(status, expected_status);
}
/* Decrypt check, multi-part */
PSA_ASSERT(psa_aead_abort(&operation));
status = psa_aead_decrypt_setup(&operation, key, exercise_alg);
if ((policy_usage & PSA_KEY_USAGE_DECRYPT) == 0) {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
} else {
TEST_EQUAL(status, expected_status);
}
exit:
PSA_ASSERT(psa_aead_abort(&operation));
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_encryption_key_policy(int policy_usage_arg,
int policy_alg,
int key_type,
data_t *key_data,
int exercise_alg,
int use_opaque_key)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t policy_usage = policy_usage_arg;
psa_status_t status;
size_t key_bits;
size_t buffer_length;
unsigned char *buffer = NULL;
size_t output_length;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
if (use_opaque_key) {
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_VOLATILE, TEST_DRIVER_LOCATION));
}
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* Check if no key usage implication is done */
TEST_EQUAL(policy_usage,
mbedtls_test_update_key_usage_flags(policy_usage));
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
buffer_length = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits,
exercise_alg);
TEST_CALLOC(buffer, buffer_length);
status = psa_asymmetric_encrypt(key, exercise_alg,
NULL, 0,
NULL, 0,
buffer, buffer_length,
&output_length);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_ENCRYPT) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
if (buffer_length != 0) {
memset(buffer, 0, buffer_length);
}
status = psa_asymmetric_decrypt(key, exercise_alg,
buffer, buffer_length,
NULL, 0,
buffer, buffer_length,
&output_length);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_DECRYPT) != 0) {
TEST_EQUAL(status, PSA_ERROR_INVALID_PADDING);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
mbedtls_free(buffer);
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_signature_key_policy(int policy_usage_arg,
int policy_alg,
int key_type,
data_t *key_data,
int exercise_alg,
int payload_length_arg,
int expected_usage_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t policy_usage = policy_usage_arg;
psa_key_usage_t expected_usage = expected_usage_arg;
psa_status_t status;
unsigned char payload[PSA_HASH_MAX_SIZE] = { 1 };
/* If `payload_length_arg > 0`, `exercise_alg` is supposed to be
* compatible with the policy and `payload_length_arg` is supposed to be
* a valid input length to sign. If `payload_length_arg <= 0`,
* `exercise_alg` is supposed to be forbidden by the policy. */
int compatible_alg = payload_length_arg > 0;
size_t payload_length = compatible_alg ? payload_length_arg : 0;
unsigned char signature[PSA_SIGNATURE_MAX_SIZE] = { 0 };
size_t signature_length;
/* Check if all implicit usage flags are deployed
in the expected usage flags. */
TEST_EQUAL(expected_usage,
mbedtls_test_update_key_usage_flags(policy_usage));
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
TEST_EQUAL(psa_get_key_usage_flags(&attributes), expected_usage);
status = psa_sign_hash(key, exercise_alg,
payload, payload_length,
signature, sizeof(signature),
&signature_length);
if (compatible_alg && (expected_usage & PSA_KEY_USAGE_SIGN_HASH) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
memset(signature, 0, sizeof(signature));
status = psa_verify_hash(key, exercise_alg,
payload, payload_length,
signature, sizeof(signature));
if (compatible_alg && (expected_usage & PSA_KEY_USAGE_VERIFY_HASH) != 0) {
TEST_EQUAL(status, PSA_ERROR_INVALID_SIGNATURE);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
if (PSA_ALG_IS_SIGN_HASH(exercise_alg) &&
PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(exercise_alg))) {
status = psa_sign_message(key, exercise_alg,
payload, payload_length,
signature, sizeof(signature),
&signature_length);
if (compatible_alg && (expected_usage & PSA_KEY_USAGE_SIGN_MESSAGE) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
memset(signature, 0, sizeof(signature));
status = psa_verify_message(key, exercise_alg,
payload, payload_length,
signature, sizeof(signature));
if (compatible_alg && (expected_usage & PSA_KEY_USAGE_VERIFY_MESSAGE) != 0) {
TEST_EQUAL(status, PSA_ERROR_INVALID_SIGNATURE);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
}
exit:
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key_policy(int policy_usage,
int policy_alg,
int key_type,
data_t *key_data,
int exercise_alg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
PSA_ASSERT(psa_key_derivation_setup(&operation, exercise_alg));
if (PSA_ALG_IS_TLS12_PRF(exercise_alg) ||
PSA_ALG_IS_TLS12_PSK_TO_MS(exercise_alg)) {
PSA_ASSERT(psa_key_derivation_input_bytes(
&operation,
PSA_KEY_DERIVATION_INPUT_SEED,
(const uint8_t *) "", 0));
}
status = psa_key_derivation_input_key(&operation,
PSA_KEY_DERIVATION_INPUT_SECRET,
key);
if (policy_alg == exercise_alg &&
(policy_usage & PSA_KEY_USAGE_DERIVE) != 0) {
PSA_ASSERT(status);
} else {
TEST_EQUAL(status, PSA_ERROR_NOT_PERMITTED);
}
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void agreement_key_policy(int policy_usage,
int policy_alg,
int key_type_arg,
data_t *key_data,
int exercise_alg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type = key_type_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_status_t status;
psa_status_t expected_status = expected_status_arg;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
PSA_ASSERT(psa_key_derivation_setup(&operation, exercise_alg));
status = mbedtls_test_psa_key_agreement_with_self(&operation, key, 0);
TEST_EQUAL(status, expected_status);
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void key_policy_alg2(int key_type_arg, data_t *key_data,
int usage_arg, int alg_arg, int alg2_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t usage = usage_arg;
psa_algorithm_t alg = alg_arg;
psa_algorithm_t alg2 = alg2_arg;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_enrollment_algorithm(&attributes, alg2);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* Update the usage flags to obtain implicit usage flags */
usage = mbedtls_test_update_key_usage_flags(usage);
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_usage_flags(&got_attributes), usage);
TEST_EQUAL(psa_get_key_algorithm(&got_attributes), alg);
TEST_EQUAL(psa_get_key_enrollment_algorithm(&got_attributes), alg2);
if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
goto exit;
}
if (!mbedtls_test_psa_exercise_key(key, usage, alg2, 0)) {
goto exit;
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void raw_agreement_key_policy(int policy_usage,
int policy_alg,
int key_type_arg,
data_t *key_data,
int exercise_alg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type = key_type_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_status_t status;
psa_status_t expected_status = expected_status_arg;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, policy_usage);
psa_set_key_algorithm(&attributes, policy_alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
status = mbedtls_test_psa_raw_key_agreement_with_self(exercise_alg, key, 0);
TEST_EQUAL(status, expected_status);
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void copy_success(int source_usage_arg,
int source_alg_arg, int source_alg2_arg,
int source_lifetime_arg,
int type_arg, data_t *material,
int copy_attributes,
int target_usage_arg,
int target_alg_arg, int target_alg2_arg,
int target_lifetime_arg,
int expected_usage_arg,
int expected_alg_arg, int expected_alg2_arg)
{
psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t expected_usage = expected_usage_arg;
psa_algorithm_t expected_alg = expected_alg_arg;
psa_algorithm_t expected_alg2 = expected_alg2_arg;
psa_key_lifetime_t source_lifetime = source_lifetime_arg;
psa_key_lifetime_t target_lifetime = target_lifetime_arg;
mbedtls_svc_key_id_t source_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t target_key = MBEDTLS_SVC_KEY_ID_INIT;
uint8_t *export_buffer = NULL;
PSA_ASSERT(psa_crypto_init());
/* Prepare the source key. */
psa_set_key_usage_flags(&source_attributes, source_usage_arg);
psa_set_key_algorithm(&source_attributes, source_alg_arg);
psa_set_key_enrollment_algorithm(&source_attributes, source_alg2_arg);
psa_set_key_type(&source_attributes, type_arg);
psa_set_key_lifetime(&source_attributes, source_lifetime);
PSA_ASSERT(psa_import_key(&source_attributes,
material->x, material->len,
&source_key));
PSA_ASSERT(psa_get_key_attributes(source_key, &source_attributes));
/* Prepare the target attributes. */
if (copy_attributes) {
target_attributes = source_attributes;
}
psa_set_key_lifetime(&target_attributes, target_lifetime);
if (target_usage_arg != -1) {
psa_set_key_usage_flags(&target_attributes, target_usage_arg);
}
if (target_alg_arg != -1) {
psa_set_key_algorithm(&target_attributes, target_alg_arg);
}
if (target_alg2_arg != -1) {
psa_set_key_enrollment_algorithm(&target_attributes, target_alg2_arg);
}
/* Copy the key. */
PSA_ASSERT(psa_copy_key(source_key,
&target_attributes, &target_key));
/* Destroy the source to ensure that this doesn't affect the target. */
PSA_ASSERT(psa_destroy_key(source_key));
/* Test that the target slot has the expected content and policy. */
PSA_ASSERT(psa_get_key_attributes(target_key, &target_attributes));
TEST_EQUAL(psa_get_key_type(&source_attributes),
psa_get_key_type(&target_attributes));
TEST_EQUAL(psa_get_key_bits(&source_attributes),
psa_get_key_bits(&target_attributes));
TEST_EQUAL(expected_usage, psa_get_key_usage_flags(&target_attributes));
TEST_EQUAL(expected_alg, psa_get_key_algorithm(&target_attributes));
TEST_EQUAL(expected_alg2,
psa_get_key_enrollment_algorithm(&target_attributes));
if (expected_usage & PSA_KEY_USAGE_EXPORT) {
size_t length;
TEST_CALLOC(export_buffer, material->len);
PSA_ASSERT(psa_export_key(target_key, export_buffer,
material->len, &length));
TEST_MEMORY_COMPARE(material->x, material->len,
export_buffer, length);
}
if (!psa_key_lifetime_is_external(target_lifetime)) {
if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg, 0)) {
goto exit;
}
if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2, 0)) {
goto exit;
}
}
PSA_ASSERT(psa_destroy_key(target_key));
exit:
/*
* Source and target key attributes may have been returned by
* psa_get_key_attributes() thus reset them as required.
*/
psa_reset_key_attributes(&source_attributes);
psa_reset_key_attributes(&target_attributes);
PSA_DONE();
mbedtls_free(export_buffer);
}
/* END_CASE */
/* BEGIN_CASE */
void copy_fail(int source_usage_arg,
int source_alg_arg, int source_alg2_arg,
int source_lifetime_arg,
int type_arg, data_t *material,
int target_type_arg, int target_bits_arg,
int target_usage_arg,
int target_alg_arg, int target_alg2_arg,
int target_id_arg, int target_lifetime_arg,
int expected_status_arg)
{
psa_key_attributes_t source_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t target_attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t source_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t target_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, target_id_arg);
PSA_ASSERT(psa_crypto_init());
/* Prepare the source key. */
psa_set_key_usage_flags(&source_attributes, source_usage_arg);
psa_set_key_algorithm(&source_attributes, source_alg_arg);
psa_set_key_enrollment_algorithm(&source_attributes, source_alg2_arg);
psa_set_key_type(&source_attributes, type_arg);
psa_set_key_lifetime(&source_attributes, source_lifetime_arg);
PSA_ASSERT(psa_import_key(&source_attributes,
material->x, material->len,
&source_key));
/* Prepare the target attributes. */
psa_set_key_id(&target_attributes, key_id);
psa_set_key_lifetime(&target_attributes, target_lifetime_arg);
psa_set_key_type(&target_attributes, target_type_arg);
psa_set_key_bits(&target_attributes, target_bits_arg);
psa_set_key_usage_flags(&target_attributes, target_usage_arg);
psa_set_key_algorithm(&target_attributes, target_alg_arg);
psa_set_key_enrollment_algorithm(&target_attributes, target_alg2_arg);
/* Try to copy the key. */
TEST_EQUAL(psa_copy_key(source_key,
&target_attributes, &target_key),
expected_status_arg);
PSA_ASSERT(psa_destroy_key(source_key));
exit:
psa_reset_key_attributes(&source_attributes);
psa_reset_key_attributes(&target_attributes);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void hash_operation_init()
{
const uint8_t input[1] = { 0 };
/* Test each valid way of initializing the object, except for `= {0}`, as
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
* though it's OK by the C standard. We could test for this, but we'd need
* to suppress the Clang warning for the test. */
psa_hash_operation_t func = psa_hash_operation_init();
psa_hash_operation_t init = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t zero;
memset(&zero, 0, sizeof(zero));
/* A freshly-initialized hash operation should not be usable. */
TEST_EQUAL(psa_hash_update(&func, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_hash_update(&init, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_hash_update(&zero, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
/* A default hash operation should be abortable without error. */
PSA_ASSERT(psa_hash_abort(&func));
PSA_ASSERT(psa_hash_abort(&init));
PSA_ASSERT(psa_hash_abort(&zero));
}
/* END_CASE */
/* BEGIN_CASE */
void hash_setup(int alg_arg,
int expected_status_arg)
{
psa_algorithm_t alg = alg_arg;
uint8_t *output = NULL;
size_t output_size = 0;
size_t output_length = 0;
psa_status_t expected_status = expected_status_arg;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
/* Hash Setup, one-shot */
output_size = PSA_HASH_LENGTH(alg);
TEST_CALLOC(output, output_size);
status = psa_hash_compute(alg, NULL, 0,
output, output_size, &output_length);
TEST_EQUAL(status, expected_status);
/* Hash Setup, multi-part */
status = psa_hash_setup(&operation, alg);
TEST_EQUAL(status, expected_status);
/* Whether setup succeeded or failed, abort must succeed. */
PSA_ASSERT(psa_hash_abort(&operation));
/* If setup failed, reproduce the failure, so as to
* test the resulting state of the operation object. */
if (status != PSA_SUCCESS) {
TEST_EQUAL(psa_hash_setup(&operation, alg), status);
}
/* Now the operation object should be reusable. */
#if defined(KNOWN_SUPPORTED_HASH_ALG)
PSA_ASSERT(psa_hash_setup(&operation, KNOWN_SUPPORTED_HASH_ALG));
PSA_ASSERT(psa_hash_abort(&operation));
#endif
exit:
mbedtls_free(output);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void hash_compute_fail(int alg_arg, data_t *input,
int output_size_arg, int expected_status_arg)
{
psa_algorithm_t alg = alg_arg;
uint8_t *output = NULL;
size_t output_size = output_size_arg;
size_t output_length = INVALID_EXPORT_LENGTH;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t expected_status = expected_status_arg;
psa_status_t status;
TEST_CALLOC(output, output_size);
PSA_ASSERT(psa_crypto_init());
/* Hash Compute, one-shot */
status = psa_hash_compute(alg, input->x, input->len,
output, output_size, &output_length);
TEST_EQUAL(status, expected_status);
TEST_LE_U(output_length, output_size);
/* Hash Compute, multi-part */
status = psa_hash_setup(&operation, alg);
if (status == PSA_SUCCESS) {
status = psa_hash_update(&operation, input->x, input->len);
if (status == PSA_SUCCESS) {
status = psa_hash_finish(&operation, output, output_size,
&output_length);
if (status == PSA_SUCCESS) {
TEST_LE_U(output_length, output_size);
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
exit:
PSA_ASSERT(psa_hash_abort(&operation));
mbedtls_free(output);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void hash_compare_fail(int alg_arg, data_t *input,
data_t *reference_hash,
int expected_status_arg)
{
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
/* Hash Compare, one-shot */
status = psa_hash_compare(alg, input->x, input->len,
reference_hash->x, reference_hash->len);
TEST_EQUAL(status, expected_status);
/* Hash Compare, multi-part */
status = psa_hash_setup(&operation, alg);
if (status == PSA_SUCCESS) {
status = psa_hash_update(&operation, input->x, input->len);
if (status == PSA_SUCCESS) {
status = psa_hash_verify(&operation, reference_hash->x,
reference_hash->len);
TEST_EQUAL(status, expected_status);
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
exit:
PSA_ASSERT(psa_hash_abort(&operation));
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void hash_compute_compare(int alg_arg, data_t *input,
data_t *expected_output)
{
psa_algorithm_t alg = alg_arg;
uint8_t output[PSA_HASH_MAX_SIZE + 1];
size_t output_length = INVALID_EXPORT_LENGTH;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
size_t i;
PSA_ASSERT(psa_crypto_init());
/* Compute with tight buffer, one-shot */
PSA_ASSERT(psa_hash_compute(alg, input->x, input->len,
output, PSA_HASH_LENGTH(alg),
&output_length));
TEST_EQUAL(output_length, PSA_HASH_LENGTH(alg));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
/* Compute with tight buffer, multi-part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
PSA_ASSERT(psa_hash_finish(&operation, output,
PSA_HASH_LENGTH(alg),
&output_length));
TEST_EQUAL(output_length, PSA_HASH_LENGTH(alg));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
/* Compute with larger buffer, one-shot */
PSA_ASSERT(psa_hash_compute(alg, input->x, input->len,
output, sizeof(output),
&output_length));
TEST_EQUAL(output_length, PSA_HASH_LENGTH(alg));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
/* Compute with larger buffer, multi-part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
PSA_ASSERT(psa_hash_finish(&operation, output,
sizeof(output), &output_length));
TEST_EQUAL(output_length, PSA_HASH_LENGTH(alg));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
/* Compare with correct hash, one-shot */
PSA_ASSERT(psa_hash_compare(alg, input->x, input->len,
output, output_length));
/* Compare with correct hash, multi-part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
PSA_ASSERT(psa_hash_verify(&operation, output,
output_length));
/* Compare with trailing garbage, one-shot */
TEST_EQUAL(psa_hash_compare(alg, input->x, input->len,
output, output_length + 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Compare with trailing garbage, multi-part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
TEST_EQUAL(psa_hash_verify(&operation, output, output_length + 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Compare with truncated hash, one-shot */
TEST_EQUAL(psa_hash_compare(alg, input->x, input->len,
output, output_length - 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Compare with truncated hash, multi-part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
TEST_EQUAL(psa_hash_verify(&operation, output, output_length - 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Compare with corrupted value */
for (i = 0; i < output_length; i++) {
mbedtls_test_set_step(i);
output[i] ^= 1;
/* One-shot */
TEST_EQUAL(psa_hash_compare(alg, input->x, input->len,
output, output_length),
PSA_ERROR_INVALID_SIGNATURE);
/* Multi-Part */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_update(&operation, input->x, input->len));
TEST_EQUAL(psa_hash_verify(&operation, output, output_length),
PSA_ERROR_INVALID_SIGNATURE);
output[i] ^= 1;
}
exit:
PSA_ASSERT(psa_hash_abort(&operation));
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
void hash_bad_order()
{
psa_algorithm_t alg = PSA_ALG_SHA_256;
unsigned char input[] = "";
/* SHA-256 hash of an empty string */
const unsigned char valid_hash[] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
};
unsigned char hash[sizeof(valid_hash)] = { 0 };
size_t hash_len;
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
PSA_ASSERT(psa_crypto_init());
/* Call setup twice in a row. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_hash_setup(&operation, alg),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_hash_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call update without calling setup beforehand. */
TEST_EQUAL(psa_hash_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Check that update calls abort on error. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
operation.id = UINT_MAX;
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_hash_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_hash_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call update after finish. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len));
TEST_EQUAL(psa_hash_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call verify without calling setup beforehand. */
TEST_EQUAL(psa_hash_verify(&operation,
valid_hash, sizeof(valid_hash)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call verify after finish. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len));
TEST_EQUAL(psa_hash_verify(&operation,
valid_hash, sizeof(valid_hash)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call verify twice in a row. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
PSA_ASSERT(psa_hash_verify(&operation,
valid_hash, sizeof(valid_hash)));
ASSERT_OPERATION_IS_INACTIVE(operation);
TEST_EQUAL(psa_hash_verify(&operation,
valid_hash, sizeof(valid_hash)),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call finish without calling setup beforehand. */
TEST_EQUAL(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call finish twice in a row. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len));
TEST_EQUAL(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
/* Call finish after calling verify. */
PSA_ASSERT(psa_hash_setup(&operation, alg));
PSA_ASSERT(psa_hash_verify(&operation,
valid_hash, sizeof(valid_hash)));
TEST_EQUAL(psa_hash_finish(&operation,
hash, sizeof(hash), &hash_len),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_abort(&operation));
exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
void hash_verify_bad_args()
{
psa_algorithm_t alg = PSA_ALG_SHA_256;
/* SHA-256 hash of an empty string with 2 extra bytes (0xaa and 0xbb)
* appended to it */
unsigned char hash[] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, 0xaa, 0xbb
};
size_t expected_size = PSA_HASH_LENGTH(alg);
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
PSA_ASSERT(psa_crypto_init());
/* psa_hash_verify with a smaller hash than expected */
PSA_ASSERT(psa_hash_setup(&operation, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_hash_verify(&operation, hash, expected_size - 1),
PSA_ERROR_INVALID_SIGNATURE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_hash_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* psa_hash_verify with a non-matching hash */
PSA_ASSERT(psa_hash_setup(&operation, alg));
TEST_EQUAL(psa_hash_verify(&operation, hash + 1, expected_size),
PSA_ERROR_INVALID_SIGNATURE);
/* psa_hash_verify with a hash longer than expected */
PSA_ASSERT(psa_hash_setup(&operation, alg));
TEST_EQUAL(psa_hash_verify(&operation, hash, sizeof(hash)),
PSA_ERROR_INVALID_SIGNATURE);
exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
void hash_finish_bad_args()
{
psa_algorithm_t alg = PSA_ALG_SHA_256;
unsigned char hash[PSA_HASH_MAX_SIZE];
size_t expected_size = PSA_HASH_LENGTH(alg);
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
size_t hash_len;
PSA_ASSERT(psa_crypto_init());
/* psa_hash_finish with a smaller hash buffer than expected */
PSA_ASSERT(psa_hash_setup(&operation, alg));
TEST_EQUAL(psa_hash_finish(&operation,
hash, expected_size - 1, &hash_len),
PSA_ERROR_BUFFER_TOO_SMALL);
exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
void hash_clone_source_state()
{
psa_algorithm_t alg = PSA_ALG_SHA_256;
unsigned char hash[PSA_HASH_MAX_SIZE];
psa_hash_operation_t op_source = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
size_t hash_len;
PSA_ASSERT(psa_crypto_init());
PSA_ASSERT(psa_hash_setup(&op_source, alg));
PSA_ASSERT(psa_hash_setup(&op_setup, alg));
PSA_ASSERT(psa_hash_setup(&op_finished, alg));
PSA_ASSERT(psa_hash_finish(&op_finished,
hash, sizeof(hash), &hash_len));
PSA_ASSERT(psa_hash_setup(&op_aborted, alg));
PSA_ASSERT(psa_hash_abort(&op_aborted));
TEST_EQUAL(psa_hash_clone(&op_source, &op_setup),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_hash_clone(&op_source, &op_init));
PSA_ASSERT(psa_hash_finish(&op_init,
hash, sizeof(hash), &hash_len));
PSA_ASSERT(psa_hash_clone(&op_source, &op_finished));
PSA_ASSERT(psa_hash_finish(&op_finished,
hash, sizeof(hash), &hash_len));
PSA_ASSERT(psa_hash_clone(&op_source, &op_aborted));
PSA_ASSERT(psa_hash_finish(&op_aborted,
hash, sizeof(hash), &hash_len));
exit:
psa_hash_abort(&op_source);
psa_hash_abort(&op_init);
psa_hash_abort(&op_setup);
psa_hash_abort(&op_finished);
psa_hash_abort(&op_aborted);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256 */
void hash_clone_target_state()
{
psa_algorithm_t alg = PSA_ALG_SHA_256;
unsigned char hash[PSA_HASH_MAX_SIZE];
psa_hash_operation_t op_init = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_setup = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_finished = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_aborted = PSA_HASH_OPERATION_INIT;
psa_hash_operation_t op_target = PSA_HASH_OPERATION_INIT;
size_t hash_len;
PSA_ASSERT(psa_crypto_init());
PSA_ASSERT(psa_hash_setup(&op_setup, alg));
PSA_ASSERT(psa_hash_setup(&op_finished, alg));
PSA_ASSERT(psa_hash_finish(&op_finished,
hash, sizeof(hash), &hash_len));
PSA_ASSERT(psa_hash_setup(&op_aborted, alg));
PSA_ASSERT(psa_hash_abort(&op_aborted));
PSA_ASSERT(psa_hash_clone(&op_setup, &op_target));
PSA_ASSERT(psa_hash_finish(&op_target,
hash, sizeof(hash), &hash_len));
TEST_EQUAL(psa_hash_clone(&op_init, &op_target), PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_hash_clone(&op_finished, &op_target),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_hash_clone(&op_aborted, &op_target),
PSA_ERROR_BAD_STATE);
exit:
psa_hash_abort(&op_target);
psa_hash_abort(&op_init);
psa_hash_abort(&op_setup);
psa_hash_abort(&op_finished);
psa_hash_abort(&op_aborted);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void mac_operation_init()
{
const uint8_t input[1] = { 0 };
/* Test each valid way of initializing the object, except for `= {0}`, as
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
* though it's OK by the C standard. We could test for this, but we'd need
* to suppress the Clang warning for the test. */
psa_mac_operation_t func = psa_mac_operation_init();
psa_mac_operation_t init = PSA_MAC_OPERATION_INIT;
psa_mac_operation_t zero;
memset(&zero, 0, sizeof(zero));
/* A freshly-initialized MAC operation should not be usable. */
TEST_EQUAL(psa_mac_update(&func,
input, sizeof(input)),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_mac_update(&init,
input, sizeof(input)),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_mac_update(&zero,
input, sizeof(input)),
PSA_ERROR_BAD_STATE);
/* A default MAC operation should be abortable without error. */
PSA_ASSERT(psa_mac_abort(&func));
PSA_ASSERT(psa_mac_abort(&init));
PSA_ASSERT(psa_mac_abort(&zero));
}
/* END_CASE */
/* BEGIN_CASE */
void mac_setup(int key_type_arg,
data_t *key,
int alg_arg,
int expected_status_arg)
{
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
#if defined(KNOWN_SUPPORTED_MAC_ALG)
const uint8_t smoke_test_key_data[16] = "kkkkkkkkkkkkkkkk";
#endif
PSA_ASSERT(psa_crypto_init());
if (!exercise_mac_setup(key_type, key->x, key->len, alg,
&operation, &status)) {
goto exit;
}
TEST_EQUAL(status, expected_status);
/* The operation object should be reusable. */
#if defined(KNOWN_SUPPORTED_MAC_ALG)
if (!exercise_mac_setup(KNOWN_SUPPORTED_MAC_KEY_TYPE,
smoke_test_key_data,
sizeof(smoke_test_key_data),
KNOWN_SUPPORTED_MAC_ALG,
&operation, &status)) {
goto exit;
}
TEST_EQUAL(status, PSA_SUCCESS);
#endif
exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_HMAC:PSA_WANT_ALG_HMAC:PSA_WANT_ALG_SHA_256 */
void mac_bad_order()
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = PSA_KEY_TYPE_HMAC;
psa_algorithm_t alg = PSA_ALG_HMAC(PSA_ALG_SHA_256);
const uint8_t key_data[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa
};
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
uint8_t sign_mac[PSA_MAC_MAX_SIZE + 10] = { 0 };
size_t sign_mac_length = 0;
const uint8_t input[] = { 0xbb, 0xbb, 0xbb, 0xbb };
const uint8_t verify_mac[] = {
0x74, 0x65, 0x93, 0x8c, 0xeb, 0x1d, 0xb3, 0x76, 0x5a, 0x38, 0xe7, 0xdd,
0x85, 0xc5, 0xad, 0x4f, 0x07, 0xe7, 0xd5, 0xb2, 0x64, 0xf0, 0x1a, 0x1a,
0x2c, 0xf9, 0x18, 0xca, 0x59, 0x7e, 0x5d, 0xf6
};
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes, key_data, sizeof(key_data),
&key));
/* Call update without calling setup beforehand. */
TEST_EQUAL(psa_mac_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call sign finish without calling setup beforehand. */
TEST_EQUAL(psa_mac_sign_finish(&operation, sign_mac, sizeof(sign_mac),
&sign_mac_length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call verify finish without calling setup beforehand. */
TEST_EQUAL(psa_mac_verify_finish(&operation,
verify_mac, sizeof(verify_mac)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call setup twice in a row. */
PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_mac_sign_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_mac_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call update after sign finish. */
PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
PSA_ASSERT(psa_mac_sign_finish(&operation,
sign_mac, sizeof(sign_mac),
&sign_mac_length));
TEST_EQUAL(psa_mac_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call update after verify finish. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
PSA_ASSERT(psa_mac_verify_finish(&operation,
verify_mac, sizeof(verify_mac)));
TEST_EQUAL(psa_mac_update(&operation, input, sizeof(input)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call sign finish twice in a row. */
PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
PSA_ASSERT(psa_mac_sign_finish(&operation,
sign_mac, sizeof(sign_mac),
&sign_mac_length));
TEST_EQUAL(psa_mac_sign_finish(&operation,
sign_mac, sizeof(sign_mac),
&sign_mac_length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Call verify finish twice in a row. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
PSA_ASSERT(psa_mac_verify_finish(&operation,
verify_mac, sizeof(verify_mac)));
TEST_EQUAL(psa_mac_verify_finish(&operation,
verify_mac, sizeof(verify_mac)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_mac_abort(&operation));
/* Setup sign but try verify. */
PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_mac_verify_finish(&operation,
verify_mac, sizeof(verify_mac)),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_mac_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Setup verify but try sign. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation, input, sizeof(input)));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_mac_sign_finish(&operation,
sign_mac, sizeof(sign_mac),
&sign_mac_length),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_mac_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_destroy_key(key));
exit:
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void mac_sign_verify_multi(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input,
int is_verify,
data_t *expected_mac)
{
size_t data_part_len = 0;
for (data_part_len = 1; data_part_len <= input->len; data_part_len++) {
/* Split data into length(data_part_len) parts. */
mbedtls_test_set_step(2000 + data_part_len);
if (mac_multipart_internal_func(key_type_arg, key_data,
alg_arg,
input, data_part_len,
expected_mac,
is_verify, 0) == 0) {
break;
}
/* length(0) part, length(data_part_len) part, length(0) part... */
mbedtls_test_set_step(3000 + data_part_len);
if (mac_multipart_internal_func(key_type_arg, key_data,
alg_arg,
input, data_part_len,
expected_mac,
is_verify, 1) == 0) {
break;
}
}
/* Goto is required to silence warnings about unused labels, as we
* don't actually do any test assertions in this function. */
goto exit;
}
/* END_CASE */
/* BEGIN_CASE */
void mac_sign(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input,
data_t *expected_mac)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t *actual_mac = NULL;
size_t mac_buffer_size =
PSA_MAC_LENGTH(key_type, PSA_BYTES_TO_BITS(key_data->len), alg);
size_t mac_length = 0;
const size_t output_sizes_to_test[] = {
0,
1,
expected_mac->len - 1,
expected_mac->len,
expected_mac->len + 1,
};
TEST_LE_U(mac_buffer_size, PSA_MAC_MAX_SIZE);
/* We expect PSA_MAC_LENGTH to be exact. */
TEST_ASSERT(expected_mac->len == mac_buffer_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
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));
for (size_t i = 0; i < ARRAY_LENGTH(output_sizes_to_test); i++) {
const size_t output_size = output_sizes_to_test[i];
psa_status_t expected_status =
(output_size >= expected_mac->len ? PSA_SUCCESS :
PSA_ERROR_BUFFER_TOO_SMALL);
mbedtls_test_set_step(output_size);
TEST_CALLOC(actual_mac, output_size);
/* Calculate the MAC, one-shot case. */
TEST_EQUAL(psa_mac_compute(key, alg,
input->x, input->len,
actual_mac, output_size, &mac_length),
expected_status);
if (expected_status == PSA_SUCCESS) {
TEST_MEMORY_COMPARE(expected_mac->x, expected_mac->len,
actual_mac, mac_length);
}
if (output_size > 0) {
memset(actual_mac, 0, output_size);
}
/* Calculate the MAC, multi-part case. */
PSA_ASSERT(psa_mac_sign_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation,
input->x, input->len));
TEST_EQUAL(psa_mac_sign_finish(&operation,
actual_mac, output_size,
&mac_length),
expected_status);
PSA_ASSERT(psa_mac_abort(&operation));
if (expected_status == PSA_SUCCESS) {
TEST_MEMORY_COMPARE(expected_mac->x, expected_mac->len,
actual_mac, mac_length);
}
mbedtls_free(actual_mac);
actual_mac = NULL;
}
exit:
psa_mac_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
mbedtls_free(actual_mac);
}
/* END_CASE */
/* BEGIN_CASE */
void mac_verify(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input,
data_t *expected_mac)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t *perturbed_mac = NULL;
TEST_LE_U(expected_mac->len, PSA_MAC_MAX_SIZE);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
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));
/* Verify correct MAC, one-shot case. */
PSA_ASSERT(psa_mac_verify(key, alg, input->x, input->len,
expected_mac->x, expected_mac->len));
/* Verify correct MAC, multi-part case. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation,
input->x, input->len));
PSA_ASSERT(psa_mac_verify_finish(&operation,
expected_mac->x,
expected_mac->len));
/* Test a MAC that's too short, one-shot case. */
TEST_EQUAL(psa_mac_verify(key, alg,
input->x, input->len,
expected_mac->x,
expected_mac->len - 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Test a MAC that's too short, multi-part case. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation,
input->x, input->len));
TEST_EQUAL(psa_mac_verify_finish(&operation,
expected_mac->x,
expected_mac->len - 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Test a MAC that's too long, one-shot case. */
TEST_CALLOC(perturbed_mac, expected_mac->len + 1);
memcpy(perturbed_mac, expected_mac->x, expected_mac->len);
TEST_EQUAL(psa_mac_verify(key, alg,
input->x, input->len,
perturbed_mac, expected_mac->len + 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Test a MAC that's too long, multi-part case. */
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation,
input->x, input->len));
TEST_EQUAL(psa_mac_verify_finish(&operation,
perturbed_mac,
expected_mac->len + 1),
PSA_ERROR_INVALID_SIGNATURE);
/* Test changing one byte. */
for (size_t i = 0; i < expected_mac->len; i++) {
mbedtls_test_set_step(i);
perturbed_mac[i] ^= 1;
TEST_EQUAL(psa_mac_verify(key, alg,
input->x, input->len,
perturbed_mac, expected_mac->len),
PSA_ERROR_INVALID_SIGNATURE);
PSA_ASSERT(psa_mac_verify_setup(&operation, key, alg));
PSA_ASSERT(psa_mac_update(&operation,
input->x, input->len));
TEST_EQUAL(psa_mac_verify_finish(&operation,
perturbed_mac,
expected_mac->len),
PSA_ERROR_INVALID_SIGNATURE);
perturbed_mac[i] ^= 1;
}
exit:
psa_mac_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
mbedtls_free(perturbed_mac);
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_operation_init()
{
const uint8_t input[1] = { 0 };
unsigned char output[1] = { 0 };
size_t output_length;
/* Test each valid way of initializing the object, except for `= {0}`, as
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
* though it's OK by the C standard. We could test for this, but we'd need
* to suppress the Clang warning for the test. */
psa_cipher_operation_t func = psa_cipher_operation_init();
psa_cipher_operation_t init = PSA_CIPHER_OPERATION_INIT;
psa_cipher_operation_t zero;
memset(&zero, 0, sizeof(zero));
/* A freshly-initialized cipher operation should not be usable. */
TEST_EQUAL(psa_cipher_update(&func,
input, sizeof(input),
output, sizeof(output),
&output_length),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_cipher_update(&init,
input, sizeof(input),
output, sizeof(output),
&output_length),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_cipher_update(&zero,
input, sizeof(input),
output, sizeof(output),
&output_length),
PSA_ERROR_BAD_STATE);
/* A default cipher operation should be abortable without error. */
PSA_ASSERT(psa_cipher_abort(&func));
PSA_ASSERT(psa_cipher_abort(&init));
PSA_ASSERT(psa_cipher_abort(&zero));
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_setup(int key_type_arg,
data_t *key,
int alg_arg,
int expected_status_arg)
{
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_status_t status;
#if defined(KNOWN_SUPPORTED_CIPHER_ALG)
const uint8_t smoke_test_key_data[16] = "kkkkkkkkkkkkkkkk";
#endif
PSA_ASSERT(psa_crypto_init());
if (!exercise_cipher_setup(key_type, key->x, key->len, alg,
&operation, &status)) {
goto exit;
}
TEST_EQUAL(status, expected_status);
/* The operation object should be reusable. */
#if defined(KNOWN_SUPPORTED_CIPHER_ALG)
if (!exercise_cipher_setup(KNOWN_SUPPORTED_CIPHER_KEY_TYPE,
smoke_test_key_data,
sizeof(smoke_test_key_data),
KNOWN_SUPPORTED_CIPHER_ALG,
&operation, &status)) {
goto exit;
}
TEST_EQUAL(status, PSA_SUCCESS);
#endif
exit:
psa_cipher_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_CBC_PKCS7 */
void cipher_bad_order()
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = PSA_KEY_TYPE_AES;
psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
unsigned char iv[PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)] = { 0 };
const uint8_t key_data[] = {
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa
};
const uint8_t text[] = {
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb
};
uint8_t buffer[PSA_BLOCK_CIPHER_BLOCK_LENGTH(PSA_KEY_TYPE_AES)] = { 0 };
size_t length = 0;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | 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, sizeof(key_data),
&key));
/* Call encrypt setup twice in a row. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_encrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call decrypt setup twice in a row. */
PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_decrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Generate an IV without calling setup beforehand. */
TEST_EQUAL(psa_cipher_generate_iv(&operation,
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Generate an IV twice in a row. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_generate_iv(&operation,
buffer, sizeof(buffer),
&length));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_generate_iv(&operation,
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Generate an IV after it's already set. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_set_iv(&operation,
iv, sizeof(iv)));
TEST_EQUAL(psa_cipher_generate_iv(&operation,
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Set an IV without calling setup beforehand. */
TEST_EQUAL(psa_cipher_set_iv(&operation,
iv, sizeof(iv)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Set an IV after it's already set. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_set_iv(&operation,
iv, sizeof(iv)));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_set_iv(&operation,
iv, sizeof(iv)),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Set an IV after it's already generated. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_generate_iv(&operation,
buffer, sizeof(buffer),
&length));
TEST_EQUAL(psa_cipher_set_iv(&operation,
iv, sizeof(iv)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Call update without calling setup beforehand. */
TEST_EQUAL(psa_cipher_update(&operation,
text, sizeof(text),
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Call update without an IV where an IV is required. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_update(&operation,
text, sizeof(text),
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call update after finish. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_set_iv(&operation,
iv, sizeof(iv)));
PSA_ASSERT(psa_cipher_finish(&operation,
buffer, sizeof(buffer), &length));
TEST_EQUAL(psa_cipher_update(&operation,
text, sizeof(text),
buffer, sizeof(buffer),
&length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Call finish without calling setup beforehand. */
TEST_EQUAL(psa_cipher_finish(&operation,
buffer, sizeof(buffer), &length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
/* Call finish without an IV where an IV is required. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
/* Not calling update means we are encrypting an empty buffer, which is OK
* for cipher modes with padding. */
ASSERT_OPERATION_IS_ACTIVE(operation);
TEST_EQUAL(psa_cipher_finish(&operation,
buffer, sizeof(buffer), &length),
PSA_ERROR_BAD_STATE);
ASSERT_OPERATION_IS_INACTIVE(operation);
PSA_ASSERT(psa_cipher_abort(&operation));
ASSERT_OPERATION_IS_INACTIVE(operation);
/* Call finish twice in a row. */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_set_iv(&operation,
iv, sizeof(iv)));
PSA_ASSERT(psa_cipher_finish(&operation,
buffer, sizeof(buffer), &length));
TEST_EQUAL(psa_cipher_finish(&operation,
buffer, sizeof(buffer), &length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_abort(&operation));
PSA_ASSERT(psa_destroy_key(key));
exit:
psa_cipher_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_encrypt_fail(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *input,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
unsigned char iv[PSA_CIPHER_IV_MAX_SIZE] = { 0 };
size_t iv_size = PSA_CIPHER_IV_MAX_SIZE;
size_t iv_length = 0;
unsigned char *output = NULL;
size_t output_buffer_size = 0;
size_t output_length = 0;
size_t function_output_length;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
if (PSA_ERROR_BAD_STATE != expected_status) {
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg,
input->len);
TEST_CALLOC(output, output_buffer_size);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
}
/* Encrypt, one-shot */
status = psa_cipher_encrypt(key, alg, input->x, input->len, output,
output_buffer_size, &output_length);
TEST_EQUAL(status, expected_status);
/* Encrypt, multi-part */
status = psa_cipher_encrypt_setup(&operation, key, alg);
if (status == PSA_SUCCESS) {
if (alg != PSA_ALG_ECB_NO_PADDING) {
PSA_ASSERT(psa_cipher_generate_iv(&operation,
iv, iv_size,
&iv_length));
}
status = psa_cipher_update(&operation, input->x, input->len,
output, output_buffer_size,
&function_output_length);
if (status == PSA_SUCCESS) {
output_length += function_output_length;
status = psa_cipher_finish(&operation, output + output_length,
output_buffer_size - output_length,
&function_output_length);
TEST_EQUAL(status, expected_status);
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
exit:
psa_cipher_abort(&operation);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_encrypt_validate_iv_length(int alg, int key_type, data_t *key_data,
data_t *input, int iv_length,
int expected_result)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t output_buffer_size = 0;
unsigned char *output = NULL;
output_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len);
TEST_CALLOC(output, output_buffer_size);
PSA_ASSERT(psa_crypto_init());
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));
TEST_EQUAL(expected_result, psa_cipher_set_iv(&operation, output,
iv_length));
exit:
psa_cipher_abort(&operation);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_alg_without_iv(int alg_arg, int key_type_arg, data_t *key_data,
data_t *plaintext, data_t *ciphertext)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
uint8_t iv[1] = { 0x5a };
unsigned char *output = NULL;
size_t output_buffer_size = 0;
size_t output_length, length;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
/* Validate size macros */
TEST_LE_U(ciphertext->len,
PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext->len));
TEST_LE_U(PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext->len),
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(plaintext->len));
TEST_LE_U(plaintext->len,
PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext->len));
TEST_LE_U(PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, ciphertext->len),
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(ciphertext->len));
/* Set up key and output buffer */
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | 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_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg,
plaintext->len);
TEST_CALLOC(output, output_buffer_size);
/* set_iv() is not allowed */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_cipher_set_iv(&operation, iv, sizeof(iv)),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_cipher_set_iv(&operation, iv, sizeof(iv)),
PSA_ERROR_BAD_STATE);
/* generate_iv() is not allowed */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_cipher_generate_iv(&operation, iv, sizeof(iv),
&length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_cipher_generate_iv(&operation, iv, sizeof(iv),
&length),
PSA_ERROR_BAD_STATE);
/* Multipart encryption */
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
output_length = 0;
length = ~0;
PSA_ASSERT(psa_cipher_update(&operation,
plaintext->x, plaintext->len,
output, output_buffer_size,
&length));
TEST_LE_U(length, output_buffer_size);
output_length += length;
PSA_ASSERT(psa_cipher_finish(&operation,
mbedtls_buffer_offset(output, output_length),
output_buffer_size - output_length,
&length));
output_length += length;
TEST_MEMORY_COMPARE(ciphertext->x, ciphertext->len,
output, output_length);
/* Multipart encryption */
PSA_ASSERT(psa_cipher_decrypt_setup(&operation, key, alg));
output_length = 0;
length = ~0;
PSA_ASSERT(psa_cipher_update(&operation,
ciphertext->x, ciphertext->len,
output, output_buffer_size,
&length));
TEST_LE_U(length, output_buffer_size);
output_length += length;
PSA_ASSERT(psa_cipher_finish(&operation,
mbedtls_buffer_offset(output, output_length),
output_buffer_size - output_length,
&length));
output_length += length;
TEST_MEMORY_COMPARE(plaintext->x, plaintext->len,
output, output_length);
/* One-shot encryption */
output_length = ~0;
PSA_ASSERT(psa_cipher_encrypt(key, alg, plaintext->x, plaintext->len,
output, output_buffer_size,
&output_length));
TEST_MEMORY_COMPARE(ciphertext->x, ciphertext->len,
output, output_length);
/* One-shot decryption */
output_length = ~0;
PSA_ASSERT(psa_cipher_decrypt(key, alg, ciphertext->x, ciphertext->len,
output, output_buffer_size,
&output_length));
TEST_MEMORY_COMPARE(plaintext->x, plaintext->len,
output, output_length);
exit:
PSA_ASSERT(psa_cipher_abort(&operation));
mbedtls_free(output);
psa_cipher_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_bad_key(int alg_arg, int key_type_arg, data_t *key_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t key_type = key_type_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
/* Usage of either of these two size macros would cause divide by zero
* with incorrect key types previously. Input length should be irrelevant
* here. */
TEST_EQUAL(PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, 16),
0);
TEST_EQUAL(PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, 16), 0);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* Should fail due to invalid alg type (to support invalid key type).
* Encrypt or decrypt will end up in the same place. */
status = psa_cipher_encrypt_setup(&operation, key, alg);
TEST_EQUAL(status, PSA_ERROR_INVALID_ARGUMENT);
exit:
psa_cipher_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_encrypt_validation(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *input)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t iv_size = PSA_CIPHER_IV_LENGTH(key_type, alg);
unsigned char *output1 = NULL;
size_t output1_buffer_size = 0;
size_t output1_length = 0;
unsigned char *output2 = NULL;
size_t output2_buffer_size = 0;
size_t output2_length = 0;
size_t function_output_length = 0;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
output1_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len);
output2_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input->len) +
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(output1, output1_buffer_size);
TEST_CALLOC(output2, output2_buffer_size);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
/* The one-shot cipher encryption uses generated iv so validating
the output is not possible. Validating with multipart encryption. */
PSA_ASSERT(psa_cipher_encrypt(key, alg, input->x, input->len, output1,
output1_buffer_size, &output1_length));
TEST_LE_U(output1_length,
PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len));
TEST_LE_U(output1_length,
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input->len));
PSA_ASSERT(psa_cipher_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_cipher_set_iv(&operation, output1, iv_size));
PSA_ASSERT(psa_cipher_update(&operation,
input->x, input->len,
output2, output2_buffer_size,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input->len));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input->len));
output2_length += function_output_length;
PSA_ASSERT(psa_cipher_finish(&operation,
output2 + output2_length,
output2_buffer_size - output2_length,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE);
output2_length += function_output_length;
PSA_ASSERT(psa_cipher_abort(&operation));
TEST_MEMORY_COMPARE(output1 + iv_size, output1_length - iv_size,
output2, output2_length);
exit:
psa_cipher_abort(&operation);
mbedtls_free(output1);
mbedtls_free(output2);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_encrypt_multipart(int alg_arg, int key_type_arg,
data_t *key_data, data_t *iv,
data_t *input,
int first_part_size_arg,
int output1_length_arg, int output2_length_arg,
data_t *expected_output,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t status;
psa_status_t expected_status = expected_status_arg;
size_t first_part_size = first_part_size_arg;
size_t output1_length = output1_length_arg;
size_t output2_length = output2_length_arg;
unsigned char *output = NULL;
size_t output_buffer_size = 0;
size_t function_output_length = 0;
size_t total_output_length = 0;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
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));
if (iv->len > 0) {
PSA_ASSERT(psa_cipher_set_iv(&operation, iv->x, iv->len));
}
output_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input->len) +
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(output, output_buffer_size);
TEST_LE_U(first_part_size, input->len);
PSA_ASSERT(psa_cipher_update(&operation, input->x, first_part_size,
output, output_buffer_size,
&function_output_length));
TEST_ASSERT(function_output_length == output1_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(first_part_size));
total_output_length += function_output_length;
if (first_part_size < input->len) {
PSA_ASSERT(psa_cipher_update(&operation,
input->x + first_part_size,
input->len - first_part_size,
(output_buffer_size == 0 ? NULL :
output + total_output_length),
output_buffer_size - total_output_length,
&function_output_length));
TEST_ASSERT(function_output_length == output2_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
alg,
input->len - first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input->len));
total_output_length += function_output_length;
}
status = psa_cipher_finish(&operation,
(output_buffer_size == 0 ? NULL :
output + total_output_length),
output_buffer_size - total_output_length,
&function_output_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE);
total_output_length += function_output_length;
TEST_EQUAL(status, expected_status);
if (expected_status == PSA_SUCCESS) {
PSA_ASSERT(psa_cipher_abort(&operation));
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
output, total_output_length);
}
exit:
psa_cipher_abort(&operation);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_decrypt_multipart(int alg_arg, int key_type_arg,
data_t *key_data, data_t *iv,
data_t *input,
int first_part_size_arg,
int output1_length_arg, int output2_length_arg,
data_t *expected_output,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t status;
psa_status_t expected_status = expected_status_arg;
size_t first_part_size = first_part_size_arg;
size_t output1_length = output1_length_arg;
size_t output2_length = output2_length_arg;
unsigned char *output = NULL;
size_t output_buffer_size = 0;
size_t function_output_length = 0;
size_t total_output_length = 0;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
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));
if (iv->len > 0) {
PSA_ASSERT(psa_cipher_set_iv(&operation, iv->x, iv->len));
}
output_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input->len) +
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(output, output_buffer_size);
TEST_LE_U(first_part_size, input->len);
PSA_ASSERT(psa_cipher_update(&operation,
input->x, first_part_size,
output, output_buffer_size,
&function_output_length));
TEST_ASSERT(function_output_length == output1_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(first_part_size));
total_output_length += function_output_length;
if (first_part_size < input->len) {
PSA_ASSERT(psa_cipher_update(&operation,
input->x + first_part_size,
input->len - first_part_size,
(output_buffer_size == 0 ? NULL :
output + total_output_length),
output_buffer_size - total_output_length,
&function_output_length));
TEST_ASSERT(function_output_length == output2_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
alg,
input->len - first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input->len));
total_output_length += function_output_length;
}
status = psa_cipher_finish(&operation,
(output_buffer_size == 0 ? NULL :
output + total_output_length),
output_buffer_size - total_output_length,
&function_output_length);
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE);
total_output_length += function_output_length;
TEST_EQUAL(status, expected_status);
if (expected_status == PSA_SUCCESS) {
PSA_ASSERT(psa_cipher_abort(&operation));
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
output, total_output_length);
}
exit:
psa_cipher_abort(&operation);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_decrypt_fail(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *iv,
data_t *input_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
unsigned char *input = NULL;
size_t input_buffer_size = 0;
unsigned char *output = NULL;
unsigned char *output_multi = NULL;
size_t output_buffer_size = 0;
size_t output_length = 0;
size_t function_output_length;
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
if (PSA_ERROR_BAD_STATE != expected_status) {
PSA_ASSERT(psa_crypto_init());
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));
}
/* Allocate input buffer and copy the iv and the plaintext */
input_buffer_size = ((size_t) input_arg->len + (size_t) iv->len);
if (input_buffer_size > 0) {
TEST_CALLOC(input, input_buffer_size);
memcpy(input, iv->x, iv->len);
memcpy(input + iv->len, input_arg->x, input_arg->len);
}
output_buffer_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_buffer_size);
TEST_CALLOC(output, output_buffer_size);
/* Decrypt, one-short */
status = psa_cipher_decrypt(key, alg, input, input_buffer_size, output,
output_buffer_size, &output_length);
TEST_EQUAL(status, expected_status);
/* Decrypt, multi-part */
status = psa_cipher_decrypt_setup(&operation, key, alg);
if (status == PSA_SUCCESS) {
output_buffer_size = PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg,
input_arg->len) +
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(output_multi, output_buffer_size);
if (iv->len > 0) {
status = psa_cipher_set_iv(&operation, iv->x, iv->len);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_status);
}
}
if (status == PSA_SUCCESS) {
status = psa_cipher_update(&operation,
input_arg->x, input_arg->len,
output_multi, output_buffer_size,
&function_output_length);
if (status == PSA_SUCCESS) {
output_length = function_output_length;
status = psa_cipher_finish(&operation,
output_multi + output_length,
output_buffer_size - output_length,
&function_output_length);
TEST_EQUAL(status, expected_status);
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
} else {
TEST_EQUAL(status, expected_status);
}
exit:
psa_cipher_abort(&operation);
mbedtls_free(input);
mbedtls_free(output);
mbedtls_free(output_multi);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_decrypt(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *iv,
data_t *input_arg,
data_t *expected_output)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
unsigned char *input = NULL;
size_t input_buffer_size = 0;
unsigned char *output = NULL;
size_t output_buffer_size = 0;
size_t output_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
/* Allocate input buffer and copy the iv and the plaintext */
input_buffer_size = ((size_t) input_arg->len + (size_t) iv->len);
if (input_buffer_size > 0) {
TEST_CALLOC(input, input_buffer_size);
memcpy(input, iv->x, iv->len);
memcpy(input + iv->len, input_arg->x, input_arg->len);
}
output_buffer_size = PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_buffer_size);
TEST_CALLOC(output, output_buffer_size);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
PSA_ASSERT(psa_cipher_decrypt(key, alg, input, input_buffer_size, output,
output_buffer_size, &output_length));
TEST_LE_U(output_length,
PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_buffer_size));
TEST_LE_U(output_length,
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(input_buffer_size));
TEST_MEMORY_COMPARE(expected_output->x, expected_output->len,
output, output_length);
exit:
mbedtls_free(input);
mbedtls_free(output);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_verify_output(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *input)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
unsigned char *output1 = NULL;
size_t output1_size = 0;
size_t output1_length = 0;
unsigned char *output2 = NULL;
size_t output2_size = 0;
size_t output2_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | 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));
output1_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len);
TEST_CALLOC(output1, output1_size);
PSA_ASSERT(psa_cipher_encrypt(key, alg, input->x, input->len,
output1, output1_size,
&output1_length));
TEST_LE_U(output1_length,
PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len));
TEST_LE_U(output1_length,
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input->len));
output2_size = output1_length;
TEST_CALLOC(output2, output2_size);
PSA_ASSERT(psa_cipher_decrypt(key, alg, output1, output1_length,
output2, output2_size,
&output2_length));
TEST_LE_U(output2_length,
PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, output1_length));
TEST_LE_U(output2_length,
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(output1_length));
TEST_MEMORY_COMPARE(input->x, input->len, output2, output2_length);
exit:
mbedtls_free(output1);
mbedtls_free(output2);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_verify_output_multipart(int alg_arg,
int key_type_arg,
data_t *key_data,
data_t *input,
int first_part_size_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t first_part_size = first_part_size_arg;
unsigned char iv[16] = { 0 };
size_t iv_size = 16;
size_t iv_length = 0;
unsigned char *output1 = NULL;
size_t output1_buffer_size = 0;
size_t output1_length = 0;
unsigned char *output2 = NULL;
size_t output2_buffer_size = 0;
size_t output2_length = 0;
size_t function_output_length;
psa_cipher_operation_t operation1 = PSA_CIPHER_OPERATION_INIT;
psa_cipher_operation_t operation2 = PSA_CIPHER_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | 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_encrypt_setup(&operation1, key, alg));
PSA_ASSERT(psa_cipher_decrypt_setup(&operation2, key, alg));
if (alg != PSA_ALG_ECB_NO_PADDING) {
PSA_ASSERT(psa_cipher_generate_iv(&operation1,
iv, iv_size,
&iv_length));
}
output1_buffer_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input->len);
TEST_LE_U(output1_buffer_size,
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input->len));
TEST_CALLOC(output1, output1_buffer_size);
TEST_LE_U(first_part_size, input->len);
PSA_ASSERT(psa_cipher_update(&operation1, input->x, first_part_size,
output1, output1_buffer_size,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(first_part_size));
output1_length += function_output_length;
PSA_ASSERT(psa_cipher_update(&operation1,
input->x + first_part_size,
input->len - first_part_size,
output1, output1_buffer_size,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
alg,
input->len - first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(input->len - first_part_size));
output1_length += function_output_length;
PSA_ASSERT(psa_cipher_finish(&operation1,
output1 + output1_length,
output1_buffer_size - output1_length,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE);
output1_length += function_output_length;
PSA_ASSERT(psa_cipher_abort(&operation1));
output2_buffer_size = output1_length;
TEST_LE_U(output2_buffer_size,
PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, output1_length));
TEST_LE_U(output2_buffer_size,
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE(output1_length));
TEST_CALLOC(output2, output2_buffer_size);
if (iv_length > 0) {
PSA_ASSERT(psa_cipher_set_iv(&operation2,
iv, iv_length));
}
PSA_ASSERT(psa_cipher_update(&operation2, output1, first_part_size,
output2, output2_buffer_size,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(first_part_size));
output2_length += function_output_length;
PSA_ASSERT(psa_cipher_update(&operation2,
output1 + first_part_size,
output1_length - first_part_size,
output2, output2_buffer_size,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type,
alg,
output1_length - first_part_size));
TEST_LE_U(function_output_length,
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE(output1_length - first_part_size));
output2_length += function_output_length;
PSA_ASSERT(psa_cipher_finish(&operation2,
output2 + output2_length,
output2_buffer_size - output2_length,
&function_output_length));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_SIZE(key_type, alg));
TEST_LE_U(function_output_length,
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE);
output2_length += function_output_length;
PSA_ASSERT(psa_cipher_abort(&operation2));
TEST_MEMORY_COMPARE(input->x, input->len, output2, output2_length);
exit:
psa_cipher_abort(&operation1);
psa_cipher_abort(&operation2);
mbedtls_free(output1);
mbedtls_free(output2);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_encrypt_decrypt(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
int expected_result_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *output_data = NULL;
size_t output_size = 0;
size_t output_length = 0;
unsigned char *output_data2 = NULL;
size_t output_length2 = 0;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_result = expected_result_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | 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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
output_size = input_data->len + PSA_AEAD_TAG_LENGTH(key_type, key_bits,
alg);
/* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
* should be exact. */
if (expected_result != PSA_ERROR_INVALID_ARGUMENT &&
expected_result != PSA_ERROR_NOT_SUPPORTED) {
TEST_EQUAL(output_size,
PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_data->len));
TEST_LE_U(output_size,
PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(input_data->len));
}
TEST_CALLOC(output_data, output_size);
status = psa_aead_encrypt(key, alg,
nonce->x, nonce->len,
additional_data->x,
additional_data->len,
input_data->x, input_data->len,
output_data, output_size,
&output_length);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
TEST_EQUAL(status, expected_result);
if (PSA_SUCCESS == expected_result) {
TEST_CALLOC(output_data2, output_length);
/* For all currently defined algorithms, PSA_AEAD_DECRYPT_OUTPUT_SIZE
* should be exact. */
TEST_EQUAL(input_data->len,
PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, output_length));
TEST_LE_U(input_data->len,
PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(output_length));
TEST_EQUAL(psa_aead_decrypt(key, alg,
nonce->x, nonce->len,
additional_data->x,
additional_data->len,
output_data, output_length,
output_data2, output_length,
&output_length2),
expected_result);
TEST_MEMORY_COMPARE(input_data->x, input_data->len,
output_data2, output_length2);
}
exit:
psa_destroy_key(key);
mbedtls_free(output_data);
mbedtls_free(output_data2);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_encrypt(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
data_t *expected_result)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *output_data = NULL;
size_t output_size = 0;
size_t output_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
output_size = input_data->len + PSA_AEAD_TAG_LENGTH(key_type, key_bits,
alg);
/* For all currently defined algorithms, PSA_AEAD_ENCRYPT_OUTPUT_SIZE
* should be exact. */
TEST_EQUAL(output_size,
PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_data->len));
TEST_LE_U(output_size,
PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(input_data->len));
TEST_CALLOC(output_data, output_size);
status = psa_aead_encrypt(key, alg,
nonce->x, nonce->len,
additional_data->x, additional_data->len,
input_data->x, input_data->len,
output_data, output_size,
&output_length);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
PSA_ASSERT(status);
TEST_MEMORY_COMPARE(expected_result->x, expected_result->len,
output_data, output_length);
exit:
psa_destroy_key(key);
mbedtls_free(output_data);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_decrypt(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
data_t *expected_data,
int expected_result_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *output_data = NULL;
size_t output_size = 0;
size_t output_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t expected_result = expected_result_arg;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
output_size = input_data->len - PSA_AEAD_TAG_LENGTH(key_type, key_bits,
alg);
if (expected_result != PSA_ERROR_INVALID_ARGUMENT &&
expected_result != PSA_ERROR_NOT_SUPPORTED) {
/* For all currently defined algorithms, PSA_AEAD_DECRYPT_OUTPUT_SIZE
* should be exact. */
TEST_EQUAL(output_size,
PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg, input_data->len));
TEST_LE_U(output_size,
PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(input_data->len));
}
TEST_CALLOC(output_data, output_size);
status = psa_aead_decrypt(key, alg,
nonce->x, nonce->len,
additional_data->x,
additional_data->len,
input_data->x, input_data->len,
output_data, output_size,
&output_length);
/* If the operation is not supported, just skip and not fail in case the
* decryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
TEST_EQUAL(status, expected_result);
if (expected_result == PSA_SUCCESS) {
TEST_MEMORY_COMPARE(expected_data->x, expected_data->len,
output_data, output_length);
}
exit:
psa_destroy_key(key);
mbedtls_free(output_data);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_encrypt(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
int do_set_lengths,
data_t *expected_output)
{
size_t ad_part_len = 0;
size_t data_part_len = 0;
set_lengths_method_t set_lengths_method = DO_NOT_SET_LENGTHS;
for (ad_part_len = 1; ad_part_len <= additional_data->len; ad_part_len++) {
mbedtls_test_set_step(ad_part_len);
if (do_set_lengths) {
if (ad_part_len & 0x01) {
set_lengths_method = SET_LENGTHS_AFTER_NONCE;
} else {
set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
}
}
/* Split ad into length(ad_part_len) parts. */
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data,
ad_part_len,
input_data, -1,
set_lengths_method,
expected_output,
1, 0)) {
break;
}
/* length(0) part, length(ad_part_len) part, length(0) part... */
mbedtls_test_set_step(1000 + ad_part_len);
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data,
ad_part_len,
input_data, -1,
set_lengths_method,
expected_output,
1, 1)) {
break;
}
}
for (data_part_len = 1; data_part_len <= input_data->len; data_part_len++) {
/* Split data into length(data_part_len) parts. */
mbedtls_test_set_step(2000 + data_part_len);
if (do_set_lengths) {
if (data_part_len & 0x01) {
set_lengths_method = SET_LENGTHS_AFTER_NONCE;
} else {
set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
}
}
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
set_lengths_method,
expected_output,
1, 0)) {
break;
}
/* length(0) part, length(data_part_len) part, length(0) part... */
mbedtls_test_set_step(3000 + data_part_len);
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
set_lengths_method,
expected_output,
1, 1)) {
break;
}
}
/* Goto is required to silence warnings about unused labels, as we
* don't actually do any test assertions in this function. */
goto exit;
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_decrypt(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
int do_set_lengths,
data_t *expected_output)
{
size_t ad_part_len = 0;
size_t data_part_len = 0;
set_lengths_method_t set_lengths_method = DO_NOT_SET_LENGTHS;
for (ad_part_len = 1; ad_part_len <= additional_data->len; ad_part_len++) {
/* Split ad into length(ad_part_len) parts. */
mbedtls_test_set_step(ad_part_len);
if (do_set_lengths) {
if (ad_part_len & 0x01) {
set_lengths_method = SET_LENGTHS_AFTER_NONCE;
} else {
set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
}
}
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data,
ad_part_len,
input_data, -1,
set_lengths_method,
expected_output,
0, 0)) {
break;
}
/* length(0) part, length(ad_part_len) part, length(0) part... */
mbedtls_test_set_step(1000 + ad_part_len);
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data,
ad_part_len,
input_data, -1,
set_lengths_method,
expected_output,
0, 1)) {
break;
}
}
for (data_part_len = 1; data_part_len <= input_data->len; data_part_len++) {
/* Split data into length(data_part_len) parts. */
mbedtls_test_set_step(2000 + data_part_len);
if (do_set_lengths) {
if (data_part_len & 0x01) {
set_lengths_method = SET_LENGTHS_AFTER_NONCE;
} else {
set_lengths_method = SET_LENGTHS_BEFORE_NONCE;
}
}
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
set_lengths_method,
expected_output,
0, 0)) {
break;
}
/* length(0) part, length(data_part_len) part, length(0) part... */
mbedtls_test_set_step(3000 + data_part_len);
if (!aead_multipart_internal_func(key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
set_lengths_method,
expected_output,
0, 1)) {
break;
}
}
/* Goto is required to silence warnings about unused labels, as we
* don't actually do any test assertions in this function. */
goto exit;
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_generate_nonce(int key_type_arg, data_t *key_data,
int alg_arg,
int nonce_length,
int expected_nonce_length_arg,
data_t *additional_data,
data_t *input_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE];
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
size_t actual_nonce_length = 0;
size_t expected_nonce_length = expected_nonce_length_arg;
unsigned char *output = NULL;
unsigned char *ciphertext = NULL;
size_t output_size = 0;
size_t ciphertext_size = 0;
size_t ciphertext_length = 0;
size_t tag_length = 0;
uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_data->len);
TEST_CALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(ciphertext_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
TEST_CALLOC(ciphertext, ciphertext_size);
status = psa_aead_encrypt_setup(&operation, key, alg);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce_length);
}
PSA_ASSERT(status);
status = psa_aead_generate_nonce(&operation, nonce_buffer,
nonce_length,
&actual_nonce_length);
TEST_EQUAL(status, expected_status);
TEST_EQUAL(actual_nonce_length, expected_nonce_length);
if (expected_status == PSA_SUCCESS) {
TEST_EQUAL(actual_nonce_length, PSA_AEAD_NONCE_LENGTH(key_type,
alg));
}
TEST_LE_U(actual_nonce_length, PSA_AEAD_NONCE_MAX_SIZE);
if (expected_status == PSA_SUCCESS) {
/* Ensure we can still complete operation. */
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
PSA_ASSERT(psa_aead_update(&operation, input_data->x, input_data->len,
output, output_size,
&ciphertext_length));
PSA_ASSERT(psa_aead_finish(&operation, ciphertext, ciphertext_size,
&ciphertext_length, tag_buffer,
PSA_AEAD_TAG_MAX_SIZE, &tag_length));
}
exit:
psa_destroy_key(key);
mbedtls_free(output);
mbedtls_free(ciphertext);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_set_nonce(int key_type_arg, data_t *key_data,
int alg_arg,
int nonce_length_arg,
int set_lengths_method_arg,
data_t *additional_data,
data_t *input_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
uint8_t *nonce_buffer = NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
unsigned char *output = NULL;
unsigned char *ciphertext = NULL;
size_t nonce_length;
size_t output_size = 0;
size_t ciphertext_size = 0;
size_t ciphertext_length = 0;
size_t tag_length = 0;
uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
size_t index = 0;
set_lengths_method_t set_lengths_method = set_lengths_method_arg;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_data->len);
TEST_CALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(ciphertext_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
TEST_CALLOC(ciphertext, ciphertext_size);
status = psa_aead_encrypt_setup(&operation, key, alg);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce_length_arg);
}
PSA_ASSERT(status);
/* -1 == zero length and valid buffer, 0 = zero length and NULL buffer. */
if (nonce_length_arg == -1) {
/* Arbitrary size buffer, to test zero length valid buffer. */
TEST_CALLOC(nonce_buffer, 4);
nonce_length = 0;
} else {
/* If length is zero, then this will return NULL. */
nonce_length = (size_t) nonce_length_arg;
TEST_CALLOC(nonce_buffer, nonce_length);
if (nonce_buffer) {
for (index = 0; index < nonce_length - 1; ++index) {
nonce_buffer[index] = 'a' + index;
}
}
}
if (set_lengths_method == SET_LENGTHS_BEFORE_NONCE) {
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
}
status = psa_aead_set_nonce(&operation, nonce_buffer, nonce_length);
TEST_EQUAL(status, expected_status);
if (expected_status == PSA_SUCCESS) {
if (set_lengths_method == SET_LENGTHS_AFTER_NONCE) {
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
}
if (operation.alg == PSA_ALG_CCM && set_lengths_method == DO_NOT_SET_LENGTHS) {
expected_status = PSA_ERROR_BAD_STATE;
}
/* Ensure we can still complete operation, unless it's CCM and we didn't set lengths. */
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
expected_status);
TEST_EQUAL(psa_aead_update(&operation, input_data->x, input_data->len,
output, output_size,
&ciphertext_length),
expected_status);
TEST_EQUAL(psa_aead_finish(&operation, ciphertext, ciphertext_size,
&ciphertext_length, tag_buffer,
PSA_AEAD_TAG_MAX_SIZE, &tag_length),
expected_status);
}
exit:
psa_destroy_key(key);
mbedtls_free(output);
mbedtls_free(ciphertext);
mbedtls_free(nonce_buffer);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_update_buffer_test(int key_type_arg, data_t *key_data,
int alg_arg,
int output_size_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
unsigned char *output = NULL;
unsigned char *ciphertext = NULL;
size_t output_size = output_size_arg;
size_t ciphertext_size = 0;
size_t ciphertext_length = 0;
size_t tag_length = 0;
uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
TEST_CALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(ciphertext, ciphertext_size);
status = psa_aead_encrypt_setup(&operation, key, alg);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
PSA_ASSERT(status);
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
status = psa_aead_update(&operation, input_data->x, input_data->len,
output, output_size, &ciphertext_length);
TEST_EQUAL(status, expected_status);
if (expected_status == PSA_SUCCESS) {
/* Ensure we can still complete operation. */
PSA_ASSERT(psa_aead_finish(&operation, ciphertext, ciphertext_size,
&ciphertext_length, tag_buffer,
PSA_AEAD_TAG_MAX_SIZE, &tag_length));
}
exit:
psa_destroy_key(key);
mbedtls_free(output);
mbedtls_free(ciphertext);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_finish_buffer_test(int key_type_arg, data_t *key_data,
int alg_arg,
int finish_ciphertext_size_arg,
int tag_size_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
unsigned char *ciphertext = NULL;
unsigned char *finish_ciphertext = NULL;
unsigned char *tag_buffer = NULL;
size_t ciphertext_size = 0;
size_t ciphertext_length = 0;
size_t finish_ciphertext_size = (size_t) finish_ciphertext_size_arg;
size_t tag_size = (size_t) tag_size_arg;
size_t tag_length = 0;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
ciphertext_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_data->len);
TEST_CALLOC(ciphertext, ciphertext_size);
TEST_CALLOC(finish_ciphertext, finish_ciphertext_size);
TEST_CALLOC(tag_buffer, tag_size);
status = psa_aead_encrypt_setup(&operation, key, alg);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
PSA_ASSERT(status);
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
PSA_ASSERT(psa_aead_update(&operation, input_data->x, input_data->len,
ciphertext, ciphertext_size, &ciphertext_length));
/* Ensure we can still complete operation. */
status = psa_aead_finish(&operation, finish_ciphertext,
finish_ciphertext_size,
&ciphertext_length, tag_buffer,
tag_size, &tag_length);
TEST_EQUAL(status, expected_status);
exit:
psa_destroy_key(key);
mbedtls_free(ciphertext);
mbedtls_free(finish_ciphertext);
mbedtls_free(tag_buffer);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_verify(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data,
data_t *tag,
int tag_usage_arg,
int expected_setup_status_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
psa_status_t expected_setup_status = expected_setup_status_arg;
unsigned char *plaintext = NULL;
unsigned char *finish_plaintext = NULL;
size_t plaintext_size = 0;
size_t plaintext_length = 0;
size_t verify_plaintext_size = 0;
tag_usage_method_t tag_usage = tag_usage_arg;
unsigned char *tag_buffer = NULL;
size_t tag_size = 0;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
plaintext_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg,
input_data->len);
TEST_CALLOC(plaintext, plaintext_size);
verify_plaintext_size = PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg);
TEST_CALLOC(finish_plaintext, verify_plaintext_size);
status = psa_aead_decrypt_setup(&operation, key, alg);
/* If the operation is not supported, just skip and not fail in case the
* encryption involves a common limitation of cryptography hardwares and
* an alternative implementation. */
if (status == PSA_ERROR_NOT_SUPPORTED) {
MBEDTLS_TEST_PSA_SKIP_IF_ALT_AES_192(key_type, key_data->len * 8);
MBEDTLS_TEST_PSA_SKIP_IF_ALT_GCM_NOT_12BYTES_NONCE(alg, nonce->len);
}
TEST_EQUAL(status, expected_setup_status);
if (status != PSA_SUCCESS) {
goto exit;
}
PSA_ASSERT(status);
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
status = psa_aead_set_lengths(&operation, additional_data->len,
input_data->len);
PSA_ASSERT(status);
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
input_data->len,
plaintext, plaintext_size,
&plaintext_length));
if (tag_usage == USE_GIVEN_TAG) {
tag_buffer = tag->x;
tag_size = tag->len;
}
status = psa_aead_verify(&operation, finish_plaintext,
verify_plaintext_size,
&plaintext_length,
tag_buffer, tag_size);
TEST_EQUAL(status, expected_status);
exit:
psa_destroy_key(key);
mbedtls_free(plaintext);
mbedtls_free(finish_plaintext);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_setup(int key_type_arg, data_t *key_data,
int alg_arg, int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
psa_status_t expected_status = expected_status_arg;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | 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));
status = psa_aead_encrypt_setup(&operation, key, alg);
TEST_EQUAL(status, expected_status);
psa_aead_abort(&operation);
status = psa_aead_decrypt_setup(&operation, key, alg);
TEST_EQUAL(status, expected_status);
exit:
psa_destroy_key(key);
psa_aead_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void aead_multipart_state_test(int key_type_arg, data_t *key_data,
int alg_arg,
data_t *nonce,
data_t *additional_data,
data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT;
unsigned char *output_data = NULL;
unsigned char *final_data = NULL;
size_t output_size = 0;
size_t finish_output_size = 0;
size_t output_length = 0;
size_t key_bits = 0;
size_t tag_length = 0;
size_t tag_size = 0;
size_t nonce_length = 0;
uint8_t nonce_buffer[PSA_AEAD_NONCE_MAX_SIZE];
uint8_t tag_buffer[PSA_AEAD_TAG_MAX_SIZE];
size_t output_part_length = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | 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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
tag_length = PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg);
TEST_LE_U(tag_length, PSA_AEAD_TAG_MAX_SIZE);
output_size = PSA_AEAD_UPDATE_OUTPUT_SIZE(key_type, alg, input_data->len);
TEST_CALLOC(output_data, output_size);
finish_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(finish_output_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
TEST_CALLOC(final_data, finish_output_size);
/* Test all operations error without calling setup first. */
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
TEST_EQUAL(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
TEST_EQUAL(psa_aead_verify(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer,
tag_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for double setups. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_encrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_decrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_decrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_encrypt_setup(&operation, key, alg),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for not setting a nonce. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_verify(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer,
tag_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for double setting nonce. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for double generating nonce. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for generate nonce then set and vice versa */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for generating nonce after calling set lengths */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
psa_aead_abort(&operation);
/* Test for generating nonce after calling set lengths with UINT32_MAX ad_data length */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
}
psa_aead_abort(&operation);
/* Test for generating nonce after calling set lengths with SIZE_MAX ad_data length */
#if SIZE_MAX > UINT32_MAX
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
if (operation.alg == PSA_ALG_CCM || operation.alg == PSA_ALG_GCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, SIZE_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, SIZE_MAX,
input_data->len));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
}
psa_aead_abort(&operation);
#endif
/* Test for calling set lengths with a UINT32_MAX ad_data length, after generating nonce */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len));
}
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
/* Test for setting nonce after calling set lengths */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
psa_aead_abort(&operation);
/* Test for setting nonce after calling set lengths with UINT32_MAX ad_data length */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
}
psa_aead_abort(&operation);
/* Test for setting nonce after calling set lengths with SIZE_MAX ad_data length */
#if SIZE_MAX > UINT32_MAX
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
if (operation.alg == PSA_ALG_CCM || operation.alg == PSA_ALG_GCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, SIZE_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, SIZE_MAX,
input_data->len));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
}
psa_aead_abort(&operation);
#endif
/* Test for calling set lengths with an ad_data length of UINT32_MAX, after setting nonce */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len),
PSA_ERROR_INVALID_ARGUMENT);
} else {
PSA_ASSERT(psa_aead_set_lengths(&operation, UINT32_MAX,
input_data->len));
}
psa_aead_abort(&operation);
/* Test for setting nonce after calling set lengths with plaintext length of SIZE_MAX */
#if SIZE_MAX > UINT32_MAX
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
if (operation.alg == PSA_ALG_GCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
SIZE_MAX),
PSA_ERROR_INVALID_ARGUMENT);
TEST_EQUAL(psa_aead_set_nonce(&operation, nonce->x, nonce->len),
PSA_ERROR_BAD_STATE);
} else if (operation.alg != PSA_ALG_CCM) {
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
SIZE_MAX));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
}
psa_aead_abort(&operation);
#endif
/* Test for calling set lengths with a plaintext length of SIZE_MAX, after setting nonce */
#if SIZE_MAX > UINT32_MAX
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg == PSA_ALG_GCM) {
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
SIZE_MAX),
PSA_ERROR_INVALID_ARGUMENT);
} else if (operation.alg != PSA_ALG_CCM) {
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
SIZE_MAX));
}
psa_aead_abort(&operation);
#endif
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for generating nonce in decrypt setup. */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
TEST_EQUAL(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for setting lengths twice. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test for setting lengths after setting nonce + already starting data. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg == PSA_ALG_CCM) {
PSA_ASSERT(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size));
} else {
PSA_ASSERT(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* Test for setting lengths after generating nonce + already starting data. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
if (operation.alg == PSA_ALG_CCM) {
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_BAD_STATE);
} else {
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_generate_nonce(&operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length));
if (operation.alg == PSA_ALG_CCM) {
PSA_ASSERT(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size));
} else {
PSA_ASSERT(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size));
TEST_EQUAL(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* Test for not sending any additional data or data after setting non zero
* lengths for them. (encrypt) */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
TEST_EQUAL(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test for not sending any additional data or data after setting non-zero
* lengths for them. (decrypt) */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
TEST_EQUAL(psa_aead_verify(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer,
tag_length),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test for not sending any additional data after setting a non-zero length
* for it. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test for not sending any data after setting a non-zero length for it.*/
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
TEST_EQUAL(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test for sending too much additional data after setting lengths. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, 0, 0));
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
1),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test for sending too much data after setting lengths. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, 0, 0));
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* ------------------------------------------------------- */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
PSA_ASSERT(psa_aead_set_lengths(&operation, additional_data->len,
input_data->len));
PSA_ASSERT(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len));
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length));
TEST_EQUAL(psa_aead_update(&operation, input_data->x,
1, output_data,
output_size, &output_length),
PSA_ERROR_INVALID_ARGUMENT);
psa_aead_abort(&operation);
/* Test sending additional data after data. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
if (operation.alg != PSA_ALG_CCM) {
PSA_ASSERT(psa_aead_update(&operation, input_data->x,
input_data->len, output_data,
output_size, &output_length));
TEST_EQUAL(psa_aead_update_ad(&operation, additional_data->x,
additional_data->len),
PSA_ERROR_BAD_STATE);
}
psa_aead_abort(&operation);
/* Test calling finish on decryption. */
PSA_ASSERT(psa_aead_decrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
TEST_EQUAL(psa_aead_finish(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer, tag_length,
&tag_size),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
/* Test calling verify on encryption. */
PSA_ASSERT(psa_aead_encrypt_setup(&operation, key, alg));
PSA_ASSERT(psa_aead_set_nonce(&operation, nonce->x, nonce->len));
TEST_EQUAL(psa_aead_verify(&operation, final_data,
finish_output_size,
&output_part_length,
tag_buffer,
tag_length),
PSA_ERROR_BAD_STATE);
psa_aead_abort(&operation);
exit:
psa_destroy_key(key);
psa_aead_abort(&operation);
mbedtls_free(output_data);
mbedtls_free(final_data);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void signature_size(int type_arg,
int bits,
int alg_arg,
int expected_size_arg)
{
psa_key_type_t type = type_arg;
psa_algorithm_t alg = alg_arg;
size_t actual_size = PSA_SIGN_OUTPUT_SIZE(type, bits, alg);
TEST_EQUAL(actual_size, (size_t) expected_size_arg);
exit:
;
}
/* END_CASE */
/* BEGIN_CASE */
void sign_hash_deterministic(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data,
data_t *output_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
/* Perform the signature. */
PSA_ASSERT(psa_sign_hash(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length));
/* Verify that the signature is what is expected. */
TEST_MEMORY_COMPARE(output_data->x, output_data->len,
signature, signature_length);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* sign_hash_interruptible() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test interruptible sign hash with known outcomes (deterministic ECDSA
* and private keys / keypairs only).
*
* 2. Test the number of calls to psa_sign_hash_complete() required are as
* expected for different max_ops values.
*
* 3. Test that the number of ops done prior to start and after abort is zero
* and that each successful stage completes some ops (this is not mandated by
* the PSA specification, but is currently the case).
*
* 4. Test that calling psa_sign_hash_get_num_ops() multiple times between
* complete() calls does not alter the number of ops returned.
*/
void sign_hash_interruptible(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data,
data_t *output_data, int max_ops_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_OPERATION_INCOMPLETE;
uint32_t num_ops = 0;
uint32_t max_ops = max_ops_arg;
size_t num_ops_prior = 0;
size_t num_completes = 0;
size_t min_completes = 0;
size_t max_completes = 0;
psa_sign_hash_interruptible_operation_t operation =
psa_sign_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
psa_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
&min_completes, &max_completes);
num_ops_prior = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Start performing the signature. */
PSA_ASSERT(psa_sign_hash_start(&operation, key, alg,
input_data->x, input_data->len));
num_ops_prior = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Continue performing the signature until complete. */
do {
status = psa_sign_hash_complete(&operation, signature, signature_size,
&signature_length);
num_completes++;
if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
num_ops = psa_sign_hash_get_num_ops(&operation);
/* We are asserting here that every complete makes progress
* (completes some ops), which is true of the internal
* implementation and probably any implementation, however this is
* not mandated by the PSA specification. */
TEST_ASSERT(num_ops > num_ops_prior);
num_ops_prior = num_ops;
/* Ensure calling get_num_ops() twice still returns the same
* number of ops as previously reported. */
num_ops = psa_sign_hash_get_num_ops(&operation);
TEST_EQUAL(num_ops, num_ops_prior);
}
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_SUCCESS);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
/* Verify that the signature is what is expected. */
TEST_MEMORY_COMPARE(output_data->x, output_data->len,
signature, signature_length);
PSA_ASSERT(psa_sign_hash_abort(&operation));
num_ops = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops == 0);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void sign_hash_fail(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data,
int signature_size_arg, int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t signature_size = signature_size_arg;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
unsigned char *signature = NULL;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
TEST_CALLOC(signature, signature_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
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));
actual_status = psa_sign_hash(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length);
TEST_EQUAL(actual_status, expected_status);
/* The value of *signature_length is unspecified on error, but
* whatever it is, it should be less than signature_size, so that
* if the caller tries to read *signature_length bytes without
* checking the error code then they don't overflow a buffer. */
TEST_LE_U(signature_length, signature_size);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* sign_hash_fail_interruptible() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test that various failure cases for interruptible sign hash fail with the
* correct error codes, and at the correct point (at start or during
* complete).
*
* 2. Test the number of calls to psa_sign_hash_complete() required are as
* expected for different max_ops values.
*
* 3. Test that the number of ops done prior to start and after abort is zero
* and that each successful stage completes some ops (this is not mandated by
* the PSA specification, but is currently the case).
*
* 4. Check that calling complete() when start() fails and complete()
* after completion results in a BAD_STATE error.
*
* 5. Check that calling start() again after start fails results in a BAD_STATE
* error.
*/
void sign_hash_fail_interruptible(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data,
int signature_size_arg,
int expected_start_status_arg,
int expected_complete_status_arg,
int max_ops_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t signature_size = signature_size_arg;
psa_status_t actual_status;
psa_status_t expected_start_status = expected_start_status_arg;
psa_status_t expected_complete_status = expected_complete_status_arg;
unsigned char *signature = NULL;
size_t signature_length = 0xdeadbeef;
uint32_t num_ops = 0;
uint32_t max_ops = max_ops_arg;
size_t num_ops_prior = 0;
size_t num_completes = 0;
size_t min_completes = 0;
size_t max_completes = 0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_sign_hash_interruptible_operation_t operation =
psa_sign_hash_interruptible_operation_init();
TEST_CALLOC(signature, signature_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
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_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops,
expected_complete_status,
&min_completes,
&max_completes);
num_ops_prior = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Start performing the signature. */
actual_status = psa_sign_hash_start(&operation, key, alg,
input_data->x, input_data->len);
TEST_EQUAL(actual_status, expected_start_status);
if (expected_start_status != PSA_SUCCESS) {
/* Emulate poor application code, and call complete anyway, even though
* start failed. */
actual_status = psa_sign_hash_complete(&operation, signature,
signature_size,
&signature_length);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
/* Test that calling start again after failure also causes BAD_STATE. */
actual_status = psa_sign_hash_start(&operation, key, alg,
input_data->x, input_data->len);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
}
num_ops_prior = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Continue performing the signature until complete. */
do {
actual_status = psa_sign_hash_complete(&operation, signature,
signature_size,
&signature_length);
num_completes++;
if (actual_status == PSA_SUCCESS ||
actual_status == PSA_OPERATION_INCOMPLETE) {
num_ops = psa_sign_hash_get_num_ops(&operation);
/* We are asserting here that every complete makes progress
* (completes some ops), which is true of the internal
* implementation and probably any implementation, however this is
* not mandated by the PSA specification. */
TEST_ASSERT(num_ops > num_ops_prior);
num_ops_prior = num_ops;
}
} while (actual_status == PSA_OPERATION_INCOMPLETE);
TEST_EQUAL(actual_status, expected_complete_status);
/* Check that another complete returns BAD_STATE. */
actual_status = psa_sign_hash_complete(&operation, signature,
signature_size,
&signature_length);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_sign_hash_abort(&operation));
num_ops = psa_sign_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops == 0);
/* The value of *signature_length is unspecified on error, but
* whatever it is, it should be less than signature_size, so that
* if the caller tries to read *signature_length bytes without
* checking the error code then they don't overflow a buffer. */
TEST_LE_U(signature_length, signature_size);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void sign_verify_hash(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_VERIFY_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
/* Perform the signature. */
PSA_ASSERT(psa_sign_hash(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length));
/* Check that the signature length looks sensible. */
TEST_LE_U(signature_length, signature_size);
TEST_ASSERT(signature_length > 0);
/* Use the library to verify that the signature is correct. */
PSA_ASSERT(psa_verify_hash(key, alg,
input_data->x, input_data->len,
signature, signature_length));
if (input_data->len != 0) {
/* Flip a bit in the input and verify that the signature is now
* detected as invalid. Flip a bit at the beginning, not at the end,
* because ECDSA may ignore the last few bits of the input. */
input_data->x[0] ^= 1;
TEST_EQUAL(psa_verify_hash(key, alg,
input_data->x, input_data->len,
signature, signature_length),
PSA_ERROR_INVALID_SIGNATURE);
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* sign_verify_hash_interruptible() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test that we can sign an input hash with the given keypair and then
* afterwards verify that signature. This is currently the only way to test
* non deterministic ECDSA, but this test can also handle deterministic.
*
* 2. Test that after corrupting the hash, the verification detects an invalid
* signature.
*
* 3. Test the number of calls to psa_sign_hash_complete() required are as
* expected for different max_ops values.
*
* 4. Test that the number of ops done prior to starting signing and after abort
* is zero and that each successful signing stage completes some ops (this is
* not mandated by the PSA specification, but is currently the case).
*/
void sign_verify_hash_interruptible(int key_type_arg, data_t *key_data,
int alg_arg, data_t *input_data,
int max_ops_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_OPERATION_INCOMPLETE;
uint32_t max_ops = max_ops_arg;
uint32_t num_ops = 0;
uint32_t num_ops_prior = 0;
size_t num_completes = 0;
size_t min_completes = 0;
size_t max_completes = 0;
psa_sign_hash_interruptible_operation_t sign_operation =
psa_sign_hash_interruptible_operation_init();
psa_verify_hash_interruptible_operation_t verify_operation =
psa_verify_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
psa_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
&min_completes, &max_completes);
num_ops_prior = psa_sign_hash_get_num_ops(&sign_operation);
TEST_ASSERT(num_ops_prior == 0);
/* Start performing the signature. */
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
num_ops_prior = psa_sign_hash_get_num_ops(&sign_operation);
TEST_ASSERT(num_ops_prior == 0);
/* Continue performing the signature until complete. */
do {
status = psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length);
num_completes++;
if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
num_ops = psa_sign_hash_get_num_ops(&sign_operation);
/* We are asserting here that every complete makes progress
* (completes some ops), which is true of the internal
* implementation and probably any implementation, however this is
* not mandated by the PSA specification. */
TEST_ASSERT(num_ops > num_ops_prior);
num_ops_prior = num_ops;
}
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_SUCCESS);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
num_ops = psa_sign_hash_get_num_ops(&sign_operation);
TEST_ASSERT(num_ops == 0);
/* Check that the signature length looks sensible. */
TEST_LE_U(signature_length, signature_size);
TEST_ASSERT(signature_length > 0);
num_completes = 0;
/* Start verification. */
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
/* Continue performing the signature until complete. */
do {
status = psa_verify_hash_complete(&verify_operation);
num_completes++;
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_SUCCESS);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
verify_operation = psa_verify_hash_interruptible_operation_init();
if (input_data->len != 0) {
/* Flip a bit in the input and verify that the signature is now
* detected as invalid. Flip a bit at the beginning, not at the end,
* because ECDSA may ignore the last few bits of the input. */
input_data->x[0] ^= 1;
/* Start verification. */
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
/* Continue performing the signature until complete. */
do {
status = psa_verify_hash_complete(&verify_operation);
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_ERROR_INVALID_SIGNATURE);
}
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void verify_hash(int key_type_arg, data_t *key_data,
int alg_arg, data_t *hash_data,
data_t *signature_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
TEST_LE_U(signature_data->len, PSA_SIGNATURE_MAX_SIZE);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
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_verify_hash(key, alg,
hash_data->x, hash_data->len,
signature_data->x, signature_data->len));
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* verify_hash_interruptible() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test interruptible verify hash with known outcomes (deterministic ECDSA
* only). Given this test only does verification it can accept public keys as
* well as private keys / keypairs.
*
* 2. Test the number of calls to psa_verify_hash_complete() required are as
* expected for different max_ops values.
*
* 3. Test that the number of ops done prior to start and after abort is zero
* and that each successful stage completes some ops (this is not mandated by
* the PSA specification, but is currently the case).
*
* 4. Test that calling psa_sign_hash_get_num_ops() multiple times between
* complete() calls does not alter the number of ops returned.
*
* 5. Test that after corrupting the hash, the verification detects an invalid
* signature.
*/
void verify_hash_interruptible(int key_type_arg, data_t *key_data,
int alg_arg, data_t *hash_data,
data_t *signature_data, int max_ops_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status = PSA_OPERATION_INCOMPLETE;
uint32_t num_ops = 0;
uint32_t max_ops = max_ops_arg;
size_t num_ops_prior = 0;
size_t num_completes = 0;
size_t min_completes = 0;
size_t max_completes = 0;
psa_verify_hash_interruptible_operation_t operation =
psa_verify_hash_interruptible_operation_init();
TEST_LE_U(signature_data->len, PSA_SIGNATURE_MAX_SIZE);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
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_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
&min_completes, &max_completes);
num_ops_prior = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Start verification. */
PSA_ASSERT(psa_verify_hash_start(&operation, key, alg,
hash_data->x, hash_data->len,
signature_data->x, signature_data->len)
);
num_ops_prior = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Continue performing the signature until complete. */
do {
status = psa_verify_hash_complete(&operation);
num_completes++;
if (status == PSA_SUCCESS || status == PSA_OPERATION_INCOMPLETE) {
num_ops = psa_verify_hash_get_num_ops(&operation);
/* We are asserting here that every complete makes progress
* (completes some ops), which is true of the internal
* implementation and probably any implementation, however this is
* not mandated by the PSA specification. */
TEST_ASSERT(num_ops > num_ops_prior);
num_ops_prior = num_ops;
/* Ensure calling get_num_ops() twice still returns the same
* number of ops as previously reported. */
num_ops = psa_verify_hash_get_num_ops(&operation);
TEST_EQUAL(num_ops, num_ops_prior);
}
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_SUCCESS);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
PSA_ASSERT(psa_verify_hash_abort(&operation));
num_ops = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops == 0);
if (hash_data->len != 0) {
/* Flip a bit in the hash and verify that the signature is now detected
* as invalid. Flip a bit at the beginning, not at the end, because
* ECDSA may ignore the last few bits of the input. */
hash_data->x[0] ^= 1;
/* Start verification. */
PSA_ASSERT(psa_verify_hash_start(&operation, key, alg,
hash_data->x, hash_data->len,
signature_data->x, signature_data->len));
/* Continue performing the signature until complete. */
do {
status = psa_verify_hash_complete(&operation);
} while (status == PSA_OPERATION_INCOMPLETE);
TEST_ASSERT(status == PSA_ERROR_INVALID_SIGNATURE);
}
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void verify_hash_fail(int key_type_arg, data_t *key_data,
int alg_arg, data_t *hash_data,
data_t *signature_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
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));
actual_status = psa_verify_hash(key, alg,
hash_data->x, hash_data->len,
signature_data->x, signature_data->len);
TEST_EQUAL(actual_status, expected_status);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* verify_hash_fail_interruptible() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test that various failure cases for interruptible verify hash fail with
* the correct error codes, and at the correct point (at start or during
* complete).
*
* 2. Test the number of calls to psa_verify_hash_complete() required are as
* expected for different max_ops values.
*
* 3. Test that the number of ops done prior to start and after abort is zero
* and that each successful stage completes some ops (this is not mandated by
* the PSA specification, but is currently the case).
*
* 4. Check that calling complete() when start() fails and complete()
* after completion results in a BAD_STATE error.
*
* 5. Check that calling start() again after start fails results in a BAD_STATE
* error.
*/
void verify_hash_fail_interruptible(int key_type_arg, data_t *key_data,
int alg_arg, data_t *hash_data,
data_t *signature_data,
int expected_start_status_arg,
int expected_complete_status_arg,
int max_ops_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t actual_status;
psa_status_t expected_start_status = expected_start_status_arg;
psa_status_t expected_complete_status = expected_complete_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint32_t num_ops = 0;
uint32_t max_ops = max_ops_arg;
size_t num_ops_prior = 0;
size_t num_completes = 0;
size_t min_completes = 0;
size_t max_completes = 0;
psa_verify_hash_interruptible_operation_t operation =
psa_verify_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
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_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops,
expected_complete_status,
&min_completes,
&max_completes);
num_ops_prior = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Start verification. */
actual_status = psa_verify_hash_start(&operation, key, alg,
hash_data->x, hash_data->len,
signature_data->x,
signature_data->len);
TEST_EQUAL(actual_status, expected_start_status);
if (expected_start_status != PSA_SUCCESS) {
/* Emulate poor application code, and call complete anyway, even though
* start failed. */
actual_status = psa_verify_hash_complete(&operation);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
/* Test that calling start again after failure also causes BAD_STATE. */
actual_status = psa_verify_hash_start(&operation, key, alg,
hash_data->x, hash_data->len,
signature_data->x,
signature_data->len);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
}
num_ops_prior = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops_prior == 0);
/* Continue performing the signature until complete. */
do {
actual_status = psa_verify_hash_complete(&operation);
num_completes++;
if (actual_status == PSA_SUCCESS ||
actual_status == PSA_OPERATION_INCOMPLETE) {
num_ops = psa_verify_hash_get_num_ops(&operation);
/* We are asserting here that every complete makes progress
* (completes some ops), which is true of the internal
* implementation and probably any implementation, however this is
* not mandated by the PSA specification. */
TEST_ASSERT(num_ops > num_ops_prior);
num_ops_prior = num_ops;
}
} while (actual_status == PSA_OPERATION_INCOMPLETE);
TEST_EQUAL(actual_status, expected_complete_status);
/* Check that another complete returns BAD_STATE. */
actual_status = psa_verify_hash_complete(&operation);
TEST_EQUAL(actual_status, PSA_ERROR_BAD_STATE);
TEST_LE_U(min_completes, num_completes);
TEST_LE_U(num_completes, max_completes);
PSA_ASSERT(psa_verify_hash_abort(&operation));
num_ops = psa_verify_hash_get_num_ops(&operation);
TEST_ASSERT(num_ops == 0);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* interruptible_signverify_hash_state_test() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test that calling the various interruptible sign and verify hash functions
* in incorrect orders returns BAD_STATE errors.
*/
void interruptible_signverify_hash_state_test(int key_type_arg,
data_t *key_data, int alg_arg, data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_sign_hash_interruptible_operation_t sign_operation =
psa_sign_hash_interruptible_operation_init();
psa_verify_hash_interruptible_operation_t verify_operation =
psa_verify_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
/* --- Attempt completes prior to starts --- */
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
/* --- Aborts in all other places. --- */
psa_sign_hash_abort(&sign_operation);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length),
PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length));
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
/* --- Attempt double starts. --- */
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
TEST_EQUAL(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
TEST_EQUAL(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* interruptible_signverify_hash_edgecase_tests() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test various edge cases in the interruptible sign and verify hash
* interfaces.
*/
void interruptible_signverify_hash_edgecase_tests(int key_type_arg,
data_t *key_data, int alg_arg, data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t *input_buffer = NULL;
psa_sign_hash_interruptible_operation_t sign_operation =
psa_sign_hash_interruptible_operation_init();
psa_verify_hash_interruptible_operation_t verify_operation =
psa_verify_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type,
key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
/* --- Change function inputs mid run, to cause an error (sign only,
* verify passes all inputs to start. --- */
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length),
PSA_OPERATION_INCOMPLETE);
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
0,
&signature_length),
PSA_ERROR_BUFFER_TOO_SMALL);
/* And test that this invalidates the operation. */
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
0,
&signature_length),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
/* Trash the hash buffer in between start and complete, to ensure
* no reliance on external buffers. */
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
TEST_CALLOC(input_buffer, input_data->len);
memcpy(input_buffer, input_data->x, input_data->len);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_buffer, input_data->len));
memset(input_buffer, '!', input_data->len);
mbedtls_free(input_buffer);
input_buffer = NULL;
PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length));
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
TEST_CALLOC(input_buffer, input_data->len);
memcpy(input_buffer, input_data->x, input_data->len);
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_buffer, input_data->len,
signature, signature_length));
memset(input_buffer, '!', input_data->len);
mbedtls_free(input_buffer);
input_buffer = NULL;
PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
mbedtls_free(input_buffer);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
/**
* interruptible_signverify_hash_ops_tests() test intentions:
*
* Note: This test can currently only handle ECDSA.
*
* 1. Test that setting max ops is reflected in both interruptible sign and
* verify hash
* 2. Test that changing the value of max_ops to unlimited during an operation
* causes that operation to complete in the next call.
*
* 3. Test that calling get_num_ops() between complete calls gives the same
* result as calling get_num_ops() once at the end of the operation.
*/
void interruptible_signverify_hash_ops_tests(int key_type_arg,
data_t *key_data, int alg_arg,
data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
uint32_t num_ops = 0;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_sign_hash_interruptible_operation_t sign_operation =
psa_sign_hash_interruptible_operation_init();
psa_verify_hash_interruptible_operation_t verify_operation =
psa_verify_hash_interruptible_operation_init();
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Allocate a buffer which has the size advertised by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
/* Check that default max ops gets set if we don't set it. */
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
TEST_EQUAL(psa_interruptible_get_max_ops(),
PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_size));
TEST_EQUAL(psa_interruptible_get_max_ops(),
PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
/* Check that max ops gets set properly. */
psa_interruptible_set_max_ops(0xbeef);
TEST_EQUAL(psa_interruptible_get_max_ops(), 0xbeef);
/* --- Ensure changing the max ops mid operation works (operation should
* complete successfully after setting max ops to unlimited --- */
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
TEST_EQUAL(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length),
PSA_OPERATION_INCOMPLETE);
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length));
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
TEST_EQUAL(psa_verify_hash_complete(&verify_operation),
PSA_OPERATION_INCOMPLETE);
psa_interruptible_set_max_ops(PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED);
PSA_ASSERT(psa_verify_hash_complete(&verify_operation));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
/* --- Test that not calling get_num_ops inbetween complete calls does not
* result in lost ops. ---*/
psa_interruptible_set_max_ops(1);
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
/* Continue performing the signature until complete. */
do {
status = psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length);
num_ops = psa_sign_hash_get_num_ops(&sign_operation);
} while (status == PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(status);
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
PSA_ASSERT(psa_sign_hash_start(&sign_operation, key, alg,
input_data->x, input_data->len));
/* Continue performing the signature until complete. */
do {
status = psa_sign_hash_complete(&sign_operation, signature,
signature_size,
&signature_length);
} while (status == PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(status);
TEST_EQUAL(num_ops, psa_sign_hash_get_num_ops(&sign_operation));
PSA_ASSERT(psa_sign_hash_abort(&sign_operation));
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
/* Continue performing the verification until complete. */
do {
status = psa_verify_hash_complete(&verify_operation);
num_ops = psa_verify_hash_get_num_ops(&verify_operation);
} while (status == PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(status);
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
PSA_ASSERT(psa_verify_hash_start(&verify_operation, key, alg,
input_data->x, input_data->len,
signature, signature_length));
/* Continue performing the verification until complete. */
do {
status = psa_verify_hash_complete(&verify_operation);
} while (status == PSA_OPERATION_INCOMPLETE);
PSA_ASSERT(status);
TEST_EQUAL(num_ops, psa_verify_hash_get_num_ops(&verify_operation));
PSA_ASSERT(psa_verify_hash_abort(&verify_operation));
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void sign_message_deterministic(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *output_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
PSA_ASSERT(psa_sign_message(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length));
TEST_MEMORY_COMPARE(output_data->x, output_data->len,
signature, signature_length);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void sign_message_fail(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
int signature_size_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t signature_size = signature_size_arg;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
unsigned char *signature = NULL;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
TEST_CALLOC(signature, signature_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
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));
actual_status = psa_sign_message(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length);
TEST_EQUAL(actual_status, expected_status);
/* The value of *signature_length is unspecified on error, but
* whatever it is, it should be less than signature_size, so that
* if the caller tries to read *signature_length bytes without
* checking the error code then they don't overflow a buffer. */
TEST_LE_U(signature_length, signature_size);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void sign_verify_message(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *signature = NULL;
size_t signature_size;
size_t signature_length = 0xdeadbeef;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE |
PSA_KEY_USAGE_VERIFY_MESSAGE);
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
signature_size = PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_ASSERT(signature_size != 0);
TEST_LE_U(signature_size, PSA_SIGNATURE_MAX_SIZE);
TEST_CALLOC(signature, signature_size);
PSA_ASSERT(psa_sign_message(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length));
TEST_LE_U(signature_length, signature_size);
TEST_ASSERT(signature_length > 0);
PSA_ASSERT(psa_verify_message(key, alg,
input_data->x, input_data->len,
signature, signature_length));
if (input_data->len != 0) {
/* Flip a bit in the input and verify that the signature is now
* detected as invalid. Flip a bit at the beginning, not at the end,
* because ECDSA may ignore the last few bits of the input. */
input_data->x[0] ^= 1;
TEST_EQUAL(psa_verify_message(key, alg,
input_data->x, input_data->len,
signature, signature_length),
PSA_ERROR_INVALID_SIGNATURE);
}
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(signature);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void verify_message(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *signature_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
TEST_LE_U(signature_data->len, PSA_SIGNATURE_MAX_SIZE);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE);
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_verify_message(key, alg,
input_data->x, input_data->len,
signature_data->x, signature_data->len));
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void verify_message_fail(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *hash_data,
data_t *signature_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE);
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));
actual_status = psa_verify_message(key, alg,
hash_data->x, hash_data->len,
signature_data->x,
signature_data->len);
TEST_EQUAL(actual_status, expected_status);
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_encrypt(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *label,
int expected_output_length_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t expected_output_length = expected_output_length_arg;
size_t key_bits;
unsigned char *output = NULL;
size_t output_size;
size_t output_length = ~0;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
/* Import the key */
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));
/* Determine the maximum output length */
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_LE_U(output_size, PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE);
TEST_CALLOC(output, output_size);
/* Encrypt the input */
actual_status = psa_asymmetric_encrypt(key, alg,
input_data->x, input_data->len,
label->x, label->len,
output, output_size,
&output_length);
TEST_EQUAL(actual_status, expected_status);
if (actual_status == PSA_SUCCESS) {
TEST_EQUAL(output_length, expected_output_length);
} else {
TEST_LE_U(output_length, output_size);
}
/* If the label is empty, the test framework puts a non-null pointer
* in label->x. Test that a null pointer works as well. */
if (label->len == 0) {
output_length = ~0;
if (output_size != 0) {
memset(output, 0, output_size);
}
actual_status = psa_asymmetric_encrypt(key, alg,
input_data->x, input_data->len,
NULL, label->len,
output, output_size,
&output_length);
TEST_EQUAL(actual_status, expected_status);
if (actual_status == PSA_SUCCESS) {
TEST_EQUAL(output_length, expected_output_length);
} else {
TEST_LE_U(output_length, output_size);
}
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(output);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_encrypt_decrypt(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *label)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *output = NULL;
size_t output_size;
size_t output_length = ~0;
unsigned char *output2 = NULL;
size_t output2_size;
size_t output2_length = ~0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | 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));
/* Determine the maximum ciphertext length */
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
output_size = PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_LE_U(output_size, PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE);
TEST_CALLOC(output, output_size);
output2_size = input_data->len;
TEST_LE_U(output2_size,
PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg));
TEST_LE_U(output2_size, PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE);
TEST_CALLOC(output2, output2_size);
/* We test encryption by checking that encrypt-then-decrypt gives back
* the original plaintext because of the non-optional random
* part of encryption process which prevents using fixed vectors. */
PSA_ASSERT(psa_asymmetric_encrypt(key, alg,
input_data->x, input_data->len,
label->x, label->len,
output, output_size,
&output_length));
/* We don't know what ciphertext length to expect, but check that
* it looks sensible. */
TEST_LE_U(output_length, output_size);
PSA_ASSERT(psa_asymmetric_decrypt(key, alg,
output, output_length,
label->x, label->len,
output2, output2_size,
&output2_length));
TEST_MEMORY_COMPARE(input_data->x, input_data->len,
output2, output2_length);
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(output);
mbedtls_free(output2);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_decrypt(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *label,
data_t *expected_data)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
size_t key_bits;
unsigned char *output = NULL;
size_t output_size = 0;
size_t output_length = ~0;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
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_get_key_attributes(key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Determine the maximum ciphertext length */
output_size = PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg);
TEST_LE_U(output_size, PSA_ASYMMETRIC_DECRYPT_OUTPUT_MAX_SIZE);
TEST_CALLOC(output, output_size);
PSA_ASSERT(psa_asymmetric_decrypt(key, alg,
input_data->x, input_data->len,
label->x, label->len,
output,
output_size,
&output_length));
TEST_MEMORY_COMPARE(expected_data->x, expected_data->len,
output, output_length);
/* If the label is empty, the test framework puts a non-null pointer
* in label->x. Test that a null pointer works as well. */
if (label->len == 0) {
output_length = ~0;
if (output_size != 0) {
memset(output, 0, output_size);
}
PSA_ASSERT(psa_asymmetric_decrypt(key, alg,
input_data->x, input_data->len,
NULL, label->len,
output,
output_size,
&output_length));
TEST_MEMORY_COMPARE(expected_data->x, expected_data->len,
output, output_length);
}
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(output);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_decrypt_fail(int key_type_arg,
data_t *key_data,
int alg_arg,
data_t *input_data,
data_t *label,
int output_size_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t key_type = key_type_arg;
psa_algorithm_t alg = alg_arg;
unsigned char *output = NULL;
size_t output_size = output_size_arg;
size_t output_length = ~0;
psa_status_t actual_status;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
TEST_CALLOC(output, output_size);
PSA_ASSERT(psa_crypto_init());
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));
actual_status = psa_asymmetric_decrypt(key, alg,
input_data->x, input_data->len,
label->x, label->len,
output, output_size,
&output_length);
TEST_EQUAL(actual_status, expected_status);
TEST_LE_U(output_length, output_size);
/* If the label is empty, the test framework puts a non-null pointer
* in label->x. Test that a null pointer works as well. */
if (label->len == 0) {
output_length = ~0;
if (output_size != 0) {
memset(output, 0, output_size);
}
actual_status = psa_asymmetric_decrypt(key, alg,
input_data->x, input_data->len,
NULL, label->len,
output, output_size,
&output_length);
TEST_EQUAL(actual_status, expected_status);
TEST_LE_U(output_length, output_size);
}
exit:
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
mbedtls_free(output);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void key_derivation_init()
{
/* Test each valid way of initializing the object, except for `= {0}`, as
* Clang 5 complains when `-Wmissing-field-initializers` is used, even
* though it's OK by the C standard. We could test for this, but we'd need
* to suppress the Clang warning for the test. */
size_t capacity;
psa_key_derivation_operation_t func = psa_key_derivation_operation_init();
psa_key_derivation_operation_t init = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_derivation_operation_t zero;
memset(&zero, 0, sizeof(zero));
/* A default operation should not be able to report its capacity. */
TEST_EQUAL(psa_key_derivation_get_capacity(&func, &capacity),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_key_derivation_get_capacity(&init, &capacity),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_key_derivation_get_capacity(&zero, &capacity),
PSA_ERROR_BAD_STATE);
/* A default operation should be abortable without error. */
PSA_ASSERT(psa_key_derivation_abort(&func));
PSA_ASSERT(psa_key_derivation_abort(&init));
PSA_ASSERT(psa_key_derivation_abort(&zero));
}
/* END_CASE */
/* BEGIN_CASE */
void derive_setup(int alg_arg, int expected_status_arg)
{
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
PSA_ASSERT(psa_crypto_init());
TEST_EQUAL(psa_key_derivation_setup(&operation, alg),
expected_status);
exit:
psa_key_derivation_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_set_capacity(int alg_arg, int64_t capacity_arg,
int expected_status_arg)
{
psa_algorithm_t alg = alg_arg;
size_t capacity = capacity_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
PSA_ASSERT(psa_crypto_init());
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
TEST_EQUAL(psa_key_derivation_set_capacity(&operation, capacity),
expected_status);
exit:
psa_key_derivation_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void parse_binary_string_test(data_t *input, int output)
{
uint64_t value;
value = mbedtls_test_parse_binary_string(input);
TEST_EQUAL(value, output);
}
/* END_CASE */
/* BEGIN_CASE */
void derive_input(int alg_arg,
int step_arg1, int key_type_arg1, data_t *input1,
int expected_status_arg1,
int step_arg2, int key_type_arg2, data_t *input2,
int expected_status_arg2,
int step_arg3, int key_type_arg3, data_t *input3,
int expected_status_arg3,
int output_key_type_arg, int expected_output_status_arg)
{
psa_algorithm_t alg = alg_arg;
psa_key_derivation_step_t steps[] = { step_arg1, step_arg2, step_arg3 };
uint32_t key_types[] = { key_type_arg1, key_type_arg2, key_type_arg3 };
psa_status_t expected_statuses[] = { expected_status_arg1,
expected_status_arg2,
expected_status_arg3 };
data_t *inputs[] = { input1, input2, input3 };
mbedtls_svc_key_id_t keys[] = { MBEDTLS_SVC_KEY_ID_INIT,
MBEDTLS_SVC_KEY_ID_INIT,
MBEDTLS_SVC_KEY_ID_INIT };
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t i;
psa_key_type_t output_key_type = output_key_type_arg;
mbedtls_svc_key_id_t output_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t expected_output_status = expected_output_status_arg;
psa_status_t actual_output_status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
for (i = 0; i < ARRAY_LENGTH(steps); i++) {
mbedtls_test_set_step(i);
if (steps[i] == 0) {
/* Skip this step */
} else if (((psa_key_type_t) key_types[i]) != PSA_KEY_TYPE_NONE &&
key_types[i] != INPUT_INTEGER) {
psa_set_key_type(&attributes, ((psa_key_type_t) key_types[i]));
PSA_ASSERT(psa_import_key(&attributes,
inputs[i]->x, inputs[i]->len,
&keys[i]));
if (PSA_KEY_TYPE_IS_KEY_PAIR((psa_key_type_t) key_types[i]) &&
steps[i] == PSA_KEY_DERIVATION_INPUT_SECRET) {
// When taking a private key as secret input, use key agreement
// to add the shared secret to the derivation
TEST_EQUAL(mbedtls_test_psa_key_agreement_with_self(
&operation, keys[i], 0),
expected_statuses[i]);
} else {
TEST_EQUAL(psa_key_derivation_input_key(&operation, steps[i],
keys[i]),
expected_statuses[i]);
}
} else {
if (key_types[i] == INPUT_INTEGER) {
TEST_EQUAL(psa_key_derivation_input_integer(
&operation, steps[i],
mbedtls_test_parse_binary_string(inputs[i])),
expected_statuses[i]);
} else {
TEST_EQUAL(psa_key_derivation_input_bytes(
&operation, steps[i],
inputs[i]->x, inputs[i]->len),
expected_statuses[i]);
}
}
}
if (output_key_type != PSA_KEY_TYPE_NONE) {
psa_reset_key_attributes(&attributes);
psa_set_key_type(&attributes, output_key_type);
psa_set_key_bits(&attributes, 8);
actual_output_status =
psa_key_derivation_output_key(&attributes, &operation,
&output_key);
} else {
uint8_t buffer[1];
actual_output_status =
psa_key_derivation_output_bytes(&operation,
buffer, sizeof(buffer));
}
TEST_EQUAL(actual_output_status, expected_output_status);
exit:
psa_key_derivation_abort(&operation);
for (i = 0; i < ARRAY_LENGTH(keys); i++) {
psa_destroy_key(keys[i]);
}
psa_destroy_key(output_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE*/
void derive_input_invalid_cost(int alg_arg, int64_t cost)
{
psa_algorithm_t alg = alg_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
PSA_ASSERT(psa_crypto_init());
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
TEST_EQUAL(psa_key_derivation_input_integer(&operation,
PSA_KEY_DERIVATION_INPUT_COST,
cost),
PSA_ERROR_NOT_SUPPORTED);
exit:
psa_key_derivation_abort(&operation);
PSA_DONE();
}
/* END_CASE*/
/* BEGIN_CASE */
void derive_over_capacity(int alg_arg)
{
psa_algorithm_t alg = alg_arg;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
size_t key_type = PSA_KEY_TYPE_DERIVE;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
unsigned char input1[] = "Input 1";
size_t input1_length = sizeof(input1);
unsigned char input2[] = "Input 2";
size_t input2_length = sizeof(input2);
uint8_t buffer[42];
size_t capacity = sizeof(buffer);
const uint8_t key_data[22] = { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b };
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type);
PSA_ASSERT(psa_import_key(&attributes,
key_data, sizeof(key_data),
&key));
/* valid key derivation */
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
input1, input1_length,
input2, input2_length,
capacity, 0)) {
goto exit;
}
/* state of operation shouldn't allow additional generation */
TEST_EQUAL(psa_key_derivation_setup(&operation, alg),
PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_key_derivation_output_bytes(&operation, buffer, capacity));
TEST_EQUAL(psa_key_derivation_output_bytes(&operation, buffer, capacity),
PSA_ERROR_INSUFFICIENT_DATA);
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_actions_without_setup()
{
uint8_t output_buffer[16];
size_t buffer_size = 16;
size_t capacity = 0;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
TEST_ASSERT(psa_key_derivation_output_bytes(&operation,
output_buffer, buffer_size)
== PSA_ERROR_BAD_STATE);
TEST_ASSERT(psa_key_derivation_get_capacity(&operation, &capacity)
== PSA_ERROR_BAD_STATE);
PSA_ASSERT(psa_key_derivation_abort(&operation));
TEST_ASSERT(psa_key_derivation_output_bytes(&operation,
output_buffer, buffer_size)
== PSA_ERROR_BAD_STATE);
TEST_ASSERT(psa_key_derivation_get_capacity(&operation, &capacity)
== PSA_ERROR_BAD_STATE);
exit:
psa_key_derivation_abort(&operation);
}
/* END_CASE */
/* BEGIN_CASE */
void derive_output(int alg_arg,
int step1_arg, data_t *input1, int expected_status_arg1,
int step2_arg, data_t *input2, int expected_status_arg2,
int step3_arg, data_t *input3, int expected_status_arg3,
int step4_arg, data_t *input4, int expected_status_arg4,
data_t *key_agreement_peer_key,
int requested_capacity_arg,
data_t *expected_output1,
data_t *expected_output2,
int other_key_input_type,
int key_input_type,
int derive_type)
{
psa_algorithm_t alg = alg_arg;
psa_key_derivation_step_t steps[] = { step1_arg, step2_arg, step3_arg, step4_arg };
data_t *inputs[] = { input1, input2, input3, input4 };
mbedtls_svc_key_id_t keys[] = { MBEDTLS_SVC_KEY_ID_INIT,
MBEDTLS_SVC_KEY_ID_INIT,
MBEDTLS_SVC_KEY_ID_INIT,
MBEDTLS_SVC_KEY_ID_INIT };
psa_status_t statuses[] = { expected_status_arg1, expected_status_arg2,
expected_status_arg3, expected_status_arg4 };
size_t requested_capacity = requested_capacity_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
uint8_t *expected_outputs[2] =
{ expected_output1->x, expected_output2->x };
size_t output_sizes[2] =
{ expected_output1->len, expected_output2->len };
size_t output_buffer_size = 0;
uint8_t *output_buffer = NULL;
size_t expected_capacity;
size_t current_capacity;
psa_key_attributes_t attributes1 = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t attributes2 = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t attributes3 = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t attributes4 = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
size_t i;
for (i = 0; i < ARRAY_LENGTH(expected_outputs); i++) {
if (output_sizes[i] > output_buffer_size) {
output_buffer_size = output_sizes[i];
}
if (output_sizes[i] == 0) {
expected_outputs[i] = NULL;
}
}
TEST_CALLOC(output_buffer, output_buffer_size);
PSA_ASSERT(psa_crypto_init());
/* Extraction phase. */
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
PSA_ASSERT(psa_key_derivation_set_capacity(&operation,
requested_capacity));
for (i = 0; i < ARRAY_LENGTH(steps); i++) {
switch (steps[i]) {
case 0:
break;
case PSA_KEY_DERIVATION_INPUT_COST:
TEST_EQUAL(psa_key_derivation_input_integer(
&operation, steps[i],
mbedtls_test_parse_binary_string(inputs[i])),
statuses[i]);
if (statuses[i] != PSA_SUCCESS) {
goto exit;
}
break;
case PSA_KEY_DERIVATION_INPUT_PASSWORD:
case PSA_KEY_DERIVATION_INPUT_SECRET:
switch (key_input_type) {
case 0: // input bytes
TEST_EQUAL(psa_key_derivation_input_bytes(
&operation, steps[i],
inputs[i]->x, inputs[i]->len),
statuses[i]);
if (statuses[i] != PSA_SUCCESS) {
goto exit;
}
break;
case 1: // input key
psa_set_key_usage_flags(&attributes1, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes1, alg);
psa_set_key_type(&attributes1, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&attributes1,
inputs[i]->x, inputs[i]->len,
&keys[i]));
if (PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
PSA_ASSERT(psa_get_key_attributes(keys[i], &attributes1));
TEST_LE_U(PSA_BITS_TO_BYTES(psa_get_key_bits(&attributes1)),
PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE);
}
TEST_EQUAL(psa_key_derivation_input_key(&operation,
steps[i],
keys[i]),
statuses[i]);
if (statuses[i] != PSA_SUCCESS) {
goto exit;
}
break;
default:
TEST_FAIL("default case not supported");
break;
}
break;
case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:
switch (other_key_input_type) {
case 0: // input bytes
TEST_EQUAL(psa_key_derivation_input_bytes(&operation,
steps[i],
inputs[i]->x,
inputs[i]->len),
statuses[i]);
break;
case 1: // input key, type DERIVE
case 11: // input key, type RAW
psa_set_key_usage_flags(&attributes2, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes2, alg);
psa_set_key_type(&attributes2, PSA_KEY_TYPE_DERIVE);
// other secret of type RAW_DATA passed with input_key
if (other_key_input_type == 11) {
psa_set_key_type(&attributes2, PSA_KEY_TYPE_RAW_DATA);
}
PSA_ASSERT(psa_import_key(&attributes2,
inputs[i]->x, inputs[i]->len,
&keys[i]));
TEST_EQUAL(psa_key_derivation_input_key(&operation,
steps[i],
keys[i]),
statuses[i]);
break;
case 2: // key agreement
psa_set_key_usage_flags(&attributes3, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes3, alg);
psa_set_key_type(&attributes3,
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
PSA_ASSERT(psa_import_key(&attributes3,
inputs[i]->x, inputs[i]->len,
&keys[i]));
TEST_EQUAL(psa_key_derivation_key_agreement(
&operation,
PSA_KEY_DERIVATION_INPUT_OTHER_SECRET,
keys[i], key_agreement_peer_key->x,
key_agreement_peer_key->len), statuses[i]);
break;
default:
TEST_FAIL("default case not supported");
break;
}
if (statuses[i] != PSA_SUCCESS) {
goto exit;
}
break;
default:
TEST_EQUAL(psa_key_derivation_input_bytes(
&operation, steps[i],
inputs[i]->x, inputs[i]->len), statuses[i]);
if (statuses[i] != PSA_SUCCESS) {
goto exit;
}
break;
}
}
PSA_ASSERT(psa_key_derivation_get_capacity(&operation,
&current_capacity));
TEST_EQUAL(current_capacity, requested_capacity);
expected_capacity = requested_capacity;
if (derive_type == 1) { // output key
psa_status_t expected_status = PSA_ERROR_NOT_PERMITTED;
/* For output key derivation secret must be provided using
input key, otherwise operation is not permitted. */
if (key_input_type == 1) {
expected_status = PSA_SUCCESS;
}
psa_set_key_usage_flags(&attributes4, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&attributes4, alg);
psa_set_key_type(&attributes4, PSA_KEY_TYPE_DERIVE);
psa_set_key_bits(&attributes4, PSA_BYTES_TO_BITS(requested_capacity));
TEST_EQUAL(psa_key_derivation_output_key(&attributes4, &operation,
&derived_key), expected_status);
} else { // output bytes
/* Expansion phase. */
for (i = 0; i < ARRAY_LENGTH(expected_outputs); i++) {
/* Read some bytes. */
status = psa_key_derivation_output_bytes(&operation,
output_buffer, output_sizes[i]);
if (expected_capacity == 0 && output_sizes[i] == 0) {
/* Reading 0 bytes when 0 bytes are available can go either way. */
TEST_ASSERT(status == PSA_SUCCESS ||
status == PSA_ERROR_INSUFFICIENT_DATA);
continue;
} else if (expected_capacity == 0 ||
output_sizes[i] > expected_capacity) {
/* Capacity exceeded. */
TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_DATA);
expected_capacity = 0;
continue;
}
/* Success. Check the read data. */
PSA_ASSERT(status);
if (output_sizes[i] != 0) {
TEST_MEMORY_COMPARE(output_buffer, output_sizes[i],
expected_outputs[i], output_sizes[i]);
}
/* Check the operation status. */
expected_capacity -= output_sizes[i];
PSA_ASSERT(psa_key_derivation_get_capacity(&operation,
&current_capacity));
TEST_EQUAL(expected_capacity, current_capacity);
}
}
PSA_ASSERT(psa_key_derivation_abort(&operation));
exit:
mbedtls_free(output_buffer);
psa_key_derivation_abort(&operation);
for (i = 0; i < ARRAY_LENGTH(keys); i++) {
psa_destroy_key(keys[i]);
}
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_full(int alg_arg,
data_t *key_data,
data_t *input1,
data_t *input2,
int requested_capacity_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
size_t requested_capacity = requested_capacity_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
unsigned char output_buffer[32];
size_t expected_capacity = requested_capacity;
size_t current_capacity;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&key));
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, key, alg,
input1->x, input1->len,
input2->x, input2->len,
requested_capacity, 0)) {
goto exit;
}
PSA_ASSERT(psa_key_derivation_get_capacity(&operation,
&current_capacity));
TEST_EQUAL(current_capacity, expected_capacity);
/* Expansion phase. */
while (current_capacity > 0) {
size_t read_size = sizeof(output_buffer);
if (read_size > current_capacity) {
read_size = current_capacity;
}
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
output_buffer,
read_size));
expected_capacity -= read_size;
PSA_ASSERT(psa_key_derivation_get_capacity(&operation,
&current_capacity));
TEST_EQUAL(current_capacity, expected_capacity);
}
/* Check that the operation refuses to go over capacity. */
TEST_EQUAL(psa_key_derivation_output_bytes(&operation, output_buffer, 1),
PSA_ERROR_INSUFFICIENT_DATA);
PSA_ASSERT(psa_key_derivation_abort(&operation));
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_SHA_256:PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */
void derive_ecjpake_to_pms(data_t *input, int expected_input_status_arg,
int derivation_step,
int capacity, int expected_capacity_status_arg,
data_t *expected_output,
int expected_output_status_arg)
{
psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_derivation_step_t step = (psa_key_derivation_step_t) derivation_step;
uint8_t *output_buffer = NULL;
psa_status_t status;
psa_status_t expected_input_status = (psa_status_t) expected_input_status_arg;
psa_status_t expected_capacity_status = (psa_status_t) expected_capacity_status_arg;
psa_status_t expected_output_status = (psa_status_t) expected_output_status_arg;
TEST_CALLOC(output_buffer, expected_output->len);
PSA_ASSERT(psa_crypto_init());
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
TEST_EQUAL(psa_key_derivation_set_capacity(&operation, capacity),
expected_capacity_status);
TEST_EQUAL(psa_key_derivation_input_bytes(&operation,
step, input->x, input->len),
expected_input_status);
if (((psa_status_t) expected_input_status) != PSA_SUCCESS) {
goto exit;
}
status = psa_key_derivation_output_bytes(&operation, output_buffer,
expected_output->len);
TEST_EQUAL(status, expected_output_status);
if (expected_output->len != 0 && expected_output_status == PSA_SUCCESS) {
TEST_MEMORY_COMPARE(output_buffer, expected_output->len, expected_output->x,
expected_output->len);
}
exit:
mbedtls_free(output_buffer);
psa_key_derivation_abort(&operation);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key_exercise(int alg_arg,
data_t *key_data,
data_t *input1,
data_t *input2,
int derived_type_arg,
int derived_bits_arg,
int derived_usage_arg,
int derived_alg_arg)
{
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t derived_type = derived_type_arg;
size_t derived_bits = derived_bits_arg;
psa_key_usage_t derived_usage = derived_usage_arg;
psa_algorithm_t derived_alg = derived_alg_arg;
size_t capacity = PSA_BITS_TO_BYTES(derived_bits);
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&attributes, key_data->x, key_data->len,
&base_key));
/* Derive a key. */
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
capacity, 0)) {
goto exit;
}
psa_set_key_usage_flags(&attributes, derived_usage);
psa_set_key_algorithm(&attributes, derived_alg);
psa_set_key_type(&attributes, derived_type);
psa_set_key_bits(&attributes, derived_bits);
PSA_ASSERT(psa_key_derivation_output_key(&attributes, &operation,
&derived_key));
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(derived_key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), derived_type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), derived_bits);
/* Exercise the derived key. */
if (!mbedtls_test_psa_exercise_key(derived_key, derived_usage, derived_alg, 0)) {
goto exit;
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key_export(int alg_arg,
data_t *key_data,
data_t *input1,
data_t *input2,
int bytes1_arg,
int bytes2_arg)
{
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
size_t bytes1 = bytes1_arg;
size_t bytes2 = bytes2_arg;
size_t capacity = bytes1 + bytes2;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
uint8_t *output_buffer = NULL;
uint8_t *export_buffer = NULL;
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t length;
TEST_CALLOC(output_buffer, capacity);
TEST_CALLOC(export_buffer, capacity);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&base_attributes, alg);
psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
&base_key));
/* Derive some material and output it. */
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
capacity, 0)) {
goto exit;
}
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
output_buffer,
capacity));
PSA_ASSERT(psa_key_derivation_abort(&operation));
/* Derive the same output again, but this time store it in key objects. */
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
capacity, 0)) {
goto exit;
}
psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&derived_attributes, 0);
psa_set_key_type(&derived_attributes, PSA_KEY_TYPE_RAW_DATA);
psa_set_key_bits(&derived_attributes, PSA_BYTES_TO_BITS(bytes1));
PSA_ASSERT(psa_key_derivation_output_key(&derived_attributes, &operation,
&derived_key));
PSA_ASSERT(psa_export_key(derived_key,
export_buffer, bytes1,
&length));
TEST_EQUAL(length, bytes1);
PSA_ASSERT(psa_destroy_key(derived_key));
psa_set_key_bits(&derived_attributes, PSA_BYTES_TO_BITS(bytes2));
PSA_ASSERT(psa_key_derivation_output_key(&derived_attributes, &operation,
&derived_key));
PSA_ASSERT(psa_export_key(derived_key,
export_buffer + bytes1, bytes2,
&length));
TEST_EQUAL(length, bytes2);
/* Compare the outputs from the two runs. */
TEST_MEMORY_COMPARE(output_buffer, bytes1 + bytes2,
export_buffer, capacity);
exit:
mbedtls_free(output_buffer);
mbedtls_free(export_buffer);
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key_type(int alg_arg,
data_t *key_data,
data_t *input1,
data_t *input2,
int key_type_arg, int bits_arg,
data_t *expected_export)
{
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
const psa_algorithm_t alg = alg_arg;
const psa_key_type_t key_type = key_type_arg;
const size_t bits = bits_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
const size_t export_buffer_size =
PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, bits);
uint8_t *export_buffer = NULL;
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t export_length;
TEST_CALLOC(export_buffer, export_buffer_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&base_attributes, alg);
psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
&base_key));
if (mbedtls_test_psa_setup_key_derivation_wrap(
&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) {
goto exit;
}
psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&derived_attributes, 0);
psa_set_key_type(&derived_attributes, key_type);
psa_set_key_bits(&derived_attributes, bits);
PSA_ASSERT(psa_key_derivation_output_key(&derived_attributes, &operation,
&derived_key));
PSA_ASSERT(psa_export_key(derived_key,
export_buffer, export_buffer_size,
&export_length));
TEST_MEMORY_COMPARE(export_buffer, export_length,
expected_export->x, expected_export->len);
exit:
mbedtls_free(export_buffer);
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key_ext(int alg_arg,
data_t *key_data,
data_t *input1,
data_t *input2,
int key_type_arg, int bits_arg,
int flags_arg,
data_t *params_data,
psa_status_t expected_status,
data_t *expected_export)
{
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
const psa_algorithm_t alg = alg_arg;
const psa_key_type_t key_type = key_type_arg;
const size_t bits = bits_arg;
psa_key_production_parameters_t *params = NULL;
size_t params_data_length = 0;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
const size_t export_buffer_size =
PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, bits);
uint8_t *export_buffer = NULL;
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t export_length;
TEST_CALLOC(export_buffer, export_buffer_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&base_attributes, alg);
psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
&base_key));
if (mbedtls_test_psa_setup_key_derivation_wrap(
&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
PSA_KEY_DERIVATION_UNLIMITED_CAPACITY, 0) == 0) {
goto exit;
}
psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&derived_attributes, 0);
psa_set_key_type(&derived_attributes, key_type);
psa_set_key_bits(&derived_attributes, bits);
if (!setup_key_production_parameters(&params, &params_data_length,
flags_arg, params_data)) {
goto exit;
}
TEST_EQUAL(psa_key_derivation_output_key_ext(&derived_attributes, &operation,
params, params_data_length,
&derived_key),
expected_status);
if (expected_status == PSA_SUCCESS) {
PSA_ASSERT(psa_export_key(derived_key,
export_buffer, export_buffer_size,
&export_length));
TEST_MEMORY_COMPARE(export_buffer, export_length,
expected_export->x, expected_export->len);
}
exit:
mbedtls_free(export_buffer);
mbedtls_free(params);
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void derive_key(int alg_arg,
data_t *key_data, data_t *input1, data_t *input2,
int type_arg, int bits_arg,
int expected_status_arg,
int is_large_output)
{
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t derived_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t type = type_arg;
size_t bits = bits_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t derived_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&base_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&base_attributes, alg);
psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&base_attributes, key_data->x, key_data->len,
&base_key));
if (!mbedtls_test_psa_setup_key_derivation_wrap(&operation, base_key, alg,
input1->x, input1->len,
input2->x, input2->len,
SIZE_MAX, 0)) {
goto exit;
}
psa_set_key_usage_flags(&derived_attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_algorithm(&derived_attributes, 0);
psa_set_key_type(&derived_attributes, type);
psa_set_key_bits(&derived_attributes, bits);
psa_status_t status =
psa_key_derivation_output_key(&derived_attributes,
&operation,
&derived_key);
if (is_large_output > 0) {
TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
}
TEST_EQUAL(status, expected_status);
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(derived_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void key_agreement_setup(int alg_arg,
int our_key_type_arg, int our_key_alg_arg,
data_t *our_key_data, data_t *peer_key_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_algorithm_t our_key_alg = our_key_alg_arg;
psa_key_type_t our_key_type = our_key_type_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t expected_status = expected_status_arg;
psa_status_t status;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, our_key_alg);
psa_set_key_type(&attributes, our_key_type);
PSA_ASSERT(psa_import_key(&attributes,
our_key_data->x, our_key_data->len,
&our_key));
/* The tests currently include inputs that should fail at either step.
* Test cases that fail at the setup step should be changed to call
* key_derivation_setup instead, and this function should be renamed
* to key_agreement_fail. */
status = psa_key_derivation_setup(&operation, alg);
if (status == PSA_SUCCESS) {
TEST_EQUAL(psa_key_derivation_key_agreement(
&operation, PSA_KEY_DERIVATION_INPUT_SECRET,
our_key,
peer_key_data->x, peer_key_data->len),
expected_status);
} else {
TEST_ASSERT(status == expected_status);
}
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(our_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void raw_key_agreement(int alg_arg,
int our_key_type_arg, data_t *our_key_data,
data_t *peer_key_data,
data_t *expected_output)
{
mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t our_key_type = our_key_type_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
unsigned char *output = NULL;
size_t output_length = ~0;
size_t key_bits;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, our_key_type);
PSA_ASSERT(psa_import_key(&attributes,
our_key_data->x, our_key_data->len,
&our_key));
PSA_ASSERT(psa_get_key_attributes(our_key, &attributes));
key_bits = psa_get_key_bits(&attributes);
/* Validate size macros */
TEST_LE_U(expected_output->len,
PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(our_key_type, key_bits));
TEST_LE_U(PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(our_key_type, key_bits),
PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE);
/* Good case with exact output size */
TEST_CALLOC(output, expected_output->len);
PSA_ASSERT(psa_raw_key_agreement(alg, our_key,
peer_key_data->x, peer_key_data->len,
output, expected_output->len,
&output_length));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
mbedtls_free(output);
output = NULL;
output_length = ~0;
/* Larger buffer */
TEST_CALLOC(output, expected_output->len + 1);
PSA_ASSERT(psa_raw_key_agreement(alg, our_key,
peer_key_data->x, peer_key_data->len,
output, expected_output->len + 1,
&output_length));
TEST_MEMORY_COMPARE(output, output_length,
expected_output->x, expected_output->len);
mbedtls_free(output);
output = NULL;
output_length = ~0;
/* Buffer too small */
TEST_CALLOC(output, expected_output->len - 1);
TEST_EQUAL(psa_raw_key_agreement(alg, our_key,
peer_key_data->x, peer_key_data->len,
output, expected_output->len - 1,
&output_length),
PSA_ERROR_BUFFER_TOO_SMALL);
/* Not required by the spec, but good robustness */
TEST_LE_U(output_length, expected_output->len - 1);
mbedtls_free(output);
output = NULL;
exit:
mbedtls_free(output);
psa_destroy_key(our_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void key_agreement_capacity(int alg_arg,
int our_key_type_arg, data_t *our_key_data,
data_t *peer_key_data,
int expected_capacity_arg)
{
mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t our_key_type = our_key_type_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
size_t actual_capacity;
unsigned char output[16];
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, our_key_type);
PSA_ASSERT(psa_import_key(&attributes,
our_key_data->x, our_key_data->len,
&our_key));
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
PSA_ASSERT(psa_key_derivation_key_agreement(
&operation,
PSA_KEY_DERIVATION_INPUT_SECRET, our_key,
peer_key_data->x, peer_key_data->len));
if (PSA_ALG_IS_HKDF(PSA_ALG_KEY_AGREEMENT_GET_KDF(alg))) {
/* The test data is for info="" */
PSA_ASSERT(psa_key_derivation_input_bytes(&operation,
PSA_KEY_DERIVATION_INPUT_INFO,
NULL, 0));
}
/* Test the advertised capacity. */
PSA_ASSERT(psa_key_derivation_get_capacity(
&operation, &actual_capacity));
TEST_EQUAL(actual_capacity, (size_t) expected_capacity_arg);
/* Test the actual capacity by reading the output. */
while (actual_capacity > sizeof(output)) {
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
output, sizeof(output)));
actual_capacity -= sizeof(output);
}
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
output, actual_capacity));
TEST_EQUAL(psa_key_derivation_output_bytes(&operation, output, 1),
PSA_ERROR_INSUFFICIENT_DATA);
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(our_key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
void ecc_conversion_functions(int grp_id_arg, int psa_family_arg, int bits_arg)
{
mbedtls_ecp_group_id grp_id = grp_id_arg;
psa_ecc_family_t ecc_family = psa_family_arg;
size_t bits = bits_arg;
size_t bits_tmp;
TEST_EQUAL(ecc_family, mbedtls_ecc_group_to_psa(grp_id, &bits_tmp));
TEST_EQUAL(bits, bits_tmp);
TEST_EQUAL(grp_id, mbedtls_ecc_group_from_psa(ecc_family, bits));
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
void ecc_conversion_functions_fail()
{
size_t bits;
/* Invalid legacy curve identifiers. */
TEST_EQUAL(0, mbedtls_ecc_group_to_psa(MBEDTLS_ECP_DP_MAX, &bits));
TEST_EQUAL(0, bits);
TEST_EQUAL(0, mbedtls_ecc_group_to_psa(MBEDTLS_ECP_DP_NONE, &bits));
TEST_EQUAL(0, bits);
/* Invalid PSA EC family. */
TEST_EQUAL(MBEDTLS_ECP_DP_NONE, mbedtls_ecc_group_from_psa(0, 192));
/* Invalid bit-size for a valid EC family. */
TEST_EQUAL(MBEDTLS_ECP_DP_NONE, mbedtls_ecc_group_from_psa(PSA_ECC_FAMILY_SECP_R1, 512));
/* Twisted-Edward curves are not supported yet. */
TEST_EQUAL(MBEDTLS_ECP_DP_NONE,
mbedtls_ecc_group_from_psa(PSA_ECC_FAMILY_TWISTED_EDWARDS, 255));
TEST_EQUAL(MBEDTLS_ECP_DP_NONE,
mbedtls_ecc_group_from_psa(PSA_ECC_FAMILY_TWISTED_EDWARDS, 448));
}
/* END_CASE */
/* BEGIN_CASE */
void key_agreement_output(int alg_arg,
int our_key_type_arg, data_t *our_key_data,
data_t *peer_key_data,
data_t *expected_output1, data_t *expected_output2)
{
mbedtls_svc_key_id_t our_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t alg = alg_arg;
psa_key_type_t our_key_type = our_key_type_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
uint8_t *actual_output = NULL;
TEST_CALLOC(actual_output, MAX(expected_output1->len,
expected_output2->len));
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, our_key_type);
PSA_ASSERT(psa_import_key(&attributes,
our_key_data->x, our_key_data->len,
&our_key));
PSA_ASSERT(psa_key_derivation_setup(&operation, alg));
PSA_ASSERT(psa_key_derivation_key_agreement(
&operation,
PSA_KEY_DERIVATION_INPUT_SECRET, our_key,
peer_key_data->x, peer_key_data->len));
if (PSA_ALG_IS_HKDF(PSA_ALG_KEY_AGREEMENT_GET_KDF(alg))) {
/* The test data is for info="" */
PSA_ASSERT(psa_key_derivation_input_bytes(&operation,
PSA_KEY_DERIVATION_INPUT_INFO,
NULL, 0));
}
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
actual_output,
expected_output1->len));
TEST_MEMORY_COMPARE(actual_output, expected_output1->len,
expected_output1->x, expected_output1->len);
if (expected_output2->len != 0) {
PSA_ASSERT(psa_key_derivation_output_bytes(&operation,
actual_output,
expected_output2->len));
TEST_MEMORY_COMPARE(actual_output, expected_output2->len,
expected_output2->x, expected_output2->len);
}
exit:
psa_key_derivation_abort(&operation);
psa_destroy_key(our_key);
PSA_DONE();
mbedtls_free(actual_output);
}
/* END_CASE */
/* BEGIN_CASE */
void generate_random(int bytes_arg)
{
size_t bytes = bytes_arg;
unsigned char *output = NULL;
unsigned char *changed = NULL;
size_t i;
unsigned run;
TEST_ASSERT(bytes_arg >= 0);
TEST_CALLOC(output, bytes);
TEST_CALLOC(changed, bytes);
PSA_ASSERT(psa_crypto_init());
/* Run several times, to ensure that every output byte will be
* nonzero at least once with overwhelming probability
* (2^(-8*number_of_runs)). */
for (run = 0; run < 10; run++) {
if (bytes != 0) {
memset(output, 0, bytes);
}
PSA_ASSERT(psa_generate_random(output, bytes));
for (i = 0; i < bytes; i++) {
if (output[i] != 0) {
++changed[i];
}
}
}
/* Check that every byte was changed to nonzero at least once. This
* validates that psa_generate_random is overwriting every byte of
* the output buffer. */
for (i = 0; i < bytes; i++) {
TEST_ASSERT(changed[i] != 0);
}
exit:
PSA_DONE();
mbedtls_free(output);
mbedtls_free(changed);
}
/* END_CASE */
#if defined MBEDTLS_THREADING_PTHREAD
/* BEGIN_CASE depends_on:MBEDTLS_THREADING_PTHREAD */
void concurrently_generate_keys(int type_arg,
int bits_arg,
int usage_arg,
int alg_arg,
int expected_status_arg,
int is_large_key_arg,
int arg_thread_count,
int reps_arg)
{
size_t thread_count = (size_t) arg_thread_count;
mbedtls_test_thread_t *threads = NULL;
generate_key_context gkc;
gkc.type = type_arg;
gkc.usage = usage_arg;
gkc.bits = bits_arg;
gkc.alg = alg_arg;
gkc.expected_status = expected_status_arg;
gkc.is_large_key = is_large_key_arg;
gkc.reps = reps_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage_arg);
psa_set_key_algorithm(&attributes, alg_arg);
psa_set_key_type(&attributes, type_arg);
psa_set_key_bits(&attributes, bits_arg);
gkc.attributes = &attributes;
TEST_CALLOC(threads, sizeof(mbedtls_test_thread_t) * thread_count);
/* Split threads to generate key then destroy key. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(
mbedtls_test_thread_create(&threads[i], thread_generate_key,
(void *) &gkc), 0);
}
/* Join threads. */
for (size_t i = 0; i < thread_count; i++) {
TEST_EQUAL(mbedtls_test_thread_join(&threads[i]), 0);
}
exit:
mbedtls_free(threads);
PSA_DONE();
}
/* END_CASE */
#endif
/* BEGIN_CASE */
void generate_key(int type_arg,
int bits_arg,
int usage_arg,
int alg_arg,
int expected_status_arg,
int is_large_key)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
psa_key_usage_t usage = usage_arg;
size_t bits = bits_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, bits);
/* Generate a key */
psa_status_t status = psa_generate_key(&attributes, &key);
if (is_large_key > 0) {
TEST_ASSUME(status != PSA_ERROR_INSUFFICIENT_MEMORY);
}
TEST_EQUAL(status, expected_status);
if (expected_status != PSA_SUCCESS) {
goto exit;
}
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
/* Do something with the key according to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
goto exit;
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void generate_key_ext(int type_arg,
int bits_arg,
int usage_arg,
int alg_arg,
int flags_arg,
data_t *params_data,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
psa_key_usage_t usage = usage_arg;
size_t bits = bits_arg;
psa_algorithm_t alg = alg_arg;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_production_parameters_t *params = NULL;
size_t params_data_length = 0;
psa_key_attributes_t got_attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, bits);
if (!setup_key_production_parameters(&params, &params_data_length,
flags_arg, params_data)) {
goto exit;
}
/* Generate a key */
psa_status_t status = psa_generate_key_ext(&attributes,
params, params_data_length,
&key);
TEST_EQUAL(status, expected_status);
if (expected_status != PSA_SUCCESS) {
goto exit;
}
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &got_attributes));
TEST_EQUAL(psa_get_key_type(&got_attributes), type);
TEST_EQUAL(psa_get_key_bits(&got_attributes), bits);
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
TEST_ASSERT(rsa_test_e(key, bits, params_data));
}
#endif
/* Do something with the key according to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, usage, alg, 0)) {
goto exit;
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&got_attributes);
mbedtls_free(params);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void key_production_parameters_init()
{
psa_key_production_parameters_t init = PSA_KEY_PRODUCTION_PARAMETERS_INIT;
psa_key_production_parameters_t zero;
memset(&zero, 0, sizeof(zero));
TEST_EQUAL(init.flags, 0);
TEST_EQUAL(zero.flags, 0);
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_PSA_CRYPTO_STORAGE_C */
void persistent_key_load_key_from_storage(data_t *data,
int type_arg, int bits_arg,
int usage_flags_arg, int alg_arg,
int generation_method)
{
mbedtls_svc_key_id_t key_id = mbedtls_svc_key_id_make(1, 1);
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_svc_key_id_t base_key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = type_arg;
size_t bits = bits_arg;
psa_key_usage_t usage_flags = usage_flags_arg;
psa_algorithm_t alg = alg_arg;
psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
unsigned char *first_export = NULL;
unsigned char *second_export = NULL;
size_t export_size = PSA_EXPORT_KEY_OUTPUT_SIZE(type, bits);
size_t first_exported_length = 0;
size_t second_exported_length;
if (usage_flags & PSA_KEY_USAGE_EXPORT) {
TEST_CALLOC(first_export, export_size);
TEST_CALLOC(second_export, export_size);
}
PSA_ASSERT(psa_crypto_init());
psa_set_key_id(&attributes, key_id);
psa_set_key_usage_flags(&attributes, usage_flags);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, type);
psa_set_key_bits(&attributes, bits);
switch (generation_method) {
case IMPORT_KEY:
/* Import the key */
PSA_ASSERT(psa_import_key(&attributes, data->x, data->len,
&key));
break;
case GENERATE_KEY:
/* Generate a key */
PSA_ASSERT(psa_generate_key(&attributes, &key));
break;
case DERIVE_KEY:
#if defined(PSA_WANT_ALG_HKDF) && defined(PSA_WANT_ALG_SHA_256)
{
/* Create base key */
psa_algorithm_t derive_alg = PSA_ALG_HKDF(PSA_ALG_SHA_256);
psa_key_attributes_t base_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&base_attributes,
PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&base_attributes, derive_alg);
psa_set_key_type(&base_attributes, PSA_KEY_TYPE_DERIVE);
PSA_ASSERT(psa_import_key(&base_attributes,
data->x, data->len,
&base_key));
/* Derive a key. */
PSA_ASSERT(psa_key_derivation_setup(&operation, derive_alg));
PSA_ASSERT(psa_key_derivation_input_key(
&operation,
PSA_KEY_DERIVATION_INPUT_SECRET, base_key));
PSA_ASSERT(psa_key_derivation_input_bytes(
&operation, PSA_KEY_DERIVATION_INPUT_INFO,
NULL, 0));
PSA_ASSERT(psa_key_derivation_output_key(&attributes,
&operation,
&key));
PSA_ASSERT(psa_key_derivation_abort(&operation));
PSA_ASSERT(psa_destroy_key(base_key));
base_key = MBEDTLS_SVC_KEY_ID_INIT;
}
#else
TEST_ASSUME(!"KDF not supported in this configuration");
#endif
break;
default:
TEST_FAIL("generation_method not implemented in test");
break;
}
psa_reset_key_attributes(&attributes);
/* Export the key if permitted by the key policy. */
if (usage_flags & PSA_KEY_USAGE_EXPORT) {
PSA_ASSERT(psa_export_key(key,
first_export, export_size,
&first_exported_length));
if (generation_method == IMPORT_KEY) {
TEST_MEMORY_COMPARE(data->x, data->len,
first_export, first_exported_length);
}
}
/* Shutdown and restart */
PSA_ASSERT(psa_purge_key(key));
PSA_DONE();
PSA_ASSERT(psa_crypto_init());
/* Check key slot still contains key data */
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
TEST_ASSERT(mbedtls_svc_key_id_equal(
psa_get_key_id(&attributes), key_id));
TEST_EQUAL(psa_get_key_lifetime(&attributes),
PSA_KEY_LIFETIME_PERSISTENT);
TEST_EQUAL(psa_get_key_type(&attributes), type);
TEST_EQUAL(psa_get_key_bits(&attributes), bits);
TEST_EQUAL(psa_get_key_usage_flags(&attributes),
mbedtls_test_update_key_usage_flags(usage_flags));
TEST_EQUAL(psa_get_key_algorithm(&attributes), alg);
/* Export the key again if permitted by the key policy. */
if (usage_flags & PSA_KEY_USAGE_EXPORT) {
PSA_ASSERT(psa_export_key(key,
second_export, export_size,
&second_exported_length));
TEST_MEMORY_COMPARE(first_export, first_exported_length,
second_export, second_exported_length);
}
/* Do something with the key according to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, usage_flags, alg, 0)) {
goto exit;
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes()
* thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
mbedtls_free(first_export);
mbedtls_free(second_export);
psa_key_derivation_abort(&operation);
psa_destroy_key(base_key);
psa_destroy_key(key);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
void ecjpake_setup(int alg_arg, int key_type_pw_arg, int key_usage_pw_arg,
int primitive_arg, int hash_arg, int role_arg,
int test_input, data_t *pw_data,
int inj_err_type_arg,
int expected_error_arg)
{
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_pake_operation_t operation = psa_pake_operation_init();
psa_algorithm_t alg = alg_arg;
psa_pake_primitive_t primitive = primitive_arg;
psa_key_type_t key_type_pw = key_type_pw_arg;
psa_key_usage_t key_usage_pw = key_usage_pw_arg;
psa_algorithm_t hash_alg = hash_arg;
psa_pake_role_t role = role_arg;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
ecjpake_injected_failure_t inj_err_type = inj_err_type_arg;
psa_status_t expected_error = expected_error_arg;
psa_status_t status;
unsigned char *output_buffer = NULL;
size_t output_len = 0;
PSA_INIT();
size_t buf_size = PSA_PAKE_OUTPUT_SIZE(alg, primitive_arg,
PSA_PAKE_STEP_KEY_SHARE);
TEST_CALLOC(output_buffer, buf_size);
if (pw_data->len > 0) {
psa_set_key_usage_flags(&attributes, key_usage_pw);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, key_type_pw);
PSA_ASSERT(psa_import_key(&attributes, pw_data->x, pw_data->len,
&key));
}
psa_pake_cs_set_algorithm(&cipher_suite, alg);
psa_pake_cs_set_primitive(&cipher_suite, primitive);
psa_pake_cs_set_hash(&cipher_suite, hash_alg);
PSA_ASSERT(psa_pake_abort(&operation));
if (inj_err_type == INJECT_ERR_UNINITIALIZED_ACCESS) {
TEST_EQUAL(psa_pake_set_user(&operation, NULL, 0),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
TEST_EQUAL(psa_pake_set_peer(&operation, NULL, 0),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
TEST_EQUAL(psa_pake_set_password_key(&operation, key),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
TEST_EQUAL(psa_pake_set_role(&operation, role),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_KEY_SHARE,
NULL, 0, NULL),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_KEY_SHARE, NULL, 0),
expected_error);
PSA_ASSERT(psa_pake_abort(&operation));
goto exit;
}
status = psa_pake_setup(&operation, &cipher_suite);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_error);
goto exit;
}
if (inj_err_type == INJECT_ERR_DUPLICATE_SETUP) {
TEST_EQUAL(psa_pake_setup(&operation, &cipher_suite),
expected_error);
goto exit;
}
status = psa_pake_set_role(&operation, role);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_error);
goto exit;
}
if (pw_data->len > 0) {
status = psa_pake_set_password_key(&operation, key);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_error);
goto exit;
}
}
if (inj_err_type == INJECT_ERR_INVALID_USER) {
TEST_EQUAL(psa_pake_set_user(&operation, NULL, 0),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_ERR_INVALID_PEER) {
TEST_EQUAL(psa_pake_set_peer(&operation, NULL, 0),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_ERR_SET_USER) {
const uint8_t unsupported_id[] = "abcd";
TEST_EQUAL(psa_pake_set_user(&operation, unsupported_id, 4),
PSA_ERROR_NOT_SUPPORTED);
goto exit;
}
if (inj_err_type == INJECT_ERR_SET_PEER) {
const uint8_t unsupported_id[] = "abcd";
TEST_EQUAL(psa_pake_set_peer(&operation, unsupported_id, 4),
PSA_ERROR_NOT_SUPPORTED);
goto exit;
}
const size_t size_key_share = PSA_PAKE_INPUT_SIZE(alg, primitive,
PSA_PAKE_STEP_KEY_SHARE);
const size_t size_zk_public = PSA_PAKE_INPUT_SIZE(alg, primitive,
PSA_PAKE_STEP_ZK_PUBLIC);
const size_t size_zk_proof = PSA_PAKE_INPUT_SIZE(alg, primitive,
PSA_PAKE_STEP_ZK_PROOF);
if (test_input) {
if (inj_err_type == INJECT_EMPTY_IO_BUFFER) {
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PROOF, NULL, 0),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_UNKNOWN_STEP) {
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PROOF + 10,
output_buffer, size_zk_proof),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_INVALID_FIRST_STEP) {
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PROOF,
output_buffer, size_zk_proof),
PSA_ERROR_BAD_STATE);
goto exit;
}
status = psa_pake_input(&operation, PSA_PAKE_STEP_KEY_SHARE,
output_buffer, size_key_share);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_error);
goto exit;
}
if (inj_err_type == INJECT_WRONG_BUFFER_SIZE) {
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, size_zk_public + 1),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_VALID_OPERATION_AFTER_FAILURE) {
// Just trigger any kind of error. We don't care about the result here
psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, size_zk_public + 1);
TEST_EQUAL(psa_pake_input(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, size_zk_public),
PSA_ERROR_BAD_STATE);
goto exit;
}
} else {
if (inj_err_type == INJECT_EMPTY_IO_BUFFER) {
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PROOF,
NULL, 0, NULL),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_UNKNOWN_STEP) {
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PROOF + 10,
output_buffer, buf_size, &output_len),
PSA_ERROR_INVALID_ARGUMENT);
goto exit;
}
if (inj_err_type == INJECT_INVALID_FIRST_STEP) {
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PROOF,
output_buffer, buf_size, &output_len),
PSA_ERROR_BAD_STATE);
goto exit;
}
status = psa_pake_output(&operation, PSA_PAKE_STEP_KEY_SHARE,
output_buffer, buf_size, &output_len);
if (status != PSA_SUCCESS) {
TEST_EQUAL(status, expected_error);
goto exit;
}
TEST_ASSERT(output_len > 0);
if (inj_err_type == INJECT_WRONG_BUFFER_SIZE) {
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, size_zk_public - 1, &output_len),
PSA_ERROR_BUFFER_TOO_SMALL);
goto exit;
}
if (inj_err_type == INJECT_VALID_OPERATION_AFTER_FAILURE) {
// Just trigger any kind of error. We don't care about the result here
psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, size_zk_public - 1, &output_len);
TEST_EQUAL(psa_pake_output(&operation, PSA_PAKE_STEP_ZK_PUBLIC,
output_buffer, buf_size, &output_len),
PSA_ERROR_BAD_STATE);
goto exit;
}
}
exit:
PSA_ASSERT(psa_destroy_key(key));
PSA_ASSERT(psa_pake_abort(&operation));
mbedtls_free(output_buffer);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
void ecjpake_rounds_inject(int alg_arg, int primitive_arg, int hash_arg,
int client_input_first, int inject_error,
data_t *pw_data)
{
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_pake_operation_t server = psa_pake_operation_init();
psa_pake_operation_t client = psa_pake_operation_init();
psa_algorithm_t alg = alg_arg;
psa_algorithm_t hash_alg = hash_arg;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
PSA_INIT();
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
PSA_ASSERT(psa_import_key(&attributes, pw_data->x, pw_data->len,
&key));
psa_pake_cs_set_algorithm(&cipher_suite, alg);
psa_pake_cs_set_primitive(&cipher_suite, primitive_arg);
psa_pake_cs_set_hash(&cipher_suite, hash_alg);
PSA_ASSERT(psa_pake_setup(&server, &cipher_suite));
PSA_ASSERT(psa_pake_setup(&client, &cipher_suite));
PSA_ASSERT(psa_pake_set_role(&server, PSA_PAKE_ROLE_SERVER));
PSA_ASSERT(psa_pake_set_role(&client, PSA_PAKE_ROLE_CLIENT));
PSA_ASSERT(psa_pake_set_password_key(&server, key));
PSA_ASSERT(psa_pake_set_password_key(&client, key));
ecjpake_do_round(alg, primitive_arg, &server, &client,
client_input_first, 1, inject_error);
if (inject_error == 1 || inject_error == 2) {
goto exit;
}
ecjpake_do_round(alg, primitive_arg, &server, &client,
client_input_first, 2, inject_error);
exit:
psa_destroy_key(key);
psa_pake_abort(&server);
psa_pake_abort(&client);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:PSA_WANT_ALG_JPAKE */
void ecjpake_rounds(int alg_arg, int primitive_arg, int hash_arg,
int derive_alg_arg, data_t *pw_data,
int client_input_first, int inj_err_type_arg)
{
psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
psa_pake_operation_t server = psa_pake_operation_init();
psa_pake_operation_t client = psa_pake_operation_init();
psa_algorithm_t alg = alg_arg;
psa_algorithm_t hash_alg = hash_arg;
psa_algorithm_t derive_alg = derive_alg_arg;
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_derivation_operation_t server_derive =
PSA_KEY_DERIVATION_OPERATION_INIT;
psa_key_derivation_operation_t client_derive =
PSA_KEY_DERIVATION_OPERATION_INIT;
ecjpake_injected_failure_t inj_err_type = inj_err_type_arg;
PSA_INIT();
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_PASSWORD);
PSA_ASSERT(psa_import_key(&attributes, pw_data->x, pw_data->len,
&key));
psa_pake_cs_set_algorithm(&cipher_suite, alg);
psa_pake_cs_set_primitive(&cipher_suite, primitive_arg);
psa_pake_cs_set_hash(&cipher_suite, hash_alg);
/* Get shared key */
PSA_ASSERT(psa_key_derivation_setup(&server_derive, derive_alg));
PSA_ASSERT(psa_key_derivation_setup(&client_derive, derive_alg));
if (PSA_ALG_IS_TLS12_PRF(derive_alg) ||
PSA_ALG_IS_TLS12_PSK_TO_MS(derive_alg)) {
PSA_ASSERT(psa_key_derivation_input_bytes(&server_derive,
PSA_KEY_DERIVATION_INPUT_SEED,
(const uint8_t *) "", 0));
PSA_ASSERT(psa_key_derivation_input_bytes(&client_derive,
PSA_KEY_DERIVATION_INPUT_SEED,
(const uint8_t *) "", 0));
}
PSA_ASSERT(psa_pake_setup(&server, &cipher_suite));
PSA_ASSERT(psa_pake_setup(&client, &cipher_suite));
PSA_ASSERT(psa_pake_set_role(&server, PSA_PAKE_ROLE_SERVER));
PSA_ASSERT(psa_pake_set_role(&client, PSA_PAKE_ROLE_CLIENT));
PSA_ASSERT(psa_pake_set_password_key(&server, key));
PSA_ASSERT(psa_pake_set_password_key(&client, key));
if (inj_err_type == INJECT_ANTICIPATE_KEY_DERIVATION_1) {
TEST_EQUAL(psa_pake_get_implicit_key(&server, &server_derive),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_pake_get_implicit_key(&client, &client_derive),
PSA_ERROR_BAD_STATE);
goto exit;
}
/* First round */
ecjpake_do_round(alg, primitive_arg, &server, &client,
client_input_first, 1, 0);
if (inj_err_type == INJECT_ANTICIPATE_KEY_DERIVATION_2) {
TEST_EQUAL(psa_pake_get_implicit_key(&server, &server_derive),
PSA_ERROR_BAD_STATE);
TEST_EQUAL(psa_pake_get_implicit_key(&client, &client_derive),
PSA_ERROR_BAD_STATE);
goto exit;
}
/* Second round */
ecjpake_do_round(alg, primitive_arg, &server, &client,
client_input_first, 2, 0);
PSA_ASSERT(psa_pake_get_implicit_key(&server, &server_derive));
PSA_ASSERT(psa_pake_get_implicit_key(&client, &client_derive));
exit:
psa_key_derivation_abort(&server_derive);
psa_key_derivation_abort(&client_derive);
psa_destroy_key(key);
psa_pake_abort(&server);
psa_pake_abort(&client);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE */
void ecjpake_size_macros()
{
const psa_algorithm_t alg = PSA_ALG_JPAKE;
const size_t bits = 256;
const psa_pake_primitive_t prim = PSA_PAKE_PRIMITIVE(
PSA_PAKE_PRIMITIVE_TYPE_ECC, PSA_ECC_FAMILY_SECP_R1, bits);
const psa_key_type_t key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(
PSA_ECC_FAMILY_SECP_R1);
// https://armmbed.github.io/mbed-crypto/1.1_PAKE_Extension.0-bet.0/html/pake.html#pake-step-types
/* The output for KEY_SHARE and ZK_PUBLIC is the same as a public key */
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, bits));
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, bits));
/* The output for ZK_PROOF is the same bitsize as the curve */
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
PSA_BITS_TO_BYTES(bits));
/* Input sizes are the same as output sizes */
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE));
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC));
TEST_EQUAL(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF));
/* These inequalities will always hold even when other PAKEs are added */
TEST_LE_U(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
PSA_PAKE_OUTPUT_MAX_SIZE);
TEST_LE_U(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
PSA_PAKE_OUTPUT_MAX_SIZE);
TEST_LE_U(PSA_PAKE_OUTPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
PSA_PAKE_OUTPUT_MAX_SIZE);
TEST_LE_U(PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_KEY_SHARE),
PSA_PAKE_INPUT_MAX_SIZE);
TEST_LE_U(PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PUBLIC),
PSA_PAKE_INPUT_MAX_SIZE);
TEST_LE_U(PSA_PAKE_INPUT_SIZE(alg, prim, PSA_PAKE_STEP_ZK_PROOF),
PSA_PAKE_INPUT_MAX_SIZE);
}
/* END_CASE */