mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-04-16 08:42:50 +00:00
Add mbedtls_psa_crypto_init_subsystem()
Internal only for now, but can be made external with some more work. Break up psa_crypto_init into chunks to prevent deadlocks when initialising RNG, likewise break up mbedtls_crypto_free() to stop having to hold more than one mutex at a time. Signed-off-by: Paul Elliott <paul.elliott@arm.com>
This commit is contained in:
parent
358165246b
commit
47cee8e2ee
@ -93,10 +93,25 @@ static int key_type_is_raw_bytes(psa_key_type_t type)
|
|||||||
#define RNG_INITIALIZED 1
|
#define RNG_INITIALIZED 1
|
||||||
#define RNG_SEEDED 2
|
#define RNG_SEEDED 2
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 0,
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_RNG,
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_TRANSACTION,
|
||||||
|
} mbedtls_psa_crypto_subsystem;
|
||||||
|
|
||||||
|
#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED 0x01
|
||||||
|
#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED 0x02
|
||||||
|
#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED 0x04
|
||||||
|
|
||||||
|
#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED ( \
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \
|
||||||
|
PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t initialized;
|
uint8_t initialized;
|
||||||
uint8_t rng_state;
|
uint8_t rng_state;
|
||||||
uint8_t drivers_initialized;
|
|
||||||
mbedtls_psa_random_context_t rng;
|
mbedtls_psa_random_context_t rng;
|
||||||
} psa_global_data_t;
|
} psa_global_data_t;
|
||||||
|
|
||||||
@ -106,11 +121,22 @@ static uint8_t psa_get_initialized(void)
|
|||||||
{
|
{
|
||||||
uint8_t initialized;
|
uint8_t initialized;
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
initialized = global_data.rng_state == RNG_SEEDED;
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
initialized = global_data.initialized;
|
initialized =
|
||||||
|
(initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));
|
||||||
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
@ -127,7 +153,7 @@ static uint8_t psa_get_drivers_initialized(void)
|
|||||||
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
initialized = global_data.drivers_initialized;
|
initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;
|
||||||
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
@ -7490,29 +7516,53 @@ psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
|
|||||||
|
|
||||||
void mbedtls_psa_crypto_free(void)
|
void mbedtls_psa_crypto_free(void)
|
||||||
{
|
{
|
||||||
/* Need to hold the mutex here to prevent this going ahead before
|
|
||||||
* psa_crypto_init() has completed, and to ensure integrity of
|
|
||||||
* global_data. */
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
psa_wipe_all_key_slots();
|
/* Nothing to do to free transaction. */
|
||||||
if (global_data.rng_state != RNG_NOT_INITIALIZED) {
|
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {
|
||||||
mbedtls_psa_random_free(&global_data.rng);
|
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wipe all remaining data, including configuration.
|
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {
|
||||||
* In particular, this sets all state indicator to the value
|
psa_wipe_all_key_slots();
|
||||||
* indicating "uninitialized". */
|
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
|
||||||
mbedtls_platform_zeroize(&global_data, sizeof(global_data));
|
}
|
||||||
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
if (global_data.rng_state != RNG_NOT_INITIALIZED) {
|
||||||
|
mbedtls_psa_random_free(&global_data.rng);
|
||||||
|
}
|
||||||
|
global_data.rng_state = RNG_NOT_INITIALIZED;
|
||||||
|
mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
/* Terminate drivers */
|
/* Terminate drivers */
|
||||||
psa_driver_wrapper_free();
|
if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {
|
||||||
|
psa_driver_wrapper_free();
|
||||||
|
global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
|
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
|
||||||
@ -7540,74 +7590,172 @@ static psa_status_t psa_crypto_recover_transaction(
|
|||||||
}
|
}
|
||||||
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
|
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
|
||||||
|
|
||||||
|
static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)
|
||||||
|
{
|
||||||
|
psa_status_t status = PSA_SUCCESS;
|
||||||
|
uint8_t driver_wrappers_initialized = 0;
|
||||||
|
|
||||||
|
switch (subsystem) {
|
||||||
|
case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {
|
||||||
|
/* Init drivers */
|
||||||
|
status = psa_driver_wrapper_init();
|
||||||
|
|
||||||
|
/* Drivers need shutdown regardless of startup errors. */
|
||||||
|
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
|
||||||
|
&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {
|
||||||
|
status = psa_initialize_key_slots();
|
||||||
|
|
||||||
|
/* Need to wipe keys even if initialization fails. */
|
||||||
|
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
|
||||||
|
|
||||||
|
}
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
|
||||||
|
&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSA_CRYPTO_SUBSYSTEM_RNG:
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
driver_wrappers_initialized =
|
||||||
|
(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
|
||||||
|
&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
/* Need to use separate mutex here, as initialisation can require
|
||||||
|
* testing of init flags, which requires locking the global data
|
||||||
|
* mutex. */
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
/* Initialize and seed the random generator. */
|
||||||
|
if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {
|
||||||
|
mbedtls_psa_random_init(&global_data.rng);
|
||||||
|
global_data.rng_state = RNG_INITIALIZED;
|
||||||
|
|
||||||
|
status = mbedtls_psa_random_seed(&global_data.rng);
|
||||||
|
if (status == PSA_SUCCESS) {
|
||||||
|
global_data.rng_state = RNG_SEEDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
|
||||||
|
&mbedtls_threading_psa_rngdata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {
|
||||||
|
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
|
||||||
|
status = psa_crypto_load_transaction();
|
||||||
|
if (status == PSA_SUCCESS) {
|
||||||
|
status = psa_crypto_recover_transaction(&psa_crypto_transaction);
|
||||||
|
if (status == PSA_SUCCESS) {
|
||||||
|
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
|
||||||
|
}
|
||||||
|
status = psa_crypto_stop_transaction();
|
||||||
|
} else if (status == PSA_ERROR_DOES_NOT_EXIST) {
|
||||||
|
/* There's no transaction to complete. It's all good. */
|
||||||
|
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
|
||||||
|
status = PSA_SUCCESS;
|
||||||
|
}
|
||||||
|
#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
|
||||||
|
global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
|
||||||
|
status = PSA_SUCCESS;
|
||||||
|
#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
|
||||||
|
&mbedtls_threading_psa_globaldata_mutex));
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
status = PSA_ERROR_CORRUPTION_DETECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit label only required when using threading macros. */
|
||||||
|
#if defined(MBEDTLS_THREADING_C)
|
||||||
|
exit:
|
||||||
|
#endif /* defined(MBEDTLS_THREADING_C) */
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
psa_status_t psa_crypto_init(void)
|
psa_status_t psa_crypto_init(void)
|
||||||
{
|
{
|
||||||
psa_status_t status;
|
psa_status_t status;
|
||||||
|
|
||||||
/* Need to hold the mutex for the entire function to prevent incomplete
|
/* Double initialization is explicitly allowed. Early out if everything is
|
||||||
* initialisation before someone calls psa_crypto_free() or calls this
|
* done. */
|
||||||
* function again before we set global_data.initialised to 1. */
|
if (psa_get_initialized()) {
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
|
||||||
mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
|
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
|
||||||
|
|
||||||
/* We cannot use psa_get_initialized() here as we already hold the mutex. */
|
|
||||||
if (global_data.initialized == 1) {
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
|
||||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
|
||||||
|
|
||||||
/* Double initialization is explicitly allowed. */
|
|
||||||
return PSA_SUCCESS;
|
return PSA_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init drivers */
|
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);
|
||||||
status = psa_driver_wrapper_init();
|
|
||||||
if (status != PSA_SUCCESS) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
global_data.drivers_initialized = 1;
|
|
||||||
|
|
||||||
status = psa_initialize_key_slots();
|
|
||||||
if (status != PSA_SUCCESS) {
|
if (status != PSA_SUCCESS) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize and seed the random generator. */
|
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);
|
||||||
mbedtls_psa_random_init(&global_data.rng);
|
|
||||||
global_data.rng_state = RNG_INITIALIZED;
|
|
||||||
status = mbedtls_psa_random_seed(&global_data.rng);
|
|
||||||
if (status != PSA_SUCCESS) {
|
if (status != PSA_SUCCESS) {
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
global_data.rng_state = RNG_SEEDED;
|
|
||||||
|
|
||||||
#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
|
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);
|
||||||
status = psa_crypto_load_transaction();
|
if (status != PSA_SUCCESS) {
|
||||||
if (status == PSA_SUCCESS) {
|
goto exit;
|
||||||
status = psa_crypto_recover_transaction(&psa_crypto_transaction);
|
|
||||||
if (status != PSA_SUCCESS) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
status = psa_crypto_stop_transaction();
|
|
||||||
} else if (status == PSA_ERROR_DOES_NOT_EXIST) {
|
|
||||||
/* There's no transaction to complete. It's all good. */
|
|
||||||
status = PSA_SUCCESS;
|
|
||||||
}
|
}
|
||||||
#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
|
|
||||||
|
|
||||||
/* All done. */
|
status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);
|
||||||
global_data.initialized = 1;
|
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
|
||||||
#if defined(MBEDTLS_THREADING_C)
|
|
||||||
mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
|
|
||||||
#endif /* defined(MBEDTLS_THREADING_C) */
|
|
||||||
|
|
||||||
if (status != PSA_SUCCESS) {
|
if (status != PSA_SUCCESS) {
|
||||||
mbedtls_psa_crypto_free();
|
mbedtls_psa_crypto_free();
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user