diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index bd3f71d5bc..61f44e028f 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -3268,6 +3268,39 @@ */ #define MBEDTLS_PSA_ITS_FILE_C +/** + * \def MBEDTLS_PSA_STATIC_KEY_SLOTS + * + * Statically preallocate all key slot buffers to store volatile keys in PSA + * instead of allocating them dynamically when required. This helps reducing + * heap memory usage as well as heap management code's footprint in embedded + * devices. + * + * \note This feature comes with a (potentially) higher RAM usage since: + * - All the key slots are allocated no matter if they are used of not. + * - Each key slot's length is as large as the largest key type supported + * in the build. + * + * Requires: MBEDTLS_PSA_CRYPTO_C + * + */ +//#define MBEDTLS_PSA_STATIC_KEY_SLOTS + +/** + * \def MBEDTLS_PSA_STATIC_KEY_SLOTS + * + * Optionally define the size (in bytes) of each static key slot. If not + * explicitly defined then it's automatically set to hold the maximum + * asymmetric PSA key enabled in the build (through PSA_WANT_xxx symbols). + * If required by the application this parameter can be set to higher values + * in order to store larger objects (ex: raw keys), but please note that this + * will increase RAM usage. + * + * Requires: MBEDTLS_PSA_STATIC_KEY_SLOTS + * + */ +//#define MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE 256 + /** * \def MBEDTLS_RIPEMD160_C * diff --git a/include/psa/crypto_sizes.h b/include/psa/crypto_sizes.h index 635ee98f80..892bfa3e7f 100644 --- a/include/psa/crypto_sizes.h +++ b/include/psa/crypto_sizes.h @@ -1038,6 +1038,10 @@ PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif +#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \ + (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \ + PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE + /** Sufficient output buffer size for psa_raw_key_agreement(). * * This macro returns a compile-time constant if its arguments are @@ -1085,6 +1089,27 @@ #define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) #endif +/** Maximum key length for ciphers. + * + * Since there is no additional PSA_WANT_xxx symbol to specifiy the size of + * the key once a cipher is enabled (as it happens for asymmetric keys for + * example), the maximum key length is taken into account for each cipher. + * The resulting value will be the maximum cipher's key length given depending + * on which ciphers are enabled. + * + * Note: max value for AES used below would be doubled if XTS were enabled, but + * this mode is currently not supported in Mbed TLS implementation of PSA + * APIs. + */ +#if (defined(PSA_WANT_KEY_TYPE_AES) || defined(PSA_WANT_KEY_TYPE_ARIA) || \ + defined(PSA_WANT_KEY_TYPE_CAMELLIA) || defined(PSA_WANT_KEY_TYPE_CHACHA20)) +#define PSA_CIPHER_MAX_KEY_LENGTH 32u +#elif defined(PSA_WANT_KEY_TYPE_DES) +#define PSA_CIPHER_MAX_KEY_LENGTH 24u +#else +#define PSA_CIPHER_MAX_KEY_LENGTH 0u +#endif + /** The default IV size for a cipher algorithm, in bytes. * * The IV that is generated as part of a call to #psa_cipher_encrypt() is always diff --git a/library/pk.c b/library/pk.c index 3fe51ea34f..51f0c24088 100644 --- a/library/pk.c +++ b/library/pk.c @@ -35,10 +35,6 @@ #include #include -#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \ - (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \ - PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE - /* * Initialise a mbedtls_pk_context */ diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c4f41db10b..696e830b8e 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -705,6 +705,17 @@ MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do( psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, size_t buffer_length) { +#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) + if (slot->key.in_use) { + return PSA_ERROR_ALREADY_EXISTS; + } + + if (buffer_length > ((size_t) MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE)) { + return PSA_ERROR_NOT_SUPPORTED; + } + + slot->key.in_use = 1; +#else if (slot->key.data != NULL) { return PSA_ERROR_ALREADY_EXISTS; } @@ -713,6 +724,7 @@ psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot, if (slot->key.data == NULL) { return PSA_ERROR_INSUFFICIENT_MEMORY; } +#endif slot->key.bytes = buffer_length; return PSA_SUCCESS; @@ -1177,11 +1189,16 @@ static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy( psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot) { +#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) + slot->key.in_use = 0; +#else /* MBEDTLS_PSA_STATIC_KEY_SLOTS */ if (slot->key.data != NULL) { mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes); } slot->key.data = NULL; +#endif /* MBEDTLS_PSA_STATIC_KEY_SLOTS */ + slot->key.bytes = 0; return PSA_SUCCESS; @@ -2096,7 +2113,13 @@ psa_status_t psa_import_key(const psa_key_attributes_t *attributes, * storage ( thus not in the case of importing a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the imported key material. */ - if (slot->key.data == NULL) { +#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) + int is_slot_unused = (slot->key.in_use == 0); +#else + int is_slot_unused = (slot->key.data == NULL); +#endif + + if (is_slot_unused) { if (psa_key_lifetime_is_external(attributes->lifetime)) { status = psa_driver_wrapper_get_key_buffer_size_from_key_data( attributes, data, data_length, &storage_size); @@ -8013,7 +8036,13 @@ psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes, * storage ( thus not in the case of generating a key in a secure element * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a * buffer to hold the generated key material. */ - if (slot->key.data == NULL) { +#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) + int is_slot_unused = (slot->key.in_use == 0); +#else + int is_slot_unused = (slot->key.data == NULL); +#endif + + if (is_slot_unused) { if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) == PSA_KEY_LOCATION_LOCAL_STORAGE) { status = psa_validate_key_type_and_size_for_key_generation( diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h index 21e7559f01..5f59697612 100644 --- a/library/psa_crypto_core.h +++ b/library/psa_crypto_core.h @@ -55,6 +55,12 @@ typedef enum { PSA_SLOT_PENDING_DELETION, } psa_key_slot_state_t; +/* If the size of static key slots is not explicitly defined by the user, then + * set it to PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE. */ +#if !defined(MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE) +#define MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE (PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE) +#endif /* !MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE*/ + /** The data structure representing a key slot, containing key material * and metadata for one key. */ @@ -155,7 +161,12 @@ typedef struct { /* Dynamically allocated key data buffer. * Format as specified in psa_export_key(). */ struct key_data { +#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS) + int in_use; + uint8_t data[MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE]; +#else /* MBEDTLS_PSA_STATIC_KEY_SLOTS */ uint8_t *data; +#endif /* MBEDTLS_PSA_STATIC_KEY_SLOTS */ size_t bytes; } key; } psa_key_slot_t; diff --git a/scripts/config.py b/scripts/config.py index bb4a22c9cc..ef13062936 100755 --- a/scripts/config.py +++ b/scripts/config.py @@ -110,6 +110,8 @@ EXCLUDE_FROM_FULL = frozenset([ 'MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN', # build dependency (clang+memsan) 'MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND', # build dependency (valgrind headers) 'MBEDTLS_X509_REMOVE_INFO', # removes a feature + 'MBEDTLS_PSA_STATIC_KEY_SLOTS', # only relevant for embedded devices + 'MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE', # only relevant for embedded devices ]) def is_seamless_alt(name):