diff --git a/TESTS/mbed-crypto/sanity/main.cpp b/TESTS/mbed-crypto/sanity/main.cpp index ea6e83f35f..d71563dbcb 100644 --- a/TESTS/mbed-crypto/sanity/main.cpp +++ b/TESTS/mbed-crypto/sanity/main.cpp @@ -350,7 +350,7 @@ void test_crypto_key_handles(void) TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); key_handle = 0; - TEST_ASSERT_EQUAL(PSA_ERROR_EMPTY_SLOT, psa_open_key(PSA_KEY_LIFETIME_PERSISTENT, id, &key_handle)); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, psa_open_key(PSA_KEY_LIFETIME_PERSISTENT, id, &key_handle)); } void test_crypto_hash_clone(void) diff --git a/TESTS/psa/entropy_inject/main.cpp b/TESTS/psa/entropy_inject/main.cpp index 080d6e4913..355312f0fc 100644 --- a/TESTS/psa/entropy_inject/main.cpp +++ b/TESTS/psa/entropy_inject/main.cpp @@ -70,7 +70,6 @@ void validate_entropy_seed_injection(int seed_length_a, void run_entropy_inject_with_crypto_init() { - psa_its_status_t its_status; psa_status_t status; status = psa_crypto_init(); TEST_ASSERT_EQUAL_INT(PSA_ERROR_INSUFFICIENT_ENTROPY, status); @@ -158,7 +157,7 @@ utest::v1::status_t case_teardown_handler(const Case *const source, const size_t { psa_status_t status; status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); mbedtls_psa_crypto_free(); return greentea_case_teardown_handler(source, passed, failed, reason); } @@ -167,7 +166,7 @@ utest::v1::status_t case_setup_handler(const Case *const source, const size_t in { psa_status_t status; status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); return greentea_case_setup_handler(source, index_of_case); } diff --git a/TESTS/psa/its/main.cpp b/TESTS/psa/its/main.cpp deleted file mode 100644 index 63c94af926..0000000000 --- a/TESTS/psa/its/main.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -* 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/internal_trusted_storage.h" -#include "psa/lifecycle.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_FLAG_WRITE_ONCE}; - memset(read_buff, 0, TEST_BUFF_SIZE); - - status = psa_its_get_info(5, &info); - TEST_ASSERT_EQUAL(PSA_ITS_ERROR_UID_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_UID_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 = psa_its_get_info(5, &info); - TEST_ASSERT_EQUAL(PSA_ITS_ERROR_UID_NOT_FOUND, status); - - status = psa_its_set(5, TEST_BUFF_SIZE, write_buff, PSA_ITS_FLAG_WRITE_ONCE); - TEST_ASSERT_EQUAL(PSA_ITS_SUCCESS, status); - - info.size = 0; - info.flags = PSA_ITS_FLAG_NONE; - 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_FLAG_WRITE_ONCE, 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_FLAG_WRITE_ONCE); - 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 = PSA_ITS_FLAG_NONE; - 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_FLAG_WRITE_ONCE, info.flags); -} - -utest::v1::status_t case_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_LIFECYCLE_SUCCESS, status); - return greentea_case_teardown_handler(source, passed, failed, reason); -} - -utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) -{ - psa_status_t status; - status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); - TEST_ASSERT_EQUAL(PSA_LIFECYCLE_SUCCESS, status); - return greentea_case_setup_handler(source, index_of_case); -} - -Case cases[] = { - Case("PSA prot internal storage - Basic", case_setup_handler, pits_test, case_teardown_handler), - Case("PSA prot internal storage - Write-once", case_setup_handler, pits_write_once_test, case_teardown_handler) -}; - -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/TESTS/psa/its_ps/main.cpp b/TESTS/psa/its_ps/main.cpp new file mode 100644 index 0000000000..0901cf4547 --- /dev/null +++ b/TESTS/psa/its_ps/main.cpp @@ -0,0 +1,198 @@ +/* +* Copyright (c) 2019 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/PS 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/error.h" +#include "psa/storage_common.h" +#include "psa/internal_trusted_storage.h" +#include "psa/protected_storage.h" +#include "psa/lifecycle.h" + +using namespace utest::v1; + +#define TEST_BUFF_SIZE 16 + +typedef enum { + its, + ps +} storage_type_t; + +extern "C" psa_status_t psa_ps_reset(); + +static psa_status_t set_func(storage_type_t stype, psa_storage_uid_t uid, uint32_t data_length, + const void *p_data, psa_storage_create_flags_t create_flags) +{ + return (stype == its) ? + psa_its_set(uid, data_length, p_data, create_flags) : + psa_ps_set(uid, data_length, p_data, create_flags); +} + +static psa_status_t get_func(storage_type_t stype, psa_storage_uid_t uid, uint32_t data_offset, + uint32_t data_length, void *p_data) +{ + return (stype == its) ? + psa_its_get(uid, data_offset, data_length, p_data) : + psa_ps_get(uid, data_offset, data_length, p_data); +} + +static psa_status_t get_info_func(storage_type_t stype, psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + return (stype == its) ? + psa_its_get_info(uid, p_info) : + psa_ps_get_info(uid, p_info); +} + +static psa_status_t remove_func(storage_type_t stype, psa_storage_uid_t uid) +{ + return (stype == its) ? + psa_its_remove(uid) : + psa_ps_remove(uid); +} + + +template +void pits_ps_test() +{ + psa_status_t status = PSA_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_storage_info_t info = {0, PSA_STORAGE_FLAG_WRITE_ONCE}; + memset(read_buff, 0, TEST_BUFF_SIZE); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(0, info.flags); + + status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + memset(read_buff, 0, TEST_BUFF_SIZE); + status = get_func(stype, 5, 1, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_NOT_EQUAL(PSA_SUCCESS, status); + + status = get_func(stype, 5, 1, TEST_BUFF_SIZE - 1, read_buff); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff + 1, read_buff, TEST_BUFF_SIZE - 1); + + status = remove_func(stype, 5); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); +} + +template +void pits_ps_write_once_test() +{ + psa_status_t status = PSA_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_storage_info_t info = {0, 0}; + + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_ERROR_DOES_NOT_EXIST, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + + info.size = 0; + info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); + + status = get_func(stype, 5, 0, TEST_BUFF_SIZE, read_buff); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL_MEMORY(write_buff, read_buff, TEST_BUFF_SIZE); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, PSA_STORAGE_FLAG_WRITE_ONCE); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + status = set_func(stype, 5, TEST_BUFF_SIZE, write_buff, 0); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + status = remove_func(stype, 5); + TEST_ASSERT_EQUAL(PSA_ERROR_NOT_PERMITTED, status); + + info.size = 0; + info.flags = PSA_STORAGE_FLAG_WRITE_ONCE; + status = get_info_func(stype, 5, &info); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + TEST_ASSERT_EQUAL(TEST_BUFF_SIZE, info.size); + TEST_ASSERT_EQUAL(PSA_STORAGE_FLAG_WRITE_ONCE, info.flags); +} + +utest::v1::status_t case_its_teardown_handler(const Case *const source, const size_t passed, const size_t failed, const failure_t reason) +{ + psa_status_t status; + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_LIFECYCLE_SUCCESS, status); + return greentea_case_teardown_handler(source, passed, failed, reason); +} + +template +utest::v1::status_t case_its_setup_handler(const Case *const source, const size_t index_of_case) +{ + psa_status_t status; + if (stype == its) { + status = mbed_psa_reboot_and_request_new_security_state(PSA_LIFECYCLE_ASSEMBLY_AND_TEST); + TEST_ASSERT_EQUAL(PSA_LIFECYCLE_SUCCESS, status); + } else { + status = psa_ps_reset(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, status); + } + return greentea_case_setup_handler(source, index_of_case); +} + +Case cases[] = { + Case("PSA prot internal storage - Basic", case_its_setup_handler, pits_ps_test, case_its_teardown_handler), + Case("PSA prot internal storage - Write-once", case_its_setup_handler, pits_ps_write_once_test, case_its_teardown_handler), + Case("PSA protected storage - Basic", case_its_setup_handler, pits_ps_test), + Case("PSA protected storage - Write-once", case_its_setup_handler, pits_ps_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/TARGET_MBED_SPM/psa_defs.h b/components/TARGET_PSA/TARGET_MBED_SPM/psa_defs.h index a896733105..cfe3da5b40 100644 --- a/components/TARGET_PSA/TARGET_MBED_SPM/psa_defs.h +++ b/components/TARGET_PSA/TARGET_MBED_SPM/psa_defs.h @@ -26,6 +26,7 @@ #include #include +#include "psa/error.h" /* --------------------------------- extern "C" wrapper ------------------------------ */ @@ -60,7 +61,6 @@ extern "C" { #define PSA_DOORBELL (0x00000008UL) /**< Mask for PSA_DOORBELL signal.*/ -#define PSA_SUCCESS (0L) /**< A general result code for calls to psa_call() indicating success.*/ #define PSA_IPC_CONNECT (1) /**< The IPC message type that indicates a new connection.*/ #define PSA_IPC_CALL (2) /**< The IPC message type that indicates a client request.*/ #define PSA_IPC_DISCONNECT (3) /**< The IPC message type that indicates the end of a connection.*/ @@ -75,7 +75,6 @@ extern "C" { /* -------------------------------------- Typedefs ----------------------------------- */ typedef uint32_t psa_signal_t; -typedef int32_t psa_status_t; typedef int32_t psa_handle_t; typedef psa_status_t error_t; diff --git a/components/TARGET_PSA/inc/psa/error.h b/components/TARGET_PSA/inc/psa/error.h new file mode 100644 index 0000000000..ba0e0e31b5 --- /dev/null +++ b/components/TARGET_PSA/inc/psa/error.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2019 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. +*/ + +/* psa/error.h +Standard error codes for the SPM and RoT Services +As defined in PSA Firmware Framework v1.0 +*/ + +#ifndef __PSA_ERROR__ +#define __PSA_ERROR__ + +#include +#include + +typedef int32_t psa_status_t; + +#define PSA_SUCCESS ((psa_status_t)0) + +#define PSA_ERROR_PROGRAMMER_ERROR ((psa_status_t)-129) +#define PSA_ERROR_CONNECTION_REFUSED ((psa_status_t)-130) +#define PSA_ERROR_CONNECTION_BUSY ((psa_status_t)-131) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) +#define PSA_ERROR_SERVICE_FAILURE ((psa_status_t)-144) +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#endif // __PSA_ERROR__ diff --git a/components/TARGET_PSA/inc/psa/protected_storage.h b/components/TARGET_PSA/inc/psa/protected_storage.h new file mode 100644 index 0000000000..eb010adb17 --- /dev/null +++ b/components/TARGET_PSA/inc/psa/protected_storage.h @@ -0,0 +1,200 @@ +/* Copyright (C) 2019, 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. + */ + +/** @file +@brief This file describes the PSA Protected Storage API +*/ + +#ifndef __PSA_PROTECTED_STORAGE_H__ +#define __PSA_PROTECTED_STORAGE_H__ + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PSA_PS_API_VERSION_MAJOR 1 /**< The major version number of the PSA PS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_PS_API_VERSION_MINOR 1 /**< The minor version number of the PSA PS API. It will be incremented in small updates that are unlikely to include breaking changes */ + + +/** + * \brief create a new or modify an existing key/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 indicating the properties of the data + * + * \return A status indicating the success/failure of the operation + + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid. + * \retval PSA_ERROR_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_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + */ +psa_status_t psa_ps_set(psa_storage_uid_t uid, + uint32_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve the value for a provided uid + * + * \param[in] uid The identifier for the data + * \param[in] data_offset The offset within the data associated with the `uid` to start retrieving data + * \param[in] data_length The amount of data to read (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_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided uid is not the same size as `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication + */ +psa_status_t psa_ps_get(psa_storage_uid_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 identifier for the data + * \param[out] p_info A pointer to the `psa_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because of an authentication failure when attempting to get the key + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the data associated with the UID failed authentication + */ +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info); + +/** + * \brief Remove the provided uid and its associated data from the storage + * + * \param[in] uid The identifier for the data to be removed + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags etc.) + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided uid value was created with psa_eps_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_GENERIC_ERROR The operation failed because of an unspecified internal failure + */ +psa_status_t psa_ps_remove(psa_storage_uid_t uid); + +/** + * Creates an asset based on the given identifier, the maximum size and + * creation flags. This create allocates the space in the secure storage + * area without setting any data in the asset. + * + * It is only necessary to call this function for items that will be written + * with the \ref psa_ps_set_extended function. If only the \ref psa_ps_set function + * is needed, calls to this function are redundant. + * + * If the \ref PSA_STORAGE_FLAG_WRITE_ONCE flag is passed, implementations should + * return \ref PSA_ERROR_NOT_SUPPORTED. + * + * This function is optional. Not all PSA Protected Storage Implementations + * will implement this function. Consult the documentation of your chosen + * platform to determine if it is present. + * + * \param[in] uid A unique identifier for the asset. + * \param[in] size The maximum size in bytes of the asset. + * \param[in] create_flags Create flags \ref psa_storage_create_flags_t. + * + * \retval PSA_SUCCESS The assest does not exist and the input parameters are correct or + * the asset already exists, the input parameters are the same that + * have been used to create the asset and the owner is the same and the current asset content is kept + * TDB: "Owner is the same" doesn't really make sense from a PSA perspective, as each partition + * has its own UID space, making other partitions' data unadressable + * \retval PSA_ERROR_STORAGE_FAILURE The create action has a physical storage error + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The maximum size is bigger of the current available space + * \retval PSA_ERROR_NOT_SUPPORTED One or more create_flags are not valid or supported + * \retval PSA_ERROR_INVALID_ARGUMENT The asset exists and the input paramters are not the same as the existing asset + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation has failed due to an unspecified error + */ +psa_status_t psa_ps_create(psa_storage_uid_t uid, + uint32_t size, + psa_storage_create_flags_t create_flags); + +/** + * Sets partial data into an asset based on the given identifier, data_offset, + * data length and p_data. + * + * Before calling this function, the asset must have been created with a call + * to \ref psa_ps_create. + * + * This function is optional. Not all PSA Protected Storage Implementations + * will implement this function. Consult the documentation of your chosen + * platform to determine if it is present. + * + * \param[in] uid The unique identifier for the asset. + * \param[in] data_offset Offset within the asset to start the write. + * \param[in] data_length The size in bytes of the data in p_data to write. + * \param[in] p_data Pointer to a buffer which contains the data to write. + * + * \retval PSA_SUCCESS If the asset exists, the input parameters are correct and the data + * is correctly written in the physical storage + * \retval PSA_ERROR_STORAGE_FAILURE If the data is not written correctly in the physical storage + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more of the given arguments were invalid (null pointer, wrong flags, etc) + * \retval PSA_ERROR_DOES_NOT_EXIST The specified UID was not found + * \retval PSA_ERROR_NOT_SUPPORTED The implementation of the API does not support this function + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an unspecified error + * \retval PSA_ERROR_DATA_CORRUPT The operation failed because the existing data has been corrupted + * \retval PSA_ERROR_INVALID_SIGNATURE The operation failed because the existing data failed authentication (MAC check failed) + */ +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, + uint32_t data_offset, + uint32_t data_length, + const void *p_data); + +/** + * Returns a bitmask with flags set for all of the optional features supported + * by the implementation. + * + * Currently defined flags are limited to: + * - \ref PSA_STORAGE_SUPPORT_SET_EXTENDED + */ +uint32_t psa_ps_get_support(void); + +#ifdef __cplusplus +} +#endif + + +#endif // __PSA_PROTECTED_STORAGE_H__ diff --git a/components/TARGET_PSA/inc/psa/storage_common.h b/components/TARGET_PSA/inc/psa/storage_common.h new file mode 100644 index 0000000000..4008d48524 --- /dev/null +++ b/components/TARGET_PSA/inc/psa/storage_common.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2019, 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. + */ + +/** @file +@brief This file includes common definitions for PSA storage +*/ + +#ifndef __PSA_STORAGE_COMMON_H__ +#define __PSA_STORAGE_COMMON_H__ + +#include +#include +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Flags used when creating a data entry + */ +typedef uint32_t psa_storage_create_flags_t; + +#define PSA_STORAGE_FLAG_NONE 0 /**< No flags to pass */ +#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/ + +/** \brief A type for UIDs used for identifying data + */ +typedef uint64_t psa_storage_uid_t; + +/** + * \brief A container for metadata associated with a specific uid + */ +struct psa_storage_info_t { + uint32_t size; /**< The size of the data associated with a uid **/ + psa_storage_create_flags_t flags; /**< The flags set when the uid was created **/ +}; + +/** \brief Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */ +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0) + +/** \brief PSA storage specific error codes */ +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#ifdef __cplusplus +} +#endif + +#endif // __PSA_STORAGE_COMMON_H__ diff --git a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c index 43009b7ba5..27306537e0 100644 --- a/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c +++ b/components/TARGET_PSA/services/crypto/COMPONENT_PSA_SRV_IPC/psa_crypto_spm.c @@ -43,10 +43,6 @@ psa_status_t psa_crypto_init(void) err_call = psa_call(handle, NULL, 0, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -71,10 +67,6 @@ psa_status_t psa_mac_abort(psa_mac_operation_t *operation) psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -99,9 +91,6 @@ static psa_status_t psa_mac_setup(psa_mac_operation_t *operation, } err = psa_call(operation->handle, &in_vec, 1, NULL, 0); - if (err < 0) { - err = PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err); } @@ -140,13 +129,10 @@ psa_status_t psa_mac_update(psa_mac_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err = psa_call(operation->handle, in_vec, 2, NULL, 0); - if (err < 0) { - err = PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err); } @@ -167,17 +153,13 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, psa_outvec out_vec[2] = { { mac, mac_size }, { mac_length, sizeof(*mac_length) } }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(operation->handle, in_vec, 2, out_vec, 2); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -196,17 +178,13 @@ psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(operation->handle, in_vec, 3, NULL, 0); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -232,10 +210,6 @@ psa_status_t psa_hash_abort(psa_hash_operation_t *operation) psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -256,9 +230,6 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, } err = psa_call(operation->handle, &in_vec, 1, NULL, 0); - if (err < 0) { - err = PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err); } @@ -277,13 +248,10 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err = psa_call(operation->handle, in_vec, 2, NULL, 0); - if (err < 0) { - err = PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err); } @@ -306,17 +274,13 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(operation->handle, in_vec, 2, out_vec, 2); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -335,17 +299,13 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(operation->handle, in_vec, 3, NULL, 0); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } - return ((psa_status_t) err_call); } @@ -373,18 +333,12 @@ psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, psa_crypto_ipc.func = PSA_HASH_CLONE_BEGIN; err_call = psa_call(source_operation->handle, in_vec, 1, &out_vec, 1); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } if (err_call != 0) { goto exit; } psa_crypto_ipc.func = PSA_HASH_CLONE_END; err_call = psa_call(target_operation->handle, in_vec, 2, NULL, 0); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } exit: if (err_call != 0) { @@ -463,9 +417,6 @@ psa_status_t psa_aead_encrypt(psa_key_handle_t key_handle, psa_close(handle); - if (call_error < 0) { - call_error = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t)call_error); } @@ -535,9 +486,6 @@ psa_status_t psa_aead_decrypt(psa_key_handle_t key_handle, psa_close(handle); - if (call_error < 0) { - call_error = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t)call_error); } @@ -586,9 +534,6 @@ psa_status_t psa_asymmetric_sign(psa_key_handle_t key_handle, psa_close(handle); - if (call_error < 0) { - call_error = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t)call_error); } @@ -625,9 +570,6 @@ psa_status_t psa_asymmetric_verify(psa_key_handle_t key_handle, call_error = psa_call(handle, in_vec, 3, NULL, 0); psa_close(handle); - if (call_error < 0) { - call_error = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t)call_error); } @@ -686,9 +628,6 @@ static psa_status_t psa_asymmetric_operation(psa_sec_function_t func, psa_close(handle); - if (call_error < 0) { - call_error = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t)call_error); } @@ -754,9 +693,6 @@ psa_status_t psa_allocate_key(psa_key_handle_t *key_handle) err_call = psa_call(handle, in_vec, 1, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -787,9 +723,6 @@ psa_status_t psa_create_key(psa_key_lifetime_t lifetime, err_call = psa_call(handle, in_vec, 2, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -820,9 +753,6 @@ psa_status_t psa_open_key(psa_key_lifetime_t lifetime, err_call = psa_call(handle, in_vec, 2, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -845,9 +775,6 @@ psa_status_t psa_close_key(psa_key_handle_t key_handle) err_call = psa_call(handle, in_vec, 1, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -876,9 +803,6 @@ psa_status_t psa_get_key_lifetime(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 1, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -921,9 +845,6 @@ psa_status_t psa_set_key_policy(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 2, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -954,9 +875,6 @@ psa_status_t psa_get_key_policy(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 1, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -984,9 +902,6 @@ psa_status_t psa_import_key(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 2, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1009,9 +924,6 @@ psa_status_t psa_destroy_key(psa_key_handle_t key_handle) err_call = psa_call(handle, in_vec, 1, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1047,9 +959,6 @@ psa_status_t psa_get_key_information(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 1, out_vec, 2); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1078,9 +987,6 @@ static psa_status_t psa_export_key_common(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 1, out_vec, 2); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1138,9 +1044,6 @@ psa_status_t psa_generate_key(psa_key_handle_t key_handle, err_call = psa_call(handle, in_vec, 3, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1163,9 +1066,6 @@ psa_status_t psa_generate_random(uint8_t *output, err_call = psa_call(handle, NULL, 0, out_vec, 1); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1187,9 +1087,6 @@ psa_status_t mbedtls_psa_inject_entropy(const unsigned char *seed, err_call = psa_call(handle, &in_vec, 1, NULL, 0); psa_close(handle); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1206,14 +1103,11 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, psa_outvec out_vec = { capacity, sizeof(*capacity) }; if (generator->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(generator->handle, &in_vec, 1, &out_vec, 1); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1228,14 +1122,11 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, psa_outvec out_vec = { output, output_length }; if (generator->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(generator->handle, &in_vec, 1, &out_vec, 1); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1254,14 +1145,11 @@ psa_status_t psa_generator_import_key(psa_key_handle_t key_handle, }; if (generator->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(generator->handle, in_vec, 3, NULL, 0); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1293,11 +1181,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, err_call = psa_call(generator->handle, in_vec, 3, NULL, 0); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); - } psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, @@ -1323,9 +1207,6 @@ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, err_call = psa_call(generator->handle, in_vec, 2, NULL, 0); - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); } @@ -1340,9 +1221,6 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator) psa_close(generator->handle); generator->handle = PSA_NULL_HANDLE; } - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } return ((psa_status_t) err_call); @@ -1373,9 +1251,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, } err = psa_call(operation->handle, &in_vec, 1, NULL, 0); - if (err < 0) { - err = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err); } @@ -1402,9 +1278,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, } err = psa_call(operation->handle, &in_vec, 1, NULL, 0); - if (err < 0) { - err = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err); } @@ -1432,13 +1306,11 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err = psa_call(operation->handle, &in_vec, 1, out_vec, 2); - if (err < 0) { - err = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err); } @@ -1460,13 +1332,11 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err = psa_call(operation->handle, in_vec, 2, NULL, 0); - if (err < 0) { - err = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err); } @@ -1500,13 +1370,11 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err = psa_call(operation->handle, in_vec, 2, out_vec, 2); - if (err < 0) { - err = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err); } @@ -1535,15 +1403,13 @@ psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, }; if (operation->handle <= 0) { - return (PSA_ERROR_BAD_STATE); + return (PSA_ERROR_INVALID_ARGUMENT); } err_call = psa_call(operation->handle, &in_vec, 1, out_vec, 2); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err_call); } @@ -1566,9 +1432,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) err_call = psa_call(operation->handle, &in_vec, 1, NULL, 0); psa_close(operation->handle); operation->handle = PSA_NULL_HANDLE; - if (err_call < 0) { - err_call = (psa_status_t) PSA_ERROR_COMMUNICATION_FAILURE; - } + return ((psa_status_t) err_call); } diff --git a/components/TARGET_PSA/services/platform/COMPONENT_PSA_SRV_IMPL/platform_srv_impl.c b/components/TARGET_PSA/services/platform/COMPONENT_PSA_SRV_IMPL/platform_srv_impl.c index 9951df50ba..6dfd51fd24 100644 --- a/components/TARGET_PSA/services/platform/COMPONENT_PSA_SRV_IMPL/platform_srv_impl.c +++ b/components/TARGET_PSA/services/platform/COMPONENT_PSA_SRV_IMPL/platform_srv_impl.c @@ -31,7 +31,7 @@ psa_status_t psa_platfrom_lifecycle_get_impl(uint32_t *lc_state) return PSA_LIFECYCLE_SUCCESS; } -psa_its_status_t psa_its_reset(); +psa_status_t psa_its_reset(); psa_status_t psa_platfrom_lifecycle_change_request_impl(uint32_t state) { diff --git a/components/TARGET_PSA/services/platform/COMPONENT_SPE/platform_partition.c b/components/TARGET_PSA/services/platform/COMPONENT_SPE/platform_partition.c index 6dc0cf6e69..5943e166c9 100644 --- a/components/TARGET_PSA/services/platform/COMPONENT_SPE/platform_partition.c +++ b/components/TARGET_PSA/services/platform/COMPONENT_SPE/platform_partition.c @@ -37,7 +37,7 @@ static psa_status_t lifecycle_get(psa_msg_t *msg) return PSA_DROP_CONNECTION; } - psa_its_status_t status = psa_platfrom_lifecycle_get_impl(&lc_state); + psa_status_t status = psa_platfrom_lifecycle_get_impl(&lc_state); if (status == PSA_SUCCESS) { psa_write(msg->handle, 0, &lc_state, sizeof(lc_state)); } diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_version_impl.h b/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_version_impl.h deleted file mode 100644 index 4f2ecba51c..0000000000 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_version_impl.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2019 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_VER_IMPL_H__ -#define __PITS_VER_IMPL_H__ - -#include "psa/internal_trusted_storage.h" - -#ifdef __cplusplus -extern "C" -{ -#endif - -#define ITS_VERSION_KEY "PSA_ITS_VERSION" // ITS version entry identifier in TDBStore - -typedef struct its_version { - uint32_t major; - uint32_t minor; -} its_version_t; - -psa_its_status_t its_version_migrate(void *storage, const its_version_t *version); - -#ifdef __cplusplus -} -#endif - -#endif // __PITS_VER_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 deleted file mode 100644 index 326a949320..0000000000 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/psa_prot_internal_storage.h +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2019, 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. - */ -/** @file -@brief This file describes the PSA Internal Trusted Storage API -*/ - -#ifndef __INTERNAL_TRUSTED_STORAGE_H__ -#define __INTERNAL_TRUSTED_STORAGE_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ -#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ - -/** \brief Flags used when creating a key - */ -typedef uint32_t psa_its_create_flags_t; - -/** \brief A type for UIDs used for identifying data - */ -typedef uint64_t psa_its_uid_t; - -#define PSA_ITS_FLAG_NONE 0 /**< No flags to pass */ -#define PSA_ITS_FLAG_WRITE_ONCE ( 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` */ -/** Mask for all of the ITS Flags - */ -#define PSA_ITS_FLAGS_MSK ( \ - PSA_ITS_FLAG_NONE | \ - PSA_ITS_FLAG_WRITE_ONCE \ - ) - -/** - * \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_STORAGE_FAILURE 4 /**< The operation failed because the physical storage has failed (Fatal error) */ -#define PSA_ITS_ERROR_INVALID_ARGUMENTS 5 /**< 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_UID_NOT_FOUND 6 /**< The operation failed because the provided key value was not found in the storage */ -#define PSA_ITS_ERROR_INCORRECT_SIZE 7 /**< The operation failed because the data associated with provided key is not the same size as `data_size`, or `offset+data_size` is too large for the data, but `offset` is less than the size */ -#define PSA_ITS_ERROR_OFFSET_INVALID 8 /**< The operation failed because an offset was supplied that is invalid for the existing data associated with the uid. For example, offset is greater that the size 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_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) - * \retval PSA_ITS_ERROR_INVALID_ARGUMENTS 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(psa_its_uid_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_UID_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_INVALID_ARGUMENTS 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_ITS_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(psa_its_uid_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_SUCCESS The operation completed successfully - * \retval PSA_ITS_ERROR_UID_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_INVALID_ARGUMENTS 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(psa_its_uid_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_UID_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(psa_its_uid_t uid); - -#ifdef __cplusplus -} -#endif - -#endif // __INTERNAL_TRUSTED_STORAGE_H__ diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp b/components/TARGET_PSA/services/storage/common/psa_storage_common_impl.cpp similarity index 52% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp rename to components/TARGET_PSA/services/storage/common/psa_storage_common_impl.cpp index 925f7efd90..c39995e13a 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp +++ b/components/TARGET_PSA/services/storage/common/psa_storage_common_impl.cpp @@ -16,43 +16,26 @@ */ #include -#include "KVStore.h" #include "TDBStore.h" -#include "psa/internal_trusted_storage.h" -#include "pits_impl.h" -#include "pits_version_impl.h" +#include "psa_storage_common_impl.h" #include "mbed_error.h" #include "mbed_assert.h" #include "mbed_toolchain.h" -#if defined(TARGET_TFM) - using namespace mbed; -KVStore *get_its_kvstore_instance(void); - -#else - -#include "KVMap.h" - -using namespace mbed; - -/* - * \brief Get default KVStore instance for internal flesh storage - * - * \return valid pointer to KVStore - */ -KVStore *get_its_kvstore_instance(void) +#ifdef __cplusplus +extern "C" { - KVMap &kv_map = KVMap::get_instance(); - return kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); -} -#endif // defined(TARGET_TFM) +#endif // Maximum length of filename we use for kvstore API. // pid: 6; delimiter: 1; uid: 11; str terminator: 1 -#define PSA_ITS_FILENAME_MAX_LEN 19 +#define PSA_STORAGE_FILE_NAME_MAX 19 +#define FLAGS_MSK PSA_STORAGE_FLAG_WRITE_ONCE + +#define STR_EXPAND(tok) #tok const uint8_t base64_coding_table[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', @@ -65,65 +48,41 @@ const uint8_t base64_coding_table[] = { '4', '5', '6', '7', '8', '9', '+', '-' }; -static KVStore *kvstore = NULL; - -MBED_WEAK psa_its_status_t its_version_migrate(void *storage, const its_version_t *version) +void psa_storage_handle_version(KVStore *kvstore, const char *version_key, const psa_storage_version_t *curr_version, + migrate_func_t migrate_func) { - (void)storage; - (void)version; - return PSA_ITS_SUCCESS; -} - -static void its_init(void) -{ - kvstore = get_its_kvstore_instance(); - if (!kvstore) { - // Can only happen due to system misconfiguration. - // Thus considered as unrecoverable error for runtime. - error("Failed getting kvstore instance\n"); - } - - its_version_t version = { 0, 0 }; + psa_storage_version_t read_version = {0, 0}; size_t actual_size = 0; - KVStore::info_t kv_info; bool write_version = false; - int status = kvstore->get_info(ITS_VERSION_KEY, &kv_info); - if (status != MBED_SUCCESS) { - version.major = PSA_ITS_API_VERSION_MAJOR; - version.minor = PSA_ITS_API_VERSION_MINOR; + int status = kvstore->get(version_key, &read_version, sizeof(read_version), &actual_size, 0); + if (status == MBED_SUCCESS) { + if (actual_size != sizeof(read_version)) { + error("PSA storage version data is corrupt"); + } + } else if (status == MBED_ERROR_ITEM_NOT_FOUND) { write_version = true; } else { - if (kv_info.size != sizeof(version)) { - error("ITS version data is corrupt"); - } - - status = kvstore->get(ITS_VERSION_KEY, &version, sizeof(version), &actual_size, 0); - if ((status != MBED_SUCCESS) || - ((status == MBED_SUCCESS) && (actual_size != sizeof(version)))) { - error("Could not read ITS version data"); - } + error("Could not read PSA storage version data"); } - if ((version.major > PSA_ITS_API_VERSION_MAJOR) || - ((version.major == PSA_ITS_API_VERSION_MAJOR) && (version.minor > PSA_ITS_API_VERSION_MINOR))) { - error("Downgrading ITS version is not allowed"); + if ((read_version.major > curr_version->major) || + ((read_version.major == curr_version->major) && (read_version.minor > curr_version->minor))) { + error("Downgrading PSA storage version is not allowed"); } - if ((version.major < PSA_ITS_API_VERSION_MAJOR) || - ((version.major == PSA_ITS_API_VERSION_MAJOR) && (version.minor < PSA_ITS_API_VERSION_MINOR))) { - psa_its_status_t migration_status = its_version_migrate(kvstore, &version); - if (migration_status != PSA_ITS_SUCCESS) { - error("ITS migration failed"); + if ((read_version.major < curr_version->major) || + ((read_version.major == curr_version->major) && (read_version.minor < curr_version->minor))) { + psa_status_t migration_status = migrate_func(kvstore, &read_version, curr_version); + if (migration_status != PSA_SUCCESS) { + error("PSA storage migration failed"); } - version.major = PSA_ITS_API_VERSION_MAJOR; - version.minor = PSA_ITS_API_VERSION_MINOR; write_version = true; } if (write_version) { - if (kvstore->set(ITS_VERSION_KEY, &version, sizeof(version), 0) != MBED_SUCCESS) { - error("Could not write PSA ITS version"); + if (kvstore->set(version_key, curr_version, sizeof(psa_storage_version_t), 0) != MBED_SUCCESS) { + error("Could not write PSA storage version"); } } } @@ -134,19 +93,29 @@ static void its_init(void) * \param[in] status - KVStore status code * \return PSA internal storage status code */ -static psa_its_status_t convert_status(int status) +static psa_status_t convert_status(int status) { switch (status) { case MBED_SUCCESS: - return PSA_ITS_SUCCESS; + return PSA_SUCCESS; case MBED_ERROR_WRITE_PROTECTED: - return PSA_ITS_ERROR_WRITE_ONCE; + return PSA_ERROR_NOT_PERMITTED; case MBED_ERROR_MEDIA_FULL: - return PSA_ITS_ERROR_INSUFFICIENT_SPACE; + return PSA_ERROR_INSUFFICIENT_STORAGE; case MBED_ERROR_ITEM_NOT_FOUND: - return PSA_ITS_ERROR_UID_NOT_FOUND; + return PSA_ERROR_DOES_NOT_EXIST; + case MBED_ERROR_INVALID_DATA_DETECTED: + return PSA_ERROR_DATA_CORRUPT; + case MBED_ERROR_INVALID_ARGUMENT: + return PSA_ERROR_INVALID_ARGUMENT; + case MBED_ERROR_READ_FAILED: // fallthrough + case MBED_ERROR_WRITE_FAILED: + return PSA_ERROR_STORAGE_FAILURE; + case MBED_ERROR_AUTHENTICATION_FAILED: // fallthrough + case MBED_ERROR_RBP_AUTHENTICATION_FAILED: + return PSA_ERROR_INVALID_SIGNATURE; default: - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_GENERIC_ERROR; } } @@ -187,10 +156,10 @@ MBED_FORCEINLINE uint64_t lsr64(uint64_t x, uint32_t n) * \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, psa_its_uid_t uid, int32_t pid) +static void generate_fn(char *tdb_filename, uint32_t tdb_filename_size, psa_storage_uid_t uid, int32_t pid) { MBED_ASSERT(tdb_filename != NULL); - MBED_ASSERT(tdb_filename_size == PSA_ITS_FILENAME_MAX_LEN); + MBED_ASSERT(tdb_filename_size == PSA_STORAGE_FILE_NAME_MAX); uint8_t filename_idx = 0; uint32_t unsigned_pid = (uint32_t)pid; // binary only representation for bitwise operations @@ -211,25 +180,23 @@ static void generate_fn(char *tdb_filename, uint32_t tdb_filename_size, psa_its_ } while (uid != 0); tdb_filename[filename_idx++] = '\0'; - MBED_ASSERT(filename_idx <= PSA_ITS_FILENAME_MAX_LEN); + MBED_ASSERT(filename_idx <= PSA_STORAGE_FILE_NAME_MAX); } -psa_its_status_t psa_its_set_impl(int32_t pid, psa_its_uid_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags) +psa_status_t psa_storage_set_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + uint32_t data_length, const void *p_data, + psa_storage_create_flags_t create_flags) { - if (!kvstore) { - its_init(); - } - - if ((create_flags & (~PSA_ITS_FLAGS_MSK)) != 0) { - return PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED; + if ((create_flags & (~FLAGS_MSK)) != 0) { + return PSA_ERROR_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); + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); uint32_t kv_create_flags = 0; - if (create_flags & PSA_ITS_FLAG_WRITE_ONCE) { + if (create_flags & PSA_STORAGE_FLAG_WRITE_ONCE) { kv_create_flags = KVStore::WRITE_ONCE_FLAG; } @@ -238,55 +205,46 @@ psa_its_status_t psa_its_set_impl(int32_t pid, psa_its_uid_t uid, uint32_t data_ return convert_status(status); } -psa_its_status_t psa_its_get_impl(int32_t pid, psa_its_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +psa_status_t psa_storage_get_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + uint32_t data_offset, uint32_t data_length, void *p_data) { - if (!kvstore) { - its_init(); - } - // Generate KVStore key - char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'}; - generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid); + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); KVStore::info_t kv_info; int status = kvstore->get_info(kv_key, &kv_info); if (status == MBED_SUCCESS) { if (data_offset > kv_info.size) { - return PSA_ITS_ERROR_OFFSET_INVALID; + return PSA_ERROR_INVALID_ARGUMENT; } // Verify (size + offset) does not wrap around if (data_length + data_offset < data_length) { - return PSA_ITS_ERROR_INCORRECT_SIZE; + return PSA_ERROR_INVALID_ARGUMENT; } if (data_offset + data_length > kv_info.size) { - return PSA_ITS_ERROR_INCORRECT_SIZE; + return PSA_ERROR_BUFFER_TOO_SMALL; } size_t actual_size = 0; status = kvstore->get(kv_key, p_data, data_length, &actual_size, data_offset); - - if (status == MBED_SUCCESS) { - if (actual_size < data_length) { - status = PSA_ITS_ERROR_INCORRECT_SIZE; - } + if ((status == MBED_SUCCESS) && (actual_size < data_length)) { + return PSA_ERROR_BUFFER_TOO_SMALL; } } return convert_status(status); } -psa_its_status_t psa_its_get_info_impl(int32_t pid, psa_its_uid_t uid, struct psa_its_info_t *p_info) +psa_status_t psa_storage_get_info_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) { - if (!kvstore) { - its_init(); - } - // Generate KVStore key - char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'}; - generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid); + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); KVStore::info_t kv_info; int status = kvstore->get_info(kv_key, &kv_info); @@ -294,7 +252,7 @@ psa_its_status_t psa_its_get_info_impl(int32_t pid, psa_its_uid_t uid, struct ps if (status == MBED_SUCCESS) { p_info->flags = 0; if (kv_info.flags & KVStore::WRITE_ONCE_FLAG) { - p_info->flags |= PSA_ITS_FLAG_WRITE_ONCE; + p_info->flags |= PSA_STORAGE_FLAG_WRITE_ONCE; } p_info->size = (uint32_t)(kv_info.size); // kv_info.size is of type size_t } @@ -302,27 +260,23 @@ psa_its_status_t psa_its_get_info_impl(int32_t pid, psa_its_uid_t uid, struct ps return convert_status(status); } -psa_its_status_t psa_its_remove_impl(int32_t pid, psa_its_uid_t uid) +psa_status_t psa_storage_remove_impl(KVStore *kvstore, int32_t pid, psa_storage_uid_t uid) { - if (!kvstore) { - its_init(); - } - // Generate KVStore key - char kv_key[PSA_ITS_FILENAME_MAX_LEN] = {'\0'}; - generate_fn(kv_key, PSA_ITS_FILENAME_MAX_LEN, uid, pid); + char kv_key[PSA_STORAGE_FILE_NAME_MAX] = {'\0'}; + generate_fn(kv_key, PSA_STORAGE_FILE_NAME_MAX, uid, pid); int status = kvstore->remove(kv_key); return convert_status(status); } -psa_its_status_t psa_its_reset_impl() +psa_status_t psa_storage_reset_impl(KVStore *kvstore) { - if (!kvstore) { - its_init(); - } - int status = kvstore->reset(); return convert_status(status); } + +#ifdef __cplusplus +} +#endif diff --git a/components/TARGET_PSA/services/storage/common/psa_storage_common_impl.h b/components/TARGET_PSA/services/storage/common/psa_storage_common_impl.h new file mode 100644 index 0000000000..b8881ea6ac --- /dev/null +++ b/components/TARGET_PSA/services/storage/common/psa_storage_common_impl.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2019 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 __PSA_STORAGE_COMMON_IMPL_H__ +#define __PSA_STORAGE_COMMON_IMPL_H__ + +#include "psa/error.h" +#include "psa/storage_common.h" +#include "KVStore.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct { + uint32_t major; + uint32_t minor; +} psa_storage_version_t; + +typedef psa_status_t (*migrate_func_t)(mbed::KVStore *kvstore, const psa_storage_version_t *old_version, const psa_storage_version_t *new_version); + +void psa_storage_handle_version(mbed::KVStore *kvstore, const char *version_key, const psa_storage_version_t *version, + migrate_func_t migrate_func); +psa_status_t psa_storage_set_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); +psa_status_t psa_storage_get_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data); +psa_status_t psa_storage_get_info_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info); +psa_status_t psa_storage_remove_impl(mbed::KVStore *kvstore, int32_t pid, psa_storage_uid_t uid); +psa_status_t psa_storage_reset_impl(mbed::KVStore *kvstore); + +#ifdef __cplusplus +} +#endif + + +#endif // __PSA_STORAGE_COMMON_IMPL_H__ 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/storage/its/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp similarity index 76% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp rename to components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp index 3e1364082b..902dc0df28 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_EMUL/psa_prot_internal_storage.cpp @@ -19,6 +19,7 @@ #include #include "psa/internal_trusted_storage.h" +#include "psa/storage_common.h" #include "pits_impl.h" #include "kv_config.h" #include "mbed_error.h" @@ -27,10 +28,10 @@ // 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(psa_its_uid_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags) +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) { if (!p_data && data_length) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } // KVStore initiation: @@ -38,18 +39,18 @@ psa_its_status_t psa_its_set(psa_its_uid_t uid, uint32_t data_length, const void // - 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_ERROR_STORAGE_FAILURE; } - psa_its_status_t res = psa_its_set_impl(PSA_ITS_EMUL_PID, uid, data_length, p_data, create_flags); + psa_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(psa_its_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) { if (!p_data && data_length) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } // KVStore initiation: @@ -57,16 +58,16 @@ psa_its_status_t psa_its_get(psa_its_uid_t uid, uint32_t data_offset, uint32_t d // - 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_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(psa_its_uid_t uid, struct psa_its_info_t *p_info) +psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) { if (!p_info) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } // KVStore initiation: @@ -74,33 +75,33 @@ psa_its_status_t psa_its_get_info(psa_its_uid_t uid, struct psa_its_info_t *p_in // - 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_ERROR_STORAGE_FAILURE; } return psa_its_get_info_impl(PSA_ITS_EMUL_PID, uid, p_info); } -psa_its_status_t psa_its_remove(psa_its_uid_t uid) +psa_status_t psa_its_remove(psa_storage_uid_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_ERROR_STORAGE_FAILURE; } return psa_its_remove_impl(PSA_ITS_EMUL_PID, uid); } -extern "C" psa_its_status_t psa_its_reset() +extern "C" psa_status_t psa_its_reset() { // 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_ERROR_STORAGE_FAILURE; } return psa_its_reset_impl(); diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp similarity index 99% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp rename to components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp index a86866aa5c..46cd1a7502 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/TARGET_TFM/its_tfm_impl.cpp @@ -142,8 +142,7 @@ KVStore *get_its_kvstore_instance(void) { return internal_store; } - -int kv_init_storage_config() +extern "C" int kv_init_storage_config() { int ret = MBED_SUCCESS; diff --git a/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp new file mode 100644 index 0000000000..bba98ff1ab --- /dev/null +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.cpp @@ -0,0 +1,140 @@ +/* Copyright (c) 2019 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 "KVStore.h" +#include "TDBStore.h" +#include "psa/internal_trusted_storage.h" +#include "psa_storage_common_impl.h" +#include "pits_impl.h" +#include "mbed_error.h" +#include "mbed_toolchain.h" + +using namespace mbed; + +#if defined(TARGET_TFM) +KVStore *get_its_kvstore_instance(void); +#else +#include "KVMap.h" +#endif + + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define STR_EXPAND(tok) #tok +#define ITS_VERSION_KEY "PSA_ITS_VERSION" // ITS version entry identifier in TDBStore + +static KVStore *kvstore = NULL; + + + +MBED_WEAK psa_status_t its_version_migrate(KVStore *kvstore, + const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) +{ + (void)kvstore; + (void)old_version; + (void)new_version; + return PSA_SUCCESS; +} + + +static void its_init(void) +{ +#if defined(TARGET_TFM) + kvstore = get_its_kvstore_instance(); +#else + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); +#endif + psa_storage_version_t version = {PSA_ITS_API_VERSION_MAJOR, PSA_ITS_API_VERSION_MINOR}; + if (!kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + psa_storage_handle_version(kvstore, ITS_VERSION_KEY, &version, its_version_migrate); +} + +// used from test only +void its_deinit(void) +{ + kvstore = NULL; +} + + +psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) +{ + if (!kvstore) { + its_init(); + } + + return psa_storage_set_impl(kvstore, pid, uid, data_length, p_data, create_flags); +} + +psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +{ + if (!kvstore) { + its_init(); + } + + return psa_storage_get_impl(kvstore, pid, uid, data_offset, data_length, p_data); +} + +psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info) +{ + if (!kvstore) { + its_init(); + } + + return psa_storage_get_info_impl(kvstore, pid, uid, p_info); +} + +psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid) +{ + if (!kvstore) { + its_init(); + } + + return psa_storage_remove_impl(kvstore, pid, uid); +} + +psa_status_t psa_its_reset_impl() +{ + // Do not call its_init here to avoid version check before reset +#if defined(TARGET_TFM) + kvstore = get_its_kvstore_instance(); +#else + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_internal_kv_instance(STR_EXPAND(MBED_CONF_STORAGE_DEFAULT_KV)); +#endif + if (!kvstore) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed getting kvstore instance\n"); + } + + return psa_storage_reset_impl(kvstore); +} + +#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/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.h similarity index 53% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.h rename to components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.h index b426e68a5a..19a98809fd 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IMPL/pits_impl.h +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IMPL/pits_impl.h @@ -18,26 +18,19 @@ #ifndef __PITS_IMPL_H__ #define __PITS_IMPL_H__ -#include "psa/internal_trusted_storage.h" +#include "psa/error.h" +#include "psa/storage_common.h" #ifdef __cplusplus extern "C" { #endif -#if defined(TARGET_TFM) && defined(COMPONENT_SPE) -extern int kv_init_storage_config(); -#endif -#define PITS_DATA_PTR_AT_OFFSET(ptr, offset) ((void *)(((uintptr_t)ptr) + ((uintptr_t)offset))) -#define STR_EXPAND(tok) #tok - -psa_its_status_t psa_its_set_impl(int32_t pid, psa_its_uid_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, psa_its_uid_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, psa_its_uid_t uid, struct psa_its_info_t *p_info); -psa_its_status_t psa_its_remove_impl(int32_t pid, psa_its_uid_t uid); -psa_its_status_t psa_its_reset_impl(); - -psa_its_status_t psa_its_reset_impl(void); +psa_status_t psa_its_set_impl(int32_t pid, psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags); +psa_status_t psa_its_get_impl(int32_t pid, psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data); +psa_status_t psa_its_get_info_impl(int32_t pid, psa_storage_uid_t uid, struct psa_storage_info_t *p_info); +psa_status_t psa_its_remove_impl(int32_t pid, psa_storage_uid_t uid); +psa_status_t psa_its_reset_impl(); #ifdef __cplusplus } diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c similarity index 71% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c rename to components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c index 2508b9d09a..b8f0ad993d 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_PSA_SRV_IPC/psa_prot_internal_storage.c @@ -16,13 +16,14 @@ */ #include "psa/client.h" +#include "psa/storage_common.h" #include "psa/internal_trusted_storage.h" #include "psa_its_ifs.h" -psa_its_status_t psa_its_set(psa_its_uid_t uid, uint32_t data_length, const void *p_data, psa_its_create_flags_t create_flags) +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) { if (!p_data && data_length) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } psa_invec msg[3] = { @@ -33,22 +34,22 @@ psa_its_status_t psa_its_set(psa_its_uid_t uid, uint32_t data_length, const void psa_handle_t conn = psa_connect(PSA_ITS_SET, 1); if (conn <= PSA_NULL_HANDLE) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } psa_status_t status = psa_call(conn, msg, 3, NULL, 0); if (status == PSA_DROP_CONNECTION) { - status = PSA_ITS_ERROR_STORAGE_FAILURE; + status = PSA_ERROR_STORAGE_FAILURE; } psa_close(conn); return status; } -psa_its_status_t psa_its_get(psa_its_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +psa_status_t psa_its_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) { if (!p_data && data_length) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } psa_invec msg[2] = { @@ -59,31 +60,31 @@ psa_its_status_t psa_its_get(psa_its_uid_t uid, uint32_t data_offset, uint32_t d psa_handle_t conn = psa_connect(PSA_ITS_GET, 1); if (conn <= PSA_NULL_HANDLE) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } psa_status_t status = psa_call(conn, msg, 2, &resp, 1); if (status == PSA_DROP_CONNECTION) { - status = PSA_ITS_ERROR_STORAGE_FAILURE; + status = PSA_ERROR_STORAGE_FAILURE; } psa_close(conn); return status; } -psa_its_status_t psa_its_get_info(psa_its_uid_t uid, struct psa_its_info_t *p_info) +psa_status_t psa_its_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) { if (!p_info) { - return PSA_ITS_ERROR_INVALID_ARGUMENTS; + return PSA_ERROR_INVALID_ARGUMENT; } - struct psa_its_info_t info = { 0, PSA_ITS_FLAG_NONE }; + struct psa_storage_info_t info = { 0, PSA_STORAGE_FLAG_NONE }; psa_invec msg = { &uid, sizeof(uid) }; psa_outvec resp = { &info, sizeof(info) }; psa_handle_t conn = psa_connect(PSA_ITS_INFO, 1); if (conn <= PSA_NULL_HANDLE) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } psa_status_t status = psa_call(conn, &msg, 1, &resp, 1); @@ -91,40 +92,40 @@ psa_its_status_t psa_its_get_info(psa_its_uid_t uid, struct psa_its_info_t *p_in *p_info = info; if (status == PSA_DROP_CONNECTION) { - status = PSA_ITS_ERROR_STORAGE_FAILURE; + status = PSA_ERROR_STORAGE_FAILURE; } psa_close(conn); return status; } -psa_its_status_t psa_its_remove(psa_its_uid_t uid) +psa_status_t psa_its_remove(psa_storage_uid_t uid) { psa_invec msg = { &uid, sizeof(uid) }; psa_handle_t conn = psa_connect(PSA_ITS_REMOVE, 1); if (conn <= PSA_NULL_HANDLE) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } psa_status_t status = psa_call(conn, &msg, 1, NULL, 0); if (status == PSA_DROP_CONNECTION) { - status = PSA_ITS_ERROR_STORAGE_FAILURE; + status = PSA_ERROR_STORAGE_FAILURE; } psa_close(conn); return status; } -psa_its_status_t psa_its_reset() +psa_status_t psa_its_reset() { psa_handle_t conn = psa_connect(PSA_ITS_RESET, 1); if (conn <= PSA_NULL_HANDLE) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } psa_status_t status = psa_call(conn, NULL, 0, NULL, 0); if (status == PSA_DROP_CONNECTION) { - status = PSA_ITS_ERROR_STORAGE_FAILURE; + status = PSA_ERROR_STORAGE_FAILURE; } psa_close(conn); diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/TARGET_MBED_SPM/psa_its_partition.c b/components/TARGET_PSA/services/storage/its/COMPONENT_SPE/TARGET_MBED_SPM/psa_its_partition.c similarity index 100% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/TARGET_MBED_SPM/psa_its_partition.c rename to components/TARGET_PSA/services/storage/its/COMPONENT_SPE/TARGET_MBED_SPM/psa_its_partition.c diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/its_partition.c b/components/TARGET_PSA/services/storage/its/COMPONENT_SPE/its_partition.c similarity index 84% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/its_partition.c rename to components/TARGET_PSA/services/storage/its/COMPONENT_SPE/its_partition.c index dfc5ad648b..ac2a7ddf09 100644 --- a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/its_partition.c +++ b/components/TARGET_PSA/services/storage/its/COMPONENT_SPE/its_partition.c @@ -44,10 +44,10 @@ typedef psa_status_t (*SignalHandler)(psa_msg_t *); static psa_status_t storage_set(psa_msg_t *msg) { - psa_its_uid_t key = 0; + psa_storage_uid_t key = 0; void *data = NULL; uint32_t alloc_size = msg->in_size[1]; - psa_its_create_flags_t flags = 0; + psa_storage_create_flags_t flags = 0; if ((msg->in_size[0] != sizeof(key)) || (msg->in_size[2] != sizeof(flags))) { return PSA_DROP_CONNECTION; @@ -63,17 +63,17 @@ static psa_status_t storage_set(psa_msg_t *msg) data = malloc(alloc_size); if (data == NULL) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } if (psa_read(msg->handle, 1, data, msg->in_size[1]) != msg->in_size[1]) { free(data); - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } #if defined(TARGET_MBED_SPM) - psa_its_status_t status = psa_its_set_impl(psa_identity(msg->handle), key, alloc_size, data, flags); + psa_status_t status = psa_its_set_impl(psa_identity(msg->handle), key, alloc_size, data, flags); #else - psa_its_status_t status = psa_its_set_impl(msg->client_id, key, alloc_size, data, flags); + psa_status_t status = psa_its_set_impl(msg->client_id, key, alloc_size, data, flags); #endif memset(data, 0, alloc_size); free(data); @@ -82,7 +82,7 @@ static psa_status_t storage_set(psa_msg_t *msg) static psa_status_t storage_get(psa_msg_t *msg) { - psa_its_uid_t key = 0; + psa_storage_uid_t key = 0; uint32_t offset = 0; if ((msg->in_size[0] != sizeof(key)) || (msg->in_size[1] != sizeof(offset))) { @@ -99,16 +99,16 @@ static psa_status_t storage_get(psa_msg_t *msg) uint8_t *data = (uint8_t *)malloc(msg->out_size[0]); if (data == NULL) { - return PSA_ITS_ERROR_STORAGE_FAILURE; + return PSA_ERROR_STORAGE_FAILURE; } #if defined(TARGET_MBED_SPM) - psa_its_status_t status = psa_its_get_impl(psa_identity(msg->handle), key, offset, msg->out_size[0], data); + psa_status_t status = psa_its_get_impl(psa_identity(msg->handle), key, offset, msg->out_size[0], data); #else - psa_its_status_t status = psa_its_get_impl(msg->client_id, key, offset, msg->out_size[0], data); + psa_status_t status = psa_its_get_impl(msg->client_id, key, offset, msg->out_size[0], data); #endif - if (status == PSA_ITS_SUCCESS) { + if (status == PSA_SUCCESS) { psa_write(msg->handle, 0, data, msg->out_size[0]); } @@ -119,8 +119,8 @@ static psa_status_t storage_get(psa_msg_t *msg) static psa_status_t storage_info(psa_msg_t *msg) { - struct psa_its_info_t info = { 0 }; - psa_its_uid_t key = 0; + struct psa_storage_info_t info = { 0 }; + psa_storage_uid_t key = 0; if ((msg->in_size[0] != sizeof(key)) || (msg->out_size[0] != sizeof(info))) { return PSA_DROP_CONNECTION; @@ -131,12 +131,12 @@ static psa_status_t storage_info(psa_msg_t *msg) } #if defined(TARGET_MBED_SPM) - psa_its_status_t status = psa_its_get_info_impl(psa_identity(msg->handle), key, &info); + psa_status_t status = psa_its_get_info_impl(psa_identity(msg->handle), key, &info); #else - psa_its_status_t status = psa_its_get_info_impl(msg->client_id, key, &info); + psa_status_t status = psa_its_get_info_impl(msg->client_id, key, &info); #endif - if (status == PSA_ITS_SUCCESS) { + if (status == PSA_SUCCESS) { psa_write(msg->handle, 0, &info, msg->out_size[0]); } @@ -145,7 +145,7 @@ static psa_status_t storage_info(psa_msg_t *msg) static psa_status_t storage_remove(psa_msg_t *msg) { - psa_its_uid_t key = 0; + psa_storage_uid_t key = 0; if (msg->in_size[0] != sizeof(key)) { return PSA_DROP_CONNECTION; diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/psa_its_partition.h b/components/TARGET_PSA/services/storage/its/COMPONENT_SPE/psa_its_partition.h similarity index 100% rename from components/TARGET_PSA/services/psa_prot_internal_storage/COMPONENT_SPE/psa_its_partition.h rename to components/TARGET_PSA/services/storage/its/COMPONENT_SPE/psa_its_partition.h diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/pits_psa.json b/components/TARGET_PSA/services/storage/its/pits_psa.json similarity index 100% rename from components/TARGET_PSA/services/psa_prot_internal_storage/pits_psa.json rename to components/TARGET_PSA/services/storage/its/pits_psa.json diff --git a/components/TARGET_PSA/services/psa_prot_internal_storage/psa_its_ifs.h b/components/TARGET_PSA/services/storage/its/psa_its_ifs.h similarity index 100% rename from components/TARGET_PSA/services/psa_prot_internal_storage/psa_its_ifs.h rename to components/TARGET_PSA/services/storage/its/psa_its_ifs.h diff --git a/components/TARGET_PSA/services/storage/its/psa_prot_internal_storage.h b/components/TARGET_PSA/services/storage/its/psa_prot_internal_storage.h new file mode 100644 index 0000000000..aeb129dde2 --- /dev/null +++ b/components/TARGET_PSA/services/storage/its/psa_prot_internal_storage.h @@ -0,0 +1,145 @@ +/* Copyright (C) 2019, 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. + */ +/** @file +@brief This file describes the PSA Internal Trusted Storage API +*/ + +#ifndef __PSA_INTERNAL_TRUSTED_STORAGE_H__ +#define __PSA_INTERNAL_TRUSTED_STORAGE_H__ + +#include +#include + +#include "psa/error.h" +#include "psa/storage_common.h" +#include "mbed_toolchain.h" + +#ifdef __cplusplus +extern "C" { +#endif +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */ +#define PSA_ITS_API_VERSION_MINOR 1 /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */ + +// These deprecated types are still used by our PSA compliance test tools +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_status_t psa_its_status_t; + +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_storage_create_flags_t psa_its_create_flags_t; + +MBED_DEPRECATED("ITS specific types should not be used") +typedef psa_storage_uid_t psa_its_uid_t; + +MBED_DEPRECATED("ITS specific types should not be used") +struct psa_its_info_t { + uint32_t size; + psa_its_create_flags_t flags; +}; + +// These defines should also be deprecated +#define PSA_ITS_SUCCESS PSA_SUCCESS +#define PSA_ITS_ERROR_UID_NOT_FOUND PSA_ERROR_DOES_NOT_EXIST +#define PSA_ITS_ERROR_STORAGE_FAILURE PSA_ERROR_STORAGE_FAILURE +#define PSA_ITS_ERROR_INSUFFICIENT_SPACE PSA_ERROR_INSUFFICIENT_STORAGE +#define PSA_ITS_ERROR_OFFSET_INVALID PSA_ERROR_INVALID_ARGUMENT +#define PSA_ITS_ERROR_INCORRECT_SIZE PSA_ERROR_INVALID_ARGUMENT +#define PSA_ITS_ERROR_INVALID_ARGUMENTS PSA_ERROR_INVALID_ARGUMENT +#define PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED PSA_ERROR_NOT_SUPPORTED +#define PSA_ITS_ERROR_WRITE_ONCE PSA_ERROR_ALREADY_EXISTS + + +/** + * \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_SUCCESS The operation completed successfully + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided `uid` value was already created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_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_ERROR_INSUFFICIENT_STORAGE The operation failed because there was insufficient space on the storage medium + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENTS 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_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); + +/** + * \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_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided `uid` value was not found in the storage + * \retval PSA_ERROR_BUFFER_TOO_SMALL The operation failed because the data associated with provided `uid` is not the same size as `data_size` + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT 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 + */ +psa_status_t psa_its_get(psa_storage_uid_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_storage_info_t` struct that will be populated with the metadata + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided uid value was not found in the storage + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + * \retval PSA_ERROR_INVALID_ARGUMENT 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_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_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_SUCCESS The operation completed successfully + * \retval PSA_ERROR_DOES_NOT_EXIST The operation failed because the provided key value was not found in the storage + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because the provided key value was created with PSA_STORAGE_WRITE_ONCE_FLAG + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the physical storage has failed (Fatal error) + */ +psa_status_t psa_its_remove(psa_storage_uid_t uid); + +#ifdef __cplusplus +} +#endif + +#endif // __PSA_INTERNAL_TRUSTED_STORAGE_H__ diff --git a/components/TARGET_PSA/services/storage/ps/COMPONENT_NSPE/protected_storage.cpp b/components/TARGET_PSA/services/storage/ps/COMPONENT_NSPE/protected_storage.cpp new file mode 100644 index 0000000000..794e8dd7e9 --- /dev/null +++ b/components/TARGET_PSA/services/storage/ps/COMPONENT_NSPE/protected_storage.cpp @@ -0,0 +1,139 @@ +/* Copyright (c) 2019 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 "kv_config.h" +#include "TDBStore.h" +#include "psa/protected_storage.h" +#include "psa_storage_common_impl.h" +#include "mbed_error.h" +#include "mbed_toolchain.h" + +using namespace mbed; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define STR_EXPAND(tok) #tok +#define PS_VERSION_KEY "PSA_PS_VERSION" // PS version entry identifier in TDBStore + +// Global PID for protected storage, used when calling IMPL functions +#define PSA_PS_GLOBAL_PID 1 + +static KVStore *kvstore = NULL; + +MBED_WEAK psa_status_t ps_version_migrate(KVStore *kvstore, + const psa_storage_version_t *old_version, const psa_storage_version_t *new_version) +{ + (void)kvstore; + (void)old_version; + (void)new_version; + return PSA_SUCCESS; +} + + +static void ps_init(void) +{ + int ret = kv_init_storage_config(); + if (ret) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed initializing kvstore configuration\n"); + } + KVMap &kv_map = KVMap::get_instance(); + psa_storage_version_t version = {PSA_PS_API_VERSION_MAJOR, PSA_PS_API_VERSION_MINOR}; + kvstore = kv_map.get_main_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"); + } + + psa_storage_handle_version(kvstore, PS_VERSION_KEY, &version, ps_version_migrate); +} + +// used from test only +void ps_deinit(void) +{ + kvstore = NULL; +} + + +psa_status_t psa_ps_set(psa_storage_uid_t uid, uint32_t data_length, const void *p_data, psa_storage_create_flags_t create_flags) +{ + if (!kvstore) { + ps_init(); + } + + return psa_storage_set_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_length, p_data, create_flags); +} + +psa_status_t psa_ps_get(psa_storage_uid_t uid, uint32_t data_offset, uint32_t data_length, void *p_data) +{ + if (!kvstore) { + ps_init(); + } + + return psa_storage_get_impl(kvstore, PSA_PS_GLOBAL_PID, uid, data_offset, data_length, p_data); +} + +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, struct psa_storage_info_t *p_info) +{ + if (!kvstore) { + ps_init(); + } + + return psa_storage_get_info_impl(kvstore, PSA_PS_GLOBAL_PID, uid, p_info); +} + +psa_status_t psa_ps_remove(psa_storage_uid_t uid) +{ + if (!kvstore) { + ps_init(); + } + + return psa_storage_remove_impl(kvstore, PSA_PS_GLOBAL_PID, uid); +} + +extern "C" psa_status_t psa_ps_reset() +{ + // Do not call its_init here to avoid version check before reset + int ret = kv_init_storage_config(); + if (ret) { + // Can only happen due to system misconfiguration. + // Thus considered as unrecoverable error for runtime. + error("Failed initializing kvstore configuration\n"); + } + + KVMap &kv_map = KVMap::get_instance(); + kvstore = kv_map.get_main_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 psa_storage_reset_impl(kvstore); +} + +#ifdef __cplusplus +} +#endif diff --git a/features/mbedtls/mbed-crypto/VERSION.txt b/features/mbedtls/mbed-crypto/VERSION.txt index 07ad87f46e..17d6b30a1b 100644 --- a/features/mbedtls/mbed-crypto/VERSION.txt +++ b/features/mbedtls/mbed-crypto/VERSION.txt @@ -1 +1 @@ -mbedcrypto-1.0.0d2 +mbedcrypto-1.0.0d4 diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile index b121c28182..385d33d7a7 100644 --- a/features/mbedtls/mbed-crypto/importer/Makefile +++ b/features/mbedtls/mbed-crypto/importer/Makefile @@ -29,7 +29,7 @@ # Set the Mbed Crypto release to import (this can/should be edited before # import) -CRYPTO_RELEASE ?= mbedcrypto-1.0.0d2 +CRYPTO_RELEASE ?= mbedcrypto-1.0.0d4 CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git # Translate between Mbed Crypto namespace and Mbed OS namespace diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto.h b/features/mbedtls/mbed-crypto/inc/psa/crypto.h index 06f9eb81f7..b62788b492 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto.h @@ -93,445 +93,6 @@ psa_status_t psa_crypto_init(void); /**@}*/ -/** \defgroup key_management Key management - * @{ - */ - -/** \brief Retrieve the lifetime of an open key. - * - * \param handle Handle to query. - * \param[out] lifetime On success, the lifetime value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, - psa_key_lifetime_t *lifetime); - - -/** Allocate a key slot for a transient key, i.e. a key which is only stored - * in volatile memory. - * - * The allocated key slot and its handle remain valid until the - * application calls psa_close_key() or psa_destroy_key() or until the - * application terminates. - * - * \param[out] handle On success, a handle to a volatile key slot. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the newly allocated key slot. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * There was not enough memory, or the maximum number of key slots - * has been reached. - */ -psa_status_t psa_allocate_key(psa_key_handle_t *handle); - -/** Open a handle to an existing persistent key. - * - * Open a handle to a key which was previously created with psa_create_key(). - * - * \param lifetime The lifetime of the key. This designates a storage - * area where the key material is stored. This must not - * be #PSA_KEY_LIFETIME_VOLATILE. - * \param id The persistent identifier of the key. - * \param[out] handle On success, a handle to a key slot which contains - * the data and metadata loaded from the specified - * persistent location. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the newly allocated key slot. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_EMPTY_SLOT - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is invalid for the specified lifetime. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p lifetime is not supported. - * \retval #PSA_ERROR_NOT_PERMITTED - * The specified key exists, but the application does not have the - * permission to access it. Note that this specification does not - * define any way to create such a key, but it may be possible - * through implementation-specific means. - */ -psa_status_t psa_open_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, - psa_key_handle_t *handle); - -/** Create a new persistent key slot. - * - * Create a new persistent key slot and return a handle to it. The handle - * remains valid until the application calls psa_close_key() or terminates. - * The application can open the key again with psa_open_key() until it - * removes the key by calling psa_destroy_key(). - * - * \param lifetime The lifetime of the key. This designates a storage - * area where the key material is stored. This must not - * be #PSA_KEY_LIFETIME_VOLATILE. - * \param id The persistent identifier of the key. - * \param[out] handle On success, a handle to the newly created key slot. - * When key material is later created in this key slot, - * it will be saved to the specified persistent location. - * - * \retval #PSA_SUCCESS - * Success. The application can now use the value of `*handle` - * to access the newly allocated key slot. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_OCCUPIED_SLOT - * There is already a key with the identifier \p id in the storage - * area designated by \p lifetime. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * \p id is invalid for the specified lifetime. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \p lifetime is not supported. - * \retval #PSA_ERROR_NOT_PERMITTED - * \p lifetime is valid, but the application does not have the - * permission to create a key there. - */ -psa_status_t psa_create_key(psa_key_lifetime_t lifetime, - psa_key_id_t id, - psa_key_handle_t *handle); - -/** Close a key handle. - * - * If the handle designates a volatile key, destroy the key material and - * free all associated resources, just like psa_destroy_key(). - * - * If the handle designates a persistent key, free all resources associated - * with the key in volatile memory. The key slot in persistent storage is - * not affected and can be opened again later with psa_open_key(). - * - * \param handle The key handle to close. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - */ -psa_status_t psa_close_key(psa_key_handle_t handle); - -/**@}*/ - -/** \defgroup import_export Key import and export - * @{ - */ - -/** - * \brief Import a key in binary format. - * - * This function supports any output from psa_export_key(). Refer to the - * documentation of psa_export_public_key() for the format of public keys - * and to the documentation of psa_export_key() for the format for - * other key types. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * \param handle Handle to the slot where the key will be stored. - * It must have been obtained by calling - * psa_allocate_key() or psa_create_key() and must - * not contain key material yet. - * \param type Key type (a \c PSA_KEY_TYPE_XXX value). On a successful - * import, the key slot will contain a key of this type. - * \param[in] data Buffer containing the key data. The content of this - * buffer is interpreted according to \p type. It must - * contain the format described in the documentation - * of psa_export_key() or psa_export_public_key() for - * the chosen type. - * \param data_length Size of the \p data buffer in bytes. - * - * \retval #PSA_SUCCESS - * Success. - * If the key is persistent, the key material and the key's metadata - * have been saved to persistent storage. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_NOT_SUPPORTED - * The key type or key size is not supported, either by the - * implementation in general or in this particular slot. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid, - * or the key data is not correctly formatted. - * \retval #PSA_ERROR_OCCUPIED_SLOT - * There is already a key in the specified slot. - * \retval #PSA_ERROR_INSUFFICIENT_MEMORY - * \retval #PSA_ERROR_INSUFFICIENT_STORAGE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_import_key(psa_key_handle_t handle, - psa_key_type_t type, - const uint8_t *data, - size_t data_length); - -/** - * \brief Destroy a key. - * - * This function destroys the content of the key slot from both volatile - * memory and, if applicable, non-volatile storage. Implementations shall - * make a best effort to ensure that any previous content of the slot is - * unrecoverable. - * - * This function also erases any metadata such as policies and frees all - * resources associated with the key. - * - * \param handle Handle to the key slot to erase. - * - * \retval #PSA_SUCCESS - * The slot's content, if any, has been erased. - * \retval #PSA_ERROR_NOT_PERMITTED - * The slot holds content and cannot be erased because it is - * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * There was an failure in communication with the cryptoprocessor. - * The key material may still be present in the cryptoprocessor. - * \retval #PSA_ERROR_STORAGE_FAILURE - * The storage is corrupted. Implementations shall make a best effort - * to erase key material even in this stage, however applications - * should be aware that it may be impossible to guarantee that the - * key material is not recoverable in such cases. - * \retval #PSA_ERROR_TAMPERING_DETECTED - * An unexpected condition which is not a storage corruption or - * a communication failure occurred. The cryptoprocessor may have - * been compromised. - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_destroy_key(psa_key_handle_t handle); - -/** - * \brief Get basic metadata about a key. - * - * \param handle Handle to the key slot to query. - * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX value). - * This may be a null pointer, in which case the key type - * is not written. - * \param[out] bits On success, the key size in bits. - * This may be a null pointer, in which case the key size - * is not written. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT - * The handle is to a key slot which does not contain key material yet. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_get_key_information(psa_key_handle_t handle, - psa_key_type_t *type, - size_t *bits); - -/** - * \brief Export a key in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an equivalent object. - * - * If the implementation of psa_import_key() supports other formats - * beyond the format specified here, the output from psa_export_key() - * must use the representation specified here, not the original - * representation. - * - * For standard key types, the output format is as follows: - * - * - For symmetric keys (including MAC keys), the format is the - * raw bytes of the key. - * - For DES, the key data consists of 8 bytes. The parity bits must be - * correct. - * - For Triple-DES, the format is the concatenation of the - * two or three DES keys. - * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format - * is the non-encrypted DER encoding of the representation defined by - * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. - * ``` - * RSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * modulus INTEGER, -- n - * publicExponent INTEGER, -- e - * privateExponent INTEGER, -- d - * prime1 INTEGER, -- p - * prime2 INTEGER, -- q - * exponent1 INTEGER, -- d mod (p-1) - * exponent2 INTEGER, -- d mod (q-1) - * coefficient INTEGER, -- (inverse of q) mod p - * } - * ``` - * - For DSA private keys (#PSA_KEY_TYPE_DSA_KEYPAIR), the format - * is the non-encrypted DER encoding of the representation used by - * OpenSSL and OpenSSH, whose structure is described in ASN.1 as follows: - * ``` - * DSAPrivateKey ::= SEQUENCE { - * version INTEGER, -- must be 0 - * prime INTEGER, -- p - * subprime INTEGER, -- q - * generator INTEGER, -- g - * public INTEGER, -- y - * private INTEGER, -- x - * } - * ``` - * - For elliptic curve key pairs (key types for which - * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is - * a representation of the private value as a `ceiling(m/8)`-byte string - * where `m` is the bit size associated with the curve, i.e. the bit size - * of the order of the curve's coordinate field. This byte string is - * in little-endian order for Montgomery curves (curve types - * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass - * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` - * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). - * This is the content of the `privateKey` field of the `ECPrivateKey` - * format defined by RFC 5915. - * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is - * true), the format is the same as for psa_export_public_key(). - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT - * \retval #PSA_ERROR_NOT_PERMITTED - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/** - * \brief Export a public key or the public part of a key pair in binary format. - * - * The output of this function can be passed to psa_import_key() to - * create an object that is equivalent to the public key. - * - * This specification supports a single format for each key type. - * Implementations may support other formats as long as the standard - * format is supported. Implementations that support other formats - * should ensure that the formats are clearly unambiguous so as to - * minimize the risk that an invalid input is accidentally interpreted - * according to a different format. - * - * For standard key types, the output format is as follows: - * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of - * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. - * ``` - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * ``` - * - For elliptic curve public keys (key types for which - * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed - * representation defined by SEC1 §2.3.3 as the content of an ECPoint: - * Let `m` be the bit size associated with the curve, i.e. the bit size of - * `q` for a curve over `F_q`. The representation consists of: - * - The byte 0x04; - * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; - * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. - * - * For other public key types, the format is the DER representation defined by - * RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format - * specified below. - * ``` - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * ``` - * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), - * the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as - * `DSAPublicKey`, - * with the OID `id-dsa`, - * and with the parameters `DSS-Parms`. - * ``` - * id-dsa OBJECT IDENTIFIER ::= { - * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } - * - * Dss-Parms ::= SEQUENCE { - * p INTEGER, - * q INTEGER, - * g INTEGER } - * DSAPublicKey ::= INTEGER -- public key, Y - * ``` - * - * \param handle Handle to the key to export. - * \param[out] data Buffer where the key data is to be written. - * \param data_size Size of the \p data buffer in bytes. - * \param[out] data_length On success, the number of bytes - * that make up the key data. - * - * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key is neither a public key nor a key pair. - * \retval #PSA_ERROR_NOT_SUPPORTED - * \retval #PSA_ERROR_BUFFER_TOO_SMALL - * The size of the \p data buffer is too small. You can determine a - * sufficient buffer size by calling - * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(\c type), \c bits) - * where \c type is the key type - * and \c bits is the key size in bits. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \retval #PSA_ERROR_BAD_STATE - * The library has not been previously initialized by psa_crypto_init(). - * It is implementation-dependent whether a failure to initialize - * results in this error code. - */ -psa_status_t psa_export_public_key(psa_key_handle_t handle, - uint8_t *data, - size_t data_size, - size_t *data_length); - -/**@}*/ - /** \defgroup policy Key policies * @{ */ @@ -632,7 +193,7 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * the policy has been saved to persistent storage. Implementations * may defer saving the policy until the key material is created. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_OCCUPIED_SLOT + * \retval #PSA_ERROR_ALREADY_EXISTS * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_COMMUNICATION_FAILURE @@ -666,6 +227,511 @@ psa_status_t psa_get_key_policy(psa_key_handle_t handle, /**@}*/ +/** \defgroup key_management Key management + * @{ + */ + +/** \brief Retrieve the lifetime of an open key. + * + * \param handle Handle to query. + * \param[out] lifetime On success, the lifetime value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, + psa_key_lifetime_t *lifetime); + + +/** Allocate a key slot for a transient key, i.e. a key which is only stored + * in volatile memory. + * + * The allocated key slot and its handle remain valid until the + * application calls psa_close_key() or psa_destroy_key() or until the + * application terminates. + * + * \param[out] handle On success, a handle to a volatile key slot. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was not enough memory, or the maximum number of key slots + * has been reached. + */ +psa_status_t psa_allocate_key(psa_key_handle_t *handle); + +/** Open a handle to an existing persistent key. + * + * Open a handle to a key which was previously created with psa_create_key(). + * + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to a key slot which contains + * the data and metadata loaded from the specified + * persistent location. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \retval #PSA_ERROR_NOT_PERMITTED + * The specified key exists, but the application does not have the + * permission to access it. Note that this specification does not + * define any way to create such a key, but it may be possible + * through implementation-specific means. + */ +psa_status_t psa_open_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle); + +/** Create a new persistent key slot. + * + * Create a new persistent key slot and return a handle to it. The handle + * remains valid until the application calls psa_close_key() or terminates. + * The application can open the key again with psa_open_key() until it + * removes the key by calling psa_destroy_key(). + * + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the newly created key slot. + * When key material is later created in this key slot, + * it will be saved to the specified persistent location. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key with the identifier \p id in the storage + * area designated by \p lifetime. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \retval #PSA_ERROR_NOT_PERMITTED + * \p lifetime is valid, but the application does not have the + * permission to create a key there. + */ +psa_status_t psa_create_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle); + +/** Close a key handle. + * + * If the handle designates a volatile key, destroy the key material and + * free all associated resources, just like psa_destroy_key(). + * + * If the handle designates a persistent key, free all resources associated + * with the key in volatile memory. The key slot in persistent storage is + * not affected and can be opened again later with psa_open_key(). + * + * \param handle The key handle to close. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + */ +psa_status_t psa_close_key(psa_key_handle_t handle); + +/**@}*/ + +/** \defgroup import_export Key import and export + * @{ + */ + +/** + * \brief Import a key in binary format. + * + * This function supports any output from psa_export_key(). Refer to the + * documentation of psa_export_public_key() for the format of public keys + * and to the documentation of psa_export_key() for the format for + * other key types. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * \param handle Handle to the slot where the key will be stored. + * It must have been obtained by calling + * psa_allocate_key() or psa_create_key() and must + * not contain key material yet. + * \param type Key type (a \c PSA_KEY_TYPE_XXX value). On a successful + * import, the key slot will contain a key of this type. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to \p type. It must + * contain the format described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular slot. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key slot is invalid, + * or the key data is not correctly formatted. + * \retval #PSA_ERROR_ALREADY_EXISTS + * There is already a key in the specified slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_import_key(psa_key_handle_t handle, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +/** + * \brief Destroy a key. + * + * This function destroys the content of the key slot from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that any previous content of the slot is + * unrecoverable. + * + * This function also erases any metadata such as policies and frees all + * resources associated with the key. + * + * \param handle Handle to the key slot to erase. + * + * \retval #PSA_SUCCESS + * The slot's content, if any, has been erased. + * \retval #PSA_ERROR_NOT_PERMITTED + * The slot holds content and cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * There was an failure in communication with the cryptoprocessor. + * The key material may still be present in the cryptoprocessor. + * \retval #PSA_ERROR_STORAGE_FAILURE + * The storage is corrupted. Implementations shall make a best effort + * to erase key material even in this stage, however applications + * should be aware that it may be impossible to guarantee that the + * key material is not recoverable in such cases. + * \retval #PSA_ERROR_TAMPERING_DETECTED + * An unexpected condition which is not a storage corruption or + * a communication failure occurred. The cryptoprocessor may have + * been compromised. + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_destroy_key(psa_key_handle_t handle); + +/** + * \brief Get basic metadata about a key. + * + * \param handle Handle to the key slot to query. + * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX value). + * This may be a null pointer, in which case the key type + * is not written. + * \param[out] bits On success, the key size in bits. + * This may be a null pointer, in which case the key size + * is not written. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_DOES_NOT_EXIST + * The handle is to a key slot which does not contain key material yet. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_get_key_information(psa_key_handle_t handle, + psa_key_type_t *type, + size_t *bits); + +/** + * \brief Export a key in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an equivalent object. + * + * If the implementation of psa_import_key() supports other formats + * beyond the format specified here, the output from psa_export_key() + * must use the representation specified here, not the original + * representation. + * + * For standard key types, the output format is as follows: + * + * - For symmetric keys (including MAC keys), the format is the + * raw bytes of the key. + * - For DES, the key data consists of 8 bytes. The parity bits must be + * correct. + * - For Triple-DES, the format is the concatenation of the + * two or three DES keys. + * - For RSA key pairs (#PSA_KEY_TYPE_RSA_KEYPAIR), the format + * is the non-encrypted DER encoding of the representation defined by + * PKCS\#1 (RFC 8017) as `RSAPrivateKey`, version 0. + * ``` + * RSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * } + * ``` + * - For DSA private keys (#PSA_KEY_TYPE_DSA_KEYPAIR), the format + * is the non-encrypted DER encoding of the representation used by + * OpenSSL and OpenSSH, whose structure is described in ASN.1 as follows: + * ``` + * DSAPrivateKey ::= SEQUENCE { + * version INTEGER, -- must be 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * ``` + * - For elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEYPAIR is true), the format is + * a representation of the private value as a `ceiling(m/8)`-byte string + * where `m` is the bit size associated with the curve, i.e. the bit size + * of the order of the curve's coordinate field. This byte string is + * in little-endian order for Montgomery curves (curve types + * `PSA_ECC_CURVE_CURVEXXX`), and in big-endian order for Weierstrass + * curves (curve types `PSA_ECC_CURVE_SECTXXX`, `PSA_ECC_CURVE_SECPXXX` + * and `PSA_ECC_CURVE_BRAINPOOL_PXXX`). + * This is the content of the `privateKey` field of the `ECPrivateKey` + * format defined by RFC 5915. + * - For public keys (key types for which #PSA_KEY_TYPE_IS_PUBLIC_KEY is + * true), the format is the same as for psa_export_public_key(). + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(\c type, \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** + * \brief Export a public key or the public part of a key pair in binary format. + * + * The output of this function can be passed to psa_import_key() to + * create an object that is equivalent to the public key. + * + * This specification supports a single format for each key type. + * Implementations may support other formats as long as the standard + * format is supported. Implementations that support other formats + * should ensure that the formats are clearly unambiguous so as to + * minimize the risk that an invalid input is accidentally interpreted + * according to a different format. + * + * For standard key types, the output format is as follows: + * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), the DER encoding of + * the representation defined by RFC 3279 §2.3.1 as `RSAPublicKey`. + * ``` + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * ``` + * - For elliptic curve public keys (key types for which + * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), the format is the uncompressed + * representation defined by SEC1 §2.3.3 as the content of an ECPoint: + * Let `m` be the bit size associated with the curve, i.e. the bit size of + * `q` for a curve over `F_q`. The representation consists of: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian. + * + * For other public key types, the format is the DER representation defined by + * RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format + * specified below. + * ``` + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * ``` + * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), + * the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as + * `DSAPublicKey`, + * with the OID `id-dsa`, + * and with the parameters `DSS-Parms`. + * ``` + * id-dsa OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 1 } + * + * Dss-Parms ::= SEQUENCE { + * p INTEGER, + * q INTEGER, + * g INTEGER } + * DSAPublicKey ::= INTEGER -- public key, Y + * ``` + * + * \param handle Handle to the key to export. + * \param[out] data Buffer where the key data is to be written. + * \param data_size Size of the \p data buffer in bytes. + * \param[out] data_length On success, the number of bytes + * that make up the key data. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key is neither a public key nor a key pair. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p data buffer is too small. You can determine a + * sufficient buffer size by calling + * #PSA_KEY_EXPORT_MAX_SIZE(#PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(\c type), \c bits) + * where \c type is the key type + * and \c bits is the key size in bits. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * The library has not been previously initialized by psa_crypto_init(). + * It is implementation-dependent whether a failure to initialize + * results in this error code. + */ +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length); + +/** Make a copy of a key. + * + * Copy key material from one location to another. + * + * This function is primarily useful to copy a key from one location + * to another, since it populates a key using the material from + * another key which may have a different lifetime. + * + * In an implementation where slots have different ownerships, + * this function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * In this case \p constraint would typically prevent the recipient + * from exporting the key. + * + * The resulting key may only be used in a way that conforms to all + * three of: the policy of the source key, the policy previously set + * on the target, and the \p constraint parameter passed when calling + * this function. + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy, the previously-set target policy + * and the policy constraint. + * - If all three policies allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If one of the policies allows an algorithm and all the other policies + * either allow the same algorithm or a wildcard-based algorithm policy + * that includes this algorithm, the resulting key allows the same + * algorithm. + * + * The effect of this function on implementation-defined metadata is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a handle to an + * occupied slot. + * \param target_handle A handle to the target slot. It must not contain + * key material yet. + * \param[in] constraint An optional policy constraint. If this parameter + * is non-null then the resulting key will conform + * to this policy in addition to the source policy + * and the policy already present on the target + * slot. If this parameter is null then the + * function behaves in the same way as if it was + * the target policy, i.e. only the source and + * target policies apply. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_ALREADY_EXISTS + * \p target already contains key material. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * \p source does not contain key material. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source, on the target and + * \p constraints are incompatible. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key is not exportable and its lifetime does not + * allow copying it to the target's lifetime. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + psa_key_handle_t target_handle, + const psa_key_policy_t *constraint); + +/**@}*/ + /** \defgroup hash Message digests * @{ */ @@ -716,7 +782,7 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; */ static psa_hash_operation_t psa_hash_operation_init(void); -/** Start a multipart hash operation. +/** Set up a multipart hash operation. * * The sequence of operations to calculate a hash (message digest) * is as follows: @@ -750,6 +816,9 @@ static psa_hash_operation_t psa_hash_operation_init(void); * Success. * \retval #PSA_ERROR_NOT_SUPPORTED * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (already set up and not + * subsequently completed). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -771,7 +840,7 @@ psa_status_t psa_hash_setup(psa_hash_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -808,7 +877,7 @@ psa_status_t psa_hash_update(psa_hash_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p hash buffer is too small. You can determine a * sufficient buffer size by calling #PSA_HASH_SIZE(\c alg) @@ -848,7 +917,7 @@ psa_status_t psa_hash_finish(psa_hash_operation_t *operation, * The hash of the message was calculated successfully, but it * differs from the expected hash. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -966,7 +1035,7 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; */ static psa_mac_operation_t psa_mac_operation_init(void); -/** Start a multipart MAC calculation operation. +/** Set up a multipart MAC calculation operation. * * This function sets up the calculation of the MAC * (message authentication code) of a byte string. @@ -1005,7 +1074,7 @@ static psa_mac_operation_t psa_mac_operation_init(void); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. @@ -1016,6 +1085,9 @@ static psa_mac_operation_t psa_mac_operation_init(void); * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (already set up and not + * subsequently completed). + * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. @@ -1024,7 +1096,7 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, psa_key_handle_t handle, psa_algorithm_t alg); -/** Start a multipart MAC verification operation. +/** Set up a multipart MAC verification operation. * * This function sets up the verification of the MAC * (message authentication code) of a byte string against an expected value. @@ -1062,7 +1134,7 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key is not compatible with \c alg. @@ -1073,6 +1145,9 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (already set up and not + * subsequently completed). + * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. @@ -1096,7 +1171,7 @@ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -1135,7 +1210,7 @@ psa_status_t psa_mac_update(psa_mac_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p mac buffer is too small. You can determine a * sufficient buffer size by calling PSA_MAC_FINAL_SIZE(). @@ -1174,7 +1249,7 @@ psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, * The MAC of the message was calculated successfully, but it * differs from the expected MAC. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or already completed). + * The operation state is not valid (not set up, or already completed). * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE @@ -1307,7 +1382,7 @@ static psa_cipher_operation_t psa_cipher_operation_init(void); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. @@ -1318,6 +1393,9 @@ static psa_cipher_operation_t psa_cipher_operation_init(void); * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (already set up and not + * subsequently completed). + * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. @@ -1366,7 +1444,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. @@ -1377,6 +1455,9 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (already set up and not + * subsequently completed). + * \retval #PSA_ERROR_BAD_STATE * The library has not been previously initialized by psa_crypto_init(). * It is implementation-dependent whether a failure to initialize * results in this error code. @@ -1405,7 +1486,7 @@ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or IV already set). + * The operation state is not valid (not set up, or IV already set). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p iv buffer is too small. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -1439,7 +1520,7 @@ psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, or IV already set). + * The operation state is not valid (not set up, or IV already set). * \retval #PSA_ERROR_INVALID_ARGUMENT * The size of \p iv is not acceptable for the chosen algorithm, * or the chosen algorithm does not use an IV. @@ -1475,7 +1556,7 @@ psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, IV required but + * The operation state is not valid (not set up, IV required but * not set, or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. @@ -1513,7 +1594,7 @@ psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_BAD_STATE - * The operation state is not valid (not started, IV required but + * The operation state is not valid (not set up, IV required but * not set, or already completed). * \retval #PSA_ERROR_BUFFER_TOO_SMALL * The size of the \p output buffer is too small. @@ -1594,7 +1675,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \p key is not compatible with \p alg. @@ -1650,7 +1731,7 @@ psa_status_t psa_aead_encrypt(psa_key_handle_t handle, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. * \retval #PSA_ERROR_NOT_PERMITTED @@ -1968,7 +2049,7 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, * \param output_length Number of bytes to output. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY + * \retval #PSA_ERROR_INSUFFICIENT_DATA * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. @@ -2010,7 +2091,7 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * Success. * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. - * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY + * \retval #PSA_ERROR_INSUFFICIENT_DATA * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. @@ -2022,7 +2103,7 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * implementation in general or in this particular slot. * \retval #PSA_ERROR_BAD_STATE * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_OCCUPIED_SLOT + * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key in the specified slot. * \retval #PSA_ERROR_INSUFFICIENT_MEMORY * \retval #PSA_ERROR_INSUFFICIENT_STORAGE @@ -2106,7 +2187,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \c key is not compatible with \c alg, @@ -2167,7 +2248,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * \retval #PSA_SUCCESS * Success. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \c private_key is not compatible with \c alg, @@ -2266,7 +2347,7 @@ typedef struct { * If the key is persistent, the key material and the key's metadata * have been saved to persistent storage. * \retval #PSA_ERROR_INVALID_HANDLE - * \retval #PSA_ERROR_OCCUPIED_SLOT + * \retval #PSA_ERROR_ALREADY_EXISTS * There is already a key in the specified slot. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h index 7f08857942..96b478b7f4 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h @@ -111,7 +111,6 @@ void mbedtls_psa_crypto_free( void ); * \retval #PSA_ERROR_INVALID_ARGUMENT * \p seed_size is out of range. * \retval #PSA_ERROR_STORAGE_FAILURE - * \retval `PSA_ITS_ERROR_XXX` * There was a failure reading or writing from storage. * \retval #PSA_ERROR_NOT_PERMITTED * The library has already been initialized. It is no longer diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h index 50ca546fb6..42cdad32a4 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h @@ -49,4 +49,53 @@ /* Integral type representing a key handle. */ typedef uint16_t psa_key_handle_t; +/* This implementation distinguishes *application key identifiers*, which + * are the key identifiers specified by the application, from + * *key file identifiers*, which are the key identifiers that the library + * sees internally. The two types can be different if there is a remote + * call layer between the application and the library which supports + * multiple client applications that do not have access to each others' + * keys. The point of having different types is that the key file + * identifier may encode not only the key identifier specified by the + * application, but also the the identity of the application. + * + * Note that this is an internal concept of the library and the remote + * call layer. The application itself never sees anything other than + * #psa_app_key_id_t with its standard definition. + */ + +/* The application key identifier is always what the application sees as + * #psa_key_id_t. */ +typedef uint32_t psa_app_key_id_t; + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) + +#if defined(PSA_CRYPTO_SECURE) +/* Building for the PSA Crypto service on a PSA platform. */ +/* A key owner is a PSA partition identifier. */ +typedef int32_t psa_key_owner_id_t; +#endif + +typedef struct +{ + uint32_t key_id; + psa_key_owner_id_t owner; +} psa_key_file_id_t; +#define PSA_KEY_FILE_GET_KEY_ID( file_id ) ( ( file_id ).key_id ) + +/* Since crypto.h is used as part of the PSA Cryptography API specification, + * it must use standard types for things like the argument of psa_open_key(). + * If it wasn't for that constraint, psa_open_key() would take a + * `psa_key_file_id_t` argument. As a workaround, make `psa_key_id_t` an + * alias for `psa_key_file_id_t` when building for a multi-client service. */ +typedef psa_key_file_id_t psa_key_id_t; + +#else /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ + +/* By default, a key file identifier is just the application key identifier. */ +typedef psa_app_key_id_t psa_key_file_id_t; +#define PSA_KEY_FILE_GET_KEY_ID( id ) ( id ) + +#endif /* !MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER */ + #endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h index 0578664453..20cd4b45e1 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h @@ -754,7 +754,7 @@ typedef psa_status_t (*psa_drv_destroy_key_t)(psa_key_slot_t key); * that make up the key data. * * \retval #PSA_SUCCESS - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_COMMUNICATION_FAILURE diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h index 9ad0536295..34664fc10c 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h @@ -292,9 +292,9 @@ (plaintext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ 0) -#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ 11 /*PKCS#1v1.5*/) /** diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h index 9b44d6aef9..923b94ad4b 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h @@ -47,8 +47,13 @@ * This is either #PSA_SUCCESS (which is zero), indicating success, * or a nonzero value indicating that an error occurred. Errors are * encoded as one of the \c PSA_ERROR_xxx values defined here. + * If #PSA_SUCCESS is already defined, it means that #psa_status_t + * is also defined in an external header, so prevent its multiple + * definition. */ +#ifndef PSA_SUCCESS typedef int32_t psa_status_t; +#endif /**@}*/ @@ -85,7 +90,14 @@ typedef uint32_t psa_key_lifetime_t; /** Encoding of identifiers of persistent keys. */ +/* Implementation-specific quirk: The Mbed Crypto library can be built as + * part of a multi-client service that exposes the PSA Crypto API in each + * client and encodes the client identity in the key id argument of functions + * such as psa_open_key(). In this build configuration, we define + * psa_key_id_t in crypto_platform.h instead of here. */ +#if !defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) typedef uint32_t psa_key_id_t; +#endif /**@}*/ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h index acf856dd1b..d42d8c28a8 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h @@ -40,25 +40,17 @@ * @{ */ -#if !defined(PSA_SUCCESS) -/* If PSA_SUCCESS is defined, assume that PSA crypto is being used - * together with PSA IPC, which also defines the identifier - * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case; - * the other error code names don't clash. This is a temporary hack - * until we unify error reporting in PSA IPC and PSA crypto. - * - * Note that psa_defs.h must be included before this header! - */ +/* PSA error codes */ + /** The action was completed successfully. */ #define PSA_SUCCESS ((psa_status_t)0) -#endif /* !defined(PSA_SUCCESS) */ /** An error occurred that does not correspond to any defined * failure cause. * * Implementations may use this error code if none of the other standard * error codes are applicable. */ -#define PSA_ERROR_UNKNOWN_ERROR ((psa_status_t)1) +#define PSA_ERROR_GENERIC_ERROR ((psa_status_t)-132) /** The requested operation or a parameter is not supported * by this implementation. @@ -67,7 +59,7 @@ * parameter such as a key type, algorithm, etc. is not recognized. * If a combination of parameters is recognized and identified as * not valid, return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)2) +#define PSA_ERROR_NOT_SUPPORTED ((psa_status_t)-134) /** The requested action is denied by a policy. * @@ -80,7 +72,7 @@ * not valid or not supported, it is unspecified whether the function * returns #PSA_ERROR_NOT_PERMITTED, #PSA_ERROR_NOT_SUPPORTED or * #PSA_ERROR_INVALID_ARGUMENT. */ -#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)3) +#define PSA_ERROR_NOT_PERMITTED ((psa_status_t)-133) /** An output buffer is too small. * @@ -92,23 +84,19 @@ * buffer would succeed. However implementations may return this * error if a function has invalid or unsupported parameters in addition * to the parameters that determine the necessary output buffer size. */ -#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)4) +#define PSA_ERROR_BUFFER_TOO_SMALL ((psa_status_t)-138) -/** A slot is occupied, but must be empty to carry out the - * requested action. +/** Asking for an item that already exists * - * If a handle is invalid, it does not designate an occupied slot. - * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. - */ -#define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5) + * Implementations should return this error, when attempting + * to write an item (like a key) that already exists. */ +#define PSA_ERROR_ALREADY_EXISTS ((psa_status_t)-139) -/** A slot is empty, but must be occupied to carry out the - * requested action. +/** Asking for an item that doesn't exist * - * If a handle is invalid, it does not designate an empty slot. - * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. - */ -#define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6) + * Implementations should return this error, if a requested item (like + * a key) does not exist. */ +#define PSA_ERROR_DOES_NOT_EXIST ((psa_status_t)-140) /** The requested action cannot be performed in the current state. * @@ -118,9 +106,9 @@ * * Implementations shall not return this error code to indicate * that a key slot is occupied when it needs to be free or vice versa, - * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT + * but shall return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST * as applicable. */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)7) +#define PSA_ERROR_BAD_STATE ((psa_status_t)-137) /** The parameters passed to the function are invalid. * @@ -129,20 +117,20 @@ * * Implementations shall not return this error code to indicate * that a key slot is occupied when it needs to be free or vice versa, - * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT + * but shall return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST * as applicable. * * Implementation shall not return this error code to indicate that a * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE * instead. */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8) +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)-135) /** There is not enough runtime memory. * * If the action is carried out across multiple security realms, this * error can refer to available memory in any of the security realms. */ -#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)9) +#define PSA_ERROR_INSUFFICIENT_MEMORY ((psa_status_t)-141) /** There is not enough persistent storage. * @@ -151,7 +139,7 @@ * many functions that do not otherwise access storage may return this * error code if the implementation requires a mandatory log entry for * the requested action and the log storage space is full. */ -#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)10) +#define PSA_ERROR_INSUFFICIENT_STORAGE ((psa_status_t)-142) /** There was a communication failure inside the implementation. * @@ -168,7 +156,7 @@ * cryptoprocessor but there was a breakdown of communication before * the cryptoprocessor could report the status to the application. */ -#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)11) +#define PSA_ERROR_COMMUNICATION_FAILURE ((psa_status_t)-145) /** There was a storage failure that may have led to data loss. * @@ -193,13 +181,13 @@ * permanent storage corruption. However application writers should * keep in mind that transient errors while reading the storage may be * reported using this error code. */ -#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)12) +#define PSA_ERROR_STORAGE_FAILURE ((psa_status_t)-146) /** A hardware failure was detected. * * A hardware failure may be transient or permanent depending on the * cause. */ -#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)13) +#define PSA_ERROR_HARDWARE_FAILURE ((psa_status_t)-147) /** A tampering attempt was detected. * @@ -230,7 +218,7 @@ * This error indicates an attack against the application. Implementations * shall not return this error code as a consequence of the behavior of * the application itself. */ -#define PSA_ERROR_TAMPERING_DETECTED ((psa_status_t)14) +#define PSA_ERROR_TAMPERING_DETECTED ((psa_status_t)-151) /** There is not enough entropy to generate random data needed * for the requested action. @@ -249,7 +237,7 @@ * secure pseudorandom generator (PRNG). However implementations may return * this error at any time if a policy requires the PRNG to be reseeded * during normal operation. */ -#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)15) +#define PSA_ERROR_INSUFFICIENT_ENTROPY ((psa_status_t)-148) /** The signature, MAC or hash is incorrect. * @@ -259,7 +247,7 @@ * * If the value to verify has an invalid size, implementations may return * either #PSA_ERROR_INVALID_ARGUMENT or #PSA_ERROR_INVALID_SIGNATURE. */ -#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)16) +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) /** The decrypted padding is incorrect. * @@ -275,17 +263,15 @@ * as close as possible to indistinguishable to an external observer. * In particular, the timing of a decryption operation should not * depend on the validity of the padding. */ -#define PSA_ERROR_INVALID_PADDING ((psa_status_t)17) +#define PSA_ERROR_INVALID_PADDING ((psa_status_t)-150) -/** The generator has insufficient capacity left. - * - * Once a function returns this error, attempts to read from the - * generator will always return this error. */ -#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18) +/** Return this error when there's insufficient data when attempting + * to read from a resource. */ +#define PSA_ERROR_INSUFFICIENT_DATA ((psa_status_t)-143) /** The key handle is not valid. */ -#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)19) +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) /**@}*/ @@ -766,7 +752,7 @@ * algorithm is considered identical to the untruncated algorithm * for policy comparison purposes. * - * \param alg A MAC algorithm identifier (value of type + * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) * is true). This may be a truncated or untruncated * MAC algorithm. @@ -782,14 +768,14 @@ * MAC algorithm or if \p mac_length is too small or * too large for the specified MAC algorithm. */ -#define PSA_ALG_TRUNCATED_MAC(alg, mac_length) \ - (((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ +#define PSA_ALG_TRUNCATED_MAC(mac_alg, mac_length) \ + (((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ ((mac_length) << PSA_MAC_TRUNCATION_OFFSET & PSA_ALG_MAC_TRUNCATION_MASK)) /** Macro to build the base MAC algorithm corresponding to a truncated * MAC algorithm. * - * \param alg A MAC algorithm identifier (value of type + * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) * is true). This may be a truncated or untruncated * MAC algorithm. @@ -798,12 +784,12 @@ * \return Unspecified if \p alg is not a supported * MAC algorithm. */ -#define PSA_ALG_FULL_LENGTH_MAC(alg) \ - ((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) /** Length to which a MAC algorithm is truncated. * - * \param alg A MAC algorithm identifier (value of type + * \param mac_alg A MAC algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) * is true). * @@ -812,8 +798,8 @@ * \return Unspecified if \p alg is not a supported * MAC algorithm. */ -#define PSA_MAC_TRUNCATED_LENGTH(alg) \ - (((alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) +#define PSA_MAC_TRUNCATED_LENGTH(mac_alg) \ + (((mac_alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) #define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) #define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) @@ -910,7 +896,7 @@ * Depending on the algorithm, the tag length may affect the calculation * of the ciphertext. * - * \param alg A AEAD algorithm identifier (value of type + * \param aead_alg An AEAD algorithm identifier (value of type * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p alg) * is true). * \param tag_length Desired length of the authentication tag in bytes. @@ -921,26 +907,26 @@ * AEAD algorithm or if \p tag_length is not valid * for the specified AEAD algorithm. */ -#define PSA_ALG_AEAD_WITH_TAG_LENGTH(alg, tag_length) \ - (((alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ +#define PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, tag_length) \ + (((aead_alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ PSA_ALG_AEAD_TAG_LENGTH_MASK)) /** Calculate the corresponding AEAD algorithm with the default tag length. * - * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param aead_alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). * - * \return The corresponding AEAD algorithm with the default tag length - * for that algorithm. + * \return The corresponding AEAD algorithm with the default + * tag length for that algorithm. */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) \ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ ( \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_CCM) \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_GCM) \ + PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, PSA_ALG_CCM) \ + PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, PSA_ALG_GCM) \ 0) -#define PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(alg, 0) == \ +#define PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(aead_alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(aead_alg, 0) == \ PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ ref : diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c index 7fb1adb295..cfa07a6eee 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c @@ -26,22 +26,8 @@ #endif #if defined(MBEDTLS_PSA_CRYPTO_C) -/* - * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM - * (Secure Partition Manager) integration which separates the code into two - * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing - * Environment). When building for the SPE, an additional header file should be - * included. - */ -#if defined(MBEDTLS_PSA_CRYPTO_SPM) -/* - * PSA_CRYPTO_SECURE means that this file is compiled for the SPE. - * Some headers will be affected by this flag. - */ -#define PSA_CRYPTO_SECURE 1 -#include "crypto_spe.h" -#endif +#include "psa_crypto_service_integration.h" #include "psa/crypto.h" #include "psa_crypto_core.h" @@ -172,13 +158,21 @@ static psa_status_t mbedtls_to_psa_error( int ret ) case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL: return( PSA_ERROR_BUFFER_TOO_SMALL ); +#if defined(MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA) + case MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) case MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH: +#endif case MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH: return( PSA_ERROR_NOT_SUPPORTED ); case MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED: return( PSA_ERROR_HARDWARE_FAILURE ); +#if defined(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA) + case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA: +#elif defined(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) case MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH: +#endif case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH: return( PSA_ERROR_NOT_SUPPORTED ); case MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED: @@ -346,7 +340,7 @@ static psa_status_t mbedtls_to_psa_error( int ret ) return( PSA_ERROR_HARDWARE_FAILURE ); default: - return( PSA_ERROR_UNKNOWN_ERROR ); + return( PSA_ERROR_GENERIC_ERROR ); } } @@ -742,12 +736,38 @@ static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, return( status ); if( slot->type != PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_OCCUPIED_SLOT ); + return( PSA_ERROR_ALREADY_EXISTS ); *p_slot = slot; return( status ); } +/** Calculate the intersection of two algorithm usage policies. + * + * Return 0 (which allows no operation) on incompatibility. + */ +static psa_algorithm_t psa_key_policy_algorithm_intersection( + psa_algorithm_t alg1, + psa_algorithm_t alg2 ) +{ + /* Common case: the policy only allows alg. */ + if( alg1 == alg2 ) + return( alg1 ); + /* If the policies are from the same hash-and-sign family, check + * if one is a wildcard. If so the other has the specific algorithm. */ + if( PSA_ALG_IS_HASH_AND_SIGN( alg1 ) && + PSA_ALG_IS_HASH_AND_SIGN( alg2 ) && + ( alg1 & ~PSA_ALG_HASH_MASK ) == ( alg2 & ~PSA_ALG_HASH_MASK ) ) + { + if( PSA_ALG_SIGN_GET_HASH( alg1 ) == PSA_ALG_ANY_HASH ) + return( alg2 ); + if( PSA_ALG_SIGN_GET_HASH( alg2 ) == PSA_ALG_ANY_HASH ) + return( alg1 ); + } + /* If the policies are incompatible, allow nothing. */ + return( 0 ); +} + /** Test whether a policy permits an algorithm. * * The caller must test usage flags separately. @@ -771,6 +791,31 @@ static int psa_key_policy_permits( const psa_key_policy_t *policy, return( 0 ); } +/** Restrict a key policy based on a constraint. + * + * \param[in,out] policy The policy to restrict. + * \param[in] constraint The policy constraint to apply. + * + * \retval #PSA_SUCCESS + * \c *policy contains the intersection of the original value of + * \c *policy and \c *constraint. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c *policy and \c *constraint are incompatible. + * \c *policy is unchanged. + */ +static psa_status_t psa_restrict_key_policy( + psa_key_policy_t *policy, + const psa_key_policy_t *constraint ) +{ + psa_algorithm_t intersection_alg = + psa_key_policy_algorithm_intersection( policy->alg, constraint->alg ); + if( intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + policy->usage &= constraint->usage; + policy->alg = intersection_alg; + return( PSA_SUCCESS ); +} + /** Retrieve a slot which must contain a key. The key must have allow all the * usage flags set in \p usage. If \p alg is nonzero, the key must allow * operations with this algorithm. */ @@ -788,7 +833,7 @@ static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, if( status != PSA_SUCCESS ) return( status ); if( slot->type == PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_EMPTY_SLOT ); + return( PSA_ERROR_DOES_NOT_EXIST ); /* Enforce that usage policy for the key slot contains all the flags * required by the usage parameter. There is one exception: public @@ -950,7 +995,7 @@ psa_status_t psa_get_key_information( psa_key_handle_t handle, return( status ); if( slot->type == PSA_KEY_TYPE_NONE ) - return( PSA_ERROR_EMPTY_SLOT ); + return( PSA_ERROR_DOES_NOT_EXIST ); if( type != NULL ) *type = slot->type; if( bits != NULL ) @@ -974,11 +1019,11 @@ static int pk_write_pubkey_simple( mbedtls_pk_context *key, } #endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */ -static psa_status_t psa_internal_export_key( psa_key_slot_t *slot, - uint8_t *data, - size_t data_size, - size_t *data_length, - int export_public_key ) +static psa_status_t psa_internal_export_key( const psa_key_slot_t *slot, + uint8_t *data, + size_t data_size, + size_t *data_length, + int export_public_key ) { *data_length = 0; @@ -1165,6 +1210,65 @@ exit: } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ +static psa_status_t psa_copy_key_material( const psa_key_slot_t *source, + psa_key_handle_t target ) +{ + psa_status_t status; + uint8_t *buffer = NULL; + size_t buffer_size = 0; + size_t length; + + buffer_size = PSA_KEY_EXPORT_MAX_SIZE( source->type, + psa_get_key_bits( source ) ); + buffer = mbedtls_calloc( 1, buffer_size ); + if( buffer == NULL && buffer_size != 0 ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + status = psa_internal_export_key( source, buffer, buffer_size, &length, 0 ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_import_key( target, source->type, buffer, length ); + +exit: + if( buffer_size != 0 ) + mbedtls_platform_zeroize( buffer, buffer_size ); + mbedtls_free( buffer ); + return( status ); +} + +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + psa_key_handle_t target_handle, + const psa_key_policy_t *constraint) +{ + psa_key_slot_t *source_slot = NULL; + psa_key_slot_t *target_slot = NULL; + psa_key_policy_t new_policy; + psa_status_t status; + status = psa_get_key_from_slot( source_handle, &source_slot, 0, 0 ); + if( status != PSA_SUCCESS ) + return( status ); + status = psa_get_empty_key_slot( target_handle, &target_slot ); + if( status != PSA_SUCCESS ) + return( status ); + + new_policy = target_slot->policy; + status = psa_restrict_key_policy( &new_policy, &source_slot->policy ); + if( status != PSA_SUCCESS ) + return( status ); + if( constraint != NULL ) + { + status = psa_restrict_key_policy( &new_policy, constraint ); + if( status != PSA_SUCCESS ) + return( status ); + } + + status = psa_copy_key_material( source_slot, target_handle ); + if( status != PSA_SUCCESS ) + return( status ); + + target_slot->policy = new_policy; + return( PSA_SUCCESS ); +} + /****************************************************************/ @@ -2988,7 +3092,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, size_t output_size, size_t *output_length ) { - psa_status_t status = PSA_ERROR_UNKNOWN_ERROR; + psa_status_t status = PSA_ERROR_GENERIC_ERROR; int cipher_ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH]; @@ -3511,6 +3615,12 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, size_t *capacity) { + if( generator->alg == 0 ) + { + /* This is a blank generator. */ + return PSA_ERROR_BAD_STATE; + } + *capacity = generator->capacity; return( PSA_SUCCESS ); } @@ -3740,24 +3850,29 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, { psa_status_t status; + if( generator->alg == 0 ) + { + /* This is a blank generator. */ + return PSA_ERROR_BAD_STATE; + } + if( output_length > generator->capacity ) { generator->capacity = 0; /* Go through the error path to wipe all confidential data now * that the generator object is useless. */ - status = PSA_ERROR_INSUFFICIENT_CAPACITY; + status = PSA_ERROR_INSUFFICIENT_DATA; goto exit; } - if( output_length == 0 && - generator->capacity == 0 && generator->alg == 0 ) + if( output_length == 0 && generator->capacity == 0 ) { - /* Edge case: this is a blank or finished generator, and 0 - * bytes were requested. The right error in this case could + /* Edge case: this is a finished generator, and 0 bytes + * were requested. The right error in this case could * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return * INSUFFICIENT_CAPACITY, which is right for a finished * generator, for consistency with the case when * output_length > 0. */ - return( PSA_ERROR_INSUFFICIENT_CAPACITY ); + return( PSA_ERROR_INSUFFICIENT_DATA ); } generator->capacity -= output_length; @@ -3801,7 +3916,13 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, exit: if( status != PSA_SUCCESS ) { + /* Preserve the algorithm upon errors, but clear all sensitive state. + * This allows us to differentiate between exhausted generators and + * blank generators, so we can return PSA_ERROR_BAD_STATE on blank + * generators. */ + psa_algorithm_t alg = generator->alg; psa_generator_abort( generator ); + generator->alg = alg; memset( output, '!', output_length ); } return( status ); @@ -4281,45 +4402,11 @@ psa_status_t psa_generate_random( uint8_t *output, #if ( defined(MBEDTLS_ENTROPY_NV_SEED) && defined(MBEDTLS_PSA_HAS_ITS_IO) ) -/* Support function for error conversion between psa_its error codes to psa crypto */ -static psa_status_t its_to_psa_error( psa_its_status_t ret ) -{ - switch( ret ) - { - case PSA_ITS_SUCCESS: - return( PSA_SUCCESS ); - - case PSA_ITS_ERROR_UID_NOT_FOUND: - return( PSA_ERROR_EMPTY_SLOT ); - - case PSA_ITS_ERROR_STORAGE_FAILURE: - return( PSA_ERROR_STORAGE_FAILURE ); - - case PSA_ITS_ERROR_INSUFFICIENT_SPACE: - return( PSA_ERROR_INSUFFICIENT_STORAGE ); - - case PSA_ITS_ERROR_OFFSET_INVALID: - case PSA_ITS_ERROR_INCORRECT_SIZE: - case PSA_ITS_ERROR_INVALID_ARGUMENTS: - return( PSA_ERROR_INVALID_ARGUMENT ); - - case PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED: - return( PSA_ERROR_NOT_SUPPORTED ); - - case PSA_ITS_ERROR_WRITE_ONCE: - return( PSA_ERROR_OCCUPIED_SLOT ); - - default: - return( PSA_ERROR_UNKNOWN_ERROR ); - } -} - psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, size_t seed_size ) { psa_status_t status; - psa_its_status_t its_status; - struct psa_its_info_t p_info; + struct psa_storage_info_t p_info; if( global_data.initialized ) return( PSA_ERROR_NOT_PERMITTED ); @@ -4328,15 +4415,13 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, ( seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) ) return( PSA_ERROR_INVALID_ARGUMENT ); - its_status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); - status = its_to_psa_error( its_status ); + status = psa_its_get_info( PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info ); - if( PSA_ITS_ERROR_UID_NOT_FOUND == its_status ) /* No seed exists */ + if( PSA_ERROR_DOES_NOT_EXIST == status ) /* No seed exists */ { - its_status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); - status = its_to_psa_error( its_status ); + status = psa_its_set( PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0 ); } - else if( PSA_ITS_SUCCESS == its_status ) + else if( PSA_SUCCESS == status ) { /* You should not be here. Seed needs to be injected only once */ status = PSA_ERROR_NOT_PERMITTED; diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h index c289681973..0f75624597 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h @@ -41,7 +41,7 @@ typedef struct psa_key_type_t type; psa_key_policy_t policy; psa_key_lifetime_t lifetime; - psa_key_id_t persistent_storage_id; + psa_key_file_id_t persistent_storage_id; unsigned allocated : 1; union { diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h new file mode 100644 index 0000000000..938bfe1dec --- /dev/null +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_service_integration.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2019, 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SERVICE_INTEGRATION_H +#define PSA_CRYPTO_SERVICE_INTEGRATION_H + +/* + * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM + * (Secure Partition Manager) integration which separates the code into two + * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing + * Environment). When building for the SPE, an additional header file should be + * included. + */ +#if defined(MBEDTLS_PSA_CRYPTO_SPM) +/* + * PSA_CRYPTO_SECURE means that the file which included this file is being + * compiled for SPE. The files crypto_structs.h and crypto_types.h have + * different implementations for NSPE and SPE and are compiled according to this + * flag. + */ +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif // MBEDTLS_PSA_CRYPTO_SPM + +#endif // PSA_CRYPTO_SERVICE_INTEGRATION_H diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c index c151c5eee7..33c03a7991 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c @@ -26,22 +26,8 @@ #endif #if defined(MBEDTLS_PSA_CRYPTO_C) -/* - * When MBEDTLS_PSA_CRYPTO_SPM is defined, the code is being built for SPM - * (Secure Partition Manager) integration which separates the code into two - * parts: NSPE (Non-Secure Processing Environment) and SPE (Secure Processing - * Environment). When building for the SPE, an additional header file should be - * included. - */ -#if defined(MBEDTLS_PSA_CRYPTO_SPM) -/* - * PSA_CRYPTO_SECURE means that this file is compiled for the SPE. - * Some headers will be affected by this flag. - */ -#define PSA_CRYPTO_SECURE 1 -#include "crypto_spe.h" -#endif +#include "psa_crypto_service_integration.h" #include "psa/crypto.h" #include "psa_crypto_core.h" @@ -182,6 +168,30 @@ exit: psa_free_persistent_key_data( key_data, key_data_length ); return( status ); } + +/** Check whether a key identifier is acceptable. + * + * For backward compatibility, key identifiers that were valid in a + * past released version must remain valid, unless a migration path + * is provided. + * + * \param file_id The key identifier to check. + * + * \return 1 if \p file_id is acceptable, otherwise 0. + */ +static int psa_is_key_id_valid( psa_key_file_id_t file_id ) +{ + psa_app_key_id_t key_id = PSA_KEY_FILE_GET_KEY_ID( file_id ); + /* Reject id=0 because by general library conventions, 0 is an invalid + * value wherever possible. */ + if( key_id == 0 ) + return( 0 ); + /* Reject high values because the file names are reserved for the + * library's internal use. */ + if( key_id > PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) + return( 0 ); + return( 1 ); +} #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ /** Declare a slot as persistent and load it from storage. @@ -194,7 +204,7 @@ exit: * * \retval #PSA_SUCCESS * The slot content was loaded successfully. - * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_DOES_NOT_EXIST * There is no content for this slot in persistent storage. * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -203,19 +213,13 @@ exit: * \retval #PSA_ERROR_STORAGE_FAILURE */ static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, - psa_key_id_t id ) + psa_key_file_id_t id ) { #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) psa_key_slot_t *slot; psa_status_t status; - /* Reject id=0 because by general library conventions, 0 is an invalid - * value wherever possible. */ - if( id == 0 ) - return( PSA_ERROR_INVALID_ARGUMENT ); - /* Reject high values because the file names are reserved for the - * library's internal use. */ - if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) + if( ! psa_is_key_id_valid( id ) ) return( PSA_ERROR_INVALID_ARGUMENT ); status = psa_get_key_slot( handle, &slot ); @@ -236,7 +240,7 @@ static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, } static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime, - psa_key_id_t id, + psa_key_file_id_t id, psa_key_handle_t *handle, psa_status_t wanted_load_status ) { @@ -261,24 +265,24 @@ static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime, } psa_status_t psa_open_key( psa_key_lifetime_t lifetime, - psa_key_id_t id, + psa_key_file_id_t id, psa_key_handle_t *handle ) { return( persistent_key_setup( lifetime, id, handle, PSA_SUCCESS ) ); } psa_status_t psa_create_key( psa_key_lifetime_t lifetime, - psa_key_id_t id, + psa_key_file_id_t id, psa_key_handle_t *handle ) { psa_status_t status; status = persistent_key_setup( lifetime, id, handle, - PSA_ERROR_EMPTY_SLOT ); + PSA_ERROR_DOES_NOT_EXIST ); switch( status ) { - case PSA_SUCCESS: return( PSA_ERROR_OCCUPIED_SLOT ); - case PSA_ERROR_EMPTY_SLOT: return( PSA_SUCCESS ); + case PSA_SUCCESS: return( PSA_ERROR_ALREADY_EXISTS ); + case PSA_ERROR_DOES_NOT_EXIST: return( PSA_SUCCESS ); default: return( status ); } } diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c index 687269b079..84a6ed5585 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c @@ -30,6 +30,7 @@ #include #include +#include "psa_crypto_service_integration.h" #include "psa/crypto.h" #include "psa_crypto_storage.h" #include "psa_crypto_storage_backend.h" @@ -38,6 +39,7 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#include #define mbedtls_calloc calloc #define mbedtls_free free #endif @@ -147,7 +149,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, return( PSA_SUCCESS ); } -psa_status_t psa_save_persistent_key( const psa_key_id_t key, +psa_status_t psa_save_persistent_key( const psa_key_file_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -185,7 +187,7 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) mbedtls_free( key_data ); } -psa_status_t psa_load_persistent_key( psa_key_id_t key, +psa_status_t psa_load_persistent_key( psa_key_file_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h index 85881c1644..7e5aae9f98 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h @@ -59,7 +59,7 @@ extern "C" { * This limitation will probably become moot when we implement client * separation for key storage. */ -#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xffff0000 +#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER 0xfffeffff /** * \brief Format key data and metadata and save to a location for given key @@ -84,9 +84,9 @@ extern "C" { * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_OCCUPIED_SLOT + * \retval PSA_ERROR_ALREADY_EXISTS */ -psa_status_t psa_save_persistent_key( const psa_key_id_t key, +psa_status_t psa_save_persistent_key( const psa_key_file_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -115,9 +115,9 @@ psa_status_t psa_save_persistent_key( const psa_key_id_t key, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_EMPTY_SLOT + * \retval PSA_ERROR_DOES_NOT_EXIST */ -psa_status_t psa_load_persistent_key( psa_key_id_t key, +psa_status_t psa_load_persistent_key( psa_key_file_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, @@ -134,7 +134,7 @@ psa_status_t psa_load_persistent_key( psa_key_id_t key, * or the key did not exist. * \retval PSA_ERROR_STORAGE_FAILURE */ -psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ); +psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ); /** * \brief Free the temporary buffer allocated by psa_load_persistent_key(). diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h index 47896b8726..dd534d2ff1 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h @@ -54,9 +54,9 @@ extern "C" { * * \retval PSA_SUCCESS * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_EMPTY_SLOT + * \retval PSA_ERROR_DOES_NOT_EXIST */ -psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, uint8_t *data, size_t data_size ); /** @@ -73,9 +73,9 @@ psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE - * \retval PSA_ERROR_OCCUPIED_SLOT + * \retval PSA_ERROR_ALREADY_EXISTS */ -psa_status_t psa_crypto_storage_store( const psa_key_id_t key, +psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key, const uint8_t *data, size_t data_length ); @@ -92,7 +92,7 @@ psa_status_t psa_crypto_storage_store( const psa_key_id_t key, * \retval 1 * Persistent data present for slot number */ -int psa_is_key_present_in_storage( const psa_key_id_t key ); +int psa_is_key_present_in_storage( const psa_key_file_id_t key ); /** * \brief Get data length for given key slot number. @@ -104,7 +104,7 @@ int psa_is_key_present_in_storage( const psa_key_id_t key ); * \retval PSA_SUCCESS * \retval PSA_ERROR_STORAGE_FAILURE */ -psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_file_id_t key, size_t *data_length ); diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c index 87420be98a..c4a534fe36 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c @@ -36,6 +36,7 @@ #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else +#include #define mbedtls_snprintf snprintf #endif @@ -48,7 +49,7 @@ enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 }; -static void key_id_to_location( const psa_key_id_t key, +static void key_id_to_location( const psa_key_file_id_t key, char *location, size_t location_size ) { @@ -57,7 +58,7 @@ static void key_id_to_location( const psa_key_id_t key, (unsigned long) key ); } -psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, uint8_t *data, size_t data_size ) { psa_status_t status = PSA_SUCCESS; @@ -82,7 +83,7 @@ exit: return( status ); } -int psa_is_key_present_in_storage( const psa_key_id_t key ) +int psa_is_key_present_in_storage( const psa_key_file_id_t key ) { char slot_location[MAX_LOCATION_LEN]; FILE *file; @@ -100,7 +101,7 @@ int psa_is_key_present_in_storage( const psa_key_id_t key ) return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_id_t key, +psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key, const uint8_t *data, size_t data_length ) { @@ -118,7 +119,7 @@ psa_status_t psa_crypto_storage_store( const psa_key_id_t key, key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); if( psa_is_key_present_in_storage( key ) == 1 ) - return( PSA_ERROR_OCCUPIED_SLOT ); + return( PSA_ERROR_ALREADY_EXISTS ); file = fopen( temp_location, "wb" ); if( file == NULL ) @@ -155,7 +156,7 @@ exit: return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ) { FILE *file; char slot_location[MAX_LOCATION_LEN]; @@ -174,7 +175,7 @@ psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_file_id_t key, size_t *data_length ) { psa_status_t status = PSA_SUCCESS; @@ -186,7 +187,7 @@ psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, file = fopen( slot_location, "rb" ); if( file == NULL ) - return( PSA_ERROR_EMPTY_SLOT ); + return( PSA_ERROR_DOES_NOT_EXIST ); if( fseek( file, 0, SEEK_END ) != 0 ) { diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c index 1873c69ccb..447c0aebb4 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c @@ -27,6 +27,8 @@ #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C) +#include "psa/error.h" +#include "psa_crypto_service_integration.h" #include "psa/crypto.h" #include "psa_crypto_storage_backend.h" #include "psa/internal_trusted_storage.h" @@ -35,96 +37,77 @@ #include "mbedtls/platform.h" #endif -static psa_status_t its_to_psa_error( psa_its_status_t ret ) +/* Determine a file name (ITS file identifier) for the given key file + * identifier. The file name must be distinct from any file that is used + * for a purpose other than storing a key. Currently, the only such file + * is the random seed file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID + * and whose value is 0xFFFFFF52. */ +static psa_storage_uid_t psa_its_identifier_of_slot( psa_key_file_id_t file_id ) { - switch( ret ) - { - case PSA_ITS_SUCCESS: - return( PSA_SUCCESS ); - - case PSA_ITS_ERROR_UID_NOT_FOUND: - return( PSA_ERROR_EMPTY_SLOT ); - - case PSA_ITS_ERROR_STORAGE_FAILURE: - return( PSA_ERROR_STORAGE_FAILURE ); - - case PSA_ITS_ERROR_INSUFFICIENT_SPACE: - return( PSA_ERROR_INSUFFICIENT_STORAGE ); - - case PSA_ITS_ERROR_OFFSET_INVALID: - case PSA_ITS_ERROR_INCORRECT_SIZE: - case PSA_ITS_ERROR_INVALID_ARGUMENTS: - return( PSA_ERROR_INVALID_ARGUMENT ); - - case PSA_ITS_ERROR_FLAGS_NOT_SUPPORTED: - return( PSA_ERROR_NOT_SUPPORTED ); - - case PSA_ITS_ERROR_WRITE_ONCE: - return( PSA_ERROR_OCCUPIED_SLOT ); - - default: - return( PSA_ERROR_UNKNOWN_ERROR ); - } +#if defined(MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER) && \ + defined(PSA_CRYPTO_SECURE) + /* Encode the owner in the upper 32 bits. This means that if + * owner values are nonzero (as they are on a PSA platform), + * no key file will ever have a value less than 0x100000000, so + * the whole range 0..0xffffffff is available for non-key files. */ + uint32_t unsigned_owner = (uint32_t) file_id.owner; + return( (uint64_t) unsigned_owner << 32 | file_id.key_id ); +#else + /* Use the key id directly as a file name. + * psa_is_key_file_id_valid() in psa_crypto_slot_management.c + * is responsible for ensuring that key identifiers do not have a + * value that is reserved for non-key files. */ + return( file_id ); +#endif } -static psa_its_uid_t psa_its_identifier_of_slot( psa_key_id_t key ) -{ - return( key ); -} - -psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_file_id_t key, uint8_t *data, size_t data_size ) { - psa_its_status_t ret; psa_status_t status; - psa_its_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_its_info_t data_identifier_info; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - status = its_to_psa_error( ret ); - if( status != PSA_SUCCESS ) + status = psa_its_get_info( data_identifier, &data_identifier_info ); + if( status != PSA_SUCCESS ) return( status ); - ret = psa_its_get( data_identifier, 0, data_size, data ); - status = its_to_psa_error( ret ); + status = psa_its_get( data_identifier, 0, data_size, data ); return( status ); } -int psa_is_key_present_in_storage( const psa_key_id_t key ) +int psa_is_key_present_in_storage( const psa_key_file_id_t key ) { - psa_its_status_t ret; - psa_its_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_its_info_t data_identifier_info; + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info( data_identifier, &data_identifier_info ); - if( ret == PSA_ITS_ERROR_UID_NOT_FOUND ) + if( ret == PSA_ERROR_DOES_NOT_EXIST ) return( 0 ); return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_id_t key, +psa_status_t psa_crypto_storage_store( const psa_key_file_id_t key, const uint8_t *data, size_t data_length ) { - psa_its_status_t ret; psa_status_t status; - psa_its_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_its_info_t data_identifier_info; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; if( psa_is_key_present_in_storage( key ) == 1 ) - return( PSA_ERROR_OCCUPIED_SLOT ); + return( PSA_ERROR_ALREADY_EXISTS ); - ret = psa_its_set( data_identifier, data_length, data, 0 ); - status = its_to_psa_error( ret ); + status = psa_its_set( data_identifier, data_length, data, 0 ); if( status != PSA_SUCCESS ) { return( PSA_ERROR_STORAGE_FAILURE ); } - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - status = its_to_psa_error( ret ); + status = psa_its_get_info( data_identifier, &data_identifier_info ); if( status != PSA_SUCCESS ) { goto exit; @@ -142,36 +125,34 @@ exit: return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_file_id_t key ) { - psa_its_status_t ret; - psa_its_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_its_info_t data_identifier_info; + psa_status_t ret; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; ret = psa_its_get_info( data_identifier, &data_identifier_info ); - if( ret == PSA_ITS_ERROR_UID_NOT_FOUND ) + if( ret == PSA_ERROR_DOES_NOT_EXIST ) return( PSA_SUCCESS ); - if( psa_its_remove( data_identifier ) != PSA_ITS_SUCCESS ) + if( psa_its_remove( data_identifier ) != PSA_SUCCESS ) return( PSA_ERROR_STORAGE_FAILURE ); ret = psa_its_get_info( data_identifier, &data_identifier_info ); - if( ret != PSA_ITS_ERROR_UID_NOT_FOUND ) + if( ret != PSA_ERROR_DOES_NOT_EXIST ) return( PSA_ERROR_STORAGE_FAILURE ); return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_file_id_t key, size_t *data_length ) { - psa_its_status_t ret; psa_status_t status; - psa_its_uid_t data_identifier = psa_its_identifier_of_slot( key ); - struct psa_its_info_t data_identifier_info; + psa_storage_uid_t data_identifier = psa_its_identifier_of_slot( key ); + struct psa_storage_info_t data_identifier_info; - ret = psa_its_get_info( data_identifier, &data_identifier_info ); - status = its_to_psa_error( ret ); + status = psa_its_get_info( data_identifier, &data_identifier_info ); if( status != PSA_SUCCESS ) return( status ); diff --git a/features/mbedtls/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/src/default_random_seed.cpp b/features/mbedtls/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/src/default_random_seed.cpp index 5217fb4d52..22a58f72f3 100644 --- a/features/mbedtls/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/src/default_random_seed.cpp +++ b/features/mbedtls/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/src/default_random_seed.cpp @@ -5,21 +5,13 @@ int mbed_default_seed_read(unsigned char *buf, size_t buf_len) { - /* Make sure that in case of an error the value will be negative - * return (-1 * rc); - * Mbed TLS errors are negative values - */ - psa_its_status_t rc = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0, buf_len, buf); - return ( -1 * rc ); + psa_status_t rc = psa_its_get(PSA_CRYPTO_ITS_RANDOM_SEED_UID, 0, buf_len, buf); + return ( rc ); } int mbed_default_seed_write(unsigned char *buf, size_t buf_len) { - psa_its_status_t rc = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, buf_len, buf, 0); - /* Make sure that in case of an error the value will be negative - * return (-1 * rc); - * Mbed TLS errors are negative values - */ - return ( -1 * rc ); + psa_status_t rc = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, buf_len, buf, 0); + return ( rc ); } diff --git a/targets/targets.json b/targets/targets.json index 4de79c748c..af76f396ab 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -8083,7 +8083,7 @@ "inherits": ["NSPE_Target", "FUTURE_SEQUANA"], "extra_labels_add": ["PSA", "MBED_SPM"], "extra_labels_remove": ["CORDIO"], - "components_add": ["SPM_MAILBOX"], + "components_add": ["SPM_MAILBOX", "FLASHIAP"], "macros_add": ["PSOC6_DYNSRM_DISABLE=1", "MBEDTLS_PSA_CRYPTO_C"], "hex_filename": "psa_release_1.0.hex", "overrides": { diff --git a/tools/psa/generate_tfm_partition_code.py b/tools/psa/generate_tfm_partition_code.py index 947c3b8d61..462e9f1de1 100644 --- a/tools/psa/generate_tfm_partition_code.py +++ b/tools/psa/generate_tfm_partition_code.py @@ -34,7 +34,7 @@ TEMPLATES_LIST_FILE = path_join(SCRIPT_DIR, 'tfm', 'tfm_generated_file_list.json SERVICES_DIR = os.path.join(MBED_OS_ROOT, "components", "TARGET_PSA", "services") SERVICES_MANIFESTS = [ - path_join(SERVICES_DIR, 'psa_prot_internal_storage', 'pits_psa.json'), + path_join(SERVICES_DIR, 'storage', 'its', 'pits_psa.json'), path_join(SERVICES_DIR, 'platform', 'platform_psa.json'), path_join(SERVICES_DIR, 'crypto', 'crypto_partition_psa.json') ]