diff --git a/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_EMUL/test_pits.c b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_EMUL/test_pits.c new file mode 100644 index 00000000000..60a2d9a8547 --- /dev/null +++ b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_EMUL/test_pits.c @@ -0,0 +1,28 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TARGET_PSA +#error [NOT_SUPPORTED] ITS tests can run only on PSA-enabled targets. +#endif // TARGET_PSA + +#include "test_pits.h" +#include "test_pits_impl.h" + +psa_its_status_t test_psa_its_reset(void) +{ + return test_psa_its_reset_impl(); +} diff --git a/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.cpp b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.cpp new file mode 100644 index 00000000000..7b2f4e57f35 --- /dev/null +++ b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.cpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "psa_prot_internal_storage.h" +#include "test_pits_impl.h" +#include "kv_config.h" +#include "KVMap.h" +#include "KVStore.h" +#include "mbed_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +using namespace mbed; + +#define STR_EXPAND(tok) #tok + +psa_its_status_t test_psa_its_reset_impl(void) +{ + psa_its_status_t status = PSA_ITS_SUCCESS; + + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + KVMap &kv_map = KVMap::get_instance(); + KVStore *kvstore = kv_map.get_main_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); + if (!kvstore) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + if (kvstore->reset() != MBED_SUCCESS) { + status = PSA_ITS_ERROR_STORAGE_FAILURE; + } + + return status; +} + +#ifdef __cplusplus +} +#endif diff --git a/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.h b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.h new file mode 100644 index 00000000000..4b072345212 --- /dev/null +++ b/TESTS/psa/prot_internal_storage/its_reset/COMPONENT_PSA_SRV_IMPL/test_pits_impl.h @@ -0,0 +1,34 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PITS_IMPL_H__ +#define __PITS_IMPL_H__ + +#include "psa_prot_internal_storage.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +psa_its_status_t test_psa_its_reset_impl(void); + +#ifdef __cplusplus +} +#endif + +#endif // __PITS_IMPL_H__ diff --git a/TESTS/psa/prot_internal_storage/its_reset/test_pits.h b/TESTS/psa/prot_internal_storage/its_reset/test_pits.h new file mode 100644 index 00000000000..31b5d668120 --- /dev/null +++ b/TESTS/psa/prot_internal_storage/its_reset/test_pits.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TEST_INTERNAL_TRUSTED_STORAGE_H__ +#define __TEST_INTERNAL_TRUSTED_STORAGE_H__ + +/** @file +@brief This file describes the PSA Internal Trusted Storage API +*/ + +#include +#include +#include "psa_prot_internal_storage.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_ITS_SUCCESS The operation completed successfully + * \retval PSA_ITS_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_its_status_t test_psa_its_reset(void); + +#ifdef __cplusplus +} +#endif + +#endif // __TEST_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/TESTS/psa/prot_internal_storage/main.cpp b/TESTS/psa/prot_internal_storage/main.cpp new file mode 100644 index 00000000000..ec274a4bf8c --- /dev/null +++ b/TESTS/psa/prot_internal_storage/main.cpp @@ -0,0 +1,136 @@ +/* +* Copyright (c) 2018 ARM Limited. All rights reserved. +* +* SPDX-License-Identifier: Apache-2.0 +* +* Licensed under the Apache License, Version 2.0 (the License); you may +* not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an AS IS BASIS, WITHOUT +* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef TARGET_PSA +#error [NOT_SUPPORTED] ITS tests can run only on PSA-enabled targets. +#endif // TARGET_PSA + +#include "greentea-client/test_env.h" +#include "unity/unity.h" +#include "utest/utest.h" +#include "psa_prot_internal_storage.h" +#include "test_pits.h" + +using namespace utest::v1; + +#define TEST_BUFF_SIZE 16 + +static void pits_test() +{ + psa_its_status_t status = PSA_ITS_SUCCESS; + uint8_t write_buff[TEST_BUFF_SIZE] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F}; + uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + struct psa_its_info_t info = {0, PSA_ITS_WRITE_ONCE_FLAG}; + memset(read_buff, 0, TEST_BUFF_SIZE); + + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_ERROR_KEY_NOT_FOUND, status); + + status = psa_its_set(5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(0, info.flags); + + status = psa_its_get(5, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + memset(read_buff, 0, TEST_BUFF_SIZE); + status = psa_its_get(5, 1, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_NOT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_get(5, 1, TEST_BUFF_SIZE - 1, read_buff); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff + 1, read_buff, TEST_BUFF_SIZE - 1); + + status = psa_its_remove(5); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_ERROR_KEY_NOT_FOUND, status); +} + +static void pits_write_once_test() +{ + psa_its_status_t status = PSA_ITS_SUCCESS; + uint8_t write_buff[TEST_BUFF_SIZE] = {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}; + uint8_t read_buff[TEST_BUFF_SIZE] = {0}; + struct psa_its_info_t info = {0, 0}; + + status = test_psa_its_reset(); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_ERROR_KEY_NOT_FOUND, status); + + status = psa_its_set(5, TEST_BUFF_SIZE, write_buff, PSA_ITS_WRITE_ONCE_FLAG); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + + info.size = 0; + info.flags = 0; + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_ITS_WRITE_ONCE_FLAG, info.flags); + + status = psa_its_get(5, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + status = psa_its_set(5, TEST_BUFF_SIZE, write_buff, PSA_ITS_WRITE_ONCE_FLAG); + TEST_ASSERT_NOT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_set(5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_NOT_EQUAL(PSA_ITS_SUCCESS, status); + + status = psa_its_remove(5); + TEST_ASSERT_NOT_EQUAL(PSA_ITS_SUCCESS, status); + + info.size = 0; + info.flags = 0; + status = psa_its_get_info(5, &info); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_ITS_WRITE_ONCE_FLAG, info.flags); + + status = test_psa_its_reset(); + TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); +} + +Case cases[] = { + Case("PSA prot internal storage - Basic", pits_test), + Case("PSA prot internal storage - Write-once", pits_write_once_test), +}; + +utest::v1::status_t greentea_test_setup(const size_t number_of_cases) +{ +#ifndef NO_GREENTEA + GREENTEA_SETUP(60, "default_auto"); +#endif + return greentea_test_setup_handler(number_of_cases); +} + +Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler); + +int main() +{ + return !Harness::run(specification); +} diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp new file mode 100644 index 00000000000..a7800e78fcd --- /dev/null +++ b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "psa_prot_internal_storage.h" +#include "pits_impl.h" +#include "kv_config.h" +#include "mbed_error.h" + +// In EMUL world, there is no real partitioning, which makes the source partition irrelevant. +// So here we set a global pid value to be used for when calling IMPL functions +#define PSA_ITS_EMUL_PID 1 + +psa_its_status_t psa_its_set(uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags) +{ + if (!p_data && data_length) { + return PSA_ITS_ERROR_BAD_POINTER; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + psa_its_status_t res = psa_its_set_impl(PSA_ITS_EMUL_PID, uid, data_length, p_data, create_flags); + + return res; +} + +psa_its_status_t psa_its_get(uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +{ + if (!p_data && data_length) { + return PSA_ITS_ERROR_BAD_POINTER; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + return psa_its_get_impl(PSA_ITS_EMUL_PID, uid, data_offset, data_length, p_data); +} + +psa_its_status_t psa_its_get_info(uint32_t uid, struct psa_its_info_t *p_info) +{ + if (!p_info) { + return PSA_ITS_ERROR_BAD_POINTER; + } + + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + return psa_its_get_info_impl(PSA_ITS_EMUL_PID, uid, p_info); +} + +psa_its_status_t psa_its_remove(uint32_t uid) +{ + // KVStore initiation: + // - In EMUL (non-secure single core) we do it here since we don't have another context to do it inside. + // - Repeating calls has no effect + int kv_status = kv_init_storage_config(); + if (kv_status != MBED_SUCCESS) { + return PSA_ITS_ERROR_STORAGE_FAILURE; + } + + return psa_its_remove_impl(PSA_ITS_EMUL_PID, uid); +} diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp new file mode 100644 index 00000000000..1e520c5c93d --- /dev/null +++ b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp @@ -0,0 +1,258 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "KVMap.h" +#include "KVStore.h" +#include "TDBStore.h" +#include "psa_prot_internal_storage.h" +#include "pits_impl.h" +#include "mbed_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +using namespace mbed; + +#define STR_EXPAND(tok) #tok + +// Maximum length of filename we use for kvstore API. +// uid: 6; delimiter: 1; pid: 6; str terminator: 1 +#define PSA_ITS_FILENAME_MAX_LEN 14 + + +const uint8_t base64_coding_table[] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '-' +}; + + +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)); +} + +static void generate_fn(char *tdb_filename, uint32_t tdb_file_len, uint32_t uid, uint32_t pid) +{ + MBED_ASSERT(tdb_filename != NULL); + MBED_ASSERT(tdb_file_len >= PSA_ITS_FILENAME_MAX_LEN); + + uint8_t filename_idx = 0; + uint32_t tmp_uid = uid; + uint32_t tmp_pid = pid; + + // 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_uid & 0x3F]; + tmp_uid = tmp_uid >> 6; + } while (tmp_uid != 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 + 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); + + 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) +{ + KVStore *kvstore = get_kvstore_instance(); + if (!kvstore) { + error("psa_its_set_impl() - Failed getting kvstore instance\n"); + } + + if ((create_flags != 0) && (create_flags != PSA_ITS_WRITE_ONCE_FLAG)) { + return PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED; + } + + // Generate KVStore key + char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'}; + generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid); + + uint32_t kv_create_flags = 0; + if (create_flags & PSA_ITS_WRITE_ONCE_FLAG) { + 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; + } + } + + return 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) +{ + KVStore *kvstore = get_kvstore_instance(); + if (!kvstore) { + error("psa_its_get_impl() - Failed getting kvstore instance\n"); + } + + // 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; + } + } + + if (kvstore_status == MBED_SUCCESS) { + if (data_offset > kv_info.size) { + return PSA_PS_ERROR_OFFSET_INVALID; + } + + // Verify (size + offset) does not wrap around + if (data_length + data_offset < data_length) { + return PSA_ITS_ERROR_INCORRECT_SIZE; + } + + if (data_offset + data_length > kv_info.size) { + return PSA_ITS_ERROR_INCORRECT_SIZE; + } + + size_t actual_size = 0; + kvstore_status = kvstore->get(kv_key, p_data, data_length, &actual_size, data_offset); + + if (kvstore_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; +} + +psa_its_status_t psa_its_get_info_impl(uint32_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"); + } + + // 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; + } + } + + if (kvstore_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; +} + +psa_its_status_t psa_its_remove_impl(uint32_t pid, uint32_t uid) +{ + KVStore *kvstore = get_kvstore_instance(); + if (!kvstore) { + error("psa_its_remove_impl() - Failed getting kvstore instance\n"); + } + + // 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; + } + } + + return status; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.h b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.h new file mode 100644 index 00000000000..06bde2d8fd5 --- /dev/null +++ b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __PITS_IMPL_H__ +#define __PITS_IMPL_H__ + +#include "psa_prot_internal_storage.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#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); + +#ifdef __cplusplus +} +#endif + +#endif // __PITS_IMPL_H__ diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/psa_prot_internal_storage.h b/components/TARGET_PSA/services/psa_prot_internal_storage/psa_prot_internal_storage.h new file mode 100644 index 00000000000..366f7897ffc --- /dev/null +++ b/components/TARGET_PSA/services/psa_prot_internal_storage/psa_prot_internal_storage.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2018 ARM Limited + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __INTERNAL_TRUSTED_STORAGE_H__ +#define __INTERNAL_TRUSTED_STORAGE_H__ + +/** @file +@brief This file describes the PSA Internal Trusted Storage API +*/ + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** \brief Flags used when creating a key + */ +typedef uint32_t psa_its_create_flags_t; + +#define PSA_ITS_WRITE_ONCE_FLAG (1 << 0) /**< The data associated with the key will not be able to be modified or deleted. Intended to be used to set bits in `psa_its_create_flags_t` */ + +/** + * \brief A container for metadata associated with a specific key + */ +struct psa_its_info_t { + uint32_t size; /**< The size of the data associated with a key **/ + psa_its_create_flags_t flags; /**< The flags set when the key was created **/ +}; +/** + * \brief The return status type for the PSA Trusted Storage functions + */ +typedef uint32_t psa_its_status_t; + +#define PSA_ITS_SUCCESS 0 /**< The operation completed successfully */ +#define PSA_ITS_ERROR_WRITE_ONCE 1 /**< The operation failed because the provided key value was already created with PSA_ITS_WRITE_ONCE_FLAG */ +#define PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED 2 /**< The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid */ +#define PSA_ITS_ERROR_INSUFFICIENT_SPACE 3 /**< The operation failed because there was insufficient space on the storage medium */ +#define PSA_ITS_ERROR_INVALID_KEY 4 /**< The operation failed because the key value provided was invalid */ +#define PSA_ITS_ERROR_STORAGE_FAILURE 5 /**< The operation failed because the physical storage has failed (Fatal error) */ +#define PSA_ITS_ERROR_BAD_POINTER 6 /**< The operation failed because one of the provided pointers is invalid, for example is `NULL` or references memory the caller cannot access */ +#define PSA_ITS_ERROR_KEY_NOT_FOUND 7 /**< The operation failed because the provided key value was not found in the storage */ +#define PSA_ITS_ERROR_INCORRECT_SIZE 8 /**< The operation failed because the data associated with provided key is not the same size as `data_size` */ +#define PSA_PS_ERROR_OFFSET_INVALID 9 /**< The operation failed because an offset was supplied that is invalid for the existing data associated with the uid. For example, offset + size is + past the end of the data */ + +/** + * \brief create a new or modify an existing uid/value pair + * + * \param[in] uid the identifier for the data + * \param[in] data_length The size in bytes of the data in `p_data` + * \param[in] p_data A buffer containing the data + * \param[in] create_flags The flags that the data will be stored with + * + * \return A status indicating the success/failure of the operation + + * \retval PSA_ITS_SUCCESS The operation completed successfully + * \retval PSA_ITS_ERROR_WRITE_ONCE The operation failed because the provided `uid` value was already created with PSA_ITS_WRITE_ONCE_FLAG + * \retval PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid + * \retval PSA_ITS_ERROR_INSUFFICIENT_SPACE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ITS_ERROR_INVALID_KEY The operation failed because the value provided in `uid` was invalid + * \retval PSA_ITS_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ITS_ERROR_BAD_POINTER The operation failed because one of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_its_status_t psa_its_set(uint32_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags); + +/** + * \brief Retrieve the value associated with a provided uid + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_length the amount of data requested (and the minimum allocated size of the `p_data` buffer) + * \param[out] p_data The buffer where the data will be placed upon successful completion + + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_ITS_SUCCESS The operation completed successfully + * \retval PSA_ITS_ERROR_KEY_NOT_FOUND The operation failed because the provided `uid` value was not found in the storage + * \retval PSA_ITS_ERROR_INCORRECT_SIZE The operation failed because the data associated with provided `uid` is not the same size as `data_size` + * \retval PSA_ITS_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ITS_ERROR_BAD_POINTER The operation failed because one of the provided pointers(`p_data`, `p_data_length`) + * is invalid. For example is `NULL` or references memory the caller cannot access + * \retval PSA_PS_ERROR_OFFSET_INVALID The operation failed because an offset was supplied that is invalid for the existing data associated with the + * uid. For example, offset + size is invalid, + */ +psa_its_status_t psa_its_get(uint32_t uid, uint32_t data_offset, uint32_t data_length, void *p_data); + +/** + * \brief Retrieve the metadata about the provided uid + * + * \param[in] uid The uid value + * \param[out] p_info A pointer to the `psa_its_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_ITS_ERROR_SUCCESS The operation completed successfully + * \retval PSA_ITS_ERROR_KEY_NOT_FOUND The operation failed because the provided uid value was not found in the storage + * \retval PSA_ITS_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ITS_ERROR_BAD_POINTER The operation failed because one of the provided pointers(`p_info`) + * is invalid, for example is `NULL` or references memory the caller cannot access + */ +psa_its_status_t psa_its_get_info(uint32_t uid, struct psa_its_info_t *p_info); + +/** + * \brief Remove the provided key and its associated data from the storage + * + * \param[in] uid The uid value + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_ITS_SUCCESS The operation completed successfully + * \retval PSA_ITS_ERROR_KEY_NOT_FOUND The operation failed because the provided key value was not found in the storage + * \retval PSA_ITS_ERROR_WRITE_ONCE The operation failed because the provided key value was created with psa_its_WRITE_ONCE_FLAG + * \retval PSA_ITS_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_its_status_t psa_its_remove(uint32_t uid); + +#ifdef __cplusplus +} +#endif + +#endif // __INTERNAL_TRUSTED_STORAGE_H__ diff --git a/features/storage/kvstore/conf/mbed_lib.json b/features/storage/kvstore/conf/mbed_lib.json index cd9200d26d6..fc8c0211cea 100644 --- a/features/storage/kvstore/conf/mbed_lib.json +++ b/features/storage/kvstore/conf/mbed_lib.json @@ -11,6 +11,9 @@ } }, "target_overrides": { + "K64F": { + "storage_type": "TDB_INTERNAL" + }, "K66F": { "storage_type": "TDB_INTERNAL" } diff --git a/features/storage/kvstore/conf/tdb_internal/mbed_lib.json b/features/storage/kvstore/conf/tdb_internal/mbed_lib.json index f9d37e9b13f..c5ade697873 100644 --- a/features/storage/kvstore/conf/tdb_internal/mbed_lib.json +++ b/features/storage/kvstore/conf/tdb_internal/mbed_lib.json @@ -10,4 +10,4 @@ "value": "0" } } -} \ No newline at end of file +} diff --git a/targets/targets.json b/targets/targets.json index 51224cf58d5..135a6b48394 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -1361,7 +1361,8 @@ "KPSDK_MCUS", "KPSDK_CODE", "MCU_K64F", - "Freescale_EMAC" + "Freescale_EMAC", + "PSA" ], "is_disk_virtual": true, "macros": ["CPU_MK64FN1M0VMD12", "FSL_RTOS_MBED"],