mbedtls/tests/suites/test_suite_psa_crypto.function
Paul Elliott f8e5b56ad8 Fix get_num_ops internal code.
Previously calling get_num_ops more than once would have ended up with ops
getting double counted, and not calling inbetween completes would have ended up
with ops getting missed. Fix this by moving this to where the work is actually
done, and add tests for double calls to get_num_ops().

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
2023-02-19 18:55:10 +00:00

9941 lines
369 KiB
C

/* BEGIN_HEADER */
#include <stdint.h>
#include "mbedtls/asn1.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
#include "common.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"
#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
#include "mbedtls/legacy_or_psa.h"
/* 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 */
/* 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;
}
ASSERT_ALLOC(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);
}
ASSERT_ALLOC(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);
ASSERT_ALLOC(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));
}
ASSERT_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));
ASSERT_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;
ASSERT_ALLOC(buffer0, buffer_length);
ASSERT_ALLOC(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 */
/* END_HEADER */
/* BEGIN_DEPENDENCIES
* depends_on:MBEDTLS_PSA_CRYPTO_C
* END_DEPENDENCIES
*/
/* 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);
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 */
ASSERT_ALLOC_WEAK(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());
ASSERT_ALLOC(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;
ASSERT_ALLOC(exported, export_size);
if (!canonical_input) {
ASSERT_ALLOC(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);
/* 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), (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)) {
goto exit;
}
}
if (canonical_input) {
ASSERT_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));
ASSERT_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)));
TEST_LE_U(exported_length, PSA_EXPORT_KEY_PAIR_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 */
ASSERT_ALLOC(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);
ASSERT_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 */
/* 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)) {
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);
ASSERT_ALLOC(input, input_buffer_size);
ASSERT_ALLOC(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)
{
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);
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);
ASSERT_ALLOC(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);
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)) {
goto exit;
}
if (!mbedtls_test_psa_exercise_key(key, usage, alg2)) {
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);
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,
unsigned 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,
unsigned 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;
ASSERT_ALLOC(export_buffer, material->len);
PSA_ASSERT(psa_export_key(target_key, export_buffer,
material->len, &length));
ASSERT_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)) {
goto exit;
}
if (!mbedtls_test_psa_exercise_key(target_key, expected_usage, expected_alg2)) {
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);
ASSERT_ALLOC(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;
ASSERT_ALLOC(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));
ASSERT_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));
ASSERT_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));
ASSERT_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));
ASSERT_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);
ASSERT_ALLOC(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) {
ASSERT_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) {
ASSERT_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. */
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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;
ASSERT_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;
ASSERT_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));
ASSERT_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));
ASSERT_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);
ASSERT_ALLOC(output1, output1_buffer_size);
ASSERT_ALLOC(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));
ASSERT_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);
ASSERT_ALLOC(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));
ASSERT_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);
ASSERT_ALLOC(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));
ASSERT_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) {
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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) {
ASSERT_ALLOC(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);
ASSERT_ALLOC(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));
ASSERT_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);
ASSERT_ALLOC(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;
ASSERT_ALLOC(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));
ASSERT_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));
ASSERT_ALLOC(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));
ASSERT_ALLOC(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));
ASSERT_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));
}
ASSERT_ALLOC(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) {
ASSERT_ALLOC(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);
ASSERT_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));
ASSERT_ALLOC(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);
ASSERT_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));
}
ASSERT_ALLOC(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) {
ASSERT_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);
ASSERT_ALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(ciphertext_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
ASSERT_ALLOC(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);
ASSERT_ALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
TEST_LE_U(ciphertext_size, PSA_AEAD_FINISH_OUTPUT_MAX_SIZE);
ASSERT_ALLOC(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. */
ASSERT_ALLOC(nonce_buffer, 4);
nonce_length = 0;
} else {
/* If length is zero, then this will return NULL. */
nonce_length = (size_t) nonce_length_arg;
ASSERT_ALLOC(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));
ASSERT_ALLOC(output, output_size);
ciphertext_size = PSA_AEAD_FINISH_OUTPUT_SIZE(key_type, alg);
ASSERT_ALLOC(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);
ASSERT_ALLOC(ciphertext, ciphertext_size);
ASSERT_ALLOC(finish_ciphertext, finish_ciphertext_size);
ASSERT_ALLOC(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);
ASSERT_ALLOC(plaintext, plaintext_size);
verify_plaintext_size = PSA_AEAD_VERIFY_OUTPUT_SIZE(key_type, alg);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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. */
ASSERT_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 */
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);
ASSERT_ALLOC(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. */
ASSERT_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;
ASSERT_ALLOC(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 */
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();
ASSERT_ALLOC(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) {
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);
ASSERT_ALLOC(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 */
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;
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);
ASSERT_ALLOC(signature, signature_size);
psa_interruptible_set_max_ops(max_ops);
interruptible_signverify_get_minmax_completes(max_ops, PSA_SUCCESS,
&min_completes, &max_completes);
/* Start performing the signature. */
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_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_sign_hash_abort(&sign_operation));
/* 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 */
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);
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 */
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) {
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 */
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);
ASSERT_ALLOC(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 */
void interruptible_signverify_hash_negative_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);
ASSERT_ALLOC(signature, signature_size);
/* --- 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));
/* --- 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);
input_buffer = mbedtls_calloc(1, input_data->len);
TEST_ASSERT(input_buffer != NULL);
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));
input_buffer = mbedtls_calloc(1, input_data->len);
TEST_ASSERT(input_buffer != NULL);
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);
PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */
void interruptible_signverify_hash_maxops_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;
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);
ASSERT_ALLOC(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);
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);
ASSERT_ALLOC(signature, signature_size);
PSA_ASSERT(psa_sign_message(key, alg,
input_data->x, input_data->len,
signature, signature_size,
&signature_length));
ASSERT_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;
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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);
TEST_EQUAL(output_length, expected_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);
}
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);
TEST_EQUAL(output_length, expected_output_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);
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);
ASSERT_ALLOC(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);
ASSERT_ALLOC(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));
ASSERT_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);
ASSERT_ALLOC(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));
ASSERT_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));
ASSERT_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;
ASSERT_ALLOC(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, int 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 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 };
psa_key_type_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 (key_types[i] != PSA_KEY_TYPE_NONE) {
psa_set_key_type(&attributes, key_types[i]);
PSA_ASSERT(psa_import_key(&attributes,
inputs[i]->x, inputs[i]->len,
&keys[i]));
if (PSA_KEY_TYPE_IS_KEY_PAIR(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]),
expected_statuses[i]);
} else {
TEST_EQUAL(psa_key_derivation_input_key(&operation, steps[i],
keys[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_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)) {
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;
}
}
ASSERT_ALLOC(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_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);
}
PSA_ASSERT(psa_key_derivation_input_key(&operation,
steps[i],
keys[i]));
break;
default:
TEST_ASSERT(!"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_ASSERT(!"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) {
ASSERT_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[16];
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)) {
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:MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
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;
ASSERT_ALLOC(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) {
ASSERT_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)) {
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)) {
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;
ASSERT_ALLOC(output_buffer, capacity);
ASSERT_ALLOC(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)) {
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)) {
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. */
ASSERT_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;
ASSERT_ALLOC(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) {
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));
ASSERT_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(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)) {
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 */
ASSERT_ALLOC(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));
ASSERT_COMPARE(output, output_length,
expected_output->x, expected_output->len);
mbedtls_free(output);
output = NULL;
output_length = ~0;
/* Larger buffer */
ASSERT_ALLOC(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));
ASSERT_COMPARE(output, output_length,
expected_output->x, expected_output->len);
mbedtls_free(output);
output = NULL;
output_length = ~0;
/* Buffer too small */
ASSERT_ALLOC(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 */
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;
ASSERT_ALLOC(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));
ASSERT_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));
ASSERT_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);
ASSERT_ALLOC(output, bytes);
ASSERT_ALLOC(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 */
/* 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)) {
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 depends_on:PSA_WANT_KEY_TYPE_RSA_KEY_PAIR:PSA_WANT_ALG_RSA_PKCS1V15_CRYPT:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_GENPRIME */
void generate_key_rsa(int bits_arg,
data_t *e_arg,
int expected_status_arg)
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_type_t type = PSA_KEY_TYPE_RSA_KEY_PAIR;
size_t bits = bits_arg;
psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT;
psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW;
psa_status_t expected_status = expected_status_arg;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
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;
uint8_t *e_read_buffer = NULL;
int is_default_public_exponent = 0;
size_t e_read_size = PSA_KEY_DOMAIN_PARAMETERS_SIZE(type, bits);
size_t e_read_length = SIZE_MAX;
if (e_arg->len == 0 ||
(e_arg->len == 3 &&
e_arg->x[0] == 1 && e_arg->x[1] == 0 && e_arg->x[2] == 1)) {
is_default_public_exponent = 1;
e_read_size = 0;
}
ASSERT_ALLOC(e_read_buffer, e_read_size);
ASSERT_ALLOC(exported, exported_size);
PSA_ASSERT(psa_crypto_init());
psa_set_key_usage_flags(&attributes, usage);
psa_set_key_algorithm(&attributes, alg);
PSA_ASSERT(psa_set_key_domain_parameters(&attributes, type,
e_arg->x, e_arg->len));
psa_set_key_bits(&attributes, bits);
/* Generate a key */
TEST_EQUAL(psa_generate_key(&attributes, &key), expected_status);
if (expected_status != PSA_SUCCESS) {
goto exit;
}
/* Test the key information */
PSA_ASSERT(psa_get_key_attributes(key, &attributes));
TEST_EQUAL(psa_get_key_type(&attributes), type);
TEST_EQUAL(psa_get_key_bits(&attributes), bits);
PSA_ASSERT(psa_get_key_domain_parameters(&attributes,
e_read_buffer, e_read_size,
&e_read_length));
if (is_default_public_exponent) {
TEST_EQUAL(e_read_length, 0);
} else {
ASSERT_COMPARE(e_read_buffer, e_read_length, e_arg->x, e_arg->len);
}
/* Do something with the key according to its type and permitted usage. */
if (!mbedtls_test_psa_exercise_key(key, usage, alg)) {
goto exit;
}
/* Export the key and check the public exponent. */
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 {
ASSERT_COMPARE(p, len, e_arg->x, e_arg->len);
}
}
exit:
/*
* Key attributes may have been returned by psa_get_key_attributes() or
* set by psa_set_key_domain_parameters() thus reset them as required.
*/
psa_reset_key_attributes(&attributes);
psa_destroy_key(key);
PSA_DONE();
mbedtls_free(e_read_buffer);
mbedtls_free(exported);
}
/* 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;
size_t second_exported_length;
if (usage_flags & PSA_KEY_USAGE_EXPORT) {
ASSERT_ALLOC(first_export, export_size);
ASSERT_ALLOC(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_ASSERT(!"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) {
ASSERT_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));
ASSERT_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)) {
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);
ASSERT_ALLOC(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 */