mbedtls/tests/suites/test_suite_psa_crypto.function
Paul Elliott b0450febe6 Tests for sending too much data after set lengths
We previously had tests for not sending enough (additional) data, but
were missing tests for sending too much. I have added these to the state
tests, as I don't think this is complex enough to deserve a standalone
test.

Signed-off-by: Paul Elliott <paul.elliott@arm.com>
2021-09-01 15:09:15 +01:00

6473 lines
239 KiB
Text

/* BEGIN_HEADER */
#include <stdint.h>
#include "mbedtls/asn1.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.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"
/** 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 );
}
/* 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 );
}
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;
/*!
* \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 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 If not -1, the length of chunks to feed the
* data in to be encrypted / decrypted. If -1,
* no chunking
* \param do_set_lengths If non-zero, then set lengths prior to
* calling encryption / decryption.
* \param expected_output Expected output
* \param expect_valid_signature If non zero, we expect the signature to be
* valid
* \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
* \param swap_set_functions If non-zero, swap the order of set lengths
* and set nonce.
*
* \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,
data_t *input_data,
int data_part_len,
int do_set_lengths,
data_t *expected_output,
int expect_valid_signature,
int is_encrypt,
int do_zero_parts,
int swap_set_functions )
{
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;
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;
uint32_t part_offset = 0;
size_t part_length = 0;
size_t output_part_length = 0;
size_t tag_size = 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;
uint32_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_VERIFY_OUTPUT_SIZE( key_type, alg );
TEST_ASSERT( final_output_size <= PSA_AEAD_VERIFY_OUTPUT_MAX_SIZE );
}
else
{
final_output_size = PSA_AEAD_FINISH_OUTPUT_SIZE( key_type, alg );
TEST_ASSERT( final_output_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
}
ASSERT_ALLOC( final_data, final_output_size );
operation = psa_aead_operation_init( );
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( swap_set_functions )
{
if( do_set_lengths )
{
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
{
PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
if( do_set_lengths )
{
PSA_ASSERT( psa_aead_set_lengths( &operation, additional_data->len,
data_true_size ) );
}
}
if( ad_part_len != -1 )
{
/* Pass additional data in parts */
part_offset = 0;
while( part_offset < additional_data->len )
{
if( do_zero_parts && part_count++ & 0x01 )
{
part_length = 0;
}
else
{
if( additional_data->len - part_offset <
( uint32_t ) 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 ) );
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 != -1 )
{
/* Pass data in parts */
part_data_size = PSA_AEAD_UPDATE_OUTPUT_SIZE( key_type, alg,
( size_t ) data_part_len );
ASSERT_ALLOC( part_data, part_data_size );
part_offset = 0;
while( part_offset < data_true_size )
{
if( do_zero_parts && part_count++ & 0x01 )
{
part_length = 0;
}
else
{
if( ( data_true_size - part_offset ) < ( uint32_t ) 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 + part_offset ), part_data,
output_part_length );
}
part_offset += 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
{
status = psa_aead_verify( &operation, final_data,
final_output_size,
&output_part_length,
( input_data->x + data_true_size ),
tag_length );
if( status != PSA_SUCCESS )
{
if( !expect_valid_signature )
{
/* Expected failure. */
test_ok = 1;
goto exit;
}
else
PSA_ASSERT( status );
}
}
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_ASSERT( 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_ASSERT( 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 );
}
/* 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_ASSERT( 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 ), 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 */
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
* accomodate 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 */
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 expected_bits,
int export_size_delta,
int expected_export_status_arg,
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;
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_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_ASSERT( 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( ! 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_ASSERT( exported_length <=
PSA_EXPORT_KEY_OUTPUT_SIZE( type,
psa_get_key_bits( &got_attributes ) ) );
TEST_ASSERT( 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 );
mbedtls_free( exported );
mbedtls_free( reexported );
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void import_export_public_key( data_t *data,
int type_arg,
int alg_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;
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_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_ASSERT( expected_public_key->len <=
PSA_EXPORT_KEY_OUTPUT_SIZE( public_type, bits ) );
TEST_ASSERT( expected_public_key->len <=
PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE( public_type, bits ) );
TEST_ASSERT( 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, 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 supress 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,
int policy_alg,
int key_type,
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_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
psa_status_t status;
psa_status_t expected_status = expected_status_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 ) );
status = psa_mac_sign_setup( &operation, key, exercise_alg );
if( ( policy_usage & PSA_KEY_USAGE_SIGN_HASH ) == 0 )
TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
else
TEST_EQUAL( status, expected_status );
psa_mac_abort( &operation );
memset( mac, 0, sizeof( mac ) );
status = psa_mac_verify_setup( &operation, key, exercise_alg );
if( ( policy_usage & PSA_KEY_USAGE_VERIFY_HASH ) == 0 )
TEST_EQUAL( status, PSA_ERROR_NOT_PERMITTED );
else
TEST_EQUAL( status, expected_status );
exit:
psa_mac_abort( &operation );
psa_destroy_key( key );
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void cipher_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_cipher_operation_t operation = PSA_CIPHER_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 ) );
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 );
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 );
psa_destroy_key( key );
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void aead_key_policy( int policy_usage,
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_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_ASSERT( nonce_length <= sizeof( nonce ) );
TEST_ASSERT( 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 ) );
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 );
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 );
exit:
psa_destroy_key( key );
PSA_DONE( );
}
/* END_CASE */
/* BEGIN_CASE */
void asymmetric_encryption_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_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 ) );
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,
int policy_alg,
int key_type,
data_t *key_data,
int exercise_alg,
int payload_length_arg )
{
mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
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;
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 = psa_sign_hash( key, exercise_alg,
payload, payload_length,
signature, sizeof( signature ),
&signature_length );
if( compatible_alg && ( policy_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 && ( policy_usage & PSA_KEY_USAGE_VERIFY_HASH ) != 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 ) );
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,
int type_arg, data_t *material,
int copy_attributes,
int target_usage_arg,
int target_alg_arg, int target_alg2_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;
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_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;
/* Set volatile lifetime to reset the key identifier to 0. */
psa_set_key_lifetime( &target_attributes, PSA_KEY_LIFETIME_VOLATILE );
}
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( ! 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 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_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 supress 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;
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( ) );
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:
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_status_t expected_status = expected_status_arg;
psa_status_t status;
ASSERT_ALLOC( output, output_size );
PSA_ASSERT( psa_crypto_init( ) );
status = psa_hash_compute( alg, input->x, input->len,
output, output_size, &output_length );
TEST_EQUAL( status, expected_status );
TEST_ASSERT( output_length <= output_size );
exit:
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_status_t status;
PSA_ASSERT( psa_crypto_init( ) );
status = psa_hash_compare( alg, input->x, input->len,
reference_hash->x, reference_hash->len );
TEST_EQUAL( status, expected_status );
exit:
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;
size_t i;
PSA_ASSERT( psa_crypto_init( ) );
/* Compute with tight buffer */
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 larger buffer */
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 );
/* Compare with correct hash */
PSA_ASSERT( psa_hash_compare( alg, input->x, input->len,
output, output_length ) );
/* Compare with trailing garbage */
TEST_EQUAL( psa_hash_compare( alg, input->x, input->len,
output, output_length + 1 ),
PSA_ERROR_INVALID_SIGNATURE );
/* Compare with truncated hash */
TEST_EQUAL( psa_hash_compare( alg, input->x, input->len,
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;
TEST_EQUAL( psa_hash_compare( alg, input->x, input->len,
output, output_length ),
PSA_ERROR_INVALID_SIGNATURE );
output[i] ^= 1;
}
exit:
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 ) );
TEST_EQUAL( psa_hash_setup( &operation, alg ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_hash_abort( &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 ) );
/* 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 ) );
PSA_ASSERT( psa_hash_verify( &operation,
valid_hash, sizeof( valid_hash ) ) );
TEST_EQUAL( psa_hash_verify( &operation,
valid_hash, sizeof( valid_hash ) ),
PSA_ERROR_BAD_STATE );
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 ) );
TEST_EQUAL( psa_hash_verify( &operation, hash, expected_size - 1 ),
PSA_ERROR_INVALID_SIGNATURE );
/* 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 supress 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 ) );
TEST_EQUAL( psa_mac_sign_setup( &operation, key, alg ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_mac_abort( &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 ) ) );
TEST_EQUAL( psa_mac_verify_finish( &operation,
verify_mac, sizeof( verify_mac ) ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_mac_abort( &operation ) );
/* Setup verify but try sign. */
PSA_ASSERT( psa_mac_verify_setup( &operation, key, alg ) );
PSA_ASSERT( psa_mac_update( &operation, input, sizeof( input ) ) );
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 ) );
PSA_ASSERT( psa_destroy_key( key ) );
exit:
PSA_DONE( );
}
/* 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_ASSERT( 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. */
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_ASSERT( 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 ) );
/* Test the correct MAC. */
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. */
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. */
ASSERT_ALLOC( perturbed_mac, expected_mac->len + 1 );
memcpy( perturbed_mac, expected_mac->x, expected_mac->len );
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;
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 supress 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 ) );
TEST_EQUAL( psa_cipher_encrypt_setup( &operation, key, alg ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_cipher_abort( &operation ) );
/* Call decrypt setup twice in a row. */
PSA_ASSERT( psa_cipher_decrypt_setup( &operation, key, alg ) );
TEST_EQUAL( psa_cipher_decrypt_setup( &operation, key, alg ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_cipher_abort( &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 ) );
TEST_EQUAL( psa_cipher_generate_iv( &operation,
buffer, sizeof( buffer ),
&length ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_cipher_abort( &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 ) ) );
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 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. */
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 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. */
TEST_EQUAL( psa_cipher_finish( &operation,
buffer, sizeof( buffer ), &length ),
PSA_ERROR_BAD_STATE );
PSA_ASSERT( psa_cipher_abort( &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( int alg_arg, int key_type_arg,
data_t *key_data, data_t *iv,
data_t *input, data_t *expected_output,
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 *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_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
TEST_ASSERT( output_buffer_size <=
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output, output_buffer_size );
PSA_ASSERT( psa_cipher_update( &operation,
input->x, input->len,
output, output_buffer_size,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( 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_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 )
{
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;
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_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
TEST_ASSERT( output_buffer_size <=
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output, output_buffer_size );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size) );
total_output_length += function_output_length;
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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
alg,
input->len - first_part_size ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
total_output_length += function_output_length;
PSA_ASSERT( psa_cipher_finish( &operation,
( output_buffer_size == 0 ? NULL :
output + total_output_length ),
output_buffer_size - total_output_length,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
total_output_length += function_output_length;
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 )
{
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;
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_DECRYPT_OUTPUT_SIZE( key_type, alg, input->len );
TEST_ASSERT( output_buffer_size <=
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output, output_buffer_size );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( first_part_size ) );
total_output_length += function_output_length;
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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
alg,
input->len - first_part_size ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
total_output_length += function_output_length;
PSA_ASSERT( psa_cipher_finish( &operation,
( output_buffer_size == 0 ? NULL :
output + total_output_length ),
output_buffer_size - total_output_length,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
total_output_length += function_output_length;
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( int alg_arg, int key_type_arg,
data_t *key_data, data_t *iv,
data_t *input, data_t *expected_output,
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 *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_DECRYPT_OUTPUT_SIZE( key_type, alg, input->len );
TEST_ASSERT( output_buffer_size <=
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output, output_buffer_size );
PSA_ASSERT( psa_cipher_update( &operation,
input->x, input->len,
output, output_buffer_size,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( 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_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 iv[16] = {0};
size_t iv_size = 16;
size_t iv_length = 0;
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;
size_t function_output_length = 0;
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_size = PSA_CIPHER_ENCRYPT_OUTPUT_SIZE( key_type, alg, input->len );
TEST_ASSERT( output1_size <=
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output1, output1_size );
PSA_ASSERT( psa_cipher_update( &operation1, input->x, input->len,
output1, output1_size,
&output1_length ) );
TEST_ASSERT( output1_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, input->len ) );
TEST_ASSERT( output1_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( input->len ) );
PSA_ASSERT( psa_cipher_finish( &operation1,
output1 + output1_length,
output1_size - output1_length,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_MAX_SIZE );
output1_length += function_output_length;
PSA_ASSERT( psa_cipher_abort( &operation1 ) );
output2_size = output1_length;
TEST_ASSERT( output2_size <=
PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, output1_length ) );
TEST_ASSERT( output2_size <=
PSA_CIPHER_DECRYPT_OUTPUT_MAX_SIZE( output1_length ) );
ASSERT_ALLOC( output2, output2_size );
if( iv_length > 0 )
{
PSA_ASSERT( psa_cipher_set_iv( &operation2,
iv, iv_length ) );
}
PSA_ASSERT( psa_cipher_update( &operation2, output1, output1_length,
output2, output2_size,
&output2_length ) );
TEST_ASSERT( output2_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, output1_length ) );
TEST_ASSERT( output2_length <=
PSA_CIPHER_UPDATE_OUTPUT_MAX_SIZE( output1_length ) );
function_output_length = 0;
PSA_ASSERT( psa_cipher_finish( &operation2,
output2 + output2_length,
output2_size - output2_length,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( 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 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_ASSERT( output1_buffer_size <=
PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE( input->len ) );
ASSERT_ALLOC( output1, output1_buffer_size );
TEST_ASSERT( first_part_size <= input->len );
PSA_ASSERT( psa_cipher_update( &operation1, input->x, first_part_size,
output1, output1_buffer_size,
&function_output_length ) );
TEST_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
alg,
input->len - first_part_size ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( 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_ASSERT( output2_buffer_size <=
PSA_CIPHER_DECRYPT_OUTPUT_SIZE( key_type, alg, output1_length ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type, alg, first_part_size ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_UPDATE_OUTPUT_SIZE( key_type,
alg,
output1_length - first_part_size ) );
TEST_ASSERT( 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_ASSERT( function_output_length <=
PSA_CIPHER_FINISH_OUTPUT_SIZE( key_type, alg ) );
TEST_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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,
int do_test_ad_chunked,
data_t *input_data,
int do_test_data_chunked,
int do_set_lengths,
data_t *expected_output )
{
size_t ad_part_len = 0;
size_t data_part_len = 0;
TEST_ASSERT( do_test_ad_chunked || do_test_data_chunked );
/* Temporary whilst we have algorithms that cannot support chunking */
if( do_test_ad_chunked == 1 )
{
for( ad_part_len = 1; ad_part_len <= additional_data->len;
ad_part_len++ )
{
mbedtls_test_set_step( ad_part_len );
/* 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,
do_set_lengths,
expected_output,
1, 1, 0,
( ad_part_len & 0x01 ) ) )
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,
do_set_lengths,
expected_output,
1, 1, 1,
( ad_part_len & 0x01 ) ) )
break;
}
}
/* Temporary whilst we have algorithms that cannot support chunking */
if( do_test_data_chunked == 1 )
{
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( !aead_multipart_internal_func( key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
do_set_lengths,
expected_output,
1, 1, 0,
( data_part_len & 0x01 ) ) )
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,
do_set_lengths,
expected_output,
1, 1, 1,
( data_part_len & 0x01 ) ) )
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,
int do_test_ad_chunked,
data_t *input_data,
int do_test_data_chunked,
int do_set_lengths,
data_t *expected_output,
int expect_valid_signature )
{
size_t ad_part_len = 0;
size_t data_part_len = 0;
/* Temporary whilst we have algorithms that cannot support chunking */
if( do_test_ad_chunked == 1 )
{
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( !aead_multipart_internal_func( key_type_arg, key_data,
alg_arg, nonce,
additional_data,
ad_part_len,
input_data, -1,
do_set_lengths,
expected_output,
expect_valid_signature,
0, 0,
( ad_part_len & 0x01 ) ) )
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,
do_set_lengths,
expected_output,
expect_valid_signature,
0, 1,
( ad_part_len & 0x01 ) ) )
break;
}
}
/* Temporary whilst we have algorithms that cannot support chunking */
if( do_test_data_chunked == 1 )
{
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( !aead_multipart_internal_func( key_type_arg, key_data,
alg_arg, nonce,
additional_data, -1,
input_data, data_part_len,
do_set_lengths,
expected_output,
expect_valid_signature,
0, 0,
( data_part_len & 0x01 ) ) )
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,
do_set_lengths,
expected_output,
expect_valid_signature,
0, 1,
( data_part_len & 0x01 ) ) )
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;
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_ASSERT( ciphertext_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
ASSERT_ALLOC( ciphertext, ciphertext_size );
operation = psa_aead_operation_init( );
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 );
TEST_ASSERT( actual_nonce_length < PSA_AEAD_NONCE_MAX_SIZE );
if( expected_status == PSA_SUCCESS )
{
/* Ensure we can still complete operation. */
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,
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;
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 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];
int index = 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 ) );
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_ASSERT( ciphertext_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
ASSERT_ALLOC( ciphertext, ciphertext_size );
operation = psa_aead_operation_init( );
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 );
if( nonce_length == 0 )
{
/* Arbitrary size buffer, to test zero length valid buffer. */
ASSERT_ALLOC( nonce_buffer, 4 );
}
else
{
ASSERT_ALLOC( nonce_buffer, nonce_length );
for( index = 0; index < nonce_length - 1; ++index)
{
nonce_buffer[index] = 'a' + index;
}
}
status = psa_aead_set_nonce( &operation, nonce_buffer, nonce_length );
TEST_EQUAL( status, expected_status );
if( expected_status == PSA_SUCCESS )
{
/* Ensure we can still complete operation. */
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 );
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_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 );
operation = psa_aead_operation_init( );
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_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 buffer_size,
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_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_data = NULL;
unsigned char *final_data = NULL;
size_t output_size = 0;
size_t output_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_data, output_size );
TEST_ASSERT( buffer_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
ASSERT_ALLOC( final_data, buffer_size );
operation = psa_aead_operation_init( );
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_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 ) );
/* Ensure we can still complete operation. */
status = psa_aead_finish( &operation, final_data, buffer_size,
&output_length, tag_buffer,
PSA_AEAD_TAG_MAX_SIZE, &tag_length );
TEST_EQUAL( status, expected_status );
exit:
psa_destroy_key( key );
mbedtls_free( output_data );
mbedtls_free( final_data );
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;
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_ASSERT( 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_ASSERT( finish_output_size <= PSA_AEAD_FINISH_OUTPUT_MAX_SIZE );
ASSERT_ALLOC( final_data, finish_output_size );
/* Test all operations error without calling setup first. */
operation = psa_aead_operation_init( );
TEST_EQUAL( psa_aead_set_nonce( &operation, nonce->x, nonce->len ),
PSA_ERROR_BAD_STATE );
psa_aead_abort( &operation );
operation = psa_aead_operation_init( );
TEST_EQUAL( psa_aead_generate_nonce( &operation, nonce_buffer,
PSA_AEAD_NONCE_MAX_SIZE,
&nonce_length ),
PSA_ERROR_BAD_STATE );
psa_aead_abort( &operation );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
TEST_EQUAL( psa_aead_set_lengths( &operation, additional_data->len,
input_data->len ),
PSA_ERROR_BAD_STATE );
psa_aead_abort( &operation );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
TEST_EQUAL( psa_aead_update_ad( &operation, additional_data->x,
additional_data->len ),
PSA_ERROR_BAD_STATE );
psa_aead_abort( &operation );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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 );
/* Test for double setting nonce. */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 */
operation = psa_aead_operation_init( );
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 );
/* ------------------------------------------------------- */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 already starting data. */
operation = psa_aead_operation_init( );
PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
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 );
/* Test for not sending any additional data or data after setting non zero
* lengths for them. (encrypt) */
operation = psa_aead_operation_init( );
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) */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 sending too much additional data after setting lengths. */
operation = psa_aead_operation_init( );
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 );
/* Test for sending too much data after setting lengths. */
operation = psa_aead_operation_init( );
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 );
/* Test sending additional data after data. */
operation = psa_aead_operation_init( );
PSA_ASSERT( psa_aead_encrypt_setup( &operation, key, alg ) );
PSA_ASSERT( psa_aead_set_nonce( &operation, nonce->x, nonce->len ) );
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. */
operation = psa_aead_operation_init( );
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. */
operation = psa_aead_operation_init( );
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 advertized by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE( key_type,
key_bits, alg );
TEST_ASSERT( signature_size != 0 );
TEST_ASSERT( 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 */
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_ASSERT( 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_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 advertized by the
* library. */
signature_size = PSA_SIGN_OUTPUT_SIZE( key_type,
key_bits, alg );
TEST_ASSERT( signature_size != 0 );
TEST_ASSERT( 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_ASSERT( 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 */
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_ASSERT( 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 */
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 */
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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( output_size <= PSA_ASYMMETRIC_ENCRYPT_OUTPUT_MAX_SIZE );
ASSERT_ALLOC( output, output_size );
output2_size = input_data->len;
TEST_ASSERT( output2_size <=
PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE( key_type, key_bits, alg ) );
TEST_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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_ASSERT( 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 supress 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++ )
{
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, PSA_KEY_TYPE_RAW_DATA );
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 test_derive_invalid_key_derivation_state( 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 test_derive_invalid_key_derivation_tests( )
{
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 step2_arg, data_t *input2,
int step3_arg, data_t *input3,
int requested_capacity_arg,
data_t *expected_output1,
data_t *expected_output2 )
{
psa_algorithm_t alg = alg_arg;
psa_key_derivation_step_t steps[] = {step1_arg, step2_arg, step3_arg};
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 };
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 attributes = PSA_KEY_ATTRIBUTES_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( ) );
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 );
/* 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:
PSA_ASSERT( psa_import_key( &attributes,
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], &attributes ) );
TEST_ASSERT( PSA_BITS_TO_BYTES( psa_get_key_bits( &attributes ) ) <=
PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE );
}
PSA_ASSERT( psa_key_derivation_input_key(
&operation, steps[i], keys[i] ) );
break;
default:
PSA_ASSERT( psa_key_derivation_input_bytes(
&operation, steps[i],
inputs[i]->x, inputs[i]->len ) );
break;
}
}
PSA_ASSERT( psa_key_derivation_get_capacity( &operation,
&current_capacity ) );
TEST_EQUAL( current_capacity, requested_capacity );
expected_capacity = requested_capacity;
/* 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_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 */
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( 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;
ASSERT_ALLOC( output, expected_output->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_get_key_attributes( our_key, &attributes ) );
key_bits = psa_get_key_bits( &attributes );
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 );
TEST_ASSERT( output_length <=
PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE( our_key_type, key_bits ) );
TEST_ASSERT( output_length <=
PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE );
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 advertized 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 ), 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 */