Key derivation: test deriving a key from the KDF output
diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data
index f906874..43b9647 100644
--- a/tests/suites/test_suite_psa_crypto.data
+++ b/tests/suites/test_suite_psa_crypto.data
@@ -852,6 +852,23 @@
PSA key derivation: over capacity 42: output 43+1
depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
derive_output:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":42:"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865ff":"ff"
+
+PSA key derivation: HKDF SHA-256, exercise HMAC-SHA-256
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_HMAC:256:PSA_KEY_USAGE_SIGN:PSA_ALG_HMAC(PSA_ALG_SHA_256)
+
+PSA key derivation: HKDF SHA-256, exercise HKDF-SHA-256
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+derive_key_exercise:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":PSA_KEY_TYPE_DERIVE:400:PSA_KEY_USAGE_DERIVE:PSA_ALG_HKDF(PSA_ALG_SHA_256)
+
+PSA key derivation: HKDF SHA-256, derive key, 16+32
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":16:32
+
+PSA key derivation: HKDF SHA-256, derive key, 1+41
+depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C
+derive_key_export:PSA_ALG_HKDF(PSA_ALG_SHA_256):"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":"000102030405060708090a0b0c":"f0f1f2f3f4f5f6f7f8f9":1:41
+
PSA generate random: 0 bytes
generate_random:0
diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function
index cf72e48..1f1732e 100644
--- a/tests/suites/test_suite_psa_crypto.function
+++ b/tests/suites/test_suite_psa_crypto.function
@@ -2584,6 +2584,149 @@
/* END_CASE */
/* BEGIN_CASE */
+void derive_key_exercise( int alg_arg,
+ data_t *key_data,
+ data_t *salt,
+ data_t *label,
+ int derived_type_arg,
+ int derived_bits_arg,
+ int derived_usage_arg,
+ int derived_alg_arg )
+{
+ psa_key_slot_t base_key = 1;
+ psa_key_slot_t derived_key = 2;
+ 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_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ psa_key_policy_t policy;
+ psa_key_type_t got_type;
+ size_t got_bits;
+
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Derive a key. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ psa_key_policy_set_usage( &policy, derived_usage, derived_alg );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ derived_type,
+ derived_bits,
+ &generator ) == PSA_SUCCESS );
+
+ /* Test the key information */
+ TEST_ASSERT( psa_get_key_information( derived_key,
+ &got_type,
+ &got_bits ) == PSA_SUCCESS );
+ TEST_ASSERT( got_type == derived_type );
+ TEST_ASSERT( got_bits == derived_bits );
+
+ /* Exercise the derived key. */
+ if( ! exercise_key( derived_key, derived_usage, derived_alg ) )
+ goto exit;
+
+exit:
+ psa_generator_abort( &generator );
+ psa_destroy_key( base_key );
+ psa_destroy_key( derived_key );
+ mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void derive_key_export( int alg_arg,
+ data_t *key_data,
+ data_t *salt,
+ data_t *label,
+ int bytes1_arg,
+ int bytes2_arg )
+{
+ psa_key_slot_t base_key = 1;
+ psa_key_slot_t derived_key = 2;
+ psa_algorithm_t alg = alg_arg;
+ size_t bytes1 = bytes1_arg;
+ size_t bytes2 = bytes2_arg;
+ size_t capacity = bytes1 + bytes2;
+ psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT;
+ uint8_t *output_buffer = mbedtls_calloc( 1, capacity );
+ uint8_t *export_buffer = mbedtls_calloc( 1, capacity );
+ psa_key_policy_t policy;
+ size_t length;
+
+ TEST_ASSERT( output_buffer != NULL );
+ TEST_ASSERT( export_buffer != NULL );
+ TEST_ASSERT( psa_crypto_init( ) == PSA_SUCCESS );
+
+ psa_key_policy_init( &policy );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg );
+ TEST_ASSERT( psa_set_key_policy( base_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_import_key( base_key, PSA_KEY_TYPE_DERIVE,
+ key_data->x,
+ key_data->len ) == PSA_SUCCESS );
+
+ /* Derive some material and output it. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_read( &generator,
+ output_buffer,
+ capacity ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_abort( &generator ) == PSA_SUCCESS );
+
+ /* Derive the same output again, but this time store it in key objects. */
+ TEST_ASSERT( psa_key_derivation( &generator, base_key, alg,
+ salt->x, salt->len,
+ label->x, label->len,
+ capacity ) == PSA_SUCCESS );
+ psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_EXPORT, 0 );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ PSA_KEY_TYPE_RAW_DATA,
+ PSA_BYTES_TO_BITS( bytes1 ),
+ &generator ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_export_key( derived_key,
+ export_buffer, bytes1,
+ &length ) == PSA_SUCCESS );
+ TEST_ASSERT( length == bytes1 );
+ TEST_ASSERT( psa_destroy_key( derived_key ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_set_key_policy( derived_key, &policy ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_generator_import_key( derived_key,
+ PSA_KEY_TYPE_RAW_DATA,
+ PSA_BYTES_TO_BITS( bytes2 ),
+ &generator ) == PSA_SUCCESS );
+ TEST_ASSERT( psa_export_key( derived_key,
+ export_buffer + bytes1, bytes2,
+ &length ) == PSA_SUCCESS );
+ TEST_ASSERT( length == bytes2 );
+
+ /* Compare the outputs from the two runs. */
+ TEST_ASSERT( memcmp( output_buffer, export_buffer, capacity ) == 0 );
+
+exit:
+ mbedtls_free( output_buffer );
+ mbedtls_free( export_buffer );
+ psa_generator_abort( &generator );
+ psa_destroy_key( base_key );
+ psa_destroy_key( derived_key );
+ mbedtls_psa_crypto_free( );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void generate_random( int bytes_arg )
{
size_t bytes = bytes_arg;