Split off psa_key_derivation_internal
Refactor psa_key_derivation to prepare for key agreement algorithms
which need to plug into key derivation after argument validation.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 4584f6b..b99c808 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3432,7 +3432,8 @@
/* Set up an HKDF-based generator. This is exactly the extract phase
* of the HKDF algorithm. */
static psa_status_t psa_generator_hkdf_setup( psa_hkdf_generator_t *hkdf,
- key_slot_t *slot,
+ const uint8_t *secret,
+ size_t secret_length,
psa_algorithm_t hash_alg,
const uint8_t *salt,
size_t salt_length,
@@ -3445,9 +3446,7 @@
PSA_ALG_HMAC_GET_HASH( hash_alg ) );
if( status != PSA_SUCCESS )
return( status );
- status = psa_hash_update( &hkdf->hmac.hash_ctx,
- slot->data.raw.data,
- slot->data.raw.bytes );
+ status = psa_hash_update( &hkdf->hmac.hash_ctx, secret, secret_length );
if( status != PSA_SUCCESS )
return( status );
status = psa_hmac_finish_internal( &hkdf->hmac,
@@ -3468,6 +3467,51 @@
return( PSA_SUCCESS );
}
+static psa_status_t psa_key_derivation_internal(
+ psa_crypto_generator_t *generator,
+ const uint8_t *secret, size_t secret_length,
+ psa_algorithm_t alg,
+ const uint8_t *salt, size_t salt_length,
+ const uint8_t *label, size_t label_length,
+ size_t capacity )
+{
+ psa_status_t status;
+ size_t max_capacity;
+
+ /* Set generator->alg even on failure so that abort knows what to do. */
+ generator->alg = alg;
+
+#if defined(MBEDTLS_MD_C)
+ if( PSA_ALG_IS_HKDF( alg ) )
+ {
+ psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg );
+ size_t hash_size = PSA_HASH_SIZE( hash_alg );
+ if( hash_size == 0 )
+ return( PSA_ERROR_NOT_SUPPORTED );
+ max_capacity = 255 * hash_size;
+ status = psa_generator_hkdf_setup( &generator->ctx.hkdf,
+ secret, secret_length,
+ hash_alg,
+ salt, salt_length,
+ label, label_length );
+ }
+ else
+#endif
+ {
+ return( PSA_ERROR_NOT_SUPPORTED );
+ }
+
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ if( capacity <= max_capacity )
+ generator->capacity = capacity;
+ else
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ return( PSA_SUCCESS );
+}
+
psa_status_t psa_key_derivation( psa_crypto_generator_t *generator,
psa_key_slot_t key,
psa_algorithm_t alg,
@@ -3483,41 +3527,27 @@
if( generator->alg != 0 )
return( PSA_ERROR_BAD_STATE );
- status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg );
- if( status != PSA_SUCCESS )
- return( status );
- if( slot->type != PSA_KEY_TYPE_DERIVE )
- return( PSA_ERROR_INVALID_ARGUMENT );
-
+ /* Make sure that alg is a key derivation algorithm. This prevents
+ * key selection algorithms, which psa_key_derivation_internal
+ * accepts for the sake of key agreement. */
if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) )
return( PSA_ERROR_INVALID_ARGUMENT );
-#if defined(MBEDTLS_MD_C)
- if( PSA_ALG_IS_HKDF( alg ) )
- {
- psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH( alg );
- size_t hash_size = PSA_HASH_SIZE( hash_alg );
- if( hash_size == 0 )
- return( PSA_ERROR_NOT_SUPPORTED );
- if( capacity > 255 * hash_size )
- return( PSA_ERROR_INVALID_ARGUMENT );
- status = psa_generator_hkdf_setup( &generator->ctx.hkdf,
- slot,
- hash_alg,
- salt, salt_length,
- label, label_length );
- }
- else
-#endif
- {
- return( PSA_ERROR_NOT_SUPPORTED );
- }
+ status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg );
+ if( status != PSA_SUCCESS )
+ return( status );
- /* Set generator->alg even on failure so that abort knows what to do. */
- generator->alg = alg;
- if( status == PSA_SUCCESS )
- generator->capacity = capacity;
- else
+ if( slot->type != PSA_KEY_TYPE_DERIVE )
+ return( PSA_ERROR_INVALID_ARGUMENT );
+
+ status = psa_key_derivation_internal( generator,
+ slot->data.raw.data,
+ slot->data.raw.bytes,
+ alg,
+ salt, salt_length,
+ label, label_length,
+ capacity );
+ if( status != PSA_SUCCESS )
psa_generator_abort( generator );
return( status );
}