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