Skip to content

Commit

Permalink
Merge pull request Mbed-TLS#201 from gilles-peskine-arm/psa-se_driver…
Browse files Browse the repository at this point in the history
…-set_key_slot_number

Add slot number attribute
  • Loading branch information
gilles-peskine-arm authored Aug 8, 2019
2 parents 0c77b0e + edbed56 commit 311809a
Show file tree
Hide file tree
Showing 11 changed files with 276 additions and 8 deletions.
73 changes: 73 additions & 0 deletions include/psa/crypto_extra.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,79 @@ static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
return( attributes->core.policy.alg2 );
}

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)

/** Retrieve the slot number where a key is stored.
*
* A slot number is only defined for keys that are stored in a secure
* element.
*
* This information is only useful if the secure element is not entirely
* managed through the PSA Cryptography API. It is up to the secure
* element driver to decide how PSA slot numbers map to any other interface
* that the secure element may have.
*
* \param[in] attributes The key attribute structure to query.
* \param[out] slot_number On success, the slot number containing the key.
*
* \retval #PSA_SUCCESS
* The key is located in a secure element, and \p *slot_number
* indicates the slot number that contains it.
* \retval #PSA_ERROR_NOT_PERMITTED
* The caller is not permitted to query the slot number.
* Mbed Crypto currently does not return this error.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key is not located in a secure element.
*/
psa_status_t psa_get_key_slot_number(
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number );

/** Choose the slot number where a key is stored.
*
* This function declares a slot number in the specified attribute
* structure.
*
* A slot number is only meaningful for keys that are stored in a secure
* element. It is up to the secure element driver to decide how PSA slot
* numbers map to any other interface that the secure element may have.
*
* \note Setting a slot number in key attributes for a key creation can
* cause the following errors when creating the key:
* - #PSA_ERROR_NOT_SUPPORTED if the selected secure element does
* not support choosing a specific slot number.
* - #PSA_ERROR_NOT_PERMITTED if the caller is not permitted to
* choose slot numbers in general or to choose this specific slot.
* - #PSA_ERROR_INVALID_ARGUMENT if the chosen slot number is not
* valid in general or not valid for this specific key.
* - #PSA_ERROR_ALREADY_EXISTS if there is already a key in the
* selected slot.
*
* \param[out] attributes The attribute structure to write to.
* \param slot_number The slot number to set.
*/
static inline void psa_set_key_slot_number(
psa_key_attributes_t *attributes,
psa_key_slot_number_t slot_number )
{
attributes->core.flags |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
attributes->slot_number = slot_number;
}

/** Remove the slot number attribute from a key attribute structure.
*
* This function undoes the action of psa_set_key_slot_number().
*
* \param[out] attributes The attribute structure to write to.
*/
static inline void psa_clear_key_slot_number(
psa_key_attributes_t *attributes )
{
attributes->core.flags &= ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
}

#endif /* MBEDTLS_PSA_CRYPTO_SE_C */

/**@}*/

/**
Expand Down
7 changes: 7 additions & 0 deletions include/psa/crypto_se_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,17 @@ typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context,
void *persistent_data,
psa_key_lifetime_t lifetime);

#if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* Mbed Crypto with secure element support enabled defines this type in
* crypto_types.h because it is also visible to applications through an
* implementation-specific extension.
* For the PSA Cryptography specification, this type is only visible
* via crypto_se_driver.h. */
/** An internal designation of a key slot between the core part of the
* PSA Crypto implementation and the driver. The meaning of this value
* is driver-dependent. */
typedef uint64_t psa_key_slot_number_t;
#endif /* __DOXYGEN_ONLY__ || !MBEDTLS_PSA_CRYPTO_SE_C */

/**@}*/

Expand Down
33 changes: 32 additions & 1 deletion include/psa/crypto_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,26 +322,57 @@ typedef uint16_t psa_key_bits_t;
* conditionals. */
#define PSA_MAX_KEY_BITS 0xfff8

/** A mask of flags that can be stored in key attributes.
*
* This type is also used internally to store flags in slots. Internal
* flags are defined in library/psa_crypto_core.h. Internal flags may have
* the same value as external flags if they are properly handled during
* key creation and in psa_get_key_attributes.
*/
typedef uint16_t psa_key_attributes_flag_t;

#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \
( (psa_key_attributes_flag_t) 0x0001 )

/* A mask of key attribute flags used externally only.
* Only meant for internal checks inside the library. */
#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \
MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \
0 )

/* A mask of key attribute flags used both internally and externally.
* Currently there aren't any. */
#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \
0 )

typedef struct
{
psa_key_type_t type;
psa_key_lifetime_t lifetime;
psa_key_id_t id;
psa_key_policy_t policy;
psa_key_bits_t bits;
uint16_t flags;
psa_key_attributes_flag_t flags;
} psa_core_key_attributes_t;

#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, 0, {0, 0, 0}, 0, 0}

struct psa_key_attributes_s
{
psa_core_key_attributes_t core;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
psa_key_slot_number_t slot_number;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
void *domain_parameters;
size_t domain_parameters_size;
};

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0}
#else
#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0}
#endif

static inline struct psa_key_attributes_s psa_key_attributes_init( void )
{
const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT;
Expand Down
11 changes: 11 additions & 0 deletions include/psa/crypto_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,17 @@ typedef uint32_t psa_key_usage_t;
*/
typedef struct psa_key_attributes_s psa_key_attributes_t;


#ifndef __DOXYGEN_ONLY__
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* Mbed Crypto defines this type in crypto_types.h because it is also
* visible to applications through an implementation-specific extension.
* For the PSA Cryptography specification, this type is only visible
* via crypto_se_driver.h. */
typedef uint64_t psa_key_slot_number_t;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
#endif /* !__DOXYGEN_ONLY__ */

/**@}*/

/** \defgroup derivation Key derivation
Expand Down
51 changes: 49 additions & 2 deletions library/psa_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,13 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
return( status );

attributes->core = slot->attr;
attributes->core.flags &= ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY |
MBEDTLS_PSA_KA_MASK_DUAL_USE );

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if( psa_key_slot_is_external( slot ) )
psa_set_key_slot_number( attributes, slot->data.se.slot_number );
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */

switch( slot->attr.type )
{
Expand All @@ -1196,7 +1203,7 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* TOnogrepDO: reporting the public exponent for opaque keys
* is not yet implemented. */
if( psa_get_se_driver( slot->attr.lifetime, NULL, NULL ) )
if( psa_key_slot_is_external( slot ) )
break;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
status = psa_get_rsa_public_exponent( slot->data.rsa, attributes );
Expand All @@ -1212,6 +1219,21 @@ psa_status_t psa_get_key_attributes( psa_key_handle_t handle,
return( status );
}

#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
psa_status_t psa_get_key_slot_number(
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number )
{
if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER )
{
*slot_number = attributes->slot_number;
return( PSA_SUCCESS );
}
else
return( PSA_ERROR_INVALID_ARGUMENT );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */

#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
static int pk_write_pubkey_simple( mbedtls_pk_context *key,
unsigned char *buf, size_t size )
Expand Down Expand Up @@ -1408,6 +1430,15 @@ psa_status_t psa_export_public_key( psa_key_handle_t handle,
data_length, 1 ) );
}

#if defined(static_assert)
static_assert( ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0,
"One or more key attribute flag is listed as both external-only and dual-use" );
static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE ) == 0,
"One or more key attribute flag is listed as both internal-only and dual-use" );
static_assert( ( PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ) == 0,
"One or more key attribute flag is listed as both internal-only and external-only" );
#endif

/** Validate that a key policy is internally well-formed.
*
* This function only rejects invalid policies. It does not validate the
Expand Down Expand Up @@ -1467,6 +1498,11 @@ static psa_status_t psa_validate_key_attributes(
if( psa_get_key_bits( attributes ) > PSA_MAX_KEY_BITS )
return( PSA_ERROR_NOT_SUPPORTED );

/* Reject invalid flags. These should not be reachable through the API. */
if( attributes->core.flags & ~ ( MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY |
MBEDTLS_PSA_KA_MASK_DUAL_USE ) )
return( PSA_ERROR_INVALID_ARGUMENT );

return( PSA_SUCCESS );
}

Expand Down Expand Up @@ -1510,7 +1546,7 @@ static psa_status_t psa_start_key_creation(
if( status != PSA_SUCCESS )
return( status );

status = psa_internal_allocate_key_slot( handle, p_slot );
status = psa_get_empty_key_slot( handle, p_slot );
if( status != PSA_SUCCESS )
return( status );
slot = *p_slot;
Expand All @@ -1523,6 +1559,13 @@ static psa_status_t psa_start_key_creation(

slot->attr = attributes->core;

/* Erase external-only flags from the internal copy. To access
* external-only flags, query `attributes`. Thanks to the check
* in psa_validate_key_attributes(), this leaves the dual-use
* flags and any internal flag that psa_get_empty_key_slot()
* may have set. */
slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY;

#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
Expand All @@ -1539,6 +1582,10 @@ static psa_status_t psa_start_key_creation(
* we can roll back to a state where the key doesn't exist. */
if( *p_drv != NULL )
{
/* Choosing a slot number is not supported yet. */
if( attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER )
return( PSA_ERROR_NOT_SUPPORTED );

status = psa_find_se_slot_for_key( attributes, *p_drv,
&slot->data.se.slot_number );
if( status != PSA_SUCCESS )
Expand Down
7 changes: 7 additions & 0 deletions library/psa_crypto_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,21 @@ typedef struct
/* EC public key or key pair */
mbedtls_ecp_keypair *ecp;
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* Any key type in a secure element */
struct se
{
psa_key_slot_number_t slot_number;
} se;
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
} data;
} psa_key_slot_t;

/* A mask of key attribute flags used only internally.
* Currently there aren't any. */
#define PSA_KA_MASK_INTERNAL_ONLY ( \
0 )

/** Test whether a key slot is occupied.
*
* A key slot is occupied iff the key type is nonzero. This works because
Expand Down
4 changes: 2 additions & 2 deletions library/psa_crypto_slot_management.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void psa_wipe_all_key_slots( void )
global_data.key_slots_initialized = 0;
}

psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle,
psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle,
psa_key_slot_t **p_slot )
{
if( ! global_data.key_slots_initialized )
Expand Down Expand Up @@ -228,7 +228,7 @@ psa_status_t psa_open_key( psa_key_file_id_t id, psa_key_handle_t *handle )
if( status != PSA_SUCCESS )
return( status );

status = psa_internal_allocate_key_slot( handle, &slot );
status = psa_get_empty_key_slot( handle, &slot );
if( status != PSA_SUCCESS )
return( status );

Expand Down
4 changes: 2 additions & 2 deletions library/psa_crypto_slot_management.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ void psa_wipe_all_key_slots( void );
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* \retval #PSA_ERROR_BAD_STATE
*/
psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle,
psa_key_slot_t **p_slot );
psa_status_t psa_get_empty_key_slot( psa_key_handle_t *handle,
psa_key_slot_t **p_slot );

/** Test whether a lifetime designates a key in an external cryptoprocessor.
*
Expand Down
3 changes: 3 additions & 0 deletions tests/suites/test_suite_psa_crypto.data
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ persistence_attributes:0x1234:3:-1:0x1234:3
PSA key attributes: lifetime then id
persistence_attributes:0x1234:3:0x1235:0x1235:3

PSA key attributes: slot number
slot_number_attribute:

PSA import/export raw: 0 bytes
import_export:"":PSA_KEY_TYPE_RAW_DATA:PSA_KEY_USAGE_EXPORT:0:0:0:PSA_SUCCESS:1

Expand Down
Loading

0 comments on commit 311809a

Please sign in to comment.