|
| 1 | +/* |
| 2 | + * SPDX-License-Identifier: Apache-2.0 |
| 3 | + * Copyright (c) 2025 Silicon Laboratories Inc. |
| 4 | + */ |
| 5 | + |
| 6 | +#include <../library/psa_crypto_driver_wrappers.h> |
| 7 | +#include <zephyr/secure_storage/its/transform/aead_get.h> |
| 8 | +#include <zephyr/drivers/hwinfo.h> |
| 9 | +#include <zephyr/logging/log.h> |
| 10 | +#include <psa/crypto.h> |
| 11 | +#include <string.h> |
| 12 | + |
| 13 | +LOG_MODULE_DECLARE(secure_storage, CONFIG_SECURE_STORAGE_LOG_LEVEL); |
| 14 | + |
| 15 | +psa_status_t secure_storage_its_transform_aead_get_key( |
| 16 | + secure_storage_its_uid_t uid, |
| 17 | + uint8_t key[static CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE]) |
| 18 | +{ |
| 19 | + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; |
| 20 | + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; |
| 21 | + psa_key_lifetime_t builtin_lifetime; |
| 22 | + psa_drv_slot_number_t builtin_slot; |
| 23 | + |
| 24 | + size_t builtin_key_buffer_length = 0; |
| 25 | + uint8_t builtin_key_buffer[4]; |
| 26 | + size_t session_key_length = 0; |
| 27 | + ssize_t hwinfo_ret; |
| 28 | + struct { |
| 29 | + uint8_t device_id[8]; |
| 30 | + secure_storage_its_uid_t uid; |
| 31 | + } __packed data; |
| 32 | + |
| 33 | + /* Use device ID combined with storage uid as IV for key derivation */ |
| 34 | + hwinfo_ret = hwinfo_get_device_id(data.device_id, sizeof(data.device_id)); |
| 35 | + if (hwinfo_ret < sizeof(data.device_id)) { |
| 36 | + LOG_ERR("Failed to get device ID. (%zd)", hwinfo_ret); |
| 37 | + return PSA_ERROR_HARDWARE_FAILURE; |
| 38 | + } |
| 39 | + data.uid = uid; |
| 40 | + |
| 41 | + /* Get builtin key attributes */ |
| 42 | + psa_set_key_id(&attributes, SL_SE_BUILTIN_KEY_TRUSTZONE_ID); |
| 43 | + status = mbedtls_psa_platform_get_builtin_key(psa_get_key_id(&attributes), |
| 44 | + &builtin_lifetime, &builtin_slot); |
| 45 | + if (status != PSA_SUCCESS) { |
| 46 | + return status; |
| 47 | + } |
| 48 | + |
| 49 | + /* Load builtin key using PSA driver API. Need to use driver wrapper directly since we are |
| 50 | + * implementing the key storage used by the PSA crypto core, and therefore can't rely on |
| 51 | + * the regular PSA crypto API. |
| 52 | + */ |
| 53 | + psa_set_key_lifetime(&attributes, builtin_lifetime); |
| 54 | + status = psa_driver_wrapper_get_builtin_key(builtin_slot, &attributes, builtin_key_buffer, |
| 55 | + sizeof(builtin_key_buffer), |
| 56 | + &builtin_key_buffer_length); |
| 57 | + if (status != PSA_SUCCESS) { |
| 58 | + return status; |
| 59 | + } |
| 60 | + |
| 61 | + /* Derive session key from built-in key using AES-CMAC */ |
| 62 | + status = psa_driver_wrapper_mac_compute( |
| 63 | + &attributes, builtin_key_buffer, builtin_key_buffer_length, PSA_ALG_CMAC, |
| 64 | + (const uint8_t *)&data, sizeof(data), key, |
| 65 | + CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE, &session_key_length); |
| 66 | + |
| 67 | + /* Verify that key derivation was successful before transferring the key to the caller */ |
| 68 | + if (status != PSA_SUCCESS || |
| 69 | + session_key_length != CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE) { |
| 70 | + memset(key, 0, CONFIG_SECURE_STORAGE_ITS_TRANSFORM_AEAD_KEY_SIZE); |
| 71 | + return PSA_ERROR_HARDWARE_FAILURE; |
| 72 | + } |
| 73 | + |
| 74 | + return status; |
| 75 | +} |
0 commit comments