diff --git a/include/psa/crypto.h b/include/psa/crypto.h index cca77197c..1e7aaa8f7 100644 --- a/include/psa/crypto.h +++ b/include/psa/crypto.h @@ -3527,6 +3527,11 @@ psa_status_t psa_key_derivation_output_bytes( * In all cases, the data that is read is discarded from the operation. * The operation's capacity is decreased by the number of bytes read. * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * * \param[in] attributes The attributes for the new key. * \param[in,out] operation The key derivation operation object to read from. * \param[out] handle On success, a handle to the newly created key. @@ -3549,6 +3554,9 @@ psa_status_t psa_key_derivation_output_bytes( * implementation in general or in this particular location. * \retval #PSA_ERROR_INVALID_ARGUMENT * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. * \retval #PSA_ERROR_BAD_STATE * The operation state is not valid (it must be active and completed * all required input steps). diff --git a/include/psa/crypto_struct.h b/include/psa/crypto_struct.h index f177d5d91..9f55484e2 100644 --- a/include/psa/crypto_struct.h +++ b/include/psa/crypto_struct.h @@ -255,6 +255,7 @@ typedef struct psa_tls12_prf_key_derivation_s struct psa_key_derivation_s { psa_algorithm_t alg; + unsigned int can_output_key : 1; size_t capacity; union { @@ -268,7 +269,7 @@ struct psa_key_derivation_s }; /* This only zeroes out the first byte in the union, the rest is unspecified. */ -#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, {0}} +#define PSA_KEY_DERIVATION_OPERATION_INIT {0, 0, 0, {0}} static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) { const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; diff --git a/include/psa/crypto_values.h b/include/psa/crypto_values.h index 57d065149..6b6a9f85b 100644 --- a/include/psa/crypto_values.h +++ b/include/psa/crypto_values.h @@ -1622,7 +1622,11 @@ * (passed to psa_key_derivation_input_key()) * or the shared secret resulting from a key agreement * (obtained via psa_key_derivation_key_agreement()). - * It can also be a direct input (passed to key_derivation_input_bytes()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). */ #define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index cc60901a3..b9ea00f2c 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -4787,6 +4787,9 @@ psa_status_t psa_key_derivation_output_key( const psa_key_attributes_t *attribut if( psa_get_key_bits( attributes ) == 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); + if( ! operation->can_output_key ) + return( PSA_ERROR_NOT_PERMITTED ); + status = psa_start_key_creation( PSA_KEY_CREATION_DERIVE, attributes, handle, &slot, &driver ); #if defined(MBEDTLS_PSA_CRYPTO_SE_C) @@ -5174,6 +5177,7 @@ psa_status_t psa_key_derivation_input_key( { psa_key_slot_t *slot; psa_status_t status; + status = psa_get_transparent_key( handle, &slot, PSA_KEY_USAGE_DERIVE, operation->alg ); @@ -5182,6 +5186,12 @@ psa_status_t psa_key_derivation_input_key( psa_key_derivation_abort( operation ); return( status ); } + + /* Passing a key object as a SECRET input unlocks the permission + * to output to a key object. */ + if( step == PSA_KEY_DERIVATION_INPUT_SECRET ) + operation->can_output_key = 1; + return( psa_key_derivation_input_internal( operation, step, slot->attr.type, slot->data.raw.data, diff --git a/tests/suites/test_suite_psa_crypto.data b/tests/suites/test_suite_psa_crypto.data index cc468165d..6efdc01d1 100644 --- a/tests/suites/test_suite_psa_crypto.data +++ b/tests/suites/test_suite_psa_crypto.data @@ -1888,7 +1888,11 @@ PSA key derivation setup: bad algorithm depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_setup:PSA_ALG_CATEGORY_KEY_DERIVATION:PSA_ERROR_NOT_SUPPORTED -PSA key derivation: HKDF-SHA-256, good case +PSA key derivation: HKDF-SHA-256, good case, direct output +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS + +PSA key derivation: HKDF-SHA-256, good case, key output depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS @@ -1900,14 +1904,28 @@ PSA key derivation: HKDF-SHA-256, bad key type depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE -PSA key derivation: HKDF-SHA-256, direct secret +PSA key derivation: HKDF-SHA-256, bad key type, key output +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +# Whether we get NOT_PERMITTED or BAD_STATE for the output is an implementation +# detail. +derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_RAW_DATA:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED + +PSA key derivation: HKDF-SHA-256, direct secret, direct output depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS -PSA key derivation: HKDF-SHA-256, direct empty secret +PSA key derivation: HKDF-SHA-256, direct empty secret, direct output depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_NONE:PSA_SUCCESS +PSA key derivation: HKDF-SHA-256, direct secret, key output +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED + +PSA key derivation: HKDF-SHA-256, direct empty secret, key output +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_NOT_PERMITTED + PSA key derivation: HKDF-SHA-256, RAW_DATA key as salt depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_RAW_DATA:"412073616c74":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS @@ -1916,10 +1934,16 @@ PSA key derivation: HKDF-SHA-256, RAW_DATA key as info depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_RAW_DATA:"4120696e666f":PSA_SUCCESS:PSA_KEY_TYPE_DERIVE:PSA_SUCCESS -PSA key derivation: HKDF-SHA-256, DERIVE key as salt +PSA key derivation: HKDF-SHA-256, DERIVE key as salt, direct output depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_DERIVE:"412073616c74":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE +PSA key derivation: HKDF-SHA-256, DERIVE key as salt, key output +depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C +# Whether we get NOT_PERMITTED or BAD_STATE for the output is an implementation +# detail. +derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_DERIVE:"412073616c74":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_ERROR_BAD_STATE:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_NONE:"":PSA_ERROR_BAD_STATE:PSA_KEY_TYPE_RAW_DATA:PSA_ERROR_BAD_STATE + PSA key derivation: HKDF-SHA-256, DERIVE key as info depends_on:MBEDTLS_MD_C:MBEDTLS_SHA256_C derive_input:PSA_ALG_HKDF(PSA_ALG_SHA_256):PSA_KEY_DERIVATION_INPUT_SALT:PSA_KEY_TYPE_NONE:"":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_SECRET:PSA_KEY_TYPE_DERIVE:"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b":PSA_SUCCESS:PSA_KEY_DERIVATION_INPUT_INFO:PSA_KEY_TYPE_DERIVE:"4120696e666f":PSA_ERROR_INVALID_ARGUMENT:PSA_KEY_TYPE_NONE:PSA_ERROR_BAD_STATE