Merge branch 'psa-copy_key' into psa-api-1.0-beta
New function psa_copy_key(). Conflicts: * library/psa_crypto.c: trivial conflicts due to consecutive changes. * tests/suites/test_suite_psa_crypto.data: the same code was added on both sides, but with a conflict resolution on one side. * tests/suites/test_suite_psa_crypto_metadata.function: the same code was added on both sides, but with a conflict resolution on one side.
This commit is contained in:
commit
ea2e3604b1
5 changed files with 424 additions and 123 deletions
|
@ -747,6 +747,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( 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( alg1 ) == 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.
|
||||
|
@ -770,6 +796,18 @@ static int psa_key_policy_permits( const psa_key_policy_t *policy,
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
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;
|
||||
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. */
|
||||
|
@ -980,11 +1018,11 @@ 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,
|
||||
uint8_t *data,
|
||||
size_t data_size,
|
||||
size_t *data_length,
|
||||
int export_public_key )
|
||||
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,
|
||||
int export_public_key )
|
||||
{
|
||||
*data_length = 0;
|
||||
|
||||
|
@ -1171,6 +1209,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 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue