2 * PSA crypto layer on top of Mbed TLS crypto
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 #if defined(MBEDTLS_PSA_CRYPTO_C)
25 #include "psa_crypto_service_integration.h"
26 #include "psa/crypto.h"
28 #include "psa_crypto_core.h"
29 #include "psa_crypto_slot_management.h"
30 #include "psa_crypto_storage.h"
31 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
32 #include "psa_crypto_se.h"
37 #if defined(MBEDTLS_PLATFORM_C)
38 #include "mbedtls/platform.h"
40 #define mbedtls_calloc calloc
41 #define mbedtls_free free
44 #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) )
47 psa_key_slot_t key_slots
[MBEDTLS_PSA_KEY_SLOT_COUNT
];
48 unsigned key_slots_initialized
: 1;
51 static psa_global_data_t global_data
;
53 psa_status_t
psa_validate_key_id(
54 mbedtls_svc_key_id_t key
, int vendor_ok
) {
55 psa_key_id_t key_id
= MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key
);
57 if ((PSA_KEY_ID_USER_MIN
<= key_id
) &&
58 (key_id
<= PSA_KEY_ID_USER_MAX
))
62 (PSA_KEY_ID_VENDOR_MIN
<= key_id
) &&
63 (key_id
<= PSA_KEY_ID_VENDOR_MAX
))
66 return (PSA_ERROR_INVALID_HANDLE
);
69 /** Get the description in memory of a key given its identifier and lock it.
71 * The descriptions of volatile keys and loaded persistent keys are
72 * stored in key slots. This function returns a pointer to the key slot
73 * containing the description of a key given its identifier.
75 * The function searches the key slots containing the description of the key
76 * with \p key identifier. The function does only read accesses to the key
77 * slots. The function does not load any persistent key thus does not access
80 * For volatile key identifiers, only one key slot is queried as a volatile
81 * key with identifier key_id can only be stored in slot of index
82 * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
84 * On success, the function locks the key slot. It is the responsibility of
85 * the caller to unlock the key slot when it does not access it anymore.
87 * \param key Key identifier to query.
88 * \param[out] p_slot On success, `*p_slot` contains a pointer to the
89 * key slot containing the description of the key
90 * identified by \p key.
92 * \retval #PSA_SUCCESS
93 * The pointer to the key slot containing the description of the key
94 * identified by \p key was returned.
95 * \retval #PSA_ERROR_INVALID_HANDLE
96 * \p key is not a valid key identifier.
97 * \retval #PSA_ERROR_DOES_NOT_EXIST
98 * There is no key with key identifier \p key in the key slots.
100 static psa_status_t
psa_get_and_lock_key_slot_in_memory(
101 mbedtls_svc_key_id_t key
, psa_key_slot_t
**p_slot
) {
102 psa_status_t status
= PSA_ERROR_CORRUPTION_DETECTED
;
103 psa_key_id_t key_id
= MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key
);
105 psa_key_slot_t
*slot
= NULL
;
107 if (psa_key_id_is_volatile(key_id
)) {
108 slot
= &global_data
.key_slots
[ key_id
- PSA_KEY_ID_VOLATILE_MIN
];
111 * Check if both the PSA key identifier key_id and the owner
112 * identifier of key match those of the key slot.
114 * Note that, if the key slot is not occupied, its PSA key identifier
115 * is equal to zero. This is an invalid value for a PSA key identifier
116 * and thus cannot be equal to the valid PSA key identifier key_id.
118 status
= mbedtls_svc_key_id_equal(key
, slot
->attr
.id
) ?
119 PSA_SUCCESS
: PSA_ERROR_DOES_NOT_EXIST
;
121 status
= psa_validate_key_id(key
, 1);
122 if (status
!= PSA_SUCCESS
)
125 for (slot_idx
= 0; slot_idx
< MBEDTLS_PSA_KEY_SLOT_COUNT
; slot_idx
++) {
126 slot
= &global_data
.key_slots
[ slot_idx
];
127 if (mbedtls_svc_key_id_equal(key
, slot
->attr
.id
))
130 status
= (slot_idx
< MBEDTLS_PSA_KEY_SLOT_COUNT
) ?
131 PSA_SUCCESS
: PSA_ERROR_DOES_NOT_EXIST
;
134 if (status
== PSA_SUCCESS
) {
135 status
= psa_lock_key_slot(slot
);
136 if (status
== PSA_SUCCESS
)
143 psa_status_t
psa_initialize_key_slots(void) {
144 /* Nothing to do: program startup and psa_wipe_all_key_slots() both
145 * guarantee that the key slots are initialized to all-zero, which
146 * means that all the key slots are in a valid, empty state. */
147 global_data
.key_slots_initialized
= 1;
148 return (PSA_SUCCESS
);
151 void psa_wipe_all_key_slots(void) {
154 for (slot_idx
= 0; slot_idx
< MBEDTLS_PSA_KEY_SLOT_COUNT
; slot_idx
++) {
155 psa_key_slot_t
*slot
= &global_data
.key_slots
[ slot_idx
];
156 slot
->lock_count
= 1;
157 (void) psa_wipe_key_slot(slot
);
159 global_data
.key_slots_initialized
= 0;
162 psa_status_t
psa_get_empty_key_slot(psa_key_id_t
*volatile_key_id
,
163 psa_key_slot_t
**p_slot
) {
164 psa_status_t status
= PSA_ERROR_CORRUPTION_DETECTED
;
166 psa_key_slot_t
*selected_slot
, *unlocked_persistent_key_slot
;
168 if (! global_data
.key_slots_initialized
) {
169 status
= PSA_ERROR_BAD_STATE
;
173 selected_slot
= unlocked_persistent_key_slot
= NULL
;
174 for (slot_idx
= 0; slot_idx
< MBEDTLS_PSA_KEY_SLOT_COUNT
; slot_idx
++) {
175 psa_key_slot_t
*slot
= &global_data
.key_slots
[ slot_idx
];
176 if (! psa_is_key_slot_occupied(slot
)) {
177 selected_slot
= slot
;
181 if ((unlocked_persistent_key_slot
== NULL
) &&
182 (! PSA_KEY_LIFETIME_IS_VOLATILE(slot
->attr
.lifetime
)) &&
183 (! psa_is_key_slot_locked(slot
)))
184 unlocked_persistent_key_slot
= slot
;
188 * If there is no unused key slot and there is at least one unlocked key
189 * slot containing the description of a persistent key, recycle the first
190 * such key slot we encountered. If we later need to operate on the
191 * persistent key we are evicting now, we will reload its description from
194 if ((selected_slot
== NULL
) &&
195 (unlocked_persistent_key_slot
!= NULL
)) {
196 selected_slot
= unlocked_persistent_key_slot
;
197 selected_slot
->lock_count
= 1;
198 psa_wipe_key_slot(selected_slot
);
201 if (selected_slot
!= NULL
) {
202 status
= psa_lock_key_slot(selected_slot
);
203 if (status
!= PSA_SUCCESS
)
206 *volatile_key_id
= PSA_KEY_ID_VOLATILE_MIN
+
207 ((psa_key_id_t
)(selected_slot
- global_data
.key_slots
));
208 *p_slot
= selected_slot
;
210 return (PSA_SUCCESS
);
212 status
= PSA_ERROR_INSUFFICIENT_MEMORY
;
216 *volatile_key_id
= 0;
221 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
222 static psa_status_t
psa_load_persistent_key_into_slot(psa_key_slot_t
*slot
) {
223 psa_status_t status
= PSA_SUCCESS
;
224 uint8_t *key_data
= NULL
;
225 size_t key_data_length
= 0;
227 status
= psa_load_persistent_key(&slot
->attr
,
228 &key_data
, &key_data_length
);
229 if (status
!= PSA_SUCCESS
)
232 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
233 /* Special handling is required for loading keys associated with a
234 * dynamically registered SE interface. */
235 const psa_drv_se_t
*drv
;
236 psa_drv_se_context_t
*drv_context
;
237 if (psa_get_se_driver(slot
->attr
.lifetime
, &drv
, &drv_context
)) {
238 psa_se_key_data_storage_t
*data
;
240 if (key_data_length
!= sizeof(*data
)) {
241 status
= PSA_ERROR_DATA_INVALID
;
244 data
= (psa_se_key_data_storage_t
*) key_data
;
245 status
= psa_copy_key_material_into_slot(
246 slot
, data
->slot_number
, sizeof(data
->slot_number
));
249 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
251 status
= psa_copy_key_material_into_slot(slot
, key_data
, key_data_length
);
254 psa_free_persistent_key_data(key_data
, key_data_length
);
257 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
259 psa_status_t
psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key
,
260 psa_key_slot_t
**p_slot
) {
261 psa_status_t status
= PSA_ERROR_CORRUPTION_DETECTED
;
264 if (! global_data
.key_slots_initialized
)
265 return (PSA_ERROR_BAD_STATE
);
268 * On success, the pointer to the slot is passed directly to the caller
269 * thus no need to unlock the key slot here.
271 status
= psa_get_and_lock_key_slot_in_memory(key
, p_slot
);
272 if (status
!= PSA_ERROR_DOES_NOT_EXIST
)
275 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
276 psa_key_id_t volatile_key_id
;
278 status
= psa_get_empty_key_slot(&volatile_key_id
, p_slot
);
279 if (status
!= PSA_SUCCESS
)
282 (*p_slot
)->attr
.lifetime
= PSA_KEY_LIFETIME_PERSISTENT
;
283 (*p_slot
)->attr
.id
= key
;
285 status
= psa_load_persistent_key_into_slot(*p_slot
);
286 if (status
!= PSA_SUCCESS
)
287 psa_wipe_key_slot(*p_slot
);
291 return (PSA_ERROR_DOES_NOT_EXIST
);
292 #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
296 psa_status_t
psa_unlock_key_slot(psa_key_slot_t
*slot
) {
298 return (PSA_SUCCESS
);
300 if (slot
->lock_count
> 0) {
302 return (PSA_SUCCESS
);
306 * As the return error code may not be handled in case of multiple errors,
307 * do our best to report if the lock counter is equal to zero: if
308 * available call MBEDTLS_PARAM_FAILED that may terminate execution (if
309 * called as part of the execution of a unit test suite this will stop the
310 * test suite execution).
312 #ifdef MBEDTLS_CHECK_PARAMS
313 MBEDTLS_PARAM_FAILED(slot
->lock_count
> 0);
316 return (PSA_ERROR_CORRUPTION_DETECTED
);
319 psa_status_t
psa_validate_key_location(psa_key_lifetime_t lifetime
,
320 psa_se_drv_table_entry_t
**p_drv
) {
321 if (psa_key_lifetime_is_external(lifetime
)) {
322 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
323 /* Check whether a driver is registered against this lifetime */
324 psa_se_drv_table_entry_t
*driver
= psa_get_se_driver_entry(lifetime
);
325 if (driver
!= NULL
) {
328 return (PSA_SUCCESS
);
330 #else /* MBEDTLS_PSA_CRYPTO_SE_C */
332 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
334 #if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
335 /* Key location for external keys gets checked by the wrapper */
336 return (PSA_SUCCESS
);
337 #else /* MBEDTLS_PSA_CRYPTO_DRIVERS */
338 /* No support for external lifetimes at all, or dynamic interface
339 * did not find driver for requested lifetime. */
340 return (PSA_ERROR_INVALID_ARGUMENT
);
341 #endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
343 /* Local/internal keys are always valid */
344 return (PSA_SUCCESS
);
347 psa_status_t
psa_validate_key_persistence(psa_key_lifetime_t lifetime
) {
348 if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime
)) {
349 /* Volatile keys are always supported */
350 return (PSA_SUCCESS
);
352 /* Persistent keys require storage support */
353 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
354 return (PSA_SUCCESS
);
355 #else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
356 return (PSA_ERROR_NOT_SUPPORTED
);
357 #endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
361 psa_status_t
psa_open_key(mbedtls_svc_key_id_t key
, psa_key_handle_t
*handle
) {
362 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
364 psa_key_slot_t
*slot
;
366 status
= psa_get_and_lock_key_slot(key
, &slot
);
367 if (status
!= PSA_SUCCESS
) {
368 *handle
= PSA_KEY_HANDLE_INIT
;
374 return (psa_unlock_key_slot(slot
));
376 #else /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
378 *handle
= PSA_KEY_HANDLE_INIT
;
379 return (PSA_ERROR_NOT_SUPPORTED
);
380 #endif /* !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
383 psa_status_t
psa_close_key(psa_key_handle_t handle
) {
385 psa_key_slot_t
*slot
;
387 if (psa_key_handle_is_null(handle
))
388 return (PSA_SUCCESS
);
390 status
= psa_get_and_lock_key_slot_in_memory(handle
, &slot
);
391 if (status
!= PSA_SUCCESS
)
394 if (slot
->lock_count
<= 1)
395 return (psa_wipe_key_slot(slot
));
397 return (psa_unlock_key_slot(slot
));
400 psa_status_t
psa_purge_key(mbedtls_svc_key_id_t key
) {
402 psa_key_slot_t
*slot
;
404 status
= psa_get_and_lock_key_slot_in_memory(key
, &slot
);
405 if (status
!= PSA_SUCCESS
)
408 if ((! PSA_KEY_LIFETIME_IS_VOLATILE(slot
->attr
.lifetime
)) &&
409 (slot
->lock_count
<= 1))
410 return (psa_wipe_key_slot(slot
));
412 return (psa_unlock_key_slot(slot
));
415 void mbedtls_psa_get_stats(mbedtls_psa_stats_t
*stats
) {
418 memset(stats
, 0, sizeof(*stats
));
420 for (slot_idx
= 0; slot_idx
< MBEDTLS_PSA_KEY_SLOT_COUNT
; slot_idx
++) {
421 const psa_key_slot_t
*slot
= &global_data
.key_slots
[ slot_idx
];
422 if (psa_is_key_slot_locked(slot
)) {
423 ++stats
->locked_slots
;
425 if (! psa_is_key_slot_occupied(slot
)) {
426 ++stats
->empty_slots
;
429 if (slot
->attr
.lifetime
== PSA_KEY_LIFETIME_VOLATILE
)
430 ++stats
->volatile_slots
;
431 else if (slot
->attr
.lifetime
== PSA_KEY_LIFETIME_PERSISTENT
) {
432 psa_key_id_t id
= MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot
->attr
.id
);
433 ++stats
->persistent_slots
;
434 if (id
> stats
->max_open_internal_key_id
)
435 stats
->max_open_internal_key_id
= id
;
437 psa_key_id_t id
= MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot
->attr
.id
);
438 ++stats
->external_slots
;
439 if (id
> stats
->max_open_external_key_id
)
440 stats
->max_open_external_key_id
= id
;
445 #endif /* MBEDTLS_PSA_CRYPTO_C */