/* * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ /* * PSA ITS emulator over settings. */ #include #include #include <../library/psa_crypto_its.h> #define LOG_MODULE_NAME pts_its_emu #include #include "mesh/net.h" #include "mesh/settings.h" LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); /* The value of 52 bytes was measured practically in the mbedTLS psa security storage. */ #define MAX_ITEM_LENGTH 52 #define MAX_ITEM_NUMBER MBEDTLS_PSA_KEY_SLOT_COUNT typedef struct { uint32_t size; psa_storage_create_flags_t flags; uint8_t data[MAX_ITEM_LENGTH]; } psa_its_pst_item_t; typedef struct { psa_storage_uid_t uid; psa_its_pst_item_t pst_item; } psa_its_item_t; static psa_its_item_t item[MAX_ITEM_NUMBER]; static psa_its_item_t *get_item_by_uid(psa_storage_uid_t uid) { for (int i = 0; i < MAX_ITEM_NUMBER; i++) { if (uid == item[i].uid) { return &item[i]; } } return NULL; } static int itsemul_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { ssize_t len; uint64_t uid; psa_its_item_t *p_item; LOG_DBG("read out uid: %s", name); if (!name) { LOG_ERR("Insufficient number of arguments"); return -ENOENT; } uid = strtoull(name, NULL, 10); if (uid == ULLONG_MAX) { LOG_ERR("Invalid format for uid"); return -EINVAL; } p_item = get_item_by_uid(uid); if (p_item == NULL) { p_item = get_item_by_uid(0ull); } if (p_item == NULL) { LOG_ERR("Insufficient sources for %llu", uid); return -EINVAL; } p_item->uid = uid; len = read_cb(cb_arg, &p_item->pst_item, len_rd); if (len < 0) { LOG_ERR("Failed to read value (err %zd)", len); return -EINVAL; } LOG_HEXDUMP_DBG(&p_item->pst_item, len, "pst_item:"); if (len != len_rd) { LOG_ERR("Unexpected length (%zd != %zu)", len, len_rd); return -EINVAL; } return 0; } SETTINGS_STATIC_HANDLER_DEFINE(psa_its_emu, "itsemul", NULL, itsemul_set, NULL, NULL); psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) { psa_its_item_t *p_item; LOG_DBG("get info uid: %llu", uid); p_item = get_item_by_uid(uid); if (p_item == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } p_info->flags = p_item->pst_item.flags; p_info->size = p_item->pst_item.size; LOG_DBG("flags: %lu, size: %lu", p_info->flags, p_info->size); return PSA_SUCCESS; } psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data, size_t *p_data_length) { psa_its_item_t *p_item; psa_its_pst_item_t *p_pst_item; LOG_DBG("get uid: %llu", uid); p_item = get_item_by_uid(uid); if (p_item == NULL) { return PSA_ERROR_DOES_NOT_EXIST; } p_pst_item = &p_item->pst_item; if (data_offset > p_pst_item->size) { return PSA_ERROR_DATA_CORRUPT; } *p_data_length = MIN(p_pst_item->size - data_offset, data_length); memcpy(p_data, p_pst_item->data + data_offset, *p_data_length); return PSA_SUCCESS; } psa_status_t psa_its_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) { char path[40]; psa_its_item_t *p_item; psa_its_pst_item_t *p_pst_item; psa_status_t status = PSA_SUCCESS; LOG_DBG("Set uid: %llu, len: %lu", uid, data_length); if (data_length > MAX_ITEM_LENGTH) { LOG_ERR("Too long item data: %lu > " STRINGIFY(MAX_ITEM_LENGTH), data_length); } p_item = get_item_by_uid(uid); if (p_item == NULL) { p_item = get_item_by_uid(0ull); } if (p_item == NULL) { return PSA_ERROR_STORAGE_FAILURE; } snprintk(path, sizeof(path), "itsemul/%llu", uid); p_item->uid = uid; p_pst_item = &p_item->pst_item; p_pst_item->size = data_length; p_pst_item->flags = create_flags; memcpy(p_pst_item->data, p_data, data_length); if (settings_save_one(path, p_pst_item, sizeof(psa_its_pst_item_t))) { LOG_ERR("Failed to store its item: %s", path); status = PSA_ERROR_STORAGE_FAILURE; } else { LOG_DBG("Stored its item: %s", path); } return status; } psa_status_t psa_its_remove(psa_storage_uid_t uid) { char path[40]; psa_status_t status = PSA_SUCCESS; psa_its_item_t *p_item; LOG_DBG("remove uid: %llu", uid); p_item = get_item_by_uid(uid); if (p_item == NULL) { return status; } memset(p_item, 0, sizeof(psa_its_item_t)); snprintk(path, sizeof(path), "itsemul/%llu", uid); if (settings_delete(path)) { LOG_ERR("Failed to remove its item: %s", path); status = PSA_ERROR_STORAGE_FAILURE; } else { LOG_DBG("Removed its item: %s", path); } return status; }