More refactoring: consolidate attribute validation
Consolidate attribute validation at the beginning of key creation into
a single function. Improve comments.
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 258caad..3f5f371 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -1403,10 +1403,14 @@
data_length, 1 ) );
}
-static psa_status_t psa_check_key_slot_policy(
- const psa_key_slot_t *slot )
+/** Validate that a key policy is internally well-formed.
+ *
+ * This function only rejects invalid policies. It does not validate the
+ * consistency of the policy with respect to other attributes of the key
+ * such as the key type.
+ */
+static psa_status_t psa_validate_key_policy( const psa_key_policy_t *policy )
{
- const psa_key_policy_t *policy = &slot->attr.policy;
if( ( policy->usage & ~( PSA_KEY_USAGE_EXPORT |
PSA_KEY_USAGE_COPY |
PSA_KEY_USAGE_ENCRYPT |
@@ -1419,6 +1423,48 @@
return( PSA_SUCCESS );
}
+/** Validate the internal consistency of key attributes.
+ *
+ * This function only rejects invalid attribute values. If does not
+ * validate the consistency of the attributes with any key data that may
+ * be involved in the creation of the key.
+ *
+ * Call this function early in the key creation process.
+ *
+ * \param[in] attributes Key attributes for the new key.
+ * \param[out] p_drv On any return, the driver for the key, if any.
+ * NULL for a transparent key.
+ *
+ */
+static psa_status_t psa_validate_key_attributes(
+ const psa_key_attributes_t *attributes,
+ psa_se_drv_table_entry_t **p_drv )
+{
+ psa_status_t status;
+
+ if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE )
+ {
+ status = psa_validate_persistent_key_parameters(
+ attributes->core.lifetime, attributes->core.id,
+ p_drv, 1 );
+ if( status != PSA_SUCCESS )
+ return( status );
+ }
+
+ status = psa_validate_key_policy( &attributes->core.policy );
+ if( status != PSA_SUCCESS )
+ return( status );
+
+ /* Refuse to create overly large keys.
+ * Note that this doesn't trigger on import if the attributes don't
+ * explicitly specify a size (so psa_get_key_bits returns 0), so
+ * psa_import_key() needs its own checks. */
+ if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS )
+ return( PSA_ERROR_NOT_SUPPORTED );
+
+ return( PSA_SUCCESS );
+}
+
/** Prepare a key slot to receive key material.
*
* This function allocates a key slot and sets its metadata.
@@ -1455,26 +1501,15 @@
*p_drv = NULL;
+ status = psa_validate_key_attributes( attributes, p_drv );
+ if( status != PSA_SUCCESS )
+ return( status );
+
status = psa_internal_allocate_key_slot( handle, p_slot );
if( status != PSA_SUCCESS )
return( status );
slot = *p_slot;
- if( attributes->core.lifetime != PSA_KEY_LIFETIME_VOLATILE )
- {
- status = psa_validate_persistent_key_parameters( attributes->core.lifetime,
- attributes->core.id,
- p_drv, 1 );
- if( status != PSA_SUCCESS )
- return( status );
- }
-
- /* Refuse to create overly large keys.
- * Note that this doesn't trigger on import if the attributes don't
- * explicitly specify a size (so psa_get_key_bits returns 0), so
- * psa_import_key() needs its own checks. */
- if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS )
- return( PSA_ERROR_NOT_SUPPORTED );
/* We're storing the declared bit-size of the key. It's up to each
* creation mechanism to verify that this information is correct.
* It's automatically correct for mechanisms that use the bit-size as
@@ -1483,10 +1518,6 @@
slot->attr = attributes->core;
- status = psa_check_key_slot_policy( slot );
- if( status != PSA_SUCCESS )
- return( status );
-
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things:
* create the key file in internal storage, create the
@@ -1647,7 +1678,16 @@
psa_wipe_key_slot( slot );
}
-static psa_status_t psa_check_key_slot_attributes(
+/** Validate optional attributes during key creation.
+ *
+ * Some key attributes are optional during key creation. If they are
+ * specified in the attributes structure, check that they are consistent
+ * with the data in the slot.
+ *
+ * This function should be called near the end of key creation, after
+ * the slot in memory is fully populated but before saving persistent data.
+ */
+static psa_status_t psa_validate_optional_attributes(
const psa_key_slot_t *slot,
const psa_key_attributes_t *attributes )
{
@@ -1746,7 +1786,7 @@
if( status != PSA_SUCCESS )
goto exit;
}
- status = psa_check_key_slot_attributes( slot, attributes );
+ status = psa_validate_optional_attributes( slot, attributes );
if( status != PSA_SUCCESS )
goto exit;
@@ -1801,7 +1841,8 @@
if( status != PSA_SUCCESS )
goto exit;
- status = psa_check_key_slot_attributes( source_slot, specified_attributes );
+ status = psa_validate_optional_attributes( source_slot,
+ specified_attributes );
if( status != PSA_SUCCESS )
goto exit;