SE support: Use a transaction when registering a key

When registering a key in a secure element, go through the transaction
mechanism. This makes the code simpler, at the expense of a few extra
storage operations. Given that registering a key is typically very
rare over the lifetime of a device, this is an acceptable loss.

Drivers must now have a p_validate_slot_number method, otherwise
registering a key is not possible. This reduces the risk that due to a
mistake during the integration of a device, an application might claim
a slot in a way that is not supported by the driver.
This commit is contained in:
Gilles Peskine 2019-10-01 14:18:35 +02:00
parent 37b5c831b4
commit 3efcebbc5e
4 changed files with 30 additions and 47 deletions

View File

@ -186,6 +186,9 @@ static inline void psa_clear_key_slot_number(
* \retval #PSA_ERROR_ALREADY_EXISTS * \retval #PSA_ERROR_ALREADY_EXISTS
* There is already a key with the identifier specified in * There is already a key with the identifier specified in
* \p attributes. * \p attributes.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The secure element driver for the specified lifetime does not
* support registering a key.
* \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INVALID_ARGUMENT
* \p attributes specifies a lifetime which is not located * \p attributes specifies a lifetime which is not located
* in a secure element. * in a secure element.

View File

@ -1579,7 +1579,7 @@ static psa_status_t psa_start_key_creation(
#if defined(MBEDTLS_PSA_CRYPTO_SE_C) #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things /* For a key in a secure element, we need to do three things
* when creating a key (but not when registering an existing key): * when creating or registering a key:
* create the key file in internal storage, create the * create the key file in internal storage, create the
* key inside the secure element, and update the driver's * key inside the secure element, and update the driver's
* persistent data. Start a transaction that will encompass these * persistent data. Start a transaction that will encompass these
@ -1592,7 +1592,7 @@ static psa_status_t psa_start_key_creation(
* secure element driver updates its persistent state, but we do not yet * secure element driver updates its persistent state, but we do not yet
* save the driver's persistent state, so that if the power fails, * save the driver's persistent state, so that if the power fails,
* we can roll back to a state where the key doesn't exist. */ * we can roll back to a state where the key doesn't exist. */
if( *p_drv != NULL && method != PSA_KEY_CREATION_REGISTER ) if( *p_drv != NULL )
{ {
status = psa_find_se_slot_for_key( attributes, method, *p_drv, status = psa_find_se_slot_for_key( attributes, method, *p_drv,
&slot->data.se.slot_number ); &slot->data.se.slot_number );
@ -1609,6 +1609,12 @@ static psa_status_t psa_start_key_creation(
return( status ); return( status );
} }
} }
if( *p_drv == NULL && method == PSA_KEY_CREATION_REGISTER )
{
/* Key registration only makes sense with a secure element. */
return( PSA_ERROR_INVALID_ARGUMENT );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
return( status ); return( status );
@ -1883,7 +1889,6 @@ psa_status_t mbedtls_psa_register_se_key(
psa_status_t status; psa_status_t status;
psa_key_slot_t *slot = NULL; psa_key_slot_t *slot = NULL;
psa_se_drv_table_entry_t *driver = NULL; psa_se_drv_table_entry_t *driver = NULL;
const psa_drv_se_t *drv;
psa_key_handle_t handle = 0; psa_key_handle_t handle = 0;
/* Leaving attributes unspecified is not currently supported. /* Leaving attributes unspecified is not currently supported.
@ -1900,37 +1905,6 @@ psa_status_t mbedtls_psa_register_se_key(
if( status != PSA_SUCCESS ) if( status != PSA_SUCCESS )
goto exit; goto exit;
if( driver == NULL )
{
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
drv = psa_get_se_driver_methods( driver );
if ( psa_get_key_slot_number( attributes,
&slot->data.se.slot_number ) != PSA_SUCCESS )
{
/* The application didn't specify a slot number. This doesn't
* make sense when registering a slot. */
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
/* If the driver has a slot number validation method, call it.
* If it doesn't, it means the secure element is unable to validate
* anything and so we have to trust the application. */
if( drv->key_management != NULL &&
drv->key_management->p_validate_slot_number != NULL )
{
status = drv->key_management->p_validate_slot_number(
psa_get_se_driver_context( driver ),
attributes,
PSA_KEY_CREATION_REGISTER,
slot->data.se.slot_number );
if( status != PSA_SUCCESS )
goto exit;
}
status = psa_finish_key_creation( slot, driver ); status = psa_finish_key_creation( slot, driver );
exit: exit:

View File

@ -225,6 +225,12 @@ psa_status_t psa_find_se_slot_for_key(
attributes, method, attributes, method,
*slot_number ); *slot_number );
} }
else if( method == PSA_KEY_CREATION_REGISTER )
{
/* The application didn't specify a slot number. This doesn't
* make sense when registering a slot. */
return( PSA_ERROR_INVALID_ARGUMENT );
}
else else
{ {
/* The application didn't tell us which slot to use. Let the driver /* The application didn't tell us which slot to use. Let the driver

View File

@ -121,23 +121,23 @@ Key generation smoke test: HMAC-SHA-256
generate_key_smoke:PSA_KEY_TYPE_HMAC:256:PSA_ALG_HMAC( PSA_ALG_SHA_256 ) generate_key_smoke:PSA_KEY_TYPE_HMAC:256:PSA_ALG_HMAC( PSA_ALG_SHA_256 )
Key registration: smoke test Key registration: smoke test
register_key_smoke_test:MIN_DRIVER_LIFETIME:-1:PSA_SUCCESS
Key registration: invalid lifetime (volatile)
register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:-1:PSA_ERROR_INVALID_ARGUMENT
Key registration: invalid lifetime (internal storage)
register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:-1:PSA_ERROR_INVALID_ARGUMENT
Key registration: invalid lifetime (no registered driver)
register_key_smoke_test:MIN_DRIVER_LIFETIME + 1:-1:PSA_ERROR_INVALID_ARGUMENT
Key registration: with driver validation (accepted)
register_key_smoke_test:MIN_DRIVER_LIFETIME:1:PSA_SUCCESS register_key_smoke_test:MIN_DRIVER_LIFETIME:1:PSA_SUCCESS
Key registration: with driver validation (rejected) Key registration: invalid lifetime (volatile)
register_key_smoke_test:PSA_KEY_LIFETIME_VOLATILE:1:PSA_ERROR_INVALID_ARGUMENT
Key registration: invalid lifetime (internal storage)
register_key_smoke_test:PSA_KEY_LIFETIME_PERSISTENT:1:PSA_ERROR_INVALID_ARGUMENT
Key registration: invalid lifetime (no registered driver)
register_key_smoke_test:MIN_DRIVER_LIFETIME + 1:1:PSA_ERROR_INVALID_ARGUMENT
Key registration: rejected
register_key_smoke_test:MIN_DRIVER_LIFETIME:0:PSA_ERROR_NOT_PERMITTED register_key_smoke_test:MIN_DRIVER_LIFETIME:0:PSA_ERROR_NOT_PERMITTED
Key registration: not supported
register_key_smoke_test:MIN_DRIVER_LIFETIME:-1:PSA_ERROR_NOT_SUPPORTED
Import-sign-verify: sign in driver, ECDSA Import-sign-verify: sign in driver, ECDSA
depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED
sign_verify:SIGN_IN_DRIVER_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e" sign_verify:SIGN_IN_DRIVER_AND_PARALLEL_CREATION:PSA_KEY_TYPE_ECC_KEY_PAIR( PSA_ECC_CURVE_SECP256R1 ):PSA_ALG_ECDSA_ANY:0:"49c9a8c18c4b885638c431cf1df1c994131609b580d4fd43a0cab17db2f13eee":"54686973206973206e6f74206120686173682e"