Skip to content

Add slot number attribute #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be good to reset the slot number to an invalid number here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but there's no invalid slot number at the moment. I'm considering introducing some though, if only to be future-proof. A slot number is 64 bits, maybe we should say that a slot number is 62 bits, reserve values 0xc000000000000000..0xfffffffffffffffe and declare 0xffffffffffffffff to be permanently invalid? This would not remove the need for the HAS_SLOT_NUMBER flag, because 0 is valid.

}

#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 | \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why or it with zero?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can add/remove flags just by editing their line and not have to modify the surrounding punctuation.

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 ( \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any policy for PSA macros similar to this one with MbedTLS ones?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Mbed TLS had no internal headers (library/*.h), but Mbed Crypto does in its PSA parts (library/psa_*.h).

0 )

/** Test whether a key slot is occupied.
*
* A key slot is occupied iff the key type is nonzero. This works because
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iff -> if

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Iff = “if and only if”

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right - Chris has reminded me of this acronym - if and only if. I really don't have it memorized.

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