Skip to content

Fix PSA internal storage configuration #8908

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "psa_prot_internal_storage.h"
#include "pits_impl.h"
#include "mbed_error.h"
#include "mbed_toolchain.h"

#ifdef __cplusplus
extern "C"
Expand All @@ -48,52 +49,101 @@ const uint8_t base64_coding_table[] = {
'4', '5', '6', '7', '8', '9', '+', '-'
};


/*
* \brief Get default KVStore instance for internal flesh storage
*
* \return valid pointer to KVStore
*/
static KVStore *get_kvstore_instance(void)
{
KVMap &kv_map = KVMap::get_instance();

return kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV));
KVStore *kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV));
if (!kvstore) {
// Can only happen due to system misconfiguration.
// Thus considered as unrecoverable error for runtime.
error("Failed getting kvstore instance\n");
}
return kvstore;
}

static void generate_fn(char *tdb_filename, uint32_t tdb_file_len, uint32_t uid, uint32_t pid)
/*
* \brief Convert KVStore stauts codes to PSA internal storage status codes
*
* \param[in] status - KVStore status code
* \return PSA internal storage status code
*/
static psa_its_status_t convert_status(int status)
{
switch (status) {
case MBED_SUCCESS:
return PSA_ITS_SUCCESS;
case MBED_ERROR_WRITE_PROTECTED:
return PSA_ITS_ERROR_WRITE_ONCE;
case MBED_ERROR_MEDIA_FULL:
return PSA_ITS_ERROR_INSUFFICIENT_SPACE;
case MBED_ERROR_ITEM_NOT_FOUND:
return PSA_ITS_ERROR_KEY_NOT_FOUND;
default:
return PSA_ITS_ERROR_STORAGE_FAILURE;
}
}

/*
* \brief Logic shift right
*
* \note must operate on unsinged integers to prevent negative carry
* \param x[in] input number for shifting
* \param n[in] number of bits to shift right
* \return the result
*/
MBED_FORCEINLINE uint32_t lsr(uint32_t x, uint32_t n)
{
return x >> n;
}

/*
* \breif Generate KVStore file name
*
* Generate KVStore file name by Base64 encoding PID and UID with a delimiter.
* Delimiter is required for determining between PID and UID.
*
* \param[out] tdb_filename - pointer to a buffer for the file name
* \param[in] tdb_filename_size - output buffer size
* \param[in] uid - PSA internal storage unique ID
* \param[in] pid - owner PSA partition ID
*/
static void generate_fn(char *tdb_filename, uint32_t tdb_filename_size, uint32_t uid, int32_t pid)
{
MBED_ASSERT(tdb_filename != NULL);
MBED_ASSERT(tdb_file_len >= PSA_ITS_FILENAME_MAX_LEN);
MBED_ASSERT(tdb_filename_size == PSA_ITS_FILENAME_MAX_LEN);

uint8_t filename_idx = 0;
uint32_t tmp_uid = uid;
uint32_t tmp_pid = pid;
uint32_t unsigned_pid = (uint32_t)pid; // binary only representation for bitwise operations

// Iterate on UID; each time convert 6 bits of UID into a character; first iteration must be done
// Iterate on PID; each time convert 6 bits of PID into a character; first iteration must be done
do {
MBED_ASSERT(filename_idx <= PSA_ITS_FILENAME_MAX_LEN);
tdb_filename[filename_idx++] = base64_coding_table[tmp_uid & 0x3F];
tmp_uid = tmp_uid >> 6;
} while (tmp_uid != 0);
tdb_filename[filename_idx++] = base64_coding_table[unsigned_pid & 0x3F];
unsigned_pid = lsr(unsigned_pid, 6);
} while (unsigned_pid != 0);

// Write delimiter
MBED_ASSERT(filename_idx <= PSA_ITS_FILENAME_MAX_LEN);
tdb_filename[filename_idx++] = '#';

// Iterate on PID; each time convert 6 bits of PID into a character; first iteration must be done
// Iterate on UID; each time convert 6 bits of UID into a character; first iteration must be done
do {
MBED_ASSERT(filename_idx <= PSA_ITS_FILENAME_MAX_LEN);
tdb_filename[filename_idx++] = base64_coding_table[tmp_pid & 0x3F];
tmp_pid = tmp_pid >> 6;
} while (tmp_pid != 0);
tdb_filename[filename_idx++] = base64_coding_table[uid & 0x3F];
uid = lsr(uid, 6);
} while (uid != 0);

tdb_filename[filename_idx++] = '\0';
MBED_ASSERT(filename_idx <= PSA_ITS_FILENAME_MAX_LEN);
tdb_filename[filename_idx] = '\0';
}


psa_its_status_t psa_its_set_impl(uint32_t pid, uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags)
psa_its_status_t psa_its_set_impl(int32_t pid, uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags)
{
KVStore *kvstore = get_kvstore_instance();
if (!kvstore) {
error("psa_its_set_impl() - Failed getting kvstore instance\n");
}
MBED_ASSERT(kvstore);

if ((create_flags != 0) && (create_flags != PSA_ITS_WRITE_ONCE_FLAG)) {
return PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED;
Expand All @@ -108,51 +158,24 @@ psa_its_status_t psa_its_set_impl(uint32_t pid, uint32_t uid, uint32_t data_leng
kv_create_flags = KVStore::WRITE_ONCE_FLAG;
}

int kvstore_status = kvstore->set(kv_key, p_data, data_length, kv_create_flags);

psa_its_status_t status = PSA_ITS_SUCCESS;
if (kvstore_status != MBED_SUCCESS) {
switch (kvstore_status) {
case MBED_ERROR_WRITE_PROTECTED:
status = PSA_ITS_ERROR_WRITE_ONCE;
break;
case MBED_ERROR_MEDIA_FULL:
status = PSA_ITS_ERROR_INSUFFICIENT_SPACE;
break;
default:
status = PSA_ITS_ERROR_STORAGE_FAILURE;
}
}
int status = kvstore->set(kv_key, p_data, data_length, kv_create_flags);

return status;
return convert_status(status);
}

psa_its_status_t psa_its_get_impl(uint32_t pid, uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data)
psa_its_status_t psa_its_get_impl(int32_t pid, uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data)
{
KVStore *kvstore = get_kvstore_instance();
if (!kvstore) {
error("psa_its_get_impl() - Failed getting kvstore instance\n");
}
MBED_ASSERT(kvstore);

// Generate KVStore key
char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'};
generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid);

KVStore::info_t kv_info;
int kvstore_status = kvstore->get_info(kv_key, &kv_info);

psa_its_status_t status = PSA_ITS_SUCCESS;
if (kvstore_status != MBED_SUCCESS) {
switch (kvstore_status) {
case MBED_ERROR_ITEM_NOT_FOUND:
status = PSA_ITS_ERROR_KEY_NOT_FOUND;
break;
default:
status = PSA_ITS_ERROR_STORAGE_FAILURE;
}
}
int status = kvstore->get_info(kv_key, &kv_info);

if (kvstore_status == MBED_SUCCESS) {
if (status == MBED_SUCCESS) {
if (data_offset > kv_info.size) {
return PSA_PS_ERROR_OFFSET_INVALID;
}
Expand All @@ -167,90 +190,53 @@ psa_its_status_t psa_its_get_impl(uint32_t pid, uint32_t uid, uint32_t data_offs
}

size_t actual_size = 0;
kvstore_status = kvstore->get(kv_key, p_data, data_length, &actual_size, data_offset);
status = kvstore->get(kv_key, p_data, data_length, &actual_size, data_offset);

if (kvstore_status == MBED_SUCCESS) {
if (status == MBED_SUCCESS) {
if (actual_size < data_length) {
status = PSA_ITS_ERROR_INCORRECT_SIZE;
}
} else {
switch (kvstore_status) {
case MBED_ERROR_ITEM_NOT_FOUND:
status = PSA_ITS_ERROR_KEY_NOT_FOUND;
break;
default:
status = PSA_ITS_ERROR_STORAGE_FAILURE;
}
}
}

return status;
return convert_status(status);
}

psa_its_status_t psa_its_get_info_impl(uint32_t pid, uint32_t uid, struct psa_its_info_t *p_info)
psa_its_status_t psa_its_get_info_impl(int32_t pid, uint32_t uid, struct psa_its_info_t *p_info)
{
KVStore *kvstore = get_kvstore_instance();
if (!kvstore) {
error("psa_its_get_info_impl() - Failed getting kvstore instance\n");
}
MBED_ASSERT(kvstore);

// Generate KVStore key
char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'};
generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid);

KVStore::info_t kv_info;
int kvstore_status = kvstore->get_info(kv_key, &kv_info);

psa_its_status_t status = PSA_ITS_SUCCESS;
if (kvstore_status != MBED_SUCCESS) {
switch (kvstore_status) {
case MBED_ERROR_ITEM_NOT_FOUND:
status = PSA_ITS_ERROR_KEY_NOT_FOUND;
break;
default:
status = PSA_ITS_ERROR_STORAGE_FAILURE;
}
}
int status = kvstore->get_info(kv_key, &kv_info);

if (kvstore_status == MBED_SUCCESS) {
if (status == MBED_SUCCESS) {
p_info->flags = 0;
if (kv_info.flags & KVStore::WRITE_ONCE_FLAG) {
p_info->flags |= PSA_ITS_WRITE_ONCE_FLAG;
}
p_info->size = (uint32_t)(kv_info.size); // kv_info.size is of type size_t
}

return status;
return convert_status(status);
}

psa_its_status_t psa_its_remove_impl(uint32_t pid, uint32_t uid)
psa_its_status_t psa_its_remove_impl(int32_t pid, uint32_t uid)
{
KVStore *kvstore = get_kvstore_instance();
if (!kvstore) {
error("psa_its_remove_impl() - Failed getting kvstore instance\n");
}
MBED_ASSERT(kvstore);

// Generate KVStore key
char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'};
generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid);

int kvstore_status = kvstore->remove(kv_key);

psa_its_status_t status = PSA_ITS_SUCCESS;
if (kvstore_status != MBED_SUCCESS) {
switch (kvstore_status) {
case MBED_ERROR_WRITE_PROTECTED:
status = PSA_ITS_ERROR_WRITE_ONCE;
break;
case MBED_ERROR_ITEM_NOT_FOUND:
status = PSA_ITS_ERROR_KEY_NOT_FOUND;
break;
default:
status = PSA_ITS_ERROR_STORAGE_FAILURE;
}
}
int status = kvstore->remove(kv_key);

return status;
return convert_status(status);
}

#ifdef __cplusplus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ extern "C"

#define PITS_DATA_PTR_AT_OFFSET(ptr, offset) ((void *)(((uintptr_t)ptr) + ((uintptr_t)offset)))

psa_its_status_t psa_its_set_impl(uint32_t pid, uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags);
psa_its_status_t psa_its_get_impl(uint32_t pid, uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data);
psa_its_status_t psa_its_get_info_impl(uint32_t pid, uint32_t uid, struct psa_its_info_t *p_info);
psa_its_status_t psa_its_remove_impl(uint32_t pid, uint32_t uid);
psa_its_status_t psa_its_set_impl(int32_t pid, uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags);
psa_its_status_t psa_its_get_impl(int32_t pid, uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data);
psa_its_status_t psa_its_get_info_impl(int32_t pid, uint32_t uid, struct psa_its_info_t *p_info);
psa_its_status_t psa_its_remove_impl(int32_t pid, uint32_t uid);

#ifdef __cplusplus
}
Expand Down