New function psa_copy_key
Copy a key from one slot to another. Implemented and smoke-tested.
This commit is contained in:
parent
43bafcca94
commit
f603c718c9
4 changed files with 419 additions and 123 deletions
|
@ -93,6 +93,140 @@ psa_status_t psa_crypto_init(void);
|
|||
|
||||
/**@}*/
|
||||
|
||||
/** \defgroup policy Key policies
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The type of the key policy data structure.
|
||||
*
|
||||
* Before calling any function on a key policy, the application must initialize
|
||||
* it by any of the following means:
|
||||
* - Set the structure to all-bits-zero, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy;
|
||||
* memset(&policy, 0, sizeof(policy));
|
||||
* \endcode
|
||||
* - Initialize the structure to logical zero values, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy = {0};
|
||||
* \endcode
|
||||
* - Initialize the structure to the initializer #PSA_KEY_POLICY_INIT,
|
||||
* for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
|
||||
* \endcode
|
||||
* - Assign the result of the function psa_key_policy_init()
|
||||
* to the structure, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy;
|
||||
* policy = psa_key_policy_init();
|
||||
* \endcode
|
||||
*
|
||||
* This is an implementation-defined \c struct. Applications should not
|
||||
* make any assumptions about the content of this structure except
|
||||
* as directed by the documentation of a specific implementation. */
|
||||
typedef struct psa_key_policy_s psa_key_policy_t;
|
||||
|
||||
/** \def PSA_KEY_POLICY_INIT
|
||||
*
|
||||
* This macro returns a suitable initializer for a key policy object of type
|
||||
* #psa_key_policy_t.
|
||||
*/
|
||||
#ifdef __DOXYGEN_ONLY__
|
||||
/* This is an example definition for documentation purposes.
|
||||
* Implementations should define a suitable value in `crypto_struct.h`.
|
||||
*/
|
||||
#define PSA_KEY_POLICY_INIT {0}
|
||||
#endif
|
||||
|
||||
/** Return an initial value for a key policy that forbids all usage of the key.
|
||||
*/
|
||||
static psa_key_policy_t psa_key_policy_init(void);
|
||||
|
||||
/** \brief Set the standard fields of a policy structure.
|
||||
*
|
||||
* Note that this function does not make any consistency check of the
|
||||
* parameters. The values are only checked when applying the policy to
|
||||
* a key slot with psa_set_key_policy().
|
||||
*
|
||||
* \param[in,out] policy The key policy to modify. It must have been
|
||||
* initialized as per the documentation for
|
||||
* #psa_key_policy_t.
|
||||
* \param usage The permitted uses for the key.
|
||||
* \param alg The algorithm that the key may be used for.
|
||||
*/
|
||||
void psa_key_policy_set_usage(psa_key_policy_t *policy,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
/** \brief Retrieve the usage field of a policy structure.
|
||||
*
|
||||
* \param[in] policy The policy object to query.
|
||||
*
|
||||
* \return The permitted uses for a key with this policy.
|
||||
*/
|
||||
psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Retrieve the algorithm field of a policy structure.
|
||||
*
|
||||
* \param[in] policy The policy object to query.
|
||||
*
|
||||
* \return The permitted algorithm for a key with this policy.
|
||||
*/
|
||||
psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Set the usage policy on a key slot.
|
||||
*
|
||||
* This function must be called on an empty key slot, before importing,
|
||||
* generating or creating a key in the slot. Changing the policy of an
|
||||
* existing key is not permitted.
|
||||
*
|
||||
* Implementations may set restrictions on supported key policies
|
||||
* depending on the key type and the key slot.
|
||||
*
|
||||
* \param handle Handle to the key whose policy is to be changed.
|
||||
* \param[in] policy The policy object to query.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* If the key is persistent, it is implementation-defined whether
|
||||
* the policy has been saved to persistent storage. Implementations
|
||||
* may defer saving the policy until the key material is created.
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_OCCUPIED_SLOT
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_set_key_policy(psa_key_handle_t handle,
|
||||
const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Get the usage policy for a key slot.
|
||||
*
|
||||
* \param handle Handle to the key slot whose policy is being queried.
|
||||
* \param[out] policy On success, the key's policy.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_get_key_policy(psa_key_handle_t handle,
|
||||
psa_key_policy_t *policy);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** \defgroup key_management Key management
|
||||
* @{
|
||||
*/
|
||||
|
@ -530,139 +664,70 @@ psa_status_t psa_export_public_key(psa_key_handle_t handle,
|
|||
size_t data_size,
|
||||
size_t *data_length);
|
||||
|
||||
/**@}*/
|
||||
|
||||
/** \defgroup policy Key policies
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The type of the key policy data structure.
|
||||
/** Make a copy of a key.
|
||||
*
|
||||
* Before calling any function on a key policy, the application must initialize
|
||||
* it by any of the following means:
|
||||
* - Set the structure to all-bits-zero, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy;
|
||||
* memset(&policy, 0, sizeof(policy));
|
||||
* \endcode
|
||||
* - Initialize the structure to logical zero values, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy = {0};
|
||||
* \endcode
|
||||
* - Initialize the structure to the initializer #PSA_KEY_POLICY_INIT,
|
||||
* for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy = PSA_KEY_POLICY_INIT;
|
||||
* \endcode
|
||||
* - Assign the result of the function psa_key_policy_init()
|
||||
* to the structure, for example:
|
||||
* \code
|
||||
* psa_key_policy_t policy;
|
||||
* policy = psa_key_policy_init();
|
||||
* \endcode
|
||||
* Copy key material from one location to another.
|
||||
*
|
||||
* This is an implementation-defined \c struct. Applications should not
|
||||
* make any assumptions about the content of this structure except
|
||||
* as directed by the documentation of a specific implementation. */
|
||||
typedef struct psa_key_policy_s psa_key_policy_t;
|
||||
|
||||
/** \def PSA_KEY_POLICY_INIT
|
||||
* This function is primarily useful to copy a key from one lifetime
|
||||
* to another. The target key retains its lifetime and location.
|
||||
*
|
||||
* This macro returns a suitable initializer for a key policy object of type
|
||||
* #psa_key_policy_t.
|
||||
*/
|
||||
#ifdef __DOXYGEN_ONLY__
|
||||
/* This is an example definition for documentation purposes.
|
||||
* Implementations should define a suitable value in `crypto_struct.h`.
|
||||
*/
|
||||
#define PSA_KEY_POLICY_INIT {0}
|
||||
#endif
|
||||
|
||||
/** Return an initial value for a key policy that forbids all usage of the key.
|
||||
*/
|
||||
static psa_key_policy_t psa_key_policy_init(void);
|
||||
|
||||
/** \brief Set the standard fields of a policy structure.
|
||||
* In an implementation where slots have different ownerships,
|
||||
* this functin may be used to share a key with a different party,
|
||||
* subject to implementation-defined restrictions on key sharing.
|
||||
* In this case \p constraint would typically prevent the recipient
|
||||
* from exporting the key.
|
||||
*
|
||||
* Note that this function does not make any consistency check of the
|
||||
* parameters. The values are only checked when applying the policy to
|
||||
* a key slot with psa_set_key_policy().
|
||||
* The resulting key may only be used in a way that conforms to all
|
||||
* three of: the policy of the source key, the policy previously set
|
||||
* on the target, and the \p constraint parameter passed when calling
|
||||
* this function.
|
||||
* - The usage flags on the resulting key are the bitwise-and of the
|
||||
* usage flags on the source policy, the previously-set target policy
|
||||
* and the policy constraint.
|
||||
* - If all three policies allow the same algorithm or wildcard-based
|
||||
* algorithm policy, the resulting key has the same algorithm policy.
|
||||
* - If one of the policies allows an algorithm and all the other policies
|
||||
* either allow the same algorithm or a wildcard-based algorithm policy
|
||||
* that includes this algorithm, the resulting key allows the same
|
||||
* algorithm.
|
||||
*
|
||||
* \param[in,out] policy The key policy to modify. It must have been
|
||||
* initialized as per the documentation for
|
||||
* #psa_key_policy_t.
|
||||
* \param usage The permitted uses for the key.
|
||||
* \param alg The algorithm that the key may be used for.
|
||||
*/
|
||||
void psa_key_policy_set_usage(psa_key_policy_t *policy,
|
||||
psa_key_usage_t usage,
|
||||
psa_algorithm_t alg);
|
||||
|
||||
/** \brief Retrieve the usage field of a policy structure.
|
||||
* The effect of this function on implementation-defined metadata is
|
||||
* implementation-defined.
|
||||
*
|
||||
* \param[in] policy The policy object to query.
|
||||
*
|
||||
* \return The permitted uses for a key with this policy.
|
||||
*/
|
||||
psa_key_usage_t psa_key_policy_get_usage(const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Retrieve the algorithm field of a policy structure.
|
||||
*
|
||||
* \param[in] policy The policy object to query.
|
||||
*
|
||||
* \return The permitted algorithm for a key with this policy.
|
||||
*/
|
||||
psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Set the usage policy on a key slot.
|
||||
*
|
||||
* This function must be called on an empty key slot, before importing,
|
||||
* generating or creating a key in the slot. Changing the policy of an
|
||||
* existing key is not permitted.
|
||||
*
|
||||
* Implementations may set restrictions on supported key policies
|
||||
* depending on the key type and the key slot.
|
||||
*
|
||||
* \param handle Handle to the key whose policy is to be changed.
|
||||
* \param[in] policy The policy object to query.
|
||||
* \param source_handle The key to copy. It must be a handle to an
|
||||
* occupied slot.
|
||||
* \param target_handle A handle to the target slot. It must not contain
|
||||
* key material yet.
|
||||
* \param[in] constraint An optional policy constraint. If this parameter
|
||||
* is non-null then the resulting key will conform
|
||||
* to this policy in addition to the source policy
|
||||
* and the policy already present on the target
|
||||
* slot. If this parameter is null then the
|
||||
* function behaves in the same way as if it was
|
||||
* the target policy, i.e. only the source and
|
||||
* target policies apply.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* Success.
|
||||
* If the key is persistent, it is implementation-defined whether
|
||||
* the policy has been saved to persistent storage. Implementations
|
||||
* may defer saving the policy until the key material is created.
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_OCCUPIED_SLOT
|
||||
* \retval #PSA_ERROR_NOT_SUPPORTED
|
||||
* \p target already contains key material.
|
||||
* \retval #PSA_ERROR_EMPTY_SLOT
|
||||
* \p source does not contain key material.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* The policy constraints on the source, on the target and
|
||||
* \p constraints are incompatible.
|
||||
* \retval #PSA_ERROR_NOT_PERMITTED
|
||||
* The source key is not exportable and its lifetime does not
|
||||
* allow copying it to the target's lifetime.
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
|
||||
* \retval #PSA_ERROR_INSUFFICIENT_STORAGE
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_set_key_policy(psa_key_handle_t handle,
|
||||
const psa_key_policy_t *policy);
|
||||
|
||||
/** \brief Get the usage policy for a key slot.
|
||||
*
|
||||
* \param handle Handle to the key slot whose policy is being queried.
|
||||
* \param[out] policy On success, the key's policy.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \retval #PSA_ERROR_INVALID_HANDLE
|
||||
* \retval #PSA_ERROR_COMMUNICATION_FAILURE
|
||||
* \retval #PSA_ERROR_HARDWARE_FAILURE
|
||||
* \retval #PSA_ERROR_TAMPERING_DETECTED
|
||||
* \retval #PSA_ERROR_BAD_STATE
|
||||
* The library has not been previously initialized by psa_crypto_init().
|
||||
* It is implementation-dependent whether a failure to initialize
|
||||
* results in this error code.
|
||||
*/
|
||||
psa_status_t psa_get_key_policy(psa_key_handle_t handle,
|
||||
psa_key_policy_t *policy);
|
||||
psa_status_t psa_copy_key(psa_key_handle_t source_handle,
|
||||
psa_key_handle_t target_handle,
|
||||
const psa_key_policy_t *constraint);
|
||||
|
||||
/**@}*/
|
||||
|
||||
|
|
|
@ -748,6 +748,32 @@ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle,
|
|||
return( status );
|
||||
}
|
||||
|
||||
/** Calculate the intersection of two algorithm usage policies.
|
||||
*
|
||||
* Return 0 (which allows no operation) on incompatibility.
|
||||
*/
|
||||
static psa_algorithm_t psa_key_policy_algorithm_intersection(
|
||||
psa_algorithm_t alg1,
|
||||
psa_algorithm_t alg2 )
|
||||
{
|
||||
/* Common case: the policy only allows alg. */
|
||||
if( alg1 == alg2 )
|
||||
return( alg1 );
|
||||
/* If the policies are from the same hash-and-sign family, check
|
||||
* if one is a wildcard. If so the other has the specific algorithm. */
|
||||
if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) &&
|
||||
PSA_ALG_IS_HASH_AND_SIGN( alg2 ) &&
|
||||
( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) )
|
||||
{
|
||||
if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH )
|
||||
return( alg2 );
|
||||
if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH )
|
||||
return( alg1 );
|
||||
}
|
||||
/* If the policies are incompatible, allow nothing. */
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/** Test whether a policy permits an algorithm.
|
||||
*
|
||||
* The caller must test usage flags separately.
|
||||
|
@ -771,6 +797,31 @@ static int psa_key_policy_permits( const psa_key_policy_t *policy,
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
/** Restrict a key policy based on a constraint.
|
||||
*
|
||||
* \param[in,out] policy The policy to restrict.
|
||||
* \param[in] constraint The policy constraint to apply.
|
||||
*
|
||||
* \retval #PSA_SUCCESS
|
||||
* \c *policy contains the intersection of the original value of
|
||||
* \c *policy and \c *constraint.
|
||||
* \retval #PSA_ERROR_INVALID_ARGUMENT
|
||||
* \c *policy and \c *constraint are incompatible.
|
||||
* \c *policy is unchanged.
|
||||
*/
|
||||
static psa_status_t psa_restrict_key_policy(
|
||||
psa_key_policy_t *policy,
|
||||
const psa_key_policy_t *constraint )
|
||||
{
|
||||
psa_algorithm_t intersection_alg =
|
||||
psa_key_policy_algorithm_intersection( policy->alg, constraint->alg );
|
||||
if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 )
|
||||
return( PSA_ERROR_INVALID_ARGUMENT );
|
||||
policy->usage &= constraint->usage;
|
||||
policy->alg = intersection_alg;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
/** Retrieve a slot which must contain a key. The key must have allow all the
|
||||
* usage flags set in \p usage. If \p alg is nonzero, the key must allow
|
||||
* operations with this algorithm. */
|
||||
|
@ -974,7 +1025,7 @@ static int pk_write_pubkey_simple( mbedtls_pk_context *key,
|
|||
}
|
||||
#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */
|
||||
|
||||
static psa_status_t psa_internal_export_key( psa_key_slot_t *slot,
|
||||
static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot,
|
||||
uint8_t *data,
|
||||
size_t data_size,
|
||||
size_t *data_length,
|
||||
|
@ -1165,6 +1216,65 @@ exit:
|
|||
}
|
||||
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
|
||||
|
||||
static psa_status_t psa_copy_key_material( const psa_key_slot_t *source,
|
||||
psa_key_handle_t target )
|
||||
{
|
||||
psa_status_t status;
|
||||
uint8_t *buffer = NULL;
|
||||
size_t buffer_size = 0;
|
||||
size_t length;
|
||||
|
||||
buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->type,
|
||||
psa_get_key_bits( source ) );
|
||||
buffer = mbedtls_calloc( 1, buffer_size );
|
||||
if( buffer == NULL )
|
||||
{
|
||||
status = PSA_ERROR_INSUFFICIENT_MEMORY;
|
||||
goto exit;
|
||||
}
|
||||
status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 );
|
||||
if( status != PSA_SUCCESS )
|
||||
goto exit;
|
||||
status = psa_import_key( target, source->type, buffer, length );
|
||||
|
||||
exit:
|
||||
return( status );
|
||||
}
|
||||
|
||||
psa_status_t psa_copy_key(psa_key_handle_t source_handle,
|
||||
psa_key_handle_t target_handle,
|
||||
const psa_key_policy_t *constraint)
|
||||
{
|
||||
psa_key_slot_t *source_slot = NULL;
|
||||
psa_key_slot_t *target_slot = NULL;
|
||||
psa_key_policy_t new_policy;
|
||||
psa_status_t status;
|
||||
status = psa_get_key_from_slot( source_handle, &source_slot, 0, 0 );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
status = psa_get_empty_key_slot( target_handle, &target_slot );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
new_policy = target_slot->policy;
|
||||
status = psa_restrict_key_policy( &new_policy, &source_slot->policy );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
if( constraint != NULL )
|
||||
{
|
||||
status = psa_restrict_key_policy( &new_policy, constraint );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
}
|
||||
|
||||
status = psa_copy_key_material( source_slot, target_handle );
|
||||
if( status != PSA_SUCCESS )
|
||||
return( status );
|
||||
|
||||
target_slot->policy = new_policy;
|
||||
return( PSA_SUCCESS );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
|
|
|
@ -65,6 +65,18 @@ Create not supported
|
|||
depends_on:!MBEDTLS_PSA_CRYPTO_STORAGE_C
|
||||
create_fail:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_NOT_SUPPORTED
|
||||
|
||||
Copy volatile to volatile
|
||||
copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:-1:-1:PSA_KEY_USAGE_EXPORT:0
|
||||
|
||||
Copy volatile to persistent
|
||||
copy_across_lifetimes:PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:-1:-1:PSA_KEY_USAGE_EXPORT:0
|
||||
|
||||
Copy persistent to volatile
|
||||
copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_VOLATILE:0:PSA_KEY_USAGE_EXPORT:0:-1:-1:PSA_KEY_USAGE_EXPORT:0
|
||||
|
||||
Copy persistent to persistent
|
||||
copy_across_lifetimes:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_KEY_USAGE_EXPORT:0:PSA_KEY_TYPE_RAW_DATA:"4142434445":PSA_KEY_LIFETIME_PERSISTENT:2:PSA_KEY_USAGE_EXPORT:0:-1:-1:PSA_KEY_USAGE_EXPORT:0
|
||||
|
||||
Close/destroy invalid handle
|
||||
invalid_handle:
|
||||
|
||||
|
|
|
@ -293,6 +293,115 @@ exit:
|
|||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void copy_across_lifetimes( int source_lifetime_arg, int source_id_arg,
|
||||
int source_usage_arg, int source_alg_arg,
|
||||
int type_arg, data_t *material,
|
||||
int target_lifetime_arg, int target_id_arg,
|
||||
int target_usage_arg, int target_alg_arg,
|
||||
int constraint_usage_arg, int constraint_alg_arg,
|
||||
int expected_usage_arg, int expected_alg_arg )
|
||||
{
|
||||
psa_key_lifetime_t source_lifetime = source_lifetime_arg;
|
||||
psa_key_id_t source_id = source_id_arg;
|
||||
psa_key_usage_t source_usage = source_usage_arg;
|
||||
psa_algorithm_t source_alg = source_alg_arg;
|
||||
psa_key_handle_t source_handle = 0;
|
||||
psa_key_policy_t source_policy = PSA_KEY_POLICY_INIT;
|
||||
psa_key_type_t source_type = type_arg;
|
||||
size_t source_bits;
|
||||
psa_key_lifetime_t target_lifetime = target_lifetime_arg;
|
||||
psa_key_id_t target_id = target_id_arg;
|
||||
psa_key_usage_t target_usage = target_usage_arg;
|
||||
psa_algorithm_t target_alg = target_alg_arg;
|
||||
psa_key_handle_t target_handle = 0;
|
||||
psa_key_policy_t target_policy = PSA_KEY_POLICY_INIT;
|
||||
psa_key_type_t target_type;
|
||||
size_t target_bits;
|
||||
psa_key_usage_t constraint_usage = constraint_usage_arg;
|
||||
psa_algorithm_t constraint_alg = constraint_alg_arg;
|
||||
psa_key_policy_t constraint = PSA_KEY_POLICY_INIT;
|
||||
psa_key_policy_t *p_constraint = NULL;
|
||||
psa_key_usage_t expected_usage = expected_usage_arg;
|
||||
psa_algorithm_t expected_alg = expected_alg_arg;
|
||||
uint8_t *export_buffer = NULL;
|
||||
|
||||
if( constraint_usage_arg != -1 )
|
||||
{
|
||||
p_constraint = &constraint;
|
||||
psa_key_policy_set_usage( p_constraint,
|
||||
constraint_usage, constraint_alg );
|
||||
}
|
||||
TEST_MAX_KEY_ID( source_id );
|
||||
TEST_MAX_KEY_ID( target_id );
|
||||
|
||||
PSA_ASSERT( psa_crypto_init( ) );
|
||||
|
||||
/* Populate the source slot. */
|
||||
if( source_lifetime == PSA_KEY_LIFETIME_VOLATILE )
|
||||
PSA_ASSERT( psa_allocate_key( &source_handle ) );
|
||||
else
|
||||
PSA_ASSERT( psa_create_key( source_lifetime, source_id,
|
||||
&source_handle ) );
|
||||
psa_key_policy_set_usage( &source_policy, source_usage, source_alg );
|
||||
PSA_ASSERT( psa_set_key_policy( source_handle, &source_policy ) );
|
||||
PSA_ASSERT( psa_import_key( source_handle, source_type,
|
||||
material->x, material->len ) );
|
||||
PSA_ASSERT( psa_get_key_information( source_handle, NULL, &source_bits ) );
|
||||
|
||||
/* Prepare the target slot. */
|
||||
if( target_lifetime == PSA_KEY_LIFETIME_VOLATILE )
|
||||
PSA_ASSERT( psa_allocate_key( &target_handle ) );
|
||||
else
|
||||
PSA_ASSERT( psa_create_key( target_lifetime, target_id,
|
||||
&target_handle ) );
|
||||
psa_key_policy_set_usage( &target_policy, target_usage, target_alg );
|
||||
PSA_ASSERT( psa_set_key_policy( target_handle, &target_policy ) );
|
||||
target_policy = psa_key_policy_init();
|
||||
|
||||
/* Copy the key. */
|
||||
PSA_ASSERT( psa_copy_key( source_handle, target_handle, p_constraint ) );
|
||||
|
||||
/* Destroy the source to ensure that this doesn't affect the target. */
|
||||
PSA_ASSERT( psa_destroy_key( source_handle ) );
|
||||
|
||||
/* If the target key is persistent, restart the system to make
|
||||
* sure that the material is still alive. */
|
||||
if( target_lifetime != PSA_KEY_LIFETIME_VOLATILE )
|
||||
{
|
||||
mbedtls_psa_crypto_free( );
|
||||
PSA_ASSERT( psa_crypto_init( ) );
|
||||
PSA_ASSERT( psa_open_key( target_lifetime, target_id,
|
||||
&target_handle ) );
|
||||
}
|
||||
|
||||
/* Test that the target slot has the expected content. */
|
||||
PSA_ASSERT( psa_get_key_information( target_handle,
|
||||
&target_type, &target_bits ) );
|
||||
TEST_ASSERT( source_type == target_type );
|
||||
TEST_ASSERT( source_bits == target_bits );
|
||||
PSA_ASSERT( psa_get_key_policy( target_handle, &target_policy ) );
|
||||
TEST_ASSERT( expected_usage == psa_key_policy_get_usage( &target_policy ) );
|
||||
TEST_ASSERT( expected_alg == psa_key_policy_get_algorithm( &target_policy ) );
|
||||
if( expected_usage & PSA_KEY_USAGE_EXPORT )
|
||||
{
|
||||
size_t length;
|
||||
ASSERT_ALLOC( export_buffer, material->len );
|
||||
PSA_ASSERT( psa_export_key( target_handle, export_buffer,
|
||||
material->len, &length ) );
|
||||
ASSERT_COMPARE( material->x, material->len,
|
||||
export_buffer, length );
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_psa_crypto_free( );
|
||||
mbedtls_free( export_buffer );
|
||||
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
|
||||
psa_purge_key_storage( );
|
||||
#endif
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE */
|
||||
void invalid_handle( )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue