1/* 2 * PSA crypto layer on top of Mbed TLS crypto 3 */ 4/* 5 * Copyright The Mbed TLS Contributors 6 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 7 */ 8 9#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H 10#define PSA_CRYPTO_SLOT_MANAGEMENT_H 11 12#include "psa/crypto.h" 13#include "psa_crypto_core.h" 14#include "psa_crypto_se.h" 15 16/** Range of volatile key identifiers. 17 * 18 * The last #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation 19 * range of key identifiers are reserved for volatile key identifiers. 20 * A volatile key identifier is equal to #PSA_KEY_ID_VOLATILE_MIN plus the 21 * index of the key slot containing the volatile key definition. 22 */ 23 24/** The minimum value for a volatile key identifier. 25 */ 26#define PSA_KEY_ID_VOLATILE_MIN (PSA_KEY_ID_VENDOR_MAX - \ 27 MBEDTLS_PSA_KEY_SLOT_COUNT + 1) 28 29/** The maximum value for a volatile key identifier. 30 */ 31#define PSA_KEY_ID_VOLATILE_MAX PSA_KEY_ID_VENDOR_MAX 32 33/** Test whether a key identifier is a volatile key identifier. 34 * 35 * \param key_id Key identifier to test. 36 * 37 * \retval 1 38 * The key identifier is a volatile key identifier. 39 * \retval 0 40 * The key identifier is not a volatile key identifier. 41 */ 42static inline int psa_key_id_is_volatile(psa_key_id_t key_id) 43{ 44 return (key_id >= PSA_KEY_ID_VOLATILE_MIN) && 45 (key_id <= PSA_KEY_ID_VOLATILE_MAX); 46} 47 48/** Get the description of a key given its identifier and lock it. 49 * 50 * The descriptions of volatile keys and loaded persistent keys are stored in 51 * key slots. This function returns a pointer to the key slot containing the 52 * description of a key given its identifier. 53 * 54 * In case of a persistent key, the function loads the description of the key 55 * into a key slot if not already done. 56 * 57 * On success, the returned key slot has been registered for reading. 58 * It is the responsibility of the caller to call psa_unregister_read(slot) 59 * when they have finished reading the contents of the slot. 60 * 61 * \param key Key identifier to query. 62 * \param[out] p_slot On success, `*p_slot` contains a pointer to the 63 * key slot containing the description of the key 64 * identified by \p key. 65 * 66 * \retval #PSA_SUCCESS 67 * \p *p_slot contains a pointer to the key slot containing the 68 * description of the key identified by \p key. 69 * The key slot counter has been incremented. 70 * \retval #PSA_ERROR_BAD_STATE 71 * The library has not been initialized. 72 * \retval #PSA_ERROR_INVALID_HANDLE 73 * \p key is not a valid key identifier. 74 * \retval #PSA_ERROR_INSUFFICIENT_MEMORY 75 * \p key is a persistent key identifier. The implementation does not 76 * have sufficient resources to load the persistent key. This can be 77 * due to a lack of empty key slot, or available memory. 78 * \retval #PSA_ERROR_DOES_NOT_EXIST 79 * There is no key with key identifier \p key. 80 * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription 81 * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription 82 * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription 83 */ 84psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key, 85 psa_key_slot_t **p_slot); 86 87/** Initialize the key slot structures. 88 * 89 * \retval #PSA_SUCCESS 90 * Currently this function always succeeds. 91 */ 92psa_status_t psa_initialize_key_slots(void); 93 94/** Delete all data from key slots in memory. 95 * This function is not thread safe, it wipes every key slot regardless of 96 * state and reader count. It should only be called when no slot is in use. 97 * 98 * This does not affect persistent storage. */ 99void psa_wipe_all_key_slots(void); 100 101/** Find a free key slot and reserve it to be filled with a key. 102 * 103 * This function finds a key slot that is free, 104 * sets its state to PSA_SLOT_FILLING and then returns the slot. 105 * 106 * On success, the key slot's state is PSA_SLOT_FILLING. 107 * It is the responsibility of the caller to change the slot's state to 108 * PSA_SLOT_EMPTY/FULL once key creation has finished. 109 * 110 * If multi-threading is enabled, the caller must hold the 111 * global key slot mutex. 112 * 113 * \param[out] volatile_key_id On success, volatile key identifier 114 * associated to the returned slot. 115 * \param[out] p_slot On success, a pointer to the slot. 116 * 117 * \retval #PSA_SUCCESS \emptydescription 118 * \retval #PSA_ERROR_INSUFFICIENT_MEMORY 119 * There were no free key slots. 120 * \retval #PSA_ERROR_BAD_STATE \emptydescription 121 * \retval #PSA_ERROR_CORRUPTION_DETECTED 122 * This function attempted to operate on a key slot which was in an 123 * unexpected state. 124 */ 125psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id, 126 psa_key_slot_t **p_slot); 127 128/** Change the state of a key slot. 129 * 130 * This function changes the state of the key slot from expected_state to 131 * new state. If the state of the slot was not expected_state, the state is 132 * unchanged. 133 * 134 * If multi-threading is enabled, the caller must hold the 135 * global key slot mutex. 136 * 137 * \param[in] slot The key slot. 138 * \param[in] expected_state The current state of the slot. 139 * \param[in] new_state The new state of the slot. 140 * 141 * \retval #PSA_SUCCESS 142 The key slot's state variable is new_state. 143 * \retval #PSA_ERROR_CORRUPTION_DETECTED 144 * The slot's state was not expected_state. 145 */ 146static inline psa_status_t psa_key_slot_state_transition( 147 psa_key_slot_t *slot, psa_key_slot_state_t expected_state, 148 psa_key_slot_state_t new_state) 149{ 150 if (slot->state != expected_state) { 151 return PSA_ERROR_CORRUPTION_DETECTED; 152 } 153 slot->state = new_state; 154 return PSA_SUCCESS; 155} 156 157/** Register as a reader of a key slot. 158 * 159 * This function increments the key slot registered reader counter by one. 160 * If multi-threading is enabled, the caller must hold the 161 * global key slot mutex. 162 * 163 * \param[in] slot The key slot. 164 * 165 * \retval #PSA_SUCCESS 166 The key slot registered reader counter was incremented. 167 * \retval #PSA_ERROR_CORRUPTION_DETECTED 168 * The reader counter already reached its maximum value and was not 169 * increased, or the slot's state was not PSA_SLOT_FULL. 170 */ 171static inline psa_status_t psa_register_read(psa_key_slot_t *slot) 172{ 173 if ((slot->state != PSA_SLOT_FULL) || 174 (slot->registered_readers >= SIZE_MAX)) { 175 return PSA_ERROR_CORRUPTION_DETECTED; 176 } 177 slot->registered_readers++; 178 179 return PSA_SUCCESS; 180} 181 182/** Unregister from reading a key slot. 183 * 184 * This function decrements the key slot registered reader counter by one. 185 * If the state of the slot is PSA_SLOT_PENDING_DELETION, 186 * and there is only one registered reader (the caller), 187 * this function will call psa_wipe_key_slot(). 188 * If multi-threading is enabled, the caller must hold the 189 * global key slot mutex. 190 * 191 * \note To ease the handling of errors in retrieving a key slot 192 * a NULL input pointer is valid, and the function returns 193 * successfully without doing anything in that case. 194 * 195 * \param[in] slot The key slot. 196 * \retval #PSA_SUCCESS 197 * \p slot is NULL or the key slot reader counter has been 198 * decremented (and potentially wiped) successfully. 199 * \retval #PSA_ERROR_CORRUPTION_DETECTED 200 * The slot's state was neither PSA_SLOT_FULL nor 201 * PSA_SLOT_PENDING_DELETION. 202 * Or a wipe was attempted and the slot's state was not 203 * PSA_SLOT_PENDING_DELETION. 204 * Or registered_readers was equal to 0. 205 */ 206psa_status_t psa_unregister_read(psa_key_slot_t *slot); 207 208/** Wrap a call to psa_unregister_read in the global key slot mutex. 209 * 210 * If threading is disabled, this simply calls psa_unregister_read. 211 * 212 * \note To ease the handling of errors in retrieving a key slot 213 * a NULL input pointer is valid, and the function returns 214 * successfully without doing anything in that case. 215 * 216 * \param[in] slot The key slot. 217 * \retval #PSA_SUCCESS 218 * \p slot is NULL or the key slot reader counter has been 219 * decremented (and potentially wiped) successfully. 220 * \retval #PSA_ERROR_CORRUPTION_DETECTED 221 * The slot's state was neither PSA_SLOT_FULL nor 222 * PSA_SLOT_PENDING_DELETION. 223 * Or a wipe was attempted and the slot's state was not 224 * PSA_SLOT_PENDING_DELETION. 225 * Or registered_readers was equal to 0. 226 */ 227psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot); 228 229/** Test whether a lifetime designates a key in an external cryptoprocessor. 230 * 231 * \param lifetime The lifetime to test. 232 * 233 * \retval 1 234 * The lifetime designates an external key. There should be a 235 * registered driver for this lifetime, otherwise the key cannot 236 * be created or manipulated. 237 * \retval 0 238 * The lifetime designates a key that is volatile or in internal 239 * storage. 240 */ 241static inline int psa_key_lifetime_is_external(psa_key_lifetime_t lifetime) 242{ 243 return PSA_KEY_LIFETIME_GET_LOCATION(lifetime) 244 != PSA_KEY_LOCATION_LOCAL_STORAGE; 245} 246 247/** Validate a key's location. 248 * 249 * This function checks whether the key's attributes point to a location that 250 * is known to the PSA Core, and returns the driver function table if the key 251 * is to be found in an external location. 252 * 253 * \param[in] lifetime The key lifetime attribute. 254 * \param[out] p_drv On success, when a key is located in external 255 * storage, returns a pointer to the driver table 256 * associated with the key's storage location. 257 * 258 * \retval #PSA_SUCCESS \emptydescription 259 * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription 260 */ 261psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime, 262 psa_se_drv_table_entry_t **p_drv); 263 264/** Validate the persistence of a key. 265 * 266 * \param[in] lifetime The key lifetime attribute. 267 * 268 * \retval #PSA_SUCCESS \emptydescription 269 * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys 270 * are not supported. 271 */ 272psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime); 273 274/** Validate a key identifier. 275 * 276 * \param[in] key The key identifier. 277 * \param[in] vendor_ok Non-zero to indicate that key identifiers in the 278 * vendor range are allowed, volatile key identifiers 279 * excepted \c 0 otherwise. 280 * 281 * \retval <> 0 if the key identifier is valid, 0 otherwise. 282 */ 283int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok); 284 285#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ 286