From c525aec6ad1dd733f42259460b1ced1b5fc57b3b Mon Sep 17 00:00:00 2001 From: Charley Chu Date: Fri, 17 Jul 2020 13:39:17 -0700 Subject: [PATCH] Add TFM V1.0 Signed-off-by: Charley Chu --- .../src/platform_multicore.c | 131 + .../src/platform_ns_mailbox.c | 304 ++ .../TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c | 67 + .../src/tfm_multi_core_api.c | 52 + .../src/tfm_multi_core_psa_ns_api.c | 224 + .../TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c | 425 ++ .../TARGET_TFM_V8M/src/cmsis_nvic_virtual.c | 25 + .../TARGET_TFM_V8M/src/tfm_mbed_boot.c | 37 + .../TARGET_TFM_V8M/src/tfm_ns_interface.c | 64 + .../TARGET_TFM_V8M/src/tfm_psa_ns_api.c | 79 + .../TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt | 1 + .../include/cmsis_nvic_virtual.h | 52 + .../TARGET_TFM_V1_0/include/ns_ipc_config.h | 22 + .../include/platform_multicore.h | 102 + .../TARGET_TFM_V1_0/include/psa/client.h | 175 + .../TARGET_TFM_V1_0/include/psa/crypto.h | 3770 +++++++++++++++++ .../include/psa/crypto_compat.h | 111 + .../include/psa/crypto_extra.h | 57 + .../include/psa/crypto_platform.h | 51 + .../include/psa/crypto_sizes.h | 650 +++ .../include/psa/crypto_struct.h | 301 ++ .../include/psa/crypto_types.h | 313 ++ .../include/psa/crypto_values.h | 1701 ++++++++ .../TARGET_TFM_V1_0/include/psa/error.h | 57 + .../include/psa/initial_attestation.h | 228 + .../include/psa/internal_trusted_storage.h | 164 + .../include/psa/protected_storage.h | 282 ++ .../include/psa/storage_common.h | 49 + .../include/psa_manifest/sid.h | 151 + .../TARGET_TFM_V1_0/include/tfm_api.h | 142 + .../TARGET_TFM_V1_0/include/tfm_crypto_defs.h | 164 + .../TARGET_TFM_V1_0/include/tfm_mailbox.h | 180 + .../include/tfm_multi_core_api.h | 61 + .../include/tfm_ns_interface.h | 54 + .../TARGET_TFM_V1_0/include/tfm_ns_mailbox.h | 236 ++ .../TARGET_TFM_V1_0/include/tfm_ns_svc.h | 68 + .../include/tfm_platform_api.h | 98 + .../TARGET_TFM_V1_0/include/tfm_veneers.h | 180 + .../TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c | 1875 ++++++++ .../src/tfm_initial_attestation_ipc_api.c | 105 + .../TARGET_TFM_V1_0/src/tfm_its_ipc_api.c | 137 + .../src/tfm_platform_ipc_api.c | 78 + .../TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c | 183 + 43 files changed, 13206 insertions(+) create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c create mode 100644 features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c new file mode 100644 index 0000000000..e860ae03e9 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_multicore.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * Copyright (c) 2019 Cypress Semiconductor Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "cmsis_compiler.h" + +#include "platform_multicore.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" +#if CY_SYSTEM_CPU_CM0P +#include "spe_ipc_config.h" +#else +#include "ns_ipc_config.h" +#endif + +int platform_mailbox_fetch_msg_ptr(void **msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!data_ptr) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + + status = Cy_IPC_Drv_ReadMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + data_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + + Cy_IPC_Drv_ReleaseNotify(Cy_IPC_Drv_GetIpcBaseAddress(IPC_RX_CHAN), + IPC_RX_RELEASE_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_ptr(const void *msg_ptr) +{ + cy_en_ipcdrv_status_t status; + + if (!msg_ptr) + return PLATFORM_MAILBOX_INVAL_PARAMS; + + status = Cy_IPC_Drv_SendMsgPtr(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, msg_ptr); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +int platform_mailbox_send_msg_data(uint32_t data) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, data); + if (status != CY_IPC_DRV_SUCCESS) { + return PLATFORM_MAILBOX_TX_ERROR; + } + + return PLATFORM_MAILBOX_SUCCESS; +} + +void platform_mailbox_wait_for_notify(void) +{ + uint32_t status; + + while (1) { + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if (status & IPC_RX_INT_MASK) { + break; + } + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +int platform_ns_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return PLATFORM_MAILBOX_SUCCESS; +} + +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void) +{ + uint32_t data = 0; + + if (platform_ns_ipc_init() != PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_INVAL_PARAMS; + } + while(data != IPC_SYNC_MAGIC) + { + platform_mailbox_wait_for_notify(); + platform_mailbox_fetch_msg_data(&data); + } + + if (platform_mailbox_send_msg_data(~IPC_SYNC_MAGIC) != + PLATFORM_MAILBOX_SUCCESS) { + return PLATFORM_MAILBOX_RX_ERROR; + } + return PLATFORM_MAILBOX_SUCCESS; +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c new file mode 100644 index 0000000000..3c642c0224 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/platform_ns_mailbox.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* -------------------------------------- Includes ----------------------------------- */ +#include +#include + +#include "cmsis_compiler.h" + +#include "cy_ipc_drv.h" +#include "cy_sysint.h" +#include "cy_ipc_sema.h" + +#include "ns_ipc_config.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "cmsis_os2.h" + +static uint8_t saved_irq_state = 1; + +/* -------------------------------------- HAL API ------------------------------------ */ + +static void mailbox_ipc_init(void) +{ + Cy_IPC_Drv_SetInterruptMask(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); +} + +static void mailbox_ipc_config(void) +{ + NVIC_SetPriority(PSA_CLIENT_REPLY_NVIC_IRQn, PSA_CLIENT_REPLY_IRQ_PRIORITY); + + NVIC_EnableIRQ(PSA_CLIENT_REPLY_NVIC_IRQn); +} + +int32_t tfm_ns_mailbox_hal_notify_peer(void) +{ + cy_en_ipcdrv_status_t status; + + status = Cy_IPC_Drv_SendMsgWord(Cy_IPC_Drv_GetIpcBaseAddress(IPC_TX_CHAN), + IPC_TX_NOTIFY_MASK, + PSA_CLIENT_CALL_REQ_MAGIC); + + if (status == CY_IPC_DRV_SUCCESS) { + return MAILBOX_SUCCESS; + } else { + return MAILBOX_CHAN_BUSY; + } +} + +static int32_t mailbox_sema_init(void) +{ +#if defined(CY_IPC_DEFAULT_CFG_DISABLE) + /* semaphore data */ + static uint32_t tfm_sema __attribute__((section("TFM_SHARED_DATA"))); + + if (Cy_IPC_Sema_Init(PLATFORM_MAILBOX_IPC_CHAN_SEMA, + sizeof(tfm_sema) * CHAR_BIT, + &tfm_sema) != CY_IPC_SEMA_SUCCESS) { + return PLATFORM_MAILBOX_INIT_ERROR; + } +#endif + return PLATFORM_MAILBOX_SUCCESS; +} + +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue) +{ + uint32_t stage; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* Init semaphores used for critical sections */ + if (mailbox_sema_init() != PLATFORM_MAILBOX_SUCCESS) + return MAILBOX_INIT_ERROR; + + /* + * FIXME + * Further verification of mailbox queue address may be required according + * to diverse NSPE implementations. + */ + + mailbox_ipc_init(); + + /* + * Wait until SPE mailbox library is ready to receive NSPE mailbox queue + * address. + */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == NS_MAILBOX_INIT_ENABLE) { + break; + } + } + + /* Send out the address */ + platform_mailbox_send_msg_ptr(queue); + + /* Wait until SPE mailbox service is ready */ + while (1) { + platform_mailbox_wait_for_notify(); + + platform_mailbox_fetch_msg_data(&stage); + if (stage == S_MAILBOX_READY) { + break; + } + } + + mailbox_ipc_config(); + + return MAILBOX_SUCCESS; +} + +const void *tfm_ns_mailbox_get_task_handle(void) +{ + return osThreadGetId();; +} + +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle) +{ + osThreadFlagsWait(handle, osFlagsWaitAll, osWaitForever); +} + +static cy_en_ipcsema_status_t mailbox_raw_spin_lock(uint32_t ipc_channel, + uint32_t sema_num) +{ + uint32_t semaIndex; + uint32_t semaMask; + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcdrv_status_t acqStatus; + cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; + bool is_lock = false; + IPC_STRUCT_Type *semaIpcStruct; + + /* Get IPC register structure */ + semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); + + if (sema_num < semaStruct->maxSema) { + semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (sema_num - \ + (semaIndex * CY_IPC_SEMA_PER_WORD))); + + while (!is_lock) { + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + do { + acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); + } while (acqStatus != CY_IPC_DRV_SUCCESS); + + if ((semaStruct->arrayPtr[semaIndex] & semaMask) == 0ul) { + semaStruct->arrayPtr[semaIndex] |= semaMask; + is_lock = true; + } + + /* Release, but do not trigger a release event */ + (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, + CY_IPC_NO_NOTIFICATION); + + if (!is_lock) { + /* + * The secure core is occupying this lock. Insert a small delay + * to give the secure core a chance to acquire the IPC channel + * and release the lock. + * Otherwise, the secure core may not be able to release the + * lock if non-secure core has higher CPU frequency. It will + * generate a deadlock. + * This delay won't harm performance too much since non-secure + * core has to busy wait here anyway. + * Alternatively, non-secure core can wait for release + * notification event from secure core. However, it is more + * complex and requires more code and more modifications. + */ + volatile uint32_t count = 1000; + while(count > 0) { + count--; + } + Cy_IPC_Sema_Status(sema_num); + } + } + + ret = CY_IPC_SEMA_SUCCESS; + } + + return ret; +} + +static cy_en_ipcsema_status_t mailbox_raw_spin_unlock(uint32_t ipc_channel, + uint32_t sema_num) +{ + uint32_t semaIndex; + uint32_t semaMask; + cy_stc_ipc_sema_t *semaStruct; + cy_en_ipcdrv_status_t acqStatus; + cy_en_ipcsema_status_t ret = CY_IPC_SEMA_BAD_PARAM; + bool is_unlock = false; + IPC_STRUCT_Type *semaIpcStruct; + + /* Get IPC register structure */ + semaIpcStruct = Cy_IPC_Drv_GetIpcBaseAddress(ipc_channel); + /* Get pointer to structure */ + semaStruct = (cy_stc_ipc_sema_t *)Cy_IPC_Drv_ReadDataValue(semaIpcStruct); + + if (sema_num < semaStruct->maxSema) { + semaIndex = sema_num / CY_IPC_SEMA_PER_WORD; + semaMask = (uint32_t)(1ul << (sema_num - \ + (semaIndex * CY_IPC_SEMA_PER_WORD))); + + while (!is_unlock) { + /* Check to make sure the IPC channel is released + If so, check if specific channel can be locked. */ + do { + acqStatus = Cy_IPC_Drv_LockAcquire(semaIpcStruct); + } while (acqStatus != CY_IPC_DRV_SUCCESS); + + if ((semaStruct->arrayPtr[semaIndex] & semaMask) != 0ul) { + semaStruct->arrayPtr[semaIndex] &= ~semaMask; + is_unlock = true; + } + + /* Release, but do not trigger a release event */ + (void)Cy_IPC_Drv_LockRelease(semaIpcStruct, + CY_IPC_NO_NOTIFICATION); + } + + ret = CY_IPC_SEMA_SUCCESS; + } + + return ret; +} + +void tfm_ns_mailbox_hal_enter_critical(void) +{ + saved_irq_state = Cy_SysLib_EnterCriticalSection(); + + mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +void tfm_ns_mailbox_hal_exit_critical(void) +{ + mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); + + Cy_SysLib_ExitCriticalSection(saved_irq_state); +} + +void tfm_ns_mailbox_hal_enter_critical_isr(void) +{ + mailbox_raw_spin_lock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +void tfm_ns_mailbox_hal_exit_critical_isr(void) +{ + mailbox_raw_spin_unlock(CY_IPC_CHAN_SEMA, MAILBOX_SEMAPHORE_NUM); +} + +static bool mailbox_clear_intr(void) +{ + uint32_t status; + + status = Cy_IPC_Drv_GetInterruptStatusMasked( + Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT)); + status >>= CY_IPC_NOTIFY_SHIFT; + if ((status & IPC_RX_INT_MASK) == 0) { + return false; + } + + Cy_IPC_Drv_ClearInterrupt(Cy_IPC_Drv_GetIntrBaseAddr(IPC_RX_INTR_STRUCT), + 0, IPC_RX_INT_MASK); + return true; +} + +void cpuss_interrupts_ipc_8_IRQHandler(void) +{ + uint32_t magic; + mailbox_msg_handle_t handle; + osThreadId_t task_handle; + + if (!mailbox_clear_intr()) + return; + + platform_mailbox_fetch_msg_data(&magic); + if (magic == PSA_CLIENT_CALL_REPLY_MAGIC) { + /* Handle all the pending replies */ + while (1) { + handle = tfm_ns_mailbox_fetch_reply_msg_isr(); + if (handle == MAILBOX_MSG_NULL_HANDLE) { + break; + } + + task_handle = (osThreadId_t)tfm_ns_mailbox_get_msg_owner(handle); + if (task_handle) { + osThreadFlagsSet(task_handle, handle); + } + } + } +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c new file mode 100644 index 0000000000..c8d595fe73 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_mbed_boot.c @@ -0,0 +1,67 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 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 "mbed_error.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" +#include "platform_multicore.h" +#include "tfm_ns_interface.h" + +static struct ns_mailbox_queue_t ns_mailbox_queue; + +void mbed_tfm_init(void) +{ + /* + * In case the of dual CPU, we need to initialize IPC, mailbox + * and NS interface after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_wait_for_s_cpu_ready(); + /* + * Normally would expect "TFM_SUCCESS" returned here by TF-M, as this + * isn't a mailbox function. There may be some platforms other than PSoC6, + * which doesn't require tfm_ns_wait_for_s_cpu_ready() implementation. + * "PLATFORM_MAILBOX_SUCCESS" is a low-level error code and should be + * replaced by "TFM_SUCCESS". + * As the function definition has been imported from the TF-M, therefore + * a issue has been raised - https://developer.trustedfirmware.org/T660 + */ + if (ret != PLATFORM_MAILBOX_SUCCESS) { + /* Avoid undefined behavior after multi-core sync-up failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to sync-up multi-core"); + } + + ret = tfm_ns_mailbox_init(&ns_mailbox_queue); + if (ret != MAILBOX_SUCCESS) { + /* Avoid undefined behavior after NS mailbox initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS mailbox"); + } + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c new file mode 100644 index 0000000000..231e895b61 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_api.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_api.h" +#include "tfm_mailbox.h" +#include "tfm_multi_core_api.h" +#include "cmsis_os2.h" +#include "mbed_rtos_storage.h" + +#define MAX_SEMAPHORE_COUNT NUM_MAILBOX_QUEUE_SLOT + +static void *ns_lock_handle = NULL; +static mbed_rtos_storage_semaphore_t tfm_ns_sema_obj; + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + osSemaphoreAttr_t sema_attrib = { + .name = "tfm_ns_lock", + .attr_bits = 0, + .cb_size = sizeof(tfm_ns_sema_obj), + .cb_mem = &tfm_ns_sema_obj + }; + + ns_lock_handle = osSemaphoreNew(MAX_SEMAPHORE_COUNT, + MAX_SEMAPHORE_COUNT, + &sema_attrib); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} + +int32_t tfm_ns_wait_for_s_cpu_ready(void) +{ + return tfm_platform_ns_wait_for_s_cpu_ready(); +} + +uint32_t tfm_ns_multi_core_lock_acquire(void) +{ + return osSemaphoreAcquire(ns_lock_handle, osWaitForever); +} + +uint32_t tfm_ns_multi_core_lock_release(void) +{ + return osSemaphoreRelease(ns_lock_handle); +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c new file mode 100644 index 0000000000..fae580ecd0 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_multi_core_psa_ns_api.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include "psa/client.h" +#include "psa/error.h" +#include "tfm_api.h" +#include "tfm_multi_core_api.h" +#include "tfm_ns_mailbox.h" + +/* + * TODO + * Currently, force all the non-secure client to share the same ID. + * + * It requires a more clear mechanism to synchronize the non-secure client + * ID with SPE in dual core scenario. + * In current design, the value is transferred to SPE via mailbox message. + * A dedicated routine to receive the non-secure client information in + * TF-M core/SPM in dual core scenario should be added besides current + * implementation for single Armv8-M. + * The non-secure client identification is shared with SPE in + * single Armv8-M scenario via CMSIS TrustZone context management API, + * which may not work in dual core scenario. + */ +#define NON_SECURE_CLIENT_ID (1) + +/* + * TODO + * Require a formal definition of errors related to mailbox in PSA client call. + */ +#define PSA_INTER_CORE_COMM_ERR (INT32_MIN + 0xFF) + +static void mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + /* + * If the system can support multiple outstanding NS PSA Client calls, call + * tfm_ns_mailbox_wait_reply() to sleep and wait for reply. The NS side + * should implement tfm_ns_mailbox_hal_wait_reply() and wake-up mechanism. + * Otherwise, by default, call tfm_ns_mailbox_is_msg_replied() to simply + * poll the reply status of the mailbox message of current thread. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL + tfm_ns_mailbox_wait_reply(handle); +#else + while (!tfm_ns_mailbox_is_msg_replied(handle)) { + } +#endif +} + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_FRAMEWORK_VERSION, + ¶ms, NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_VERSION_NONE; + } + + return version; +} + +uint32_t psa_version(uint32_t sid) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + uint32_t version; + int32_t ret; + + params.psa_version_params.sid = sid; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_VERSION_NONE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_VERSION, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_VERSION_NONE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&version); + if (ret != MAILBOX_SUCCESS) { + version = PSA_VERSION_NONE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_VERSION_NONE; + } + + return version; +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t handle; + psa_handle_t psa_handle; + int32_t ret; + + params.psa_connect_params.sid = sid; + params.psa_connect_params.version = version; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_NULL_HANDLE; + } + + handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CONNECT, ¶ms, + NON_SECURE_CLIENT_ID); + if (handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_NULL_HANDLE; + } + + mailbox_wait_reply(handle); + + ret = tfm_ns_mailbox_rx_client_reply(handle, (int32_t *)&psa_handle); + if (ret != MAILBOX_SUCCESS) { + psa_handle = PSA_NULL_HANDLE; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_NULL_HANDLE; + } + + return psa_handle; +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, size_t in_len, + psa_outvec *out_vec, size_t out_len) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t ret; + psa_status_t status; + + params.psa_call_params.handle = handle; + params.psa_call_params.type = type; + params.psa_call_params.in_vec = in_vec; + params.psa_call_params.in_len = in_len; + params.psa_call_params.out_vec = out_vec; + params.psa_call_params.out_len = out_len; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CALL, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return PSA_INTER_CORE_COMM_ERR; + } + + mailbox_wait_reply(msg_handle); + + ret = tfm_ns_mailbox_rx_client_reply(msg_handle, (int32_t *)&status); + if (ret != MAILBOX_SUCCESS) { + status = PSA_INTER_CORE_COMM_ERR; + } + + if (tfm_ns_multi_core_lock_release() != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + return status; +} + +void psa_close(psa_handle_t handle) +{ + struct psa_client_params_t params; + mailbox_msg_handle_t msg_handle; + int32_t reply; + + params.psa_close_params.handle = handle; + + if (tfm_ns_multi_core_lock_acquire() != 0) { + return; + } + + msg_handle = tfm_ns_mailbox_tx_client_req(MAILBOX_PSA_CLOSE, ¶ms, + NON_SECURE_CLIENT_ID); + if (msg_handle < 0) { + tfm_ns_multi_core_lock_release(); + return; + } + + mailbox_wait_reply(msg_handle); + + (void)tfm_ns_mailbox_rx_client_reply(msg_handle, &reply); + + tfm_ns_multi_core_lock_release(); +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c new file mode 100644 index 0000000000..f7326f0926 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_DUALCPU/src/tfm_ns_mailbox.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_ns_mailbox.h" + +/* The pointer to NSPE mailbox queue */ +static struct ns_mailbox_queue_t *mailbox_queue_ptr = NULL; + +static inline void clear_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_empty(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->empty_slots |= (1 << idx); + } +} + +static inline void set_queue_slot_pend(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->pend_slots |= (1 << idx); + } +} + +static inline int32_t get_mailbox_msg_handle(uint8_t idx, + mailbox_msg_handle_t *handle) +{ + if ((idx >= NUM_MAILBOX_QUEUE_SLOT) || !handle) { + return MAILBOX_INVAL_PARAMS; + } + + *handle = (mailbox_msg_handle_t)(idx + 1); + + return MAILBOX_SUCCESS; +} + +static inline int32_t get_mailbox_msg_idx(mailbox_msg_handle_t handle, + uint8_t *idx) +{ + if ((handle == MAILBOX_MSG_NULL_HANDLE) || !idx) { + return MAILBOX_INVAL_PARAMS; + } + + *idx = (uint8_t)(handle - 1); + + return MAILBOX_SUCCESS; +} + +static inline void clear_queue_slot_replied(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->replied_slots &= ~(1 << idx); + } +} + +static inline void set_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = true; + } +} + +static inline bool is_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].is_woken; + } + + return false; +} + +static inline void clear_queue_slot_woken(uint8_t idx) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].is_woken = false; + } +} + +static uint8_t acquire_empty_slot(const struct ns_mailbox_queue_t *queue) +{ + uint8_t idx; + mailbox_queue_status_t status; + + tfm_ns_mailbox_hal_enter_critical(); + status = queue->empty_slots; + + if (!status) { + /* No empty slot */ + tfm_ns_mailbox_hal_exit_critical(); + return NUM_MAILBOX_QUEUE_SLOT; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (status & (1 << idx)) { + break; + } + } + + clear_queue_slot_empty(idx); + + tfm_ns_mailbox_hal_exit_critical(); + + return idx; +} + +static void set_msg_owner(uint8_t idx, const void *owner) +{ + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + mailbox_queue_ptr->queue[idx].owner = owner; + } +} + +#ifdef TFM_MULTI_CORE_TEST +void tfm_ns_mailbox_tx_stats_init(void) +{ + if (!mailbox_queue_ptr) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + mailbox_queue_ptr->nr_tx = 0; + mailbox_queue_ptr->nr_used_slots = 0; + + tfm_ns_mailbox_hal_exit_critical(); +} + +static void mailbox_tx_stats_update(struct ns_mailbox_queue_t *ns_queue) +{ + mailbox_queue_status_t empty_status; + uint8_t idx, nr_empty = 0; + + if (!ns_queue) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + + ns_queue->nr_tx++; + + /* Count the number of used slots when this tx arrives */ + empty_status = ns_queue->empty_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (empty_status) { + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + if (empty_status & (0x1UL << idx)) { + nr_empty++; + } + } + } + + tfm_ns_mailbox_hal_enter_critical(); + ns_queue->nr_used_slots += (NUM_MAILBOX_QUEUE_SLOT - nr_empty); + tfm_ns_mailbox_hal_exit_critical(); +} + +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res) +{ + uint32_t nr_used_slots, nr_tx; + + if (!mailbox_queue_ptr || !stats_res) { + return; + } + + tfm_ns_mailbox_hal_enter_critical(); + nr_used_slots = mailbox_queue_ptr->nr_used_slots; + nr_tx = mailbox_queue_ptr->nr_tx; + tfm_ns_mailbox_hal_exit_critical(); + + stats_res->avg_nr_slots = nr_used_slots / nr_tx; + nr_used_slots %= nr_tx; + stats_res->avg_nr_slots_tenths = nr_used_slots * 10 / nr_tx; +} +#endif + +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id) +{ + uint8_t idx; + struct mailbox_msg_t *msg_ptr; + mailbox_msg_handle_t handle; + const void *task_handle; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + if (!params) { + return MAILBOX_MSG_NULL_HANDLE; + } + + idx = acquire_empty_slot(mailbox_queue_ptr); + if (idx >= NUM_MAILBOX_QUEUE_SLOT) { + return MAILBOX_QUEUE_FULL; + } + +#ifdef TFM_MULTI_CORE_TEST + mailbox_tx_stats_update(mailbox_queue_ptr); +#endif + + /* Fill the mailbox message */ + msg_ptr = &mailbox_queue_ptr->queue[idx].msg; + + msg_ptr->call_type = call_type; + memcpy(&msg_ptr->params, params, sizeof(msg_ptr->params)); + msg_ptr->client_id = client_id; + + /* + * Fetch the current task handle. The task will be woken up according the + * handle value set in the owner field. + */ + task_handle = tfm_ns_mailbox_get_task_handle(); + set_msg_owner(idx, task_handle); + + get_mailbox_msg_handle(idx, &handle); + + tfm_ns_mailbox_hal_enter_critical(); + set_queue_slot_pend(idx); + tfm_ns_mailbox_hal_exit_critical(); + + tfm_ns_mailbox_hal_notify_peer(); + + return handle; +} + +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if ((handle == MAILBOX_MSG_NULL_HANDLE) || (!reply)) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + *reply = mailbox_queue_ptr->queue[idx].reply.return_val; + + /* Clear up the owner field */ + set_msg_owner(idx, NULL); + + tfm_ns_mailbox_hal_enter_critical(); + clear_queue_slot_replied(idx); + clear_queue_slot_woken(idx); + /* + * Make sure that the empty flag is set after all the other status flags are + * re-initialized. + */ + set_queue_slot_empty(idx); + tfm_ns_mailbox_hal_exit_critical(); + + return MAILBOX_SUCCESS; +} + +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + mailbox_queue_status_t status; + + if (!mailbox_queue_ptr) { + return false; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return false; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return false; + } + + tfm_ns_mailbox_hal_enter_critical(); + status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical(); + + if (status & (1 << idx)) { + return true; + } + + return false; +} + +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void) +{ + uint8_t idx; + mailbox_msg_handle_t handle; + mailbox_queue_status_t replied_status; + + if (!mailbox_queue_ptr) { + return MAILBOX_MSG_NULL_HANDLE; + } + + tfm_ns_mailbox_hal_enter_critical_isr(); + replied_status = mailbox_queue_ptr->replied_slots; + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (!replied_status) { + return MAILBOX_MSG_NULL_HANDLE; + } + + for (idx = 0; idx < NUM_MAILBOX_QUEUE_SLOT; idx++) { + /* Find the first replied message in queue */ + if (replied_status & (0x1UL << idx)) { + tfm_ns_mailbox_hal_enter_critical_isr(); + clear_queue_slot_replied(idx); + set_queue_slot_woken(idx); + tfm_ns_mailbox_hal_exit_critical_isr(); + + if (get_mailbox_msg_handle(idx, &handle) == MAILBOX_SUCCESS) { + return handle; + } + } + } + + return MAILBOX_MSG_NULL_HANDLE; +} + +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle) +{ + uint8_t idx; + + if (get_mailbox_msg_idx(handle, &idx) != MAILBOX_SUCCESS) { + return NULL; + } + + if (idx < NUM_MAILBOX_QUEUE_SLOT) { + return mailbox_queue_ptr->queue[idx].owner; + } + + return NULL; +} + +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue) +{ + int32_t ret; + + if (!queue) { + return MAILBOX_INVAL_PARAMS; + } + + /* + * Further verification of mailbox queue address may be required according + * to non-secure memory assignment. + */ + + memset(queue, 0, sizeof(*queue)); + + /* Initialize empty bitmask */ + queue->empty_slots = + (mailbox_queue_status_t)((1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)) - 1); + queue->empty_slots += + (mailbox_queue_status_t)(1UL << (NUM_MAILBOX_QUEUE_SLOT - 1)); + + mailbox_queue_ptr = queue; + + /* Platform specific initialization. */ + ret = tfm_ns_mailbox_hal_init(queue); + +#ifdef TFM_MULTI_CORE_TEST + tfm_ns_mailbox_tx_stats_init(); +#endif + + return ret; +} + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle) +{ + uint8_t idx; + int32_t ret; + + if (!mailbox_queue_ptr) { + return MAILBOX_INVAL_PARAMS; + } + + if (handle == MAILBOX_MSG_NULL_HANDLE) { + return MAILBOX_INVAL_PARAMS; + } + + ret = get_mailbox_msg_idx(handle, &idx); + if (ret != MAILBOX_SUCCESS) { + return ret; + } + + while (1) { + tfm_ns_mailbox_hal_wait_reply(handle); + + /* + * Woken up from sleep + * Check the completed flag to make sure that the current thread is + * woken up by reply event, rather than other events. + */ + tfm_ns_mailbox_hal_enter_critical(); + if (is_queue_slot_woken(idx)) { + tfm_ns_mailbox_hal_exit_critical(); + break; + } + tfm_ns_mailbox_hal_exit_critical(); + } + + return MAILBOX_SUCCESS; +} +#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c new file mode 100644 index 0000000000..bee8597957 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/cmsis_nvic_virtual.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019-2020 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 "cmsis_nvic_virtual.h" +#include "tfm_platform_api.h" + +void NVIC_SystemReset(void) +{ + tfm_platform_system_reset(); +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c new file mode 100644 index 0000000000..87bcbbbf66 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_mbed_boot.c @@ -0,0 +1,37 @@ +/* mbed Microcontroller Library + * Copyright (c) 2020 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 "mbed_error.h" +#include "tfm_ns_interface.h" + +void mbed_tfm_init(void) +{ + /* + * In case of V8-M, we need to initialize NS interface + * after the RTOS has started to enable + * communication from Secure and Non-Secure cores. + */ + int32_t ret; + + ret = tfm_ns_interface_init(); + if (ret != TFM_SUCCESS) { + /* Avoid undefined behavior after NS interface initialization failed */ + MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, + MBED_ERROR_CODE_INITIALIZATION_FAILED), + "Failed to initialize NS interface"); + } +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c new file mode 100644 index 0000000000..9759145590 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_ns_interface.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include + +#include "tfm_api.h" +#include "tfm_ns_interface.h" +#include "cmsis_os2.h" + +/** + * \brief the ns_lock ID + */ +static osMutexId_t ns_lock_handle = NULL; + +__attribute__((weak)) +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3) +{ + int32_t result; + osStatus_t status; + + /* TFM request protected by NS lock */ + status = osMutexAcquire(ns_lock_handle, osWaitForever); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + result = fn(arg0, arg1, arg2, arg3); + + status = osMutexRelease(ns_lock_handle); + if (status != osOK) { + return (int32_t)TFM_ERROR_GENERIC; + } + + return result; +} + +__attribute__((weak)) +enum tfm_status_e tfm_ns_interface_init(void) +{ + const osMutexAttr_t attr = { + .name = NULL, + .attr_bits = osMutexPrioInherit, /* Priority inheritance is recommended + * to enable if it is supported. + * For recursive mutex and the ability + * of auto release when owner being + * terminated is not required. + */ + .cb_mem = NULL, + .cb_size = 0U + }; + + ns_lock_handle = osMutexNew(&attr); + if (!ns_lock_handle) { + return TFM_ERROR_GENERIC; + } + + return TFM_SUCCESS; +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c new file mode 100644 index 0000000000..9a677a2cd3 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/TARGET_TFM_V8M/src/tfm_psa_ns_api.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/client.h" +#include "tfm_ns_interface.h" +#include "tfm_api.h" + +/**** API functions ****/ + +uint32_t psa_framework_version(void) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_framework_version_veneer, + 0, + 0, + 0, + 0); +} + +uint32_t psa_version(uint32_t sid) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_version_veneer, + sid, + 0, + 0, + 0); +} + +psa_handle_t psa_connect(uint32_t sid, uint32_t version) +{ + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_connect_veneer, + sid, + version, + 0, + 0); +} + +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len) +{ + /* FixMe: sanity check can be added to offload some NS thread checks from + * TFM secure API + */ + + /* Due to v8M restrictions, TF-M NS API needs to add another layer of + * serialization in order for NS to pass arguments to S + */ + const struct tfm_control_parameter_t ctrl_param = { + .type = type, + .in_len = in_len, + .out_len = out_len, + }; + + return tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_call_veneer, + (uint32_t)handle, + (uint32_t)&ctrl_param, + (uint32_t)in_vec, + (uint32_t)out_vec); +} + +void psa_close(psa_handle_t handle) +{ + (void)tfm_ns_interface_dispatch( + (veneer_fn)tfm_psa_close_veneer, + (uint32_t)handle, + 0, + 0, + 0); +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt new file mode 100644 index 0000000000..f10c47740d --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/VERSION.txt @@ -0,0 +1 @@ +eecaad9e4014 diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h new file mode 100644 index 0000000000..a1a8b61752 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/cmsis_nvic_virtual.h @@ -0,0 +1,52 @@ +/* + * 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 "cmsis.h" + +#ifndef NVIC_VIRTUAL_H +#define NVIC_VIRTUAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* NVIC functions */ +#define NVIC_SetPriorityGrouping __NVIC_SetPriorityGrouping +#define NVIC_GetPriorityGrouping __NVIC_GetPriorityGrouping +#define NVIC_EnableIRQ __NVIC_EnableIRQ +#define NVIC_GetEnableIRQ __NVIC_GetEnableIRQ +#define NVIC_DisableIRQ __NVIC_DisableIRQ +#define NVIC_GetPendingIRQ __NVIC_GetPendingIRQ +#define NVIC_SetPendingIRQ __NVIC_SetPendingIRQ +#define NVIC_ClearPendingIRQ __NVIC_ClearPendingIRQ +#define NVIC_GetActive __NVIC_GetActive +#define NVIC_SetPriority __NVIC_SetPriority +#define NVIC_GetPriority __NVIC_GetPriority + +/** + * \brief Overriding the default CMSIS system reset implementation by calling + * secure TFM service. + * + */ +void NVIC_SystemReset(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h new file mode 100644 index 0000000000..e1cd7b7430 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/ns_ipc_config.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _IPC_CONFIG_H_ +#define _IPC_CONFIG_H_ + +#include "platform_multicore.h" + +#define IPC_RX_CHAN IPC_PSA_CLIENT_REPLY_CHAN +#define IPC_RX_INTR_STRUCT IPC_PSA_CLIENT_REPLY_INTR_STRUCT +#define IPC_RX_INT_MASK IPC_PSA_CLIENT_REPLY_INTR_MASK + +#define IPC_TX_CHAN IPC_PSA_CLIENT_CALL_CHAN +#define IPC_TX_NOTIFY_MASK IPC_PSA_CLIENT_CALL_NOTIFY_MASK + +#define PSA_CLIENT_REPLY_NVIC_IRQn IPC_PSA_CLIENT_REPLY_IPC_INTR +#define PSA_CLIENT_REPLY_IRQ_PRIORITY 3 + +#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h new file mode 100644 index 0000000000..d0d72d4d29 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/platform_multicore.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _TFM_PLATFORM_MULTICORE_ +#define _TFM_PLATFORM_MULTICORE_ + +#include +#include "cy_device_headers.h" + +#define IPC_PSA_CLIENT_CALL_CHAN (8) +#define IPC_PSA_CLIENT_CALL_INTR_STRUCT (6) +#define IPC_PSA_CLIENT_CALL_INTR_MASK (1 << IPC_PSA_CLIENT_CALL_CHAN) +#define IPC_PSA_CLIENT_CALL_NOTIFY_MASK (1 << IPC_PSA_CLIENT_CALL_INTR_STRUCT) +#define IPC_PSA_CLIENT_CALL_IPC_INTR cpuss_interrupts_ipc_6_IRQn + +#define IPC_PSA_CLIENT_REPLY_CHAN (9) +#define IPC_PSA_CLIENT_REPLY_INTR_STRUCT (8) +#define IPC_PSA_CLIENT_REPLY_INTR_MASK (1 << IPC_PSA_CLIENT_REPLY_CHAN) +#define IPC_PSA_CLIENT_REPLY_NOTIFY_MASK (1 << IPC_PSA_CLIENT_REPLY_INTR_STRUCT) +#define IPC_PSA_CLIENT_REPLY_IPC_INTR cpuss_interrupts_ipc_8_IRQn + +#define IPC_RX_RELEASE_MASK (0) + +#define CY_IPC_NOTIFY_SHIFT (16) + +#define PSA_CLIENT_CALL_REQ_MAGIC (0xA5CF50C6) +#define PSA_CLIENT_CALL_REPLY_MAGIC (0xC605FC5A) + +#define NS_MAILBOX_INIT_ENABLE (0xAE) +#define S_MAILBOX_READY (0xC3) + +#define PLATFORM_MAILBOX_SUCCESS (0x0) +#define PLATFORM_MAILBOX_INVAL_PARAMS (INT32_MIN + 1) +#define PLATFORM_MAILBOX_TX_ERROR (INT32_MIN + 2) +#define PLATFORM_MAILBOX_RX_ERROR (INT32_MIN + 3) +#define PLATFORM_MAILBOX_INIT_ERROR (INT32_MIN + 4) + +/* Inter-Processor Communication (IPC) data channel for the Semaphores */ +#define PLATFORM_MAILBOX_IPC_CHAN_SEMA CY_IPC_CHAN_SEMA +#define MAILBOX_SEMAPHORE_NUM (16) + +#define IPC_SYNC_MAGIC 0x7DADE011 + +/** + * \brief Fetch a pointer from mailbox message + * + * \param[out] msg_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_ptr(void **msg_ptr); + +/** + * \brief Fetch a data value from mailbox message + * + * \param[out] data_ptr The address to write the pointer value to. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_fetch_msg_data(uint32_t *data_ptr); + +/** + * \brief Send a pointer via mailbox message + * + * \param[in] msg_ptr The pointer value to be sent. + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_ptr(const void *msg_ptr); + +/** + * \brief Send a data value via mailbox message + * + * \param[in] data The data value to be sent + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_mailbox_send_msg_data(uint32_t data); + +/** + * \brief Wait for a mailbox notify event. + */ +void platform_mailbox_wait_for_notify(void); + +/** + * \brief IPC initialization + * + * \retval 0 The operation succeeds. + * \retval else The operation fails. + */ +int platform_ns_ipc_init(void); + +#endif diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h new file mode 100644 index 0000000000..4115f930e9 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/client.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __PSA_CLIENT_H__ +#define __PSA_CLIENT_H__ + +#include +#include + +#include "psa/error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*********************** PSA Client Macros and Types *************************/ + +/** + * The version of the PSA Framework API that is being used to build the calling + * firmware. + */ +#define PSA_FRAMEWORK_VERSION (0x0100u) + +/** + * Return value from psa_version() if the requested RoT Service is not present + * in the system. + */ +#define PSA_VERSION_NONE (0u) + +/** + * The zero-value null handle can be assigned to variables used in clients and + * RoT Services, indicating that there is no current connection or message. + */ +#define PSA_NULL_HANDLE ((psa_handle_t)0) + +/** + * Tests whether a handle value returned by psa_connect() is valid. + */ +#define PSA_HANDLE_IS_VALID(handle) ((psa_handle_t)(handle) > 0) + +/** + * Converts the handle value returned from a failed call psa_connect() into + * an error code. + */ +#define PSA_HANDLE_TO_ERROR(handle) ((psa_status_t)(handle)) + +/** + * Maximum number of input and output vectors for a request to psa_call(). + */ +#define PSA_MAX_IOVEC (4u) + +/** + * An IPC message type that indicates a generic client request. + */ +#define PSA_IPC_CALL (0) + +typedef int32_t psa_handle_t; + +/** + * A read-only input memory region provided to an RoT Service. + */ +typedef struct psa_invec { + const void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_invec; + +/** + * A writable output memory region provided to an RoT Service. + */ +typedef struct psa_outvec { + void *base; /*!< the start address of the memory buffer */ + size_t len; /*!< the size in bytes */ +} psa_outvec; + +/*************************** PSA Client API **********************************/ + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return version The version of the PSA Framework implementation + * that is providing the runtime services to the + * caller. The major and minor version are encoded + * as follows: + * \arg version[15:8] -- major version number. + * \arg version[7:0] -- minor version number. + */ +uint32_t psa_framework_version(void); + +/** + * \brief Retrieve the version of an RoT Service or indicate that it is not + * present on this system. + * + * \param[in] sid ID of the RoT Service to query. + * + * \retval PSA_VERSION_NONE The RoT Service is not implemented, or the + * caller is not permitted to access the service. + * \retval > 0 The version of the implemented RoT Service. + */ +uint32_t psa_version(uint32_t sid); + +/** + * \brief Connect to an RoT Service by its SID. + * + * \param[in] sid ID of the RoT Service to connect to. + * \param[in] version Requested version of the RoT Service. + * + * \retval > 0 A handle for the connection. + * \retval PSA_ERROR_CONNECTION_REFUSED The SPM or RoT Service has refused the + * connection. + * \retval PSA_ERROR_CONNECTION_BUSY The SPM or RoT Service cannot make the + * connection at the moment. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg The RoT Service ID is not present. + * \arg The RoT Service version is not supported. + * \arg The caller is not allowed to access the RoT + * service. + */ +psa_handle_t psa_connect(uint32_t sid, uint32_t version); + +/** + * \brief Call an RoT Service on an established connection. + * + * \param[in] handle A handle to an established connection. + * \param[in] type The reuqest type. + * Must be zero( \ref PSA_IPC_CALL) or positive. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in] in_len Number of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * \param[in] out_len Number of output \ref psa_outvec structures. + * + * \retval >=0 RoT Service-specific status value. + * \retval <0 RoT Service-specific error code. + * \retval PSA_ERROR_PROGRAMMER_ERROR The connection has been terminated by the + * RoT Service. The call is a PROGRAMMER ERROR if + * one or more of the following are true: + * \arg An invalid handle was passed. + * \arg The connection is already handling a request. + * \arg type < 0. + * \arg An invalid memory reference was provided. + * \arg in_len + out_len > PSA_MAX_IOVEC. + * \arg The message is unrecognized by the RoT + * Service or incorrectly formatted. + */ +psa_status_t psa_call(psa_handle_t handle, int32_t type, + const psa_invec *in_vec, + size_t in_len, + psa_outvec *out_vec, + size_t out_len); + +/** + * \brief Close a connection to an RoT Service. + * + * \param[in] handle A handle to an established connection, or the + * null handle. + * + * \retval void Success. + * \retval "PROGRAMMER ERROR" The call is a PROGRAMMER ERROR if one or more + * of the following are true: + * \arg An invalid handle was provided that is not + * the null handle. + * \arg The connection is currently handling a + * request. + */ +void psa_close(psa_handle_t handle); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_CLIENT_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h new file mode 100644 index 0000000000..91581172c2 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto.h @@ -0,0 +1,3770 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto.h + * \brief Platform Security Architecture cryptography module + */ + +#ifndef PSA_CRYPTO_H +#define PSA_CRYPTO_H + +#include "psa/crypto_platform.h" + +#include + +#ifdef __DOXYGEN_ONLY__ +/* This __DOXYGEN_ONLY__ block contains mock definitions for things that + * must be defined in the crypto_platform.h header. These mock definitions + * are present in this file as a convenience to generate pretty-printed + * documentation that includes those definitions. */ + +/** \defgroup platform Implementation-specific definitions + * @{ + */ + +/** \brief Key handle. + * + * This type represents open handles to keys. It must be an unsigned integral + * type. The choice of type is implementation-dependent. + * + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. + */ +typedef _unsigned_integral_type_ psa_key_handle_t; + +/**@}*/ +#endif /* __DOXYGEN_ONLY__ */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "psa/crypto_types.h" + +/** \defgroup version API version + * @{ + */ + +/** + * The major version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MAJOR 1 + +/** + * The minor version of this implementation of the PSA Crypto API + */ +#define PSA_CRYPTO_API_VERSION_MINOR 0 + +/**@}*/ + +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "psa/crypto_values.h" + +/** \defgroup initialization Library initialization + * @{ + */ + +/** + * \brief Library initialization. + * + * Applications must call this function before calling any other + * function in this module. + * + * Applications may call this function more than once. Once a call + * succeeds, subsequent calls are guaranteed to succeed. + * + * If the application calls other functions before calling psa_crypto_init(), + * the behavior is undefined. Implementations are encouraged to either perform + * the operation as if the library had been initialized or to return + * #PSA_ERROR_BAD_STATE or some other applicable error. In particular, + * implementations should not return a success status if the lack of + * initialization may have security implications, for example due to improper + * seeding of the random number generator. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + */ +psa_status_t psa_crypto_init(void); + +/**@}*/ + +/** \addtogroup attributes + * @{ + */ + +/** \def PSA_KEY_ATTRIBUTES_INIT + * + * This macro returns a suitable initializer for a key attribute structure + * of type #psa_key_attributes_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_ATTRIBUTES_INIT {0} +#endif + +/** Return an initial value for a key attributes structure. + */ +static psa_key_attributes_t psa_key_attributes_init(void); + +/** Declare a key as persistent and set its key identifier. + * + * If the attribute structure currently declares the key as volatile (which + * is the default content of an attribute structure), this function sets + * the lifetime attribute to #PSA_KEY_LIFETIME_PERSISTENT. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param id The persistent identifier for the key. + */ +static void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id); + +/** Set the location of a persistent key. + * + * To make a key persistent, you must give it a persistent key identifier + * with psa_set_key_id(). By default, a key that has a persistent identifier + * is stored in the default storage area identifier by + * #PSA_KEY_LIFETIME_PERSISTENT. Call this function to choose a storage + * area, or to explicitly declare the key as volatile. + * + * This function does not access storage, it merely stores the given + * value in the structure. + * The persistent key will be written to storage when the attribute + * structure is passed to a key creation function such as + * psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param lifetime The lifetime for the key. + * If this is #PSA_KEY_LIFETIME_VOLATILE, the + * key will be volatile, and the key identifier + * attribute is reset to 0. + */ +static void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime); + +/** Retrieve the key identifier from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The persistent identifier stored in the attribute structure. + * This value is unspecified if the attribute structure declares + * the key as volatile. + */ +static psa_key_id_t psa_get_key_id(const psa_key_attributes_t *attributes); + +/** Retrieve the lifetime from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The lifetime value stored in the attribute structure. + */ +static psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes); + +/** Declare usage flags for a key. + * + * Usage flags are part of a key's usage policy. They encode what + * kind of operations are permitted on the key. For more details, + * refer to the documentation of the type #psa_key_usage_t. + * + * This function overwrites any usage flags + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param usage_flags The usage flags to write. + */ +static void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags); + +/** Retrieve the usage flags from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The usage flags stored in the attribute structure. + */ +static psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes); + +/** Declare the permitted algorithm policy for a key. + * + * The permitted algorithm policy of a key encodes which algorithm or + * algorithms are permitted to be used with this key. The following + * algorithm policies are supported: + * - 0 does not allow any cryptographic operation with the key. The key + * may be used for non-cryptographic actions such as exporting (if + * permitted by the usage flags). + * - An algorithm value permits this particular algorithm. + * - An algorithm wildcard built from #PSA_ALG_ANY_HASH allows the specified + * signature scheme with any hash algorithm. + * + * This function overwrites any algorithm policy + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param alg The permitted algorithm policy to write. + */ +static void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg); + + +/** Retrieve the algorithm policy from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The algorithm stored in the attribute structure. + */ +static psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes); + +/** Declare the type of a key. + * + * This function overwrites any key type + * previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param type The key type to write. + * If this is 0, the key type in \p attributes + * becomes unspecified. + */ +static void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type); + + +/** Declare the size of a key. + * + * This function overwrites any key size previously set in \p attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate each of its arguments exactly once. + * + * \param[out] attributes The attribute structure to write to. + * \param bits The key size in bits. + * If this is 0, the key size in \p attributes + * becomes unspecified. Keys of size 0 are + * not supported. + */ +static void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits); + +/** Retrieve the key type from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key type stored in the attribute structure. + */ +static psa_key_type_t psa_get_key_type(const psa_key_attributes_t *attributes); + +/** Retrieve the key size from key attributes. + * + * This function may be declared as `static` (i.e. without external + * linkage). This function may be provided as a function-like macro, + * but in this case it must evaluate its argument exactly once. + * + * \param[in] attributes The key attribute structure to query. + * + * \return The key size stored in the attribute structure, in bits. + */ +static size_t psa_get_key_bits(const psa_key_attributes_t *attributes); + +/** Retrieve the attributes of a key. + * + * This function first resets the attribute structure as with + * psa_reset_key_attributes(). It then copies the attributes of + * the given key into the given attribute structure. + * + * \note This function may allocate memory or other resources. + * Once you have called this function on an attribute structure, + * you must call psa_reset_key_attributes() to free these resources. + * + * \param[in] handle Handle to the key to query. + * \param[in,out] attributes On success, the attributes of the key. + * On failure, equivalent to a + * freshly-initialized structure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes); + +/** Reset a key attribute structure to a freshly initialized state. + * + * You must initialize the attribute structure as described in the + * documentation of the type #psa_key_attributes_t before calling this + * function. Once the structure has been initialized, you may call this + * function at any time. + * + * This function frees any auxiliary resources that the structure + * may contain. + * + * \param[in,out] attributes The attribute structure to reset. + */ +void psa_reset_key_attributes(psa_key_attributes_t *attributes); + +/**@}*/ + +/** \defgroup key_management Key management + * @{ + */ + +/** Open a handle to an existing persistent key. + * + * Open a handle to a persistent key. A key is persistent if it was created + * with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE. A persistent key + * always has a nonzero key identifier, set with psa_set_key_id() when + * creating the key. Implementations may provide additional pre-provisioned + * keys that can be opened with psa_open_key(). Such keys have a key identifier + * in the vendor range, as documented in the description of #psa_key_id_t. + * + * The application must eventually close the handle with psa_close_key() or + * psa_destroy_key() to release associated resources. If the application dies + * without calling one of these functions, the implementation should perform + * the equivalent of a call to psa_close_key(). + * + * Some implementations permit an application to open the same key multiple + * times. If this is successful, each call to psa_open_key() will return a + * different key handle. + * + * \note Applications that rely on opening a key multiple times will not be + * portable to implementations that only permit a single key handle to be + * opened. See also :ref:\`key-handles\`. + * + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the key. + * + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the key. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * The implementation does not have sufficient resources to open the + * key. This can be due to reaching an implementation limit on the + * number of open keys, the number of open key handles, or available + * memory. + * \retval #PSA_ERROR_DOES_NOT_EXIST + * There is no persistent key with key identifier \p id. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not a valid persistent key identifier. + * \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. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_open_key(psa_key_id_t id, + psa_key_handle_t *handle); + + +/** Close a key handle. + * + * If the handle designates a volatile key, this will destroy the key material + * and free all associated resources, just like psa_destroy_key(). + * + * If this is the last open handle to a persistent key, then closing the handle + * will free all resources associated with the key in volatile memory. The key + * data in persistent storage is not affected and can be opened again later + * with a call to psa_open_key(). + * + * Closing the key handle makes the handle invalid, and the key handle + * must not be used again by the application. + * + * \note If the key handle was used to set up an active + * :ref:\`multipart operation \`, then closing the + * key handle can cause the multipart operation to fail. Applications should + * maintain the key handle until after the multipart operation has finished. + * + * \param handle The key handle to close. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle or \c 0. It is now closed. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_close_key(psa_key_handle_t handle); + +/** 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. + * + * This function may be used to share a key with a different party, + * subject to implementation-defined restrictions on key sharing. + * + * The policy on the source key must have the usage flag + * #PSA_KEY_USAGE_COPY set. + * This flag is sufficient to permit the copy if the key has the lifetime + * #PSA_KEY_LIFETIME_VOLATILE or #PSA_KEY_LIFETIME_PERSISTENT. + * Some secure elements do not provide a way to copy a key without + * making it extractable from the secure element. If a key is located + * in such a secure element, then the key must have both usage flags + * #PSA_KEY_USAGE_COPY and #PSA_KEY_USAGE_EXPORT in order to make + * a copy of the key outside the secure element. + * + * The resulting key may only be used in a way that conforms to + * both the policy of the original key and the policy specified in + * the \p attributes parameter: + * - The usage flags on the resulting key are the bitwise-and of the + * usage flags on the source policy and the usage flags in \p attributes. + * - If both allow the same algorithm or wildcard-based + * algorithm policy, the resulting key has the same algorithm policy. + * - If either of the policies allows an algorithm and the other policy + * allows a wildcard-based algorithm policy that includes this algorithm, + * the resulting key allows the same algorithm. + * - If the policies do not allow any algorithm in common, this function + * fails with the status #PSA_ERROR_INVALID_ARGUMENT. + * + * The effect of this function on implementation-defined attributes is + * implementation-defined. + * + * \param source_handle The key to copy. It must be a valid key handle. + * \param[in] attributes The attributes for the new key. + * They are used as follows: + * - The key type and size may be 0. If either is + * nonzero, it must match the corresponding + * attribute of the source key. + * - The key location (the lifetime and, for + * persistent keys, the key identifier) is + * used directly. + * - The policy constraints (usage flags and + * algorithm policy) are combined from + * the source key and \p attributes so that + * both sets of restrictions apply, as + * described in the documentation of this function. + * \param[out] target_handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \p source_handle is invalid. + * \retval #PSA_ERROR_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The lifetime or identifier in \p attributes are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The policy constraints on the source and specified in + * \p attributes are incompatible. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p attributes specifies a key type or key size + * which does not match the attributes of the source key. + * \retval #PSA_ERROR_NOT_PERMITTED + * The source key does not have the #PSA_KEY_USAGE_COPY usage flag. + * \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_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle); + + +/** + * \brief Destroy a key. + * + * This function destroys a key from both volatile + * memory and, if applicable, non-volatile storage. Implementations shall + * make a best effort to ensure that that the key material cannot be recovered. + * + * This function also erases any metadata such as policies and frees + * resources associated with the key. To free all resources associated with + * the key, all handles to the key must be closed or destroyed. + * + * Destroying the key makes the handle invalid, and the key handle + * must not be used again by the application. Using other open handles to the + * destroyed key in a cryptographic operation will result in an error. + * + * If a key is currently in use in a multipart operation, then destroying the + * key will cause the multipart operation to fail. + * + * \param handle Handle to the key to erase. + * If this is \c 0, do nothing and return \c PSA_SUCCESS. + * + * \retval #PSA_SUCCESS + * \p handle was a valid handle and the key material that it + * referred to has been erased. + * Alternatively, \p handle is \c 0. + * \retval #PSA_ERROR_NOT_PERMITTED + * The key cannot be erased because it is + * read-only, either due to a policy or due to physical restrictions. + * \retval #PSA_ERROR_INVALID_HANDLE + * \p handle is not a valid handle nor \c 0. + * \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_CORRUPTION_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); + +/**@}*/ + +/** \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. + * + * The key data determines the key size. The attributes may optionally + * specify a key size; in this case it must match the size determined + * from the key data. A key size of 0 in \p attributes indicates that + * the key size is solely determined by the key data. + * + * Implementations must reject an attempt to import a key of size 0. + * + * 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[in] attributes The attributes for the new key. + * The key size is always determined from the + * \p data buffer. + * If the key size in \p attributes is nonzero, + * it must be equal to the size from \p data. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * \param[in] data Buffer containing the key data. The content of this + * buffer is interpreted according to the type declared + * in \p attributes. + * All implementations must support at least the format + * described in the documentation + * of psa_export_key() or psa_export_public_key() for + * the chosen type. Implementations may allow other + * formats, but should be conservative: implementations + * should err on the side of rejecting content if it + * may be erroneous (e.g. wrong type or truncated data). + * \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_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular persistent location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key attributes, as a whole, are invalid. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The key data is not correctly formatted. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size in \p attributes is nonzero and does not match the size + * of the key data. + * \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_CORRUPTION_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(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle); + + + +/** + * \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_KEY_PAIR), 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 elliptic curve key pairs (key types for which + * #PSA_KEY_TYPE_IS_ECC_KEY_PAIR 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 Diffie-Hellman key exchange key pairs (key types for which + * #PSA_KEY_TYPE_IS_DH_KEY_PAIR is true), the + * format is the representation of the private key `x` as a big-endian byte + * string. The length of the byte string is the private key size in bytes + * (leading zeroes are not stripped). + * - 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(). + * + * The policy on the key must have the usage flag #PSA_KEY_USAGE_EXPORT set. + * + * \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_NOT_PERMITTED + * The key does not have the #PSA_KEY_USAGE_EXPORT flag. + * \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_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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 Diffie-Hellman key exchange public keys (key types for which + * #PSA_KEY_TYPE_IS_DH_PUBLIC_KEY is true), + * the format is the representation of the public key `y = g^x mod p` as a + * big-endian byte string. The length of the byte string is the length of the + * base prime `p` in bytes. + * + * Exporting a public key object or the public part of a key pair is + * always permitted, regardless of the key's usage flags. + * + * \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_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_KEY_PAIR(\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_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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 hash Message digests + * @{ + */ + +/** Calculate the hash (digest) of a message. + * + * \note To verify the hash of a message against an + * expected value, use psa_hash_compare() instead. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\p alg). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p hash_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Calculate the hash (digest) of a message and compare it with a + * reference value. + * + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * \param[in] input Buffer containing the message to hash. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The hash of the message was calculated successfully, but it + * differs from the expected hash. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p input_length or \p hash_length do not match the hash size for \p alg + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length); + +/** The type of the state data structure for multipart hash operations. + * + * Before calling any function on a hash operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_hash_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_hash_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_HASH_OPERATION_INIT, + * for example: + * \code + * psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_hash_operation_init() + * to the structure, for example: + * \code + * psa_hash_operation_t operation; + * operation = psa_hash_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_hash_operation_s psa_hash_operation_t; + +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); + +/** Set up a multipart hash operation. + * + * The sequence of operations to calculate a hash (message digest) + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_hash_operation_t, e.g. #PSA_HASH_OPERATION_INIT. + * -# Call psa_hash_setup() to specify the algorithm. + * -# Call psa_hash_update() zero, one or more times, passing a fragment + * of the message each time. The hash that is calculated is the hash + * of the concatenation of these messages in order. + * -# To calculate the hash, call psa_hash_finish(). + * To compare the hash with an expected value, call psa_hash_verify(). + * + * If an error occurs at any step after a call to psa_hash_setup(), the + * operation will need to be reset by a call to psa_hash_abort(). The + * application may call psa_hash_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_hash_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_hash_finish() or psa_hash_verify(). + * - A call to psa_hash_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_hash_operation_t and not yet in use. + * \param alg The hash algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_HASH(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported hash algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a hash algorithm. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart hash operation. + * + * The application must call psa_hash_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \param[in,out] operation Active hash operation. + * \param[in] input Buffer containing the message fragment to hash. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it muct be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the hash of a message. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the hash. Call psa_hash_verify() instead. + * Beware that comparing integrity or authenticity data such as + * hash values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the hashed data which could allow an attacker to guess + * a valid hash and thereby bypass security controls. + * + * \param[in,out] operation Active hash operation. + * \param[out] hash Buffer where the hash is to be written. + * \param hash_size Size of the \p hash buffer in bytes. + * \param[out] hash_length On success, the number of bytes + * that make up the hash value. This is always + * #PSA_HASH_SIZE(\c alg) where \c alg is the + * hash algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \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) + * where \c alg is the hash algorithm that is calculated. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length); + +/** Finish the calculation of the hash of a message and compare it with + * an expected value. + * + * The application must call psa_hash_setup() before calling this function. + * This function calculates the hash of the message formed by concatenating + * the inputs passed to preceding calls to psa_hash_update(). It then + * compares the calculated hash with the expected hash passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_hash_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual hash and the expected hash is performed + * in constant time. + * + * \param[in,out] operation Active hash operation. + * \param[in] hash Buffer containing the expected hash value. + * \param hash_length Size of the \p hash buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected hash is identical to the actual hash of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * 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 (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length); + +/** Abort a hash operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_hash_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_hash_operation_t. + * + * In particular, calling psa_hash_abort() after the operation has been + * terminated by a call to psa_hash_abort(), psa_hash_finish() or + * psa_hash_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized hash operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_hash_abort(psa_hash_operation_t *operation); + +/** Clone a hash operation. + * + * This function copies the state of an ongoing hash operation to + * a new operation object. In other words, this function is equivalent + * to calling psa_hash_setup() on \p target_operation with the same + * algorithm that \p source_operation was set up for, then + * psa_hash_update() on \p target_operation with the same input that + * that was passed to \p source_operation. After this function returns, the + * two objects are independent, i.e. subsequent calls involving one of + * the objects do not affect the other object. + * + * \param[in] source_operation The active hash operation to clone. + * \param[in,out] target_operation The operation object to set up. + * It must be initialized but not active. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * The \p source_operation state is not valid (it must be active). + * \retval #PSA_ERROR_BAD_STATE + * The \p target_operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \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_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + +/**@}*/ + +/** \defgroup MAC Message authentication codes + * @{ + */ + +/** Calculate the MAC (message authentication code) of a message. + * + * \note To verify the MAC of a message against an + * expected value, use psa_mac_verify() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p mac_size is too small + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \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_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Calculate the MAC of a message and compare it with a reference value. + * + * \param handle Handle to the key to use for the operation. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * \param[in] input Buffer containing the input message. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the input. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The MAC of the message was calculated successfully, but it + * differs from the expected value. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \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_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length); + +/** The type of the state data structure for multipart MAC operations. + * + * Before calling any function on a MAC operation object, the application must + * initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_mac_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_mac_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_MAC_OPERATION_INIT, + * for example: + * \code + * psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_mac_operation_init() + * to the structure, for example: + * \code + * psa_mac_operation_t operation; + * operation = psa_mac_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_mac_operation_s psa_mac_operation_t; + +/** \def PSA_MAC_OPERATION_INIT + * + * This macro returns a suitable initializer for a MAC operation object of type + * #psa_mac_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + +/** Set up a multipart MAC calculation operation. + * + * This function sets up the calculation of the MAC + * (message authentication code) of a byte string. + * To verify the MAC of a message against an + * expected value, use psa_mac_verify_setup() instead. + * + * The sequence of operations to calculate a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_sign_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_sign_finish() to finish + * calculating the MAC value and retrieve it. + * + * If an error occurs at any step after a call to psa_mac_sign_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_sign_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_sign_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** 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. + * + * The sequence of operations to verify a MAC is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_mac_operation_t, e.g. #PSA_MAC_OPERATION_INIT. + * -# Call psa_mac_verify_setup() to specify the algorithm and key. + * -# Call psa_mac_update() zero, one or more times, passing a fragment + * of the message each time. The MAC that is calculated is the MAC + * of the concatenation of these messages in order. + * -# At the end of the message, call psa_mac_verify_finish() to finish + * calculating the actual MAC of the message and verify it against + * the expected value. + * + * If an error occurs at any step after a call to psa_mac_verify_setup(), the + * operation will need to be reset by a call to psa_mac_abort(). The + * application may call psa_mac_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_mac_verify_setup(), the application must + * eventually terminate the operation through one of the following methods: + * - A successful call to psa_mac_verify_finish(). + * - A call to psa_mac_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_mac_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value + * such that #PSA_ALG_IS_MAC(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c key is not compatible with \c alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a MAC algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * The key could not be retrieved from storage + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Add a message fragment to a multipart MAC operation. + * + * The application must call psa_mac_sign_setup() or psa_mac_verify_setup() + * before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \param[in,out] operation Active MAC operation. + * \param[in] input Buffer containing the message fragment to add to + * the MAC calculation. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Finish the calculation of the MAC of a message. + * + * The application must call psa_mac_sign_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \warning Applications should not call this function if they expect + * a specific value for the MAC. Call psa_mac_verify_finish() instead. + * Beware that comparing integrity or authenticity data such as + * MAC values with a function such as \c memcmp is risky + * because the time taken by the comparison may leak information + * about the MAC value which could allow an attacker to guess + * a valid MAC and thereby bypass security controls. + * + * \param[in,out] operation Active MAC operation. + * \param[out] mac Buffer where the MAC value is to be written. + * \param mac_size Size of the \p mac buffer in bytes. + * \param[out] mac_length On success, the number of bytes + * that make up the MAC value. This is always + * #PSA_MAC_FINAL_SIZE(\c key_type, \c key_bits, \c alg) + * where \c key_type and \c key_bits are the type and + * bit-size respectively of the key and \c alg is the + * MAC algorithm that is calculated. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active mac sign + * operation). + * \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(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length); + +/** Finish the calculation of the MAC of a message and compare it with + * an expected value. + * + * The application must call psa_mac_verify_setup() before calling this function. + * This function calculates the MAC of the message formed by concatenating + * the inputs passed to preceding calls to psa_mac_update(). It then + * compares the calculated MAC with the expected MAC passed as a + * parameter to this function. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_mac_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual MAC and the expected MAC is performed + * in constant time. + * + * \param[in,out] operation Active MAC operation. + * \param[in] mac Buffer containing the expected MAC value. + * \param mac_length Size of the \p mac buffer in bytes. + * + * \retval #PSA_SUCCESS + * The expected MAC is identical to the actual MAC of the message. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * 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 (it must be an active mac verify + * operation). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length); + +/** Abort a MAC operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_mac_sign_setup() or psa_mac_verify_setup() again. + * + * You may call this function any time after the operation object has + * been initialized by one of the methods described in #psa_mac_operation_t. + * + * In particular, calling psa_mac_abort() after the operation has been + * terminated by a call to psa_mac_abort(), psa_mac_sign_finish() or + * psa_mac_verify_finish() is safe and has no effect. + * + * \param[in,out] operation Initialized MAC operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_mac_abort(psa_mac_operation_t *operation); + +/**@}*/ + +/** \defgroup cipher Symmetric ciphers + * @{ + */ + +/** Encrypt a message using a symmetric cipher. + * + * This function encrypts a message with a random IV (initialization + * vector). Use the multipart operation interface with a + * #psa_cipher_operation_t object to provide other forms of IV. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * The output contains the IV followed by + * the ciphertext proper. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Decrypt a message using a symmetric cipher. + * + * This function decrypts a message encrypted with a symmetric cipher. + * + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * \param[in] input Buffer containing the message to decrypt. + * This consists of the IV followed by the + * ciphertext proper. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the plaintext is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** The type of the state data structure for multipart cipher operations. + * + * Before calling any function on a cipher operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_cipher_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_cipher_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_CIPHER_OPERATION_INIT, + * for example: + * \code + * psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_cipher_operation_init() + * to the structure, for example: + * \code + * psa_cipher_operation_t operation; + * operation = psa_cipher_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_cipher_operation_s psa_cipher_operation_t; + +/** \def PSA_CIPHER_OPERATION_INIT + * + * This macro returns a suitable initializer for a cipher operation object of + * type #psa_cipher_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** Return an initial value for a cipher operation object. + */ +static psa_cipher_operation_t psa_cipher_operation_init(void); + +/** Set the key for a multipart symmetric encryption operation. + * + * The sequence of operations to encrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_encrypt_setup() to specify the algorithm and key. + * -# Call either psa_cipher_generate_iv() or psa_cipher_set_iv() to + * generate or set the IV (initialization vector). You should use + * psa_cipher_generate_iv() unless the protocol you are implementing + * requires a specific IV value. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_encrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart symmetric decryption operation. + * + * The sequence of operations to decrypt a message with a symmetric cipher + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_cipher_operation_t, e.g. + * #PSA_CIPHER_OPERATION_INIT. + * -# Call psa_cipher_decrypt_setup() to specify the algorithm and key. + * -# Call psa_cipher_set_iv() with the IV (initialization vector) for the + * decryption. If the IV is prepended to the ciphertext, you can call + * psa_cipher_update() on a buffer containing the IV followed by the + * beginning of the message. + * -# Call psa_cipher_update() zero, one or more times, passing a fragment + * of the message each time. + * -# Call psa_cipher_finish(). + * + * If an error occurs at any step after a call to psa_cipher_decrypt_setup(), + * the operation will need to be reset by a call to psa_cipher_abort(). The + * application may call psa_cipher_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_cipher_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_cipher_finish(). + * - A call to psa_cipher_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_cipher_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The cipher algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_CIPHER(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not a cipher algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate an IV for a symmetric encryption operation. + * + * This function generates a random IV (initialization vector), nonce + * or initial counter value for the encryption operation as appropriate + * for the chosen algorithm, key type and key size. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] iv Buffer where the generated IV is to be written. + * \param iv_size Size of the \p iv buffer in bytes. + * \param[out] iv_length On success, the number of bytes of the + * generated IV. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no IV set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p iv buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_generate_iv(psa_cipher_operation_t *operation, + uint8_t *iv, + size_t iv_size, + size_t *iv_length); + +/** Set the IV for a symmetric encryption or decryption operation. + * + * This function sets the IV (initialization vector), nonce + * or initial counter value for the encryption or decryption operation. + * + * The application must call psa_cipher_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \note When encrypting, applications should use psa_cipher_generate_iv() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active cipher operation. + * \param[in] iv Buffer containing the IV to use. + * \param iv_length Size of the IV in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active cipher + * encrypt operation, with no IV 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. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_set_iv(psa_cipher_operation_t *operation, + const uint8_t *iv, + size_t iv_length); + +/** Encrypt or decrypt a message fragment in an active cipher operation. + * + * Before calling this function, you must: + * 1. Call either psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. If the algorithm requires an IV, call psa_cipher_generate_iv() + * (recommended when encrypting) or psa_cipher_set_iv(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting or decrypting a message in a cipher operation. + * + * The application must call psa_cipher_encrypt_setup() or + * psa_cipher_decrypt_setup() before calling this function. The choice + * of setup function determines whether this function encrypts or + * decrypts its input. + * + * This function finishes the encryption or decryption of the message + * formed by concatenating the inputs passed to preceding calls to + * psa_cipher_update(). + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_cipher_abort(). + * + * \param[in,out] operation Active cipher operation. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input size passed to this operation is not valid for + * this particular algorithm. For example, the algorithm is a based + * on block cipher and requires a whole number of blocks, but the + * total input size is not a multiple of the block size. + * \retval #PSA_ERROR_INVALID_PADDING + * This is a decryption operation for an algorithm that includes + * padding, and the ciphertext does not contain valid padding. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with an IV set + * if required for the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Abort a cipher operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_cipher_encrypt_setup() or psa_cipher_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_cipher_operation_t. + * + * In particular, calling psa_cipher_abort() after the operation has been + * terminated by a call to psa_cipher_abort() or psa_cipher_finish() + * is safe and has no effect. + * + * \param[in,out] operation Initialized cipher operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_cipher_abort(psa_cipher_operation_t *operation); + +/**@}*/ + +/** \defgroup aead Authenticated encryption with associated data (AEAD) + * @{ + */ + +/** Process an authenticated encryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that will be authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] plaintext Data that will be authenticated and + * encrypted. + * \param plaintext_length Size of \p plaintext in bytes. + * \param[out] ciphertext Output buffer for the authenticated and + * encrypted data. The additional data is not + * part of this output. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate outputs, the + * authentication tag is appended to the + * encrypted data. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(\p alg, + * \p plaintext_length). + * \param[out] ciphertext_length On success, the size of the output + * in the \p ciphertext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p ciphertext_size is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length); + +/** Process an authenticated decryption operation. + * + * \param handle Handle to the key to use for the operation. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param[in] nonce Nonce or IV to use. + * \param nonce_length Size of the \p nonce buffer in bytes. + * \param[in] additional_data Additional data that has been authenticated + * but not encrypted. + * \param additional_data_length Size of \p additional_data in bytes. + * \param[in] ciphertext Data that has been authenticated and + * encrypted. For algorithms where the + * encrypted data and the authentication tag + * are defined as separate inputs, the buffer + * must contain the encrypted data followed + * by the authentication tag. + * \param ciphertext_length Size of \p ciphertext in bytes. + * \param[out] plaintext Output buffer for the decrypted data. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(\p alg, + * \p ciphertext_length). + * \param[out] plaintext_length On success, the size of the output + * in the \p plaintext buffer. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The ciphertext is not authentic. + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p plaintext_size or \p nonce_length is too small + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length); + +/** The type of the state data structure for multipart AEAD operations. + * + * Before calling any function on an AEAD operation object, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_aead_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_aead_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_AEAD_OPERATION_INIT, + * for example: + * \code + * psa_aead_operation_t operation = PSA_AEAD_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_aead_operation_init() + * to the structure, for example: + * \code + * psa_aead_operation_t operation; + * operation = psa_aead_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. */ +typedef struct psa_aead_operation_s psa_aead_operation_t; + +/** \def PSA_AEAD_OPERATION_INIT + * + * This macro returns a suitable initializer for an AEAD operation object of + * type #psa_aead_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_AEAD_OPERATION_INIT {0} +#endif + +/** Return an initial value for an AEAD operation object. + */ +static psa_aead_operation_t psa_aead_operation_init(void); + +/** Set the key for a multipart authenticated encryption operation. + * + * The sequence of operations to encrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_encrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call either psa_aead_generate_nonce() or psa_aead_set_nonce() to + * generate or set the nonce. You should use + * psa_aead_generate_nonce() unless the protocol you are implementing + * requires a specific nonce value. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the message to encrypt each time. + * -# Call psa_aead_finish(). + * + * If an error occurs at any step after a call to psa_aead_encrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_encrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_finish(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Set the key for a multipart authenticated decryption operation. + * + * The sequence of operations to decrypt a message with authentication + * is as follows: + * -# Allocate an operation object which will be passed to all the functions + * listed here. + * -# Initialize the operation object with one of the methods described in the + * documentation for #psa_aead_operation_t, e.g. + * #PSA_AEAD_OPERATION_INIT. + * -# Call psa_aead_decrypt_setup() to specify the algorithm and key. + * -# If needed, call psa_aead_set_lengths() to specify the length of the + * inputs to the subsequent calls to psa_aead_update_ad() and + * psa_aead_update(). See the documentation of psa_aead_set_lengths() + * for details. + * -# Call psa_aead_set_nonce() with the nonce for the decryption. + * -# Call psa_aead_update_ad() zero, one or more times, passing a fragment + * of the non-encrypted additional authenticated data each time. + * -# Call psa_aead_update() zero, one or more times, passing a fragment + * of the ciphertext to decrypt each time. + * -# Call psa_aead_verify(). + * + * If an error occurs at any step after a call to psa_aead_decrypt_setup(), + * the operation will need to be reset by a call to psa_aead_abort(). The + * application may call psa_aead_abort() at any time after the operation + * has been initialized. + * + * After a successful call to psa_aead_decrypt_setup(), the application must + * eventually terminate the operation. The following events terminate an + * operation: + * - A successful call to psa_aead_verify(). + * - A call to psa_aead_abort(). + * + * \param[in,out] operation The operation object to set up. It must have + * been initialized as per the documentation for + * #psa_aead_operation_t and not yet in use. + * \param handle Handle to the key to use for the operation. + * It must remain valid until the operation + * terminates. + * \param alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p handle is not compatible with \p alg. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not supported or is not an AEAD algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg); + +/** Generate a random nonce for an authenticated encryption operation. + * + * This function generates a random nonce for the authenticated encryption + * operation with an appropriate size for the chosen algorithm, key type + * and key size. + * + * The application must call psa_aead_encrypt_setup() before + * calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] nonce Buffer where the generated nonce is to be + * written. + * \param nonce_size Size of the \p nonce buffer in bytes. + * \param[out] nonce_length On success, the number of bytes of the + * generated nonce. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active aead encrypt + operation, with no nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p nonce buffer is too small. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length); + +/** Set the nonce for an authenticated encryption or decryption operation. + * + * This function sets the nonce for the authenticated + * encryption or decryption operation. + * + * The application must call psa_aead_encrypt_setup() or + * psa_aead_decrypt_setup() before calling this function. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note When encrypting, applications should use psa_aead_generate_nonce() + * instead of this function, unless implementing a protocol that requires + * a non-random IV. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] nonce Buffer containing the nonce to use. + * \param nonce_length Size of the nonce in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, with no nonce + * set). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The size of \p nonce is not acceptable for the chosen algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length); + +/** Declare the lengths of the message and additional data for AEAD. + * + * The application must call this function before calling + * psa_aead_update_ad() or psa_aead_update() if the algorithm for + * the operation requires it. If the algorithm does not require it, + * calling this function is optional, but if this function is called + * then the implementation must enforce the lengths. + * + * You may call this function before or after setting the nonce with + * psa_aead_set_nonce() or psa_aead_generate_nonce(). + * + * - For #PSA_ALG_CCM, calling this function is required. + * - For the other AEAD algorithms defined in this specification, calling + * this function is not required. + * - For vendor-defined algorithm, refer to the vendor documentation. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param ad_length Size of the non-encrypted additional + * authenticated data in bytes. + * \param plaintext_length Size of the plaintext to encrypt in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, and + * psa_aead_update_ad() and psa_aead_update() must not have been + * called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * At least one of the lengths is not acceptable for the chosen + * algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length); + +/** Pass additional data to an active AEAD operation. + * + * Additional data is authenticated, but not encrypted. + * + * You may call this function multiple times to pass successive fragments + * of the additional data. You may not call this function after passing + * data to encrypt or decrypt with psa_aead_update(). + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS, + * treat the input as untrusted and prepare to undo any action that + * depends on the input if psa_aead_verify() returns an error status. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the fragment of + * additional data. + * \param input_length Size of the \p input buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, have lengths set if required by the algorithm, and + * psa_aead_update() must not have been called yet). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the additional data length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length); + +/** Encrypt or decrypt a message fragment in an active AEAD operation. + * + * Before calling this function, you must: + * 1. Call either psa_aead_encrypt_setup() or psa_aead_decrypt_setup(). + * The choice of setup function determines whether this function + * encrypts or decrypts its input. + * 2. Set the nonce with psa_aead_generate_nonce() or psa_aead_set_nonce(). + * 3. Call psa_aead_update_ad() to pass all the additional data. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \warning When decrypting, until psa_aead_verify() has returned #PSA_SUCCESS, + * there is no guarantee that the input is valid. Therefore, until + * you have called psa_aead_verify() and it has returned #PSA_SUCCESS: + * - Do not use the output in any way other than storing it in a + * confidential location. If you take any action that depends + * on the tentative decrypted data, this action will need to be + * undone if the input turns out not to be valid. Furthermore, + * if an adversary can observe that this action took place + * (for example through timing), they may be able to use this + * fact as an oracle to decrypt any message encrypted with the + * same key. + * - In particular, do not copy the output anywhere but to a + * memory or storage space that you have exclusive access to. + * + * This function does not require the input to be aligned to any + * particular block boundary. If the implementation can only process + * a whole block at a time, it must consume all the input provided, but + * it may delay the end of the corresponding output until a subsequent + * call to psa_aead_update(), psa_aead_finish() or psa_aead_verify() + * provides sufficient input. The amount of data that can be delayed + * in this way is bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE. + * + * \param[in,out] operation Active AEAD operation. + * \param[in] input Buffer containing the message fragment to + * encrypt or decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[out] output Buffer where the output is to be written. + * \param output_size Size of the \p output buffer in bytes. + * This must be at least + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, + * \p input_length) where \c alg is the + * algorithm that is being calculated. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active, have a nonce + * set, and have lengths set if required by the algorithm). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. + * You can determine a sufficient buffer size by calling + * #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c alg, \p input_length) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total input length overflows the plaintext length that + * was previously specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** Finish encrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_encrypt_setup(). + * + * This function finishes the authentication of the additional data + * formed by concatenating the inputs passed to preceding calls to + * psa_aead_update_ad() with the plaintext formed by concatenating the + * inputs passed to preceding calls to psa_aead_update(). + * + * This function has two output buffers: + * - \p ciphertext contains trailing ciphertext that was buffered from + * preceding calls to psa_aead_update(). + * - \p tag contains the authentication tag. Its length is always + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is the AEAD algorithm + * that the operation performs. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \param[in,out] operation Active AEAD operation. + * \param[out] ciphertext Buffer where the last part of the ciphertext + * is to be written. + * \param ciphertext_size Size of the \p ciphertext buffer in bytes. + * This must be at least + * #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] ciphertext_length On success, the number of bytes of + * returned ciphertext. + * \param[out] tag Buffer where the authentication tag is + * to be written. + * \param tag_size Size of the \p tag buffer in bytes. + * This must be at least + * #PSA_AEAD_TAG_LENGTH(\c alg) where \c alg is + * the algorithm that is being calculated. + * \param[out] tag_length On success, the number of bytes + * that make up the returned tag. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active encryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p ciphertext or \p tag buffer is too small. + * You can determine a sufficient buffer size for \p ciphertext by + * calling #PSA_AEAD_FINISH_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * You can determine a sufficient buffer size for \p tag by + * calling #PSA_AEAD_TAG_LENGTH(\c alg). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length); + +/** Finish authenticating and decrypting a message in an AEAD operation. + * + * The operation must have been set up with psa_aead_decrypt_setup(). + * + * This function finishes the authenticated decryption of the message + * components: + * + * - The additional data consisting of the concatenation of the inputs + * passed to preceding calls to psa_aead_update_ad(). + * - The ciphertext consisting of the concatenation of the inputs passed to + * preceding calls to psa_aead_update(). + * - The tag passed to this function call. + * + * If the authentication tag is correct, this function outputs any remaining + * plaintext and reports success. If the authentication tag is not correct, + * this function returns #PSA_ERROR_INVALID_SIGNATURE. + * + * When this function returns successfuly, the operation becomes inactive. + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_aead_abort(). + * + * \note Implementations shall make the best effort to ensure that the + * comparison between the actual tag and the expected tag is performed + * in constant time. + * + * \param[in,out] operation Active AEAD operation. + * \param[out] plaintext Buffer where the last part of the plaintext + * is to be written. This is the remaining data + * from previous calls to psa_aead_update() + * that could not be processed until the end + * of the input. + * \param plaintext_size Size of the \p plaintext buffer in bytes. + * This must be at least + * #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) where + * \c alg is the algorithm that is being + * calculated. + * \param[out] plaintext_length On success, the number of bytes of + * returned plaintext. + * \param[in] tag Buffer containing the authentication tag. + * \param tag_length Size of the \p tag buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculations were successful, but the authentication tag is + * not correct. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be an active decryption + * operation with a nonce set). + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p plaintext buffer is too small. + * You can determine a sufficient buffer size for \p plaintext by + * calling #PSA_AEAD_VERIFY_OUTPUT_SIZE(\c alg) + * where \c alg is the algorithm that is being calculated. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update_ad() so far is + * less than the additional data length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The total length of input to psa_aead_update() so far is + * less than the plaintext length that was previously + * specified with psa_aead_set_lengths(). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length); + +/** Abort an AEAD operation. + * + * Aborting an operation frees all associated resources except for the + * \p operation structure itself. Once aborted, the operation object + * can be reused for another operation by calling + * psa_aead_encrypt_setup() or psa_aead_decrypt_setup() again. + * + * You may call this function any time after the operation object has + * been initialized as described in #psa_aead_operation_t. + * + * In particular, calling psa_aead_abort() after the operation has been + * terminated by a call to psa_aead_abort(), psa_aead_finish() or + * psa_aead_verify() is safe and has no effect. + * + * \param[in,out] operation Initialized AEAD operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_aead_abort(psa_aead_operation_t *operation); + +/**@}*/ + +/** \defgroup asymmetric Asymmetric cryptography + * @{ + */ + +/** + * \brief Sign a hash or short message with a private key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message to sign. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[out] signature Buffer where the signature is to be written. + * \param signature_size Size of the \p signature buffer in bytes. + * \param[out] signature_length On success, the number of bytes + * that make up the returned signature value. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p signature buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \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_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length); + +/** + * \brief Verify the signature a hash or short message using a public key. + * + * Note that to perform a hash-and-sign signature algorithm, you must + * first calculate the hash by calling psa_hash_setup(), psa_hash_update() + * and psa_hash_finish(). Then pass the resulting hash as the \p hash + * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) + * to determine the hash algorithm to use. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. + * \param alg A signature algorithm that is compatible with + * the type of \p handle. + * \param[in] hash The hash or message whose signature is to be + * verified. + * \param hash_length Size of the \p hash buffer in bytes. + * \param[in] signature Buffer containing the signature to verify. + * \param signature_length Size of the \p signature buffer in bytes. + * + * \retval #PSA_SUCCESS + * The signature is valid. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_SIGNATURE + * The calculation was perfomed successfully, but the passed + * signature is not a valid signature. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length); + +/** + * \brief Encrypt a short message with a public key. + * + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to encrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the encrypted message is to + * be written. + * \param output_size Size of the \p output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \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_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/** + * \brief Decrypt a short message with a private key. + * + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. + * \param alg An asymmetric encryption algorithm that is + * compatible with the type of \p handle. + * \param[in] input The message to decrypt. + * \param input_length Size of the \p input buffer in bytes. + * \param[in] salt A salt or label, if supported by the + * encryption algorithm. + * If the algorithm does not support a + * salt, pass \c NULL. + * If the algorithm supports an optional + * salt and you do not want to pass a salt, + * pass \c NULL. + * + * - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is + * supported. + * \param salt_length Size of the \p salt buffer in bytes. + * If \p salt is \c NULL, pass 0. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * The size of the \p output buffer is too small. You can + * determine a sufficient buffer size by calling + * #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg) + * where \c key_type and \c key_bits are the type and bit-size + * respectively of \p handle. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INVALID_PADDING + * \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_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup key_derivation Key derivation and pseudorandom generation + * @{ + */ + +/** The type of the state data structure for key derivation operations. + * + * Before calling any function on a key derivation operation object, the + * application must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_derivation_operation_t operation; + * memset(&operation, 0, sizeof(operation)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_derivation_operation_t operation = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_DERIVATION_OPERATION_INIT, + * for example: + * \code + * psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT; + * \endcode + * - Assign the result of the function psa_key_derivation_operation_init() + * to the structure, for example: + * \code + * psa_key_derivation_operation_t operation; + * operation = psa_key_derivation_operation_init(); + * \endcode + * + * This is an implementation-defined \c struct. Applications should not + * make any assumptions about the content of this structure except + * as directed by the documentation of a specific implementation. + */ +typedef struct psa_key_derivation_s psa_key_derivation_operation_t; + +/** \def PSA_KEY_DERIVATION_OPERATION_INIT + * + * This macro returns a suitable initializer for a key derivation operation + * object of type #psa_key_derivation_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +#endif + +/** Return an initial value for a key derivation operation object. + */ +static psa_key_derivation_operation_t psa_key_derivation_operation_init(void); + +/** Set up a key derivation operation. + * + * A key derivation algorithm takes some inputs and uses them to generate + * a byte stream in a deterministic way. + * This byte stream can be used to produce keys and other + * cryptographic material. + * + * To derive a key: + * -# Start with an initialized object of type #psa_key_derivation_operation_t. + * -# Call psa_key_derivation_setup() to select the algorithm. + * -# Provide the inputs for the key derivation by calling + * psa_key_derivation_input_bytes() or psa_key_derivation_input_key() + * as appropriate. Which inputs are needed, in what order, and whether + * they may be keys and if so of what type depends on the algorithm. + * -# Optionally set the operation's maximum capacity with + * psa_key_derivation_set_capacity(). You may do this before, in the middle + * of or after providing inputs. For some algorithms, this step is mandatory + * because the output depends on the maximum capacity. + * -# To derive a key, call psa_key_derivation_output_key(). + * To derive a byte string for a different purpose, call + * psa_key_derivation_output_bytes(). + * Successive calls to these functions use successive output bytes + * calculated by the key derivation algorithm. + * -# Clean up the key derivation operation object with + * psa_key_derivation_abort(). + * + * If this function returns an error, the key derivation operation object is + * not changed. + * + * If an error occurs at any step after a call to psa_key_derivation_setup(), + * the operation will need to be reset by a call to psa_key_derivation_abort(). + * + * Implementations must reject an attempt to derive a key of size 0. + * + * \param[in,out] operation The key derivation operation object + * to set up. It must + * have been initialized but not set up yet. + * \param alg The key derivation algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c alg is not a key derivation algorithm. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be inactive). + * \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_key_derivation_setup( + psa_key_derivation_operation_t *operation, + psa_algorithm_t alg); + +/** Retrieve the current capacity of a key derivation operation. + * + * The capacity of a key derivation is the maximum number of bytes that it can + * return. When you get *N* bytes of output from a key derivation operation, + * this reduces its capacity by *N*. + * + * \param[in] operation The operation to query. + * \param[out] capacity On success, the capacity of the operation. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity); + +/** Set the maximum capacity of a key derivation operation. + * + * The capacity of a key derivation operation is the maximum number of bytes + * that the key derivation operation can return from this point onwards. + * + * \param[in,out] operation The key derivation operation object to modify. + * \param capacity The new capacity of the operation. + * It must be less or equal to the operation's + * current capacity. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p capacity is larger than the operation's current capacity. + * In this case, the operation object remains valid and its capacity + * remains unchanged. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active). + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity); + +/** Use the maximum possible capacity for a key derivation operation. + * + * Use this value as the capacity argument when setting up a key derivation + * to indicate that the operation should have the maximum possible capacity. + * The value of the maximum possible capacity depends on the key derivation + * algorithm. + */ +#define PSA_KEY_DERIVATION_UNLIMITED_CAPACITY ((size_t)(-1)) + +/** Provide an input for key derivation or key agreement. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function passes direct inputs, which is usually correct for + * non-secret inputs. To pass a secret input, which should be in a key + * object, call psa_key_derivation_input_key() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param[in] data Input data to use. + * \param data_length Size of the \p data buffer in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow direct inputs. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \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_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length); + +/** Provide an input for key derivation in the form of a key. + * + * Which inputs are required and in what order depends on the algorithm. + * Refer to the documentation of each key derivation or key agreement + * algorithm for information. + * + * This function obtains input from a key object, which is usually correct for + * secret inputs or for non-secret personalization strings kept in the key + * store. To pass a non-secret parameter which is not in the key store, + * call psa_key_derivation_input_bytes() instead of this function. + * Refer to the documentation of individual step types + * (`PSA_KEY_DERIVATION_INPUT_xxx` values of type ::psa_key_derivation_step_t) + * for more information. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() and must not + * have produced any output yet. + * \param step Which step the input data is for. + * \param handle Handle to the key. It must have an + * appropriate type for \p step and must + * allow the usage #PSA_KEY_USAGE_DERIVE. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step is not compatible with the operation's algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow key inputs of the given type + * or does not allow key inputs at all. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this input \p step. + * \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_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle); + +/** Perform a key agreement and use the shared secret as input to a key + * derivation. + * + * A key agreement algorithm takes two inputs: a private key \p private_key + * a public key \p peer_key. + * The result of this function is passed as input to a key derivation. + * The output of this key derivation can be extracted by reading from the + * resulting operation to produce keys and other cryptographic material. + * + * If this function returns an error status, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to use. + * It must have been set up with + * psa_key_derivation_setup() with a + * key agreement and derivation algorithm + * \c alg (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\c alg) is true + * and #PSA_ALG_IS_RAW_KEY_AGREEMENT(\c alg) + * is false). + * The operation must be ready for an + * input of the type given by \p step. + * \param step Which step the input data is for. + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. The peer key must be in the + * same format that psa_import_key() accepts for the + * public key type corresponding to the type of + * private_key. That is, this function performs the + * equivalent of + * #psa_import_key(..., + * `peer_key`, `peer_key_length`) where + * with key attributes indicating the public key + * type corresponding to the type of `private_key`. + * For example, for EC keys, this means that peer_key + * is interpreted as a point on the curve that the + * private key is on. The standard formats for public + * keys are documented in the documentation of + * psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid for this key agreement \p step. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c private_key is not compatible with \c alg, + * or \p peer_key is not valid for \c alg or not compatible with + * \c private_key. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \c alg is not supported or is not a key derivation algorithm. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \c step does not allow an input resulting from a key agreement. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length); + +/** Read some data from a key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm and + * return those bytes. + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads the requested number of bytes from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] output Buffer where the output will be written. + * \param output_length Number of bytes to output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * The operation's capacity was less than + * \p output_length bytes. Note that in this case, + * no output is written to the output buffer. + * The operation's capacity is set to 0, thus + * subsequent calls to this function will not + * succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length); + +/** Derive a key from an ongoing key derivation operation. + * + * This function calculates output bytes from a key derivation algorithm + * and uses those bytes to generate a key deterministically. + * The key's location, usage policy, type and size are taken from + * \p attributes. + * + * If you view the key derivation's output as a stream of bytes, this + * function destructively reads as many bytes as required from the + * stream. + * The operation's capacity decreases by the number of bytes read. + * + * If this function returns an error status other than + * #PSA_ERROR_INSUFFICIENT_DATA, the operation enters an error + * state and must be aborted by calling psa_key_derivation_abort(). + * + * How much output is produced and consumed from the operation, and how + * the key is derived, depends on the key type: + * + * - For key types for which the key is an arbitrary sequence of bytes + * of a given size, this function is functionally equivalent to + * calling #psa_key_derivation_output_bytes + * and passing the resulting output to #psa_import_key. + * However, this function has a security benefit: + * if the implementation provides an isolation boundary then + * the key material is not exposed outside the isolation boundary. + * As a consequence, for these key types, this function always consumes + * exactly (\p bits / 8) bytes from the operation. + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_AES; + * - #PSA_KEY_TYPE_ARC4; + * - #PSA_KEY_TYPE_CAMELLIA; + * - #PSA_KEY_TYPE_DERIVE; + * - #PSA_KEY_TYPE_HMAC. + * + * - For ECC keys on a Montgomery elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Montgomery curve), this function always draws a byte string whose + * length is determined by the curve, and sets the mandatory bits + * accordingly. That is: + * + * - #PSA_ECC_CURVE_CURVE25519: draw a 32-byte string + * and process it as specified in RFC 7748 §5. + * - #PSA_ECC_CURVE_CURVE448: draw a 56-byte string + * and process it as specified in RFC 7748 §5. + * + * - For key types for which the key is represented by a single sequence of + * \p bits bits with constraints as to which bit sequences are acceptable, + * this function draws a byte string of length (\p bits / 8) bytes rounded + * up to the nearest whole number of bytes. If the resulting byte string + * is acceptable, it becomes the key, otherwise the drawn bytes are discarded. + * This process is repeated until an acceptable byte string is drawn. + * The byte string drawn from the operation is interpreted as specified + * for the output produced by psa_export_key(). + * The following key types defined in this specification follow this scheme: + * + * - #PSA_KEY_TYPE_DES. + * Force-set the parity bits, but discard forbidden weak keys. + * For 2-key and 3-key triple-DES, the three keys are generated + * successively (for example, for 3-key triple-DES, + * if the first 8 bytes specify a weak key and the next 8 bytes do not, + * discard the first 8 bytes, use the next 8 bytes as the first key, + * and continue reading output from the operation to derive the other + * two keys). + * - Finite-field Diffie-Hellman keys (#PSA_KEY_TYPE_DH_KEY_PAIR(\c group) + * where \c group designates any Diffie-Hellman group) and + * ECC keys on a Weierstrass elliptic curve + * (#PSA_KEY_TYPE_ECC_KEY_PAIR(\c curve) where \c curve designates a + * Weierstrass curve). + * For these key types, interpret the byte string as integer + * in big-endian order. Discard it if it is not in the range + * [0, *N* - 2] where *N* is the boundary of the private key domain + * (the prime *p* for Diffie-Hellman, the subprime *q* for DSA, + * or the order of the curve's base point for ECC). + * Add 1 to the resulting integer and use this as the private key *x*. + * This method allows compliance to NIST standards, specifically + * the methods titled "key-pair generation by testing candidates" + * in NIST SP 800-56A §5.6.1.1.4 for Diffie-Hellman, + * in FIPS 186-4 §B.1.2 for DSA, and + * in NIST SP 800-56A §5.6.1.2.2 or + * FIPS 186-4 §B.4.2 for elliptic curve keys. + * + * - For other key types, including #PSA_KEY_TYPE_RSA_KEY_PAIR, + * the way in which the operation output is consumed is + * implementation-defined. + * + * In all cases, the data that is read is discarded from the operation. + * The operation's capacity is decreased by the number of bytes read. + * + * For algorithms that take an input step #PSA_KEY_DERIVATION_INPUT_SECRET, + * the input to that step must be provided with psa_key_derivation_input_key(). + * Future versions of this specification may include additional restrictions + * on the derived key based on the attributes and strength of the secret key. + * + * \param[in] attributes The attributes for the new key. + * \param[in,out] operation The key derivation operation object to read from. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \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_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_INSUFFICIENT_DATA + * There was not enough data to create the desired key. + * Note that in this case, no output is written to the output buffer. + * The operation's capacity is set to 0, thus subsequent calls to + * this function will not succeed, even with a smaller output buffer. + * \retval #PSA_ERROR_NOT_SUPPORTED + * The key type or key size is not supported, either by the + * implementation in general or in this particular location. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * The provided key attributes are not valid for the operation. + * \retval #PSA_ERROR_NOT_PERMITTED + * The #PSA_KEY_DERIVATION_INPUT_SECRET input was not provided through + * a key. + * \retval #PSA_ERROR_BAD_STATE + * The operation state is not valid (it must be active and completed + * all required input steps). + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle); + +/** Abort a key derivation operation. + * + * Aborting an operation frees all associated resources except for the \c + * operation structure itself. Once aborted, the operation object can be reused + * for another operation by calling psa_key_derivation_setup() again. + * + * This function may be called at any time after the operation + * object has been initialized as described in #psa_key_derivation_operation_t. + * + * In particular, it is valid to call psa_key_derivation_abort() twice, or to + * call psa_key_derivation_abort() on an operation that has not been set up. + * + * \param[in,out] operation The operation to abort. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_key_derivation_abort( + psa_key_derivation_operation_t *operation); + +/** Perform a key agreement and return the raw shared secret. + * + * \warning The raw result of a key agreement algorithm such as finite-field + * Diffie-Hellman or elliptic curve Diffie-Hellman has biases and should + * not be used directly as key material. It should instead be passed as + * input to a key derivation algorithm. To chain a key agreement with + * a key derivation, use psa_key_derivation_key_agreement() and other + * functions from the key derivation interface. + * + * \param alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_RAW_KEY_AGREEMENT(\p alg) + * is true). + * \param private_key Handle to the private key to use. + * \param[in] peer_key Public key of the peer. It must be + * in the same format that psa_import_key() + * accepts. The standard formats for public + * keys are documented in the documentation + * of psa_export_public_key(). + * \param peer_key_length Size of \p peer_key in bytes. + * \param[out] output Buffer where the decrypted message is to + * be written. + * \param output_size Size of the \c output buffer in bytes. + * \param[out] output_length On success, the number of bytes + * that make up the returned output. + * + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_NOT_PERMITTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p alg is not a key agreement algorithm + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p private_key is not compatible with \p alg, + * or \p peer_key is not valid for \p alg or not compatible with + * \p private_key. + * \retval #PSA_ERROR_BUFFER_TOO_SMALL + * \p output_size is too small + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p alg is not a supported key agreement algorithm. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length); + +/**@}*/ + +/** \defgroup random Random generation + * @{ + */ + +/** + * \brief Generate random bytes. + * + * \warning This function **can** fail! Callers MUST check the return status + * and MUST NOT use the content of the output buffer if the return + * status is not #PSA_SUCCESS. + * + * \note To generate a key, use psa_generate_key() instead. + * + * \param[out] output Output buffer for the generated data. + * \param output_size Number of bytes to generate and output. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_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_generate_random(uint8_t *output, + size_t output_size); + +/** + * \brief Generate a key or key pair. + * + * The key is generated randomly. + * Its location, usage policy, type and size are taken from \p attributes. + * + * Implementations must reject an attempt to generate a key of size 0. + * + * The following type-specific considerations apply: + * - For RSA keys (#PSA_KEY_TYPE_RSA_KEY_PAIR), + * the public exponent is 65537. + * The modulus is a product of two probabilistic primes + * between 2^{n-1} and 2^n where n is the bit size specified in the + * attributes. + * + * \param[in] attributes The attributes for the new key. + * \param[out] handle On success, a handle to the newly created key. + * \c 0 on failure. + * + * \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_ALREADY_EXISTS + * This is an attempt to create a persistent key, and there is + * already a persistent key with the given identifier. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_CORRUPTION_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_STORAGE_FAILURE + * \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_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +/* The file "crypto_sizes.h" contains definitions for size calculation + * macros whose definitions are implementation-specific. */ +#include "psa/crypto_sizes.h" + +/* The file "crypto_struct.h" contains definitions for + * implementation-specific structs that are declared above. */ +#include "psa/crypto_struct.h" + +/* The file "crypto_extra.h" contains vendor-specific definitions. This + * can include vendor-defined algorithms, extra functions, etc. */ +#include "psa/crypto_extra.h" + +#endif /* PSA_CRYPTO_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h new file mode 100644 index 0000000000..518008b8a7 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_compat.h @@ -0,0 +1,111 @@ +/** + * \file psa/crypto_compat.h + * + * \brief PSA cryptography module: Backward compatibility aliases + * + * This header declares alternative names for macro and functions. + * New application code should not use these names. + * These names may be removed in a future version of Mbed Crypto. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + */ +/* + * Copyright (C) 2019-2020, 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_COMPAT_H +#define PSA_CRYPTO_COMPAT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) + +/* + * Mechanism for declaring deprecated values + */ +#if defined(MBEDTLS_DEPRECATED_WARNING) && !defined(MBEDTLS_PSA_DEPRECATED) +#define MBEDTLS_PSA_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_PSA_DEPRECATED +#endif + +typedef MBEDTLS_PSA_DEPRECATED size_t mbedtls_deprecated_size_t; +typedef MBEDTLS_PSA_DEPRECATED psa_status_t mbedtls_deprecated_psa_status_t; +typedef MBEDTLS_PSA_DEPRECATED psa_key_usage_t mbedtls_deprecated_psa_key_usage_t; + +#define MBEDTLS_DEPRECATED_CONSTANT( type, value ) \ + ( (mbedtls_deprecated_##type) ( value ) ) + +/* + * Deprecated PSA Crypto error code definitions (PSA Crypto API <= 1.0 beta2) + */ +#define PSA_ERROR_UNKNOWN_ERROR \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_GENERIC_ERROR ) +#define PSA_ERROR_OCCUPIED_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_ALREADY_EXISTS ) +#define PSA_ERROR_EMPTY_SLOT \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_DOES_NOT_EXIST ) +#define PSA_ERROR_INSUFFICIENT_CAPACITY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_INSUFFICIENT_DATA ) +#define PSA_ERROR_TAMPERING_DETECTED \ + MBEDTLS_DEPRECATED_CONSTANT( psa_status_t, PSA_ERROR_CORRUPTION_DETECTED ) + +/* + * Deprecated PSA Crypto numerical encodings (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_KEY_USAGE_SIGN \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_SIGN_HASH ) +#define PSA_KEY_USAGE_VERIFY \ + MBEDTLS_DEPRECATED_CONSTANT( psa_key_usage_t, PSA_KEY_USAGE_VERIFY_HASH ) + +/* + * Deprecated PSA Crypto size calculation macros (PSA Crypto API <= 1.0 beta3) + */ +#define PSA_ASYMMETRIC_SIGNATURE_MAX_SIZE \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGNATURE_MAX_SIZE ) +#define PSA_ASYMMETRIC_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) \ + MBEDTLS_DEPRECATED_CONSTANT( size_t, PSA_SIGN_OUTPUT_SIZE( key_type, key_bits, alg ) ) + +/* + * Deprecated PSA Crypto function names (PSA Crypto API <= 1.0 beta3) + */ +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_sign( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length ); + +MBEDTLS_PSA_DEPRECATED psa_status_t psa_asymmetric_verify( psa_key_handle_t key, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length ); + +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_COMPAT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h new file mode 100644 index 0000000000..33c9c0537a --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_extra.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_extra.h + * + * \brief PSA cryptography module: vendor extensions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file is reserved for vendor-specific definitions. + */ + +#ifndef PSA_CRYPTO_EXTRA_H +#define PSA_CRYPTO_EXTRA_H + +#include "psa/crypto_compat.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Declare the enrollment algorithm for a key. + * + * An operation on a key may indifferently use the algorithm set with + * psa_set_key_algorithm() or with this function. + * + * \param[out] attributes The attribute structure to write to. + * \param alg2 A second algorithm that the key may be used + * for, in addition to the algorithm set with + * psa_set_key_algorithm(). + * + * \warning Setting an enrollment algorithm is not recommended, because + * using the same key with different algorithms can allow some + * attacks based on arithmetic relations between different + * computations made with the same key, or can escalate harmless + * side channels into exploitable ones. Use this function only + * if it is necessary to support a protocol for which it has been + * verified that the usage of the key with multiple algorithms + * is safe. + */ +static inline void psa_set_key_enrollment_algorithm( + psa_key_attributes_t *attributes, + psa_algorithm_t alg2) +{ + attributes->core.policy.alg2 = alg2; +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_EXTRA_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h new file mode 100644 index 0000000000..c3120e485b --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_platform.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_platform.h + * + * \brief PSA cryptography module: Mbed TLS platform definitions + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains platform-dependent type definitions. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + */ + +#ifndef PSA_CRYPTO_PLATFORM_H +#define PSA_CRYPTO_PLATFORM_H + +/* PSA requires several types which C99 provides in stdint.h. */ +#include + +/* 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; + +#endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h new file mode 100644 index 0000000000..4f67501b56 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_sizes.h @@ -0,0 +1,650 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_sizes.h + * + * \brief PSA cryptography module: Mbed TLS buffer size macros + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of macros that are useful to + * compute buffer sizes. The signatures and semantics of these macros + * are standardized, but the definitions are not, because they depend on + * the available algorithms and, in some cases, on permitted tolerances + * on buffer sizes. + * + * In implementations with isolation between the application and the + * cryptography module, implementers should take care to ensure that + * the definitions that are exposed to applications match what the + * module implements. + * + * Macros that compute sizes whose values do not depend on the + * implementation are in crypto.h. + */ + +#ifndef PSA_CRYPTO_SIZES_H +#define PSA_CRYPTO_SIZES_H + +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +#define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \ + (((length) + (block_size) - 1) / (block_size) * (block_size)) + +/** The size of the output of psa_hash_finish(), in bytes. + * + * This is also the hash size that psa_hash_verify() expects. + * + * \param alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p alg) is true), or an HMAC algorithm + * (#PSA_ALG_HMAC(\c hash_alg) where \c hash_alg is a + * hash algorithm). + * + * \return The hash size for the specified hash algorithm. + * If the hash algorithm is not recognized, return 0. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + +/** \def PSA_HASH_MAX_SIZE + * + * Maximum size of a hash. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a hash supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226, + * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for + * HMAC-SHA3-512. */ +#define PSA_HASH_MAX_SIZE 64 +#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128 + +/** \def PSA_MAC_MAX_SIZE + * + * Maximum size of a MAC. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a MAC supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +/* All non-HMAC MACs have a maximum size that's smaller than the + * minimum possible value of PSA_HASH_MAX_SIZE in this implementation. */ +/* Note that the encoding of truncated MAC algorithms limits this value + * to 64 bytes. + */ +#define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE + +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + +/* The maximum size of an RSA key on this implementation, in bits. + * This is a vendor-specific macro. + * + * Mbed TLS does not set a hard limit on the size of RSA keys: any key + * whose parameters fit in a bignum is accepted. However large keys can + * induce a large memory usage and long computation times. Unlike other + * auxiliary macros in this file and in crypto.h, which reflect how the + * library is configured, this macro defines how the library is + * configured. This implementation refuses to import or generate an + * RSA key whose size is larger than the value defined here. + * + * Note that an implementation may set different size limits for different + * operations, and does not need to accept all key sizes up to the limit. */ +#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096 + +/* The maximum size of an ECC key on this implementation, in bits. + * This is a vendor-specific macro. */ +#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521 + +/** Bit size associated with an elliptic curve. + * + * \param curve An elliptic curve (value of type #psa_ecc_curve_t). + * + * \return The size associated with \p curve, in bits. + * This may be 0 if the implementation does not support + * the specified curve. + */ +#define PSA_ECC_CURVE_BITS(curve) \ + ((curve) == PSA_ECC_CURVE_SECT163K1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R1 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT163R2 ? 163 : \ + (curve) == PSA_ECC_CURVE_SECT193R1 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT193R2 ? 193 : \ + (curve) == PSA_ECC_CURVE_SECT233K1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT233R1 ? 233 : \ + (curve) == PSA_ECC_CURVE_SECT239K1 ? 239 : \ + (curve) == PSA_ECC_CURVE_SECT283K1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT283R1 ? 283 : \ + (curve) == PSA_ECC_CURVE_SECT409K1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT409R1 ? 409 : \ + (curve) == PSA_ECC_CURVE_SECT571K1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECT571R1 ? 571 : \ + (curve) == PSA_ECC_CURVE_SECP160K1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R1 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP160R2 ? 160 : \ + (curve) == PSA_ECC_CURVE_SECP192K1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP192R1 ? 192 : \ + (curve) == PSA_ECC_CURVE_SECP224K1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP224R1 ? 224 : \ + (curve) == PSA_ECC_CURVE_SECP256K1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_SECP384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_SECP521R1 ? 521 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P256R1 ? 256 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P384R1 ? 384 : \ + (curve) == PSA_ECC_CURVE_BRAINPOOL_P512R1 ? 512 : \ + (curve) == PSA_ECC_CURVE_CURVE25519 ? 255 : \ + (curve) == PSA_ECC_CURVE_CURVE448 ? 448 : \ + 0) + +/** \def PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN + * + * This macro returns the maximum length of the PSK supported + * by the TLS-1.2 PSK-to-MS key derivation. + * + * Quoting RFC 4279, Sect 5.3: + * TLS implementations supporting these ciphersuites MUST support + * arbitrary PSK identities up to 128 octets in length, and arbitrary + * PSKs up to 64 octets in length. Supporting longer identities and + * keys is RECOMMENDED. + * + * Therefore, no implementation should define a value smaller than 64 + * for #PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN. + */ +#define PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN 128 + +/** The maximum size of a block cipher supported by the implementation. */ +#define PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE 16 + +/** The size of the output of psa_mac_sign_finish(), in bytes. + * + * This is also the MAC size that psa_mac_verify_finish() expects. + * + * \param key_type The type of the MAC key. + * \param key_bits The size of the MAC key in bits. + * \param alg A MAC algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_MAC(\p alg) is true). + * + * \return The MAC size for the specified algorithm with + * the specified key parameters. + * \return 0 if the MAC algorithm is not recognized. + * \return Either 0 or the correct size for a MAC algorithm that + * the implementation recognizes, but does not support. + * \return Unspecified if the key parameters are not consistent + * with the algorithm. + */ +#define PSA_MAC_FINAL_SIZE(key_type, key_bits, alg) \ + ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) : \ + PSA_ALG_IS_HMAC(alg) ? PSA_HASH_SIZE(PSA_ALG_HMAC_GET_HASH(alg)) : \ + PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type) : \ + ((void)(key_type), (void)(key_bits), 0)) + +/** The maximum size of the output of psa_aead_encrypt(), in bytes. + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_encrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the ciphertext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param plaintext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(alg, plaintext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (plaintext_length) + PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** The maximum size of the output of psa_aead_decrypt(), in bytes. + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_decrypt() will not fail due to an + * insufficient buffer size. Depending on the algorithm, the actual size of + * the plaintext may be smaller. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param ciphertext_length Size of the plaintext in bytes. + * + * \return The AEAD ciphertext size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_DECRYPT_OUTPUT_SIZE(alg, ciphertext_length) \ + (PSA_AEAD_TAG_LENGTH(alg) != 0 ? \ + (ciphertext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ + 0) + +/** A sufficient output buffer size for psa_aead_update(). + * + * If the size of the output buffer is at least this large, it is + * guaranteed that psa_aead_update() will not fail due to an + * insufficient buffer size. The actual size of the output may be smaller + * in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * \param input_length Size of the input in bytes. + * + * \return A sufficient output buffer size for the specified + * algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +/* For all the AEAD modes defined in this specification, it is possible + * to emit output without delay. However, hardware may not always be + * capable of this. So for modes based on a block cipher, allow the + * implementation to delay the output until it has a full block. */ +#define PSA_AEAD_UPDATE_OUTPUT_SIZE(alg, input_length) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_ROUND_UP_TO_MULTIPLE(PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE, (input_length)) : \ + (input_length)) + +/** A sufficient ciphertext buffer size for psa_aead_finish(). + * + * If the size of the ciphertext buffer is at least this large, it is + * guaranteed that psa_aead_finish() will not fail due to an + * insufficient ciphertext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient ciphertext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_FINISH_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +/** A sufficient plaintext buffer size for psa_aead_verify(). + * + * If the size of the plaintext buffer is at least this large, it is + * guaranteed that psa_aead_verify() will not fail due to an + * insufficient plaintext buffer size. The actual size of the output may + * be smaller in any given call. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return A sufficient plaintext buffer size for the + * specified algorithm. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_VERIFY_OUTPUT_SIZE(alg) \ + (PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ? \ + PSA_MAX_BLOCK_CIPHER_BLOCK_SIZE : \ + 0) + +#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*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + +/** Sufficient signature buffer size for psa_sign_hash(). + * + * This macro returns a sufficient buffer size for a signature using a key + * of the specified type and size, with the specified algorithm. + * Note that the actual size of the signature may be smaller + * (some algorithms produce a variable-size signature). + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \ + ((void)alg, 0)) + +#define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE \ + PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) + +/** \def PSA_SIGNATURE_MAX_SIZE + * + * Maximum size of an asymmetric signature. + * + * This macro must expand to a compile-time constant integer. This value + * should be the maximum size of a signature supported by the implementation, + * in bytes, and must be no smaller than this maximum. + */ +#define PSA_SIGNATURE_MAX_SIZE \ + (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \ + PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) : \ + PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE) + +/** Sufficient output buffer size for psa_asymmetric_encrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_encrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + ((void)alg, PSA_BITS_TO_BYTES(key_bits)) : \ + 0) + +/** Sufficient output buffer size for psa_asymmetric_decrypt(). + * + * This macro returns a sufficient buffer size for a ciphertext produced using + * a key of the specified type and size, with the specified algorithm. + * Note that the actual size of the ciphertext may be smaller, depending + * on the algorithm. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * \param key_type An asymmetric key type (this may indifferently be a + * key pair type or a public key type). + * \param key_bits The size of the key in bits. + * \param alg The signature algorithm. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_asymmetric_decrypt() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg) \ + (PSA_KEY_TYPE_IS_RSA(key_type) ? \ + PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) : \ + 0) + +/* Maximum size of the ASN.1 encoding of an INTEGER with the specified + * number of bits. + * + * This definition assumes that bits <= 2^19 - 9 so that the length field + * is at most 3 bytes. The length of the encoding is the length of the + * bit string padded to a whole number of bytes plus: + * - 1 type byte; + * - 1 to 3 length bytes; + * - 0 to 1 bytes of leading 0 due to the sign bit. + */ +#define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits) \ + ((bits) / 8 + 5) + +/* Maximum size of the export encoding of an RSA public key. + * Assumes that the public exponent is less than 2^32. + * + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER } -- e + * + * - 4 bytes of SEQUENCE overhead; + * - n : INTEGER; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) + +/* Maximum size of the export encoding of an RSA key pair. + * Assumes thatthe public exponent is less than 2^32 and that the size + * difference between the two primes is at most 1 bit. + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * modulus INTEGER, -- N-bit + * publicExponent INTEGER, -- 32-bit + * privateExponent INTEGER, -- N-bit + * prime1 INTEGER, -- N/2-bit + * prime2 INTEGER, -- N/2-bit + * exponent1 INTEGER, -- N/2-bit + * exponent2 INTEGER, -- N/2-bit + * coefficient INTEGER, -- N/2-bit + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 7 half-size INTEGERs plus 2 full-size INTEGERs, + * overapproximated as 9 half-size INTEGERS; + * - 7 bytes for the public exponent. + */ +#define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14) + +/* Maximum size of the export encoding of a DSA public key. + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } -- contains DSAPublicKey + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters Dss-Parms } -- SEQUENCE of 3 INTEGERs + * DSAPublicKey ::= INTEGER -- public key, Y + * + * - 3 * 4 bytes of SEQUENCE overhead; + * - 1 + 1 + 7 bytes of algorithm (DSA OID); + * - 4 bytes of BIT STRING overhead; + * - 3 full-size INTEGERs (p, g, y); + * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59) + +/* Maximum size of the export encoding of a DSA key pair. + * + * DSAPrivateKey ::= SEQUENCE { + * version Version, -- 0 + * prime INTEGER, -- p + * subprime INTEGER, -- q + * generator INTEGER, -- g + * public INTEGER, -- y + * private INTEGER, -- x + * } + * + * - 4 bytes of SEQUENCE overhead; + * - 3 bytes of version; + * - 3 full-size INTEGERs (p, g, y); + * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits). + */ +#define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75) + +/* Maximum size of the export encoding of an ECC public key. + * + * The representation of an ECC public key is: + * - 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; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. + */ +#define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) + +/* Maximum size of the export encoding of an ECC key pair. + * + * An ECC key pair is represented by the secret value. + */ +#define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) \ + (PSA_BITS_TO_BYTES(key_bits)) + +/** Sufficient output buffer size for psa_export_key() or psa_export_public_key(). + * + * This macro returns a compile-time constant if its arguments are + * compile-time constants. + * + * \warning This function may call its arguments multiple times or + * zero times, so you should not pass arguments that contain + * side effects. + * + * The following code illustrates how to allocate enough memory to export + * a key by querying the key type and size at runtime. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * For psa_export_public_key(), calculate the buffer size from the + * public key type. You can use the macro #PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR + * to convert a key pair type to the corresponding public key type. + * \code{c} + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * psa_status_t status; + * status = psa_get_key_attributes(key, &attributes); + * if (status != PSA_SUCCESS) handle_error(...); + * psa_key_type_t key_type = psa_get_key_type(&attributes); + * psa_key_type_t public_key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type); + * size_t key_bits = psa_get_key_bits(&attributes); + * size_t buffer_size = PSA_KEY_EXPORT_MAX_SIZE(public_key_type, key_bits); + * psa_reset_key_attributes(&attributes); + * uint8_t *buffer = malloc(buffer_size); + * if (buffer == NULL) handle_error(...); + * size_t buffer_length; + * status = psa_export_public_key(key, buffer, buffer_size, &buffer_length); + * if (status != PSA_SUCCESS) handle_error(...); + * \endcode + * + * \param key_type A supported key type. + * \param key_bits The size of the key in bits. + * + * \return If the parameters are valid and supported, return + * a buffer size in bytes that guarantees that + * psa_sign_hash() will not fail with + * #PSA_ERROR_BUFFER_TOO_SMALL. + * If the parameters are a valid combination that is not supported + * by the implementation, this macro shall return either a + * sensible size or 0. + * If the parameters are not valid, the + * return value is unspecified. + */ +#define PSA_KEY_EXPORT_MAX_SIZE(key_type, key_bits) \ + (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) : \ + (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) : \ + PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \ + 0) + +#endif /* PSA_CRYPTO_SIZES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h new file mode 100644 index 0000000000..403a734000 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_struct.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_struct.h + * + * \brief PSA cryptography module: structured type implementations + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. + * + * This file contains the definitions of some data structures with + * implementation-specific definitions. + * + * In implementations with isolation between the application and the + * cryptography module, it is expected that the front-end and the back-end + * would have different versions of this file. + */ + +#ifndef PSA_CRYPTO_STRUCT_H +#define PSA_CRYPTO_STRUCT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Note that the below structures are different from the decalrations in + * mbed-crypto. This is because TF-M maintains 'front-end' and 'back-end' + * versions of this header. In the front-end version, exported to NS + * clients in interface/include/psa, a crypto operation is defined as an + * opaque handle to a context in the Crypto service. The back-end + * version, directly included from the mbed-crypto repo by the Crypto + * service, contains the full definition of the operation structs. + * + * One of the functions of the Crypto service is to allocate the back-end + * operation contexts in its own partition memory (in crypto_alloc.c), + * and then do the mapping between front-end operation handles passed by + * NS clients and the corresponding back-end operation contexts. The + * advantage of doing it this way is that internal mbed-crypto state is never + * exposed to the NS client. + */ + +struct psa_hash_operation_s +{ + uint32_t handle; +}; + +#define PSA_HASH_OPERATION_INIT {0} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + +struct psa_mac_operation_s +{ + uint32_t handle; +}; + +#define PSA_MAC_OPERATION_INIT {0} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + +struct psa_cipher_operation_s +{ + uint32_t handle; +}; + +#define PSA_CIPHER_OPERATION_INIT {0} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + +struct psa_aead_operation_s +{ + uint32_t handle; +}; + +#define PSA_AEAD_OPERATION_INIT {0} +static inline struct psa_aead_operation_s psa_aead_operation_init( void ) +{ + const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT; + return( v ); +} + +struct psa_key_derivation_s +{ + uint32_t handle; +}; + +#define PSA_KEY_DERIVATION_OPERATION_INIT {0} +static inline struct psa_key_derivation_s psa_key_derivation_operation_init( void ) +{ + const struct psa_key_derivation_s v = PSA_KEY_DERIVATION_OPERATION_INIT; + return( v ); +} + +struct psa_key_policy_s +{ + psa_key_usage_t usage; + psa_algorithm_t alg; + psa_algorithm_t alg2; +}; +typedef struct psa_key_policy_s psa_key_policy_t; + +#define PSA_KEY_POLICY_INIT {0, 0, 0} +static inline struct psa_key_policy_s psa_key_policy_init( void ) +{ + const struct psa_key_policy_s v = PSA_KEY_POLICY_INIT; + return( v ); +} + +/* The type used internally for key sizes. + * Public interfaces use size_t, but internally we use a smaller type. */ +typedef uint16_t psa_key_bits_t; +/* The maximum value of the type used to represent bit-sizes. + * This is used to mark an invalid key size. */ +#define PSA_KEY_BITS_TOO_LARGE ( (psa_key_bits_t) ( -1 ) ) +/* The maximum size of a key in bits. + * Currently defined as the maximum that can be represented, rounded down + * to a whole number of bytes. + * This is an uncast value so that it can be used in preprocessor + * conditionals. */ +#define PSA_MAX_KEY_BITS 0xfff8 + +/** A mask of flags that can be stored in key attributes. + * + * This type is also used internally to store flags in slots. Internal + * flags are defined in library/psa_crypto_core.h. Internal flags may have + * the same value as external flags if they are properly handled during + * key creation and in psa_get_key_attributes. + */ +typedef uint16_t psa_key_attributes_flag_t; + +#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER \ + ( (psa_key_attributes_flag_t) 0x0001 ) + +/* A mask of key attribute flags used externally only. + * Only meant for internal checks inside the library. */ +#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY ( \ + MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER | \ + 0 ) + +/* A mask of key attribute flags used both internally and externally. + * Currently there aren't any. */ +#define MBEDTLS_PSA_KA_MASK_DUAL_USE ( \ + 0 ) + +typedef struct +{ + psa_key_type_t type; + psa_key_lifetime_t lifetime; + psa_key_id_t id; + psa_key_policy_t policy; + psa_key_bits_t bits; + psa_key_attributes_flag_t flags; +} psa_core_key_attributes_t; + +#define PSA_CORE_KEY_ATTRIBUTES_INIT {0, 0, PSA_KEY_ID_INIT, PSA_KEY_POLICY_INIT, 0, 0} + +struct psa_key_attributes_s +{ + psa_core_key_attributes_t core; +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) + psa_key_slot_number_t slot_number; +#endif /* MBEDTLS_PSA_CRYPTO_SE_C */ + void *domain_parameters; + size_t domain_parameters_size; +}; + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0} +#else +#define PSA_KEY_ATTRIBUTES_INIT {PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0} +#endif + +static inline struct psa_key_attributes_s psa_key_attributes_init( void ) +{ + const struct psa_key_attributes_s v = PSA_KEY_ATTRIBUTES_INIT; + return( v ); +} + +static inline void psa_set_key_id(psa_key_attributes_t *attributes, + psa_key_id_t id) +{ + attributes->core.id = id; + if( attributes->core.lifetime == PSA_KEY_LIFETIME_VOLATILE ) + attributes->core.lifetime = PSA_KEY_LIFETIME_PERSISTENT; +} + +static inline psa_key_id_t psa_get_key_id( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.id ); +} + +static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes, + psa_key_lifetime_t lifetime) +{ + attributes->core.lifetime = lifetime; + if( lifetime == PSA_KEY_LIFETIME_VOLATILE ) + { +#ifdef MBEDTLS_PSA_CRYPTO_KEY_FILE_ID_ENCODES_OWNER + attributes->core.id.key_id = 0; + attributes->core.id.owner = 0; +#else + attributes->core.id = 0; +#endif + } +} + +static inline psa_key_lifetime_t psa_get_key_lifetime( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.lifetime ); +} + +static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes, + psa_key_usage_t usage_flags) +{ + attributes->core.policy.usage = usage_flags; +} + +static inline psa_key_usage_t psa_get_key_usage_flags( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.usage ); +} + +static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes, + psa_algorithm_t alg) +{ + attributes->core.policy.alg = alg; +} + +static inline psa_algorithm_t psa_get_key_algorithm( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.policy.alg ); +} + +/* This function is declared in crypto_extra.h, which comes after this + * header file, but we need the function here, so repeat the declaration. */ +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length); + +static inline void psa_set_key_type(psa_key_attributes_t *attributes, + psa_key_type_t type) +{ + if( attributes->domain_parameters == NULL ) + { + /* Common case: quick path */ + attributes->core.type = type; + } + else + { + /* Call the bigger function to free the old domain paramteres. + * Ignore any errors which may arise due to type requiring + * non-default domain parameters, since this function can't + * report errors. */ + (void) psa_set_key_domain_parameters( attributes, type, NULL, 0 ); + } +} + +static inline psa_key_type_t psa_get_key_type( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.type ); +} + +static inline void psa_set_key_bits(psa_key_attributes_t *attributes, + size_t bits) +{ + if( bits > PSA_MAX_KEY_BITS ) + attributes->core.bits = PSA_KEY_BITS_TOO_LARGE; + else + attributes->core.bits = (psa_key_bits_t) bits; +} + +static inline size_t psa_get_key_bits( + const psa_key_attributes_t *attributes) +{ + return( attributes->core.bits ); +} + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h new file mode 100644 index 0000000000..690999f79c --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_types.h @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_types.h + * + * \brief PSA cryptography module: type aliases. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of integral types for properties + * of cryptographic keys, designations of cryptographic algorithms, and + * error codes returned by the library. + * + * This header file does not declare any function. + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a small negative 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 + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint32_t psa_key_type_t; + +/** The type of PSA elliptic curve identifiers. + * + * The curve identifier is required to create an ECC key using the + * PSA_KEY_TYPE_ECC_KEY_PAIR() or PSA_KEY_TYPE_ECC_PUBLIC_KEY() + * macros. + * + * The encoding of curve identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the curves in the IANA + * registry. Implementations that support other curves that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA curves should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_ecc_curve_t value in the range #PSA_ECC_CURVE_VENDOR_MIN to + * #PSA_ECC_CURVE_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Use a ::psa_key_type_t value that is vendor-defined. + * + * The first option is recommended. + */ +typedef uint16_t psa_ecc_curve_t; + +/** The type of PSA Diffie-Hellman group identifiers. + * + * The group identifier is required to create an Diffie-Hellman key using the + * PSA_KEY_TYPE_DH_KEY_PAIR() or PSA_KEY_TYPE_DH_PUBLIC_KEY() + * macros. + * + * The encoding of group identifiers is taken from the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * + * This specification defines identifiers for some of the groups in the IANA + * registry. Implementations that support other groups that are in the IANA + * registry should use the IANA value and a implementation-specific identifier. + * Implemenations that support non-IANA groups should use one of the following + * approaches for allocating a key type: + * + * 1. Select a ::psa_dh_group_t value in the range #PSA_DH_GROUP_VENDOR_MIN to + * #PSA_DH_GROUP_VENDOR_MAX, which is a subset of the IANA private use + * range. + * 2. Select a ::psa_dh_group_t value from the named groups allocated for + * GREASE in the IETF draft specification. The GREASE specification and + * values are listed below. + * 3. Use a ::psa_key_type_t value that is vendor-defined. + * + * Option 1 or 2 are recommended. + * + * The current draft of the GREASE specification is + * https://datatracker.ietf.org/doc/draft-ietf-tls-grease + * + * The following GREASE values are allocated for named groups: + * \code + * 0x0A0A + * 0x1A1A + * 0x2A2A + * 0x3A3A + * 0x4A4A + * 0x5A5A + * 0x6A6A + * 0x7A7A + * 0x8A8A + * 0x9A9A + * 0xAAAA + * 0xBABA + * 0xCACA + * 0xDADA + * 0xEAEA + * 0xFAFA + * \endcode + */ +typedef uint16_t psa_dh_group_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * For algorithms that can be applied to multiple key types, this type + * does not encode the key type. For example, for symmetric ciphers + * based on a block cipher, #psa_algorithm_t encodes the block cipher + * mode and the padding mode while the block cipher itself is encoded + * via #psa_key_type_t. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + * + * The lifetime of a key indicates where it is stored and what system actions + * may create and destroy it. + * + * Keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE are automatically + * destroyed when the application terminates or on a power reset. + * + * Keys with a lifetime other than #PSA_KEY_LIFETIME_VOLATILE are said + * to be _persistent_. + * Persistent keys are preserved if the application or the system restarts. + * Persistent keys have a key identifier of type #psa_key_id_t. + * The application can call psa_open_key() to open a persistent key that + * it created previously. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + * + * - Applications may freely choose key identifiers in the range + * #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX. + * - Implementations may define additional key identifiers in the range + * #PSA_KEY_ID_VENDOR_MIN to #PSA_KEY_ID_VENDOR_MAX. + * - 0 is reserved as an invalid key identifier. + * - Key identifiers outside these ranges are reserved for future use. + */ +typedef uint32_t psa_key_id_t; +#define PSA_KEY_ID_INIT 0 + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +/** \defgroup attributes Key attributes + * @{ + */ + +/** The type of a structure containing key attributes. + * + * This is an opaque structure that can represent the metadata of a key + * object. Metadata that can be stored in attributes includes: + * - The location of the key in storage, indicated by its key identifier + * and its lifetime. + * - The key's policy, comprising usage flags and a specification of + * the permitted algorithm(s). + * - Information about the key itself: the key type and its size. + * - Implementations may define additional attributes. + * + * The actual key material is not considered an attribute of a key. + * Key attributes do not contain information that is generally considered + * highly confidential. + * + * An attribute structure can be a simple data structure where each function + * `psa_set_key_xxx` sets a field and the corresponding function + * `psa_get_key_xxx` retrieves the value of the corresponding field. + * However, implementations may report values that are equivalent to the + * original one, but have a different encoding. For example, an + * implementation may use a more compact representation for types where + * many bit-patterns are invalid or not supported, and store all values + * that it does not support as a special marker value. In such an + * implementation, after setting an invalid value, the corresponding + * get function returns an invalid value which may not be the one that + * was originally stored. + * + * An attribute structure may contain references to auxiliary resources, + * for example pointers to allocated memory or indirect references to + * pre-calculated values. In order to free such resources, the application + * must call psa_reset_key_attributes(). As an exception, calling + * psa_reset_key_attributes() on an attribute structure is optional if + * the structure has only been modified by the following functions + * since it was initialized or last reset with psa_reset_key_attributes(): + * - psa_set_key_id() + * - psa_set_key_lifetime() + * - psa_set_key_type() + * - psa_set_key_bits() + * - psa_set_key_usage_flags() + * - psa_set_key_algorithm() + * + * Before calling any function on a key attribute structure, the application + * must initialize it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_attributes_t attributes; + * memset(&attributes, 0, sizeof(attributes)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_attributes_t attributes = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_ATTRIBUTES_INIT, + * for example: + * \code + * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + * \endcode + * - Assign the result of the function psa_key_attributes_init() + * to the structure, for example: + * \code + * psa_key_attributes_t attributes; + * attributes = psa_key_attributes_init(); + * \endcode + * + * A freshly initialized attribute structure contains the following + * values: + * + * - lifetime: #PSA_KEY_LIFETIME_VOLATILE. + * - key identifier: 0 (which is not a valid key identifier). + * - type: \c 0 (meaning that the type is unspecified). + * - key size: \c 0 (meaning that the size is unspecified). + * - usage flags: \c 0 (which allows no usage except exporting a public key). + * - algorithm: \c 0 (which allows no cryptographic usage, but allows + * exporting). + * + * A typical sequence to create a key is as follows: + * -# Create and initialize an attribute structure. + * -# If the key is persistent, call psa_set_key_id(). + * Also call psa_set_key_lifetime() to place the key in a non-default + * location. + * -# Set the key policy with psa_set_key_usage_flags() and + * psa_set_key_algorithm(). + * -# Set the key type with psa_set_key_type(). + * Skip this step if copying an existing key with psa_copy_key(). + * -# When generating a random key with psa_generate_key() or deriving a key + * with psa_key_derivation_output_key(), set the desired key size with + * psa_set_key_bits(). + * -# Call a key creation function: psa_import_key(), psa_generate_key(), + * psa_key_derivation_output_key() or psa_copy_key(). This function reads + * the attribute structure, creates a key with these attributes, and + * outputs a handle to the newly created key. + * -# The attribute structure is now no longer necessary. + * You may call psa_reset_key_attributes(), although this is optional + * with the workflow presented here because the attributes currently + * defined in this specification do not require any additional resources + * beyond the structure itself. + * + * A typical sequence to query a key's attributes is as follows: + * -# Call psa_get_key_attributes(). + * -# Call `psa_get_key_xxx` functions to retrieve the attribute(s) that + * you are interested in. + * -# Call psa_reset_key_attributes() to free any resources that may be + * used by the attribute structure. + * + * Once a key has been created, it is impossible to change its attributes. + */ +typedef struct psa_key_attributes_s psa_key_attributes_t; + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** \brief Encoding of the step of a key derivation. */ +typedef uint16_t psa_key_derivation_step_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h new file mode 100644 index 0000000000..7fde07385f --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/crypto_values.h @@ -0,0 +1,1701 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + * \file psa/crypto_values.h + * + * \brief PSA cryptography module: macros to build and analyze integer values. + * + * \note This file may not be included directly. Applications must + * include psa/crypto.h. Drivers must include the appropriate driver + * header file. + * + * This file contains portable definitions of macros to build and analyze + * values of integral types that encode properties of cryptographic keys, + * designations of cryptographic algorithms, and error codes returned by + * the library. + * + * This header file only defines preprocessor macros. + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +/* PSA error codes */ + +/** The action was completed successfully. */ +#ifndef PSA_SUCCESS +#define PSA_SUCCESS ((psa_status_t)0) +#endif + +/** 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_GENERIC_ERROR ((psa_status_t)-132) + +/** The requested operation or a parameter is not supported + * by this implementation. + * + * Implementations should return this error code when an enumeration + * 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)-134) + +/** The requested action is denied by a policy. + * + * Implementations should return this error code when the parameters + * are recognized as valid and supported, and a policy explicitly + * denies the requested operation. + * + * If a subset of the parameters of a function call identify a + * forbidden operation, and another subset of the parameters are + * 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)-133) + +/** An output buffer is too small. + * + * Applications can call the \c PSA_xxx_SIZE macro listed in the function + * description to determine a sufficient buffer size. + * + * Implementations should preferably return this error code only + * in cases when performing the operation with a larger output + * 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)-138) + +/** Asking for an item that already exists + * + * 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) + +/** Asking for an item that doesn't exist + * + * 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. + * + * Multipart operations return this error when one of the + * functions is called out of sequence. Refer to the function + * descriptions for permitted sequencing of functions. + * + * Implementations shall not return this error code to indicate + * that a key either exists or not, + * but shall instead return #PSA_ERROR_ALREADY_EXISTS or #PSA_ERROR_DOES_NOT_EXIST + * as applicable. + * + * Implementations 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_BAD_STATE ((psa_status_t)-137) + +/** The parameters passed to the function are invalid. + * + * Implementations may return this error any time a parameter or + * combination of parameters are recognized as invalid. + * + * Implementations 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)-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)-141) + +/** There is not enough persistent storage. + * + * Functions that modify the key storage return this error code if + * there is insufficient storage space on the host media. In addition, + * 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)-142) + +/** There was a communication failure inside the implementation. + * + * This can indicate a communication failure between the application + * and an external cryptoprocessor or between the cryptoprocessor and + * an external volatile or persistent memory. A communication failure + * may be transient or permanent depending on the cause. + * + * \warning If a function returns this error, it is undetermined + * whether the requested action has completed or not. Implementations + * should return #PSA_SUCCESS on successful completion whenever + * possible, however functions may return #PSA_ERROR_COMMUNICATION_FAILURE + * if the requested action was completed successfully in an external + * 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)-145) + +/** There was a storage failure that may have led to data loss. + * + * This error indicates that some persistent storage is corrupted. + * It should not be used for a corruption of volatile memory + * (use #PSA_ERROR_CORRUPTION_DETECTED), for a communication error + * between the cryptoprocessor and its external storage (use + * #PSA_ERROR_COMMUNICATION_FAILURE), or when the storage is + * in a valid state but is full (use #PSA_ERROR_INSUFFICIENT_STORAGE). + * + * Note that a storage failure does not indicate that any data that was + * previously read is invalid. However this previously read data may no + * longer be readable from storage. + * + * When a storage failure occurs, it is no longer possible to ensure + * the global integrity of the keystore. Depending on the global + * integrity guarantees offered by the implementation, access to other + * data may or may not fail even if the data is still readable but + * its integrity cannot be guaranteed. + * + * Implementations should only use this error code to report a + * 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)-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)-147) + +/** A tampering attempt was detected. + * + * If an application receives this error code, there is no guarantee + * that previously accessed or computed data was correct and remains + * confidential. Applications should not perform any security function + * and should enter a safe failure state. + * + * Implementations may return this error code if they detect an invalid + * state that cannot happen during normal operation and that indicates + * that the implementation's security guarantees no longer hold. Depending + * on the implementation architecture and on its security and safety goals, + * the implementation may forcibly terminate the application. + * + * This error code is intended as a last resort when a security breach + * is detected and it is unsure whether the keystore data is still + * protected. Implementations shall only return this error code + * to report an alarm from a tampering detector, to indicate that + * the confidentiality of stored data can no longer be guaranteed, + * or to indicate that the integrity of previously returned data is now + * considered compromised. Implementations shall not use this error code + * to indicate a hardware failure that merely makes it impossible to + * perform the requested operation (use #PSA_ERROR_COMMUNICATION_FAILURE, + * #PSA_ERROR_STORAGE_FAILURE, #PSA_ERROR_HARDWARE_FAILURE, + * #PSA_ERROR_INSUFFICIENT_ENTROPY or other applicable error code + * instead). + * + * 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_CORRUPTION_DETECTED ((psa_status_t)-151) + +/** There is not enough entropy to generate random data needed + * for the requested action. + * + * This error indicates a failure of a hardware random generator. + * Application writers should note that this error can be returned not + * only by functions whose purpose is to generate random data, such + * as key, IV or nonce generation, but also by functions that execute + * an algorithm with a randomized result, as well as functions that + * use randomization of intermediate computations as a countermeasure + * to certain attacks. + * + * Implementations should avoid returning this error after psa_crypto_init() + * has succeeded. Implementations should generate sufficient + * entropy during initialization and subsequently use a cryptographically + * 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)-148) + +/** The signature, MAC or hash is incorrect. + * + * Verification functions return this error if the verification + * calculations completed successfully, and the value to be verified + * was determined to be incorrect. + * + * 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)-149) + +/** The decrypted padding is incorrect. + * + * \warning In some protocols, when decrypting data, it is essential that + * the behavior of the application does not depend on whether the padding + * is correct, down to precise timing. Applications should prefer + * protocols that use authenticated encryption rather than plain + * encryption. If the application must perform a decryption of + * unauthenticated data, the application writer should take care not + * to reveal whether the padding is invalid. + * + * Implementations should strive to make valid and invalid padding + * 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)-150) + +/** 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. See also :ref:\`key-handles\`. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)-136) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) + +/** Vendor-defined key type flag. + * + * Key types defined by this standard will never have the + * #PSA_KEY_TYPE_VENDOR_FLAG bit set. Vendors who define additional key types + * must use an encoding with the #PSA_KEY_TYPE_VENDOR_FLAG bit set and should + * respect the bitwise structure used by standard encodings whenever practical. + */ +#define PSA_KEY_TYPE_VENDOR_FLAG ((psa_key_type_t)0x80000000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) + +/** Whether a key type is vendor-defined. + * + * See also #PSA_KEY_TYPE_VENDOR_FLAG. + */ +#define PSA_KEY_TYPE_IS_VENDOR_DEFINED(type) \ + (((type) & PSA_KEY_TYPE_VENDOR_FLAG) != 0) + +/** Whether a key type is an unstructured array of bytes. + * + * This encompasses both symmetric keys and non-key data. + */ +#define PSA_KEY_TYPE_IS_UNSTRUCTURED(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK & ~(psa_key_type_t)0x10000000) == \ + PSA_KEY_TYPE_CATEGORY_SYMMETRIC) + +/** Whether a key type is asymmetric: either a key pair or a public key. */ +#define PSA_KEY_TYPE_IS_ASYMMETRIC(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK \ + & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) == \ + PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is the public part of a key pair. */ +#define PSA_KEY_TYPE_IS_PUBLIC_KEY(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY) +/** Whether a key type is a key pair containing a private part and a public + * part. */ +#define PSA_KEY_TYPE_IS_KEY_PAIR(type) \ + (((type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_KEY_PAIR) +/** The key pair type corresponding to a public key type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding key pair type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_KEY_PAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) \ + ((type) & ~PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) + +/** Raw data. + * + * A "key" of this type cannot be used for any cryptographic operation. + * Applications may use this type to store arbitrary data in the keystore. */ +#define PSA_KEY_TYPE_RAW_DATA ((psa_key_type_t)0x50000001) + +/** HMAC key. + * + * The key policy determines which underlying hash algorithm the key can be + * used for. + * + * HMAC keys should generally have the same size as the underlying hash. + * This size can be calculated with #PSA_HASH_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) + +/** Key for a cipher, AEAD or MAC algorithm based on the AES block cipher. + * + * The size of the key can be 16 bytes (AES-128), 24 bytes (AES-192) or + * 32 bytes (AES-256). + */ +#define PSA_KEY_TYPE_AES ((psa_key_type_t)0x40000001) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (3-key 3DES). + * + * Note that single DES and 2-key 3DES are weak and strongly + * deprecated and should only be used to decrypt legacy data. 3-key 3DES + * is weak and deprecated and should only be used in legacy protocols. + */ +#define PSA_KEY_TYPE_DES ((psa_key_type_t)0x40000002) + +/** Key for a cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) + +/** Key for the ChaCha20 stream cipher or the Chacha20-Poly1305 AEAD algorithm. + * + * ChaCha20 and the ChaCha20_Poly1305 construction are defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + */ +#define PSA_KEY_TYPE_CHACHA20 ((psa_key_type_t)0x40000005) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEY_PAIR ((psa_key_type_t)0x70010000) +/** Whether a key type is an RSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_RSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) +#define PSA_KEY_TYPE_ECC_KEY_PAIR_BASE ((psa_key_type_t)0x70030000) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +/** Elliptic curve key pair. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_KEY_PAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEY_PAIR_BASE | (curve)) +/** Elliptic curve public key. + * + * \param curve A value of type ::psa_ecc_curve_t that identifies the + * ECC curve to be used. + */ +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve) \ + (PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE | (curve)) + +/** Whether a key type is an elliptic curve key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_ECC(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) +/** Whether a key type is an elliptic curve key pair. */ +#define PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEY_PAIR_BASE) +/** Whether a key type is an elliptic curve public key. */ +#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) + +/** Extract the curve from an elliptic curve key type. */ +#define PSA_KEY_TYPE_GET_CURVE(type) \ + ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/* The encoding of curve identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 8422 and RFC 7027. */ +#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) +#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) +#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) +#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) +#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) +#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) +#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) +#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) +#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) +#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) +#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) +#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) +#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) +#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) +#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) +#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) +#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) +#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) +#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) +#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) +#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) +#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) +#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) +#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) +#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) +/** Curve25519. + * + * This is the curve defined in Bernstein et al., + * _Curve25519: new Diffie-Hellman speed records_, LNCS 3958, 2006. + * The algorithm #PSA_ALG_ECDH performs X25519 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) +/** Curve448 + * + * This is the curve defined in Hamburg, + * _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015. + * The algorithm #PSA_ALG_ECDH performs X448 when used with this curve. + */ +#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) + +/** Minimum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MIN ((psa_ecc_curve_t) 0xfe00) +/** Maximum value for a vendor-defined ECC curve identifier + * + * The range for vendor-defined curve identifiers is a subset of the IANA + * registry private use range, `0xfe00` - `0xfeff`. + */ +#define PSA_ECC_CURVE_VENDOR_MAX ((psa_ecc_curve_t) 0xfe7f) + +#define PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE ((psa_key_type_t)0x60040000) +#define PSA_KEY_TYPE_DH_KEY_PAIR_BASE ((psa_key_type_t)0x70040000) +#define PSA_KEY_TYPE_DH_GROUP_MASK ((psa_key_type_t)0x0000ffff) +/** Diffie-Hellman key pair. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_KEY_PAIR(group) \ + (PSA_KEY_TYPE_DH_KEY_PAIR_BASE | (group)) +/** Diffie-Hellman public key. + * + * \param group A value of type ::psa_dh_group_t that identifies the + * Diffie-Hellman group to be used. + */ +#define PSA_KEY_TYPE_DH_PUBLIC_KEY(group) \ + (PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE | (group)) + +/** Whether a key type is a Diffie-Hellman key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DH(type) \ + ((PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(type) & \ + ~PSA_KEY_TYPE_DH_GROUP_MASK) == PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) +/** Whether a key type is a Diffie-Hellman key pair. */ +#define PSA_KEY_TYPE_IS_DH_KEY_PAIR(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_KEY_PAIR_BASE) +/** Whether a key type is a Diffie-Hellman public key. */ +#define PSA_KEY_TYPE_IS_DH_PUBLIC_KEY(type) \ + (((type) & ~PSA_KEY_TYPE_DH_GROUP_MASK) == \ + PSA_KEY_TYPE_DH_PUBLIC_KEY_BASE) + +/** Extract the group from a Diffie-Hellman key type. */ +#define PSA_KEY_TYPE_GET_GROUP(type) \ + ((psa_dh_group_t) (PSA_KEY_TYPE_IS_DH(type) ? \ + ((type) & PSA_KEY_TYPE_DH_GROUP_MASK) : \ + 0)) + +/* The encoding of group identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 7919. */ +#define PSA_DH_GROUP_FFDHE2048 ((psa_dh_group_t) 0x0100) +#define PSA_DH_GROUP_FFDHE3072 ((psa_dh_group_t) 0x0101) +#define PSA_DH_GROUP_FFDHE4096 ((psa_dh_group_t) 0x0102) +#define PSA_DH_GROUP_FFDHE6144 ((psa_dh_group_t) 0x0103) +#define PSA_DH_GROUP_FFDHE8192 ((psa_dh_group_t) 0x0104) + +/** Minimum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MIN ((psa_dh_group_t) 0x01fc) +/** Maximum value for a vendor-defined Diffie Hellman group identifier + * + * The range for vendor-defined group identifiers is a subset of the IANA + * registry private use range, `0x01fc` - `0x01ff`. + */ +#define PSA_DH_GROUP_VENDOR_MAX ((psa_dh_group_t) 0x01fd) + +/** The block size of a block cipher. + * + * \param type A cipher key type (value of type #psa_key_type_t). + * + * \return The block size for a block cipher, or 1 for a stream cipher. + * The return value is undefined if \p type is not a supported + * cipher key type. + * + * \note It is possible to build stream cipher algorithms on top of a block + * cipher, for example CTR mode (#PSA_ALG_CTR). + * This macro only takes the key type into account, so it cannot be + * used to determine the size of the data that #psa_cipher_update() + * might buffer for future processing in general. + * + * \note This macro returns a compile-time constant if its argument is one. + * + * \warning This macro may evaluate its argument multiple times. + */ +#define PSA_BLOCK_CIPHER_BLOCK_SIZE(type) \ + ( \ + (type) == PSA_KEY_TYPE_AES ? 16 : \ + (type) == PSA_KEY_TYPE_DES ? 8 : \ + (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ + (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ + (type) == PSA_KEY_TYPE_CHACHA20 ? 1 : \ + 0) + +/** Vendor-defined algorithm flag. + * + * Algorithms defined by this standard will never have the #PSA_ALG_VENDOR_FLAG + * bit set. Vendors who define additional algorithms must use an encoding with + * the #PSA_ALG_VENDOR_FLAG bit set and should respect the bitwise structure + * used by standard encodings whenever practical. + */ +#define PSA_ALG_VENDOR_FLAG ((psa_algorithm_t)0x80000000) + +#define PSA_ALG_CATEGORY_MASK ((psa_algorithm_t)0x7f000000) +#define PSA_ALG_CATEGORY_HASH ((psa_algorithm_t)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x20000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x30000000) + +/** Whether an algorithm is vendor-defined. + * + * See also #PSA_ALG_VENDOR_FLAG. + */ +#define PSA_ALG_IS_VENDOR_DEFINED(alg) \ + (((alg) & PSA_ALG_VENDOR_FLAG) != 0) + +/** Whether the specified algorithm is a hash algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_HASH) + +/** Whether the specified algorithm is a MAC algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_MAC(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_MAC) + +/** Whether the specified algorithm is a symmetric cipher algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a symmetric cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_CIPHER(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_CIPHER) + +/** Whether the specified algorithm is an authenticated encryption + * with associated data (AEAD) algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_AEAD) + +/** Whether the specified algorithm is a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key signature algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_SIGN(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_SIGN) + +/** Whether the specified algorithm is a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key encryption algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_ASYMMETRIC_ENCRYPTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION) + +/** Whether the specified algorithm is a key agreement algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_AGREEMENT(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a key derivation algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key derivation algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_KEY_DERIVATION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +/** MD2 */ +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +/** MD4 */ +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +/** MD5 */ +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +/** PSA_ALG_RIPEMD160 */ +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +/** SHA1 */ +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +/** In a hash-and-sign algorithm policy, allow any hash algorithm. + * + * This value may be used to form the algorithm usage field of a policy + * for a signature algorithm that is parametrized by a hash. The key + * may then be used to perform operations using the same signature + * algorithm parametrized with any supported hash. + * + * That is, suppose that `PSA_xxx_SIGNATURE` is one of the following macros: + * - #PSA_ALG_RSA_PKCS1V15_SIGN, #PSA_ALG_RSA_PSS, + * - #PSA_ALG_ECDSA, #PSA_ALG_DETERMINISTIC_ECDSA. + * Then you may create and use a key as follows: + * - Set the key usage field using #PSA_ALG_ANY_HASH, for example: + * ``` + * psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH); // or VERIFY + * psa_set_key_algorithm(&attributes, PSA_xxx_SIGNATURE(PSA_ALG_ANY_HASH)); + * ``` + * - Import or generate key material. + * - Call psa_sign_hash() or psa_verify_hash(), passing + * an algorithm built from `PSA_xxx_SIGNATURE` and a specific hash. Each + * call to sign or verify a message may use a different hash. + * ``` + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_256), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA_512), ...); + * psa_sign_hash(handle, PSA_xxx_SIGNATURE(PSA_ALG_SHA3_256), ...); + * ``` + * + * This value may not be used to build other algorithms that are + * parametrized over a hash. For any valid use of this macro to build + * an algorithm \c alg, #PSA_ALG_IS_HASH_AND_SIGN(\c alg) is true. + * + * This value may not be used to build an algorithm specification to + * perform an operation. It is only valid to build policies. + */ +#define PSA_ALG_ANY_HASH ((psa_algorithm_t)0x010000ff) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** Macro to build an HMAC algorithm. + * + * For example, #PSA_ALG_HMAC(#PSA_ALG_SHA_256) is HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HMAC algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HMAC(hash_alg) \ + (PSA_ALG_HMAC_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_HMAC_GET_HASH(hmac_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hmac_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is an HMAC algorithm. + * + * HMAC is a family of MAC algorithms that are based on a hash function. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an HMAC algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HMAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_HMAC_BASE) + +/* In the encoding of a MAC algorithm, the bits corresponding to + * PSA_ALG_MAC_TRUNCATION_MASK encode the length to which the MAC is + * truncated. As an exception, the value 0 means the untruncated algorithm, + * whatever its length is. The length is encoded in 6 bits, so it can + * reach up to 63; the largest MAC is 64 bytes so its trivial truncation + * to full length is correctly encoded as 0 and any non-trivial truncation + * is correctly encoded as a value between 1 and 63. */ +#define PSA_ALG_MAC_TRUNCATION_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** Macro to build a truncated MAC algorithm. + * + * A truncated MAC algorithm is identical to the corresponding MAC + * algorithm except that the MAC value for the truncated algorithm + * consists of only the first \p mac_length bytes of the MAC value + * for the untruncated algorithm. + * + * \note This macro may allow constructing algorithm identifiers that + * are not valid, either because the specified length is larger + * than the untruncated MAC or because the specified length is + * smaller than permitted by the implementation. + * + * \note It is implementation-defined whether a truncated MAC that + * is truncated to the same length as the MAC of the untruncated + * algorithm is considered identical to the untruncated algorithm + * for policy comparison purposes. + * + * \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. + * \param mac_length Desired length of the truncated MAC in bytes. + * This must be at most the full length of the MAC + * and must be at least an implementation-specified + * minimum. The implementation-specified minimum + * shall not be zero. + * + * \return The corresponding MAC algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * MAC algorithm or if \p mac_length is too small or + * too large for the specified MAC algorithm. + */ +#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 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. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(mac_alg) \ + ((mac_alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param mac_alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#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) +/** The CBC-MAC construction over a block cipher + * + * \warning CBC-MAC is insecure in many cases. + * A more secure mode, such as #PSA_ALG_CMAC, is recommended. + */ +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +/** The CMAC construction over a block cipher */ +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) + +/** Whether the specified algorithm is a MAC algorithm based on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a MAC algorithm based on a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_MAC_SUBCATEGORY_MASK)) == \ + PSA_ALG_CIPHER_MAC_BASE) + +#define PSA_ALG_CIPHER_STREAM_FLAG ((psa_algorithm_t)0x00800000) +#define PSA_ALG_CIPHER_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is a stream cipher. + * + * A stream cipher is a symmetric cipher that encrypts or decrypts messages + * by applying a bitwise-xor with a stream of bytes that is generated + * from a key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a stream cipher algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier or if it is not a symmetric cipher algorithm. + */ +#define PSA_ALG_IS_STREAM_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_CIPHER_STREAM_FLAG)) == \ + (PSA_ALG_CATEGORY_CIPHER | PSA_ALG_CIPHER_STREAM_FLAG)) + +/** The ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** The ChaCha20 stream cipher. + * + * ChaCha20 is defined in RFC 7539. + * + * The nonce size for psa_cipher_set_iv() or psa_cipher_generate_iv() + * must be 12. + * + * The initial block counter is always 0. + * + */ +#define PSA_ALG_CHACHA20 ((psa_algorithm_t)0x04800005) + +/** The CTR stream cipher mode. + * + * CTR is a stream cipher which is built from a block cipher. + * The underlying block cipher is determined by the key type. + * For example, to use AES-128-CTR, use this algorithm with + * a key of type #PSA_KEY_TYPE_AES and a length of 128 bits (16 bytes). + */ +#define PSA_ALG_CTR ((psa_algorithm_t)0x04c00001) + +/** The CFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +/** The OFB stream cipher mode. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** The XTS cipher mode. + * + * XTS is a cipher mode which is built from a block cipher. It requires at + * least one full block of input, but beyond this minimum the input + * does not need to be a whole number of blocks. + */ +#define PSA_ALG_XTS ((psa_algorithm_t)0x044000ff) + +/** The CBC block cipher chaining mode, with no padding. + * + * The underlying block cipher is determined by the key type. + * + * This symmetric cipher mode can only be used with messages whose lengths + * are whole number of blocks for the chosen block cipher. + */ +#define PSA_ALG_CBC_NO_PADDING ((psa_algorithm_t)0x04600100) + +/** The CBC block cipher chaining mode with PKCS#7 padding. + * + * The underlying block cipher is determined by the key type. + * + * This is the padding method defined by PKCS#7 (RFC 2315) §10.3. + */ +#define PSA_ALG_CBC_PKCS7 ((psa_algorithm_t)0x04600101) + +#define PSA_ALG_AEAD_FROM_BLOCK_FLAG ((psa_algorithm_t)0x00400000) + +/** Whether the specified algorithm is an AEAD mode on a block cipher. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is an AEAD algorithm which is an AEAD mode based on + * a block cipher, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) \ + (((alg) & (PSA_ALG_CATEGORY_MASK | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) == \ + (PSA_ALG_CATEGORY_AEAD | PSA_ALG_AEAD_FROM_BLOCK_FLAG)) + +/** The CCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_CCM ((psa_algorithm_t)0x06401001) + +/** The GCM authenticated encryption algorithm. + * + * The underlying block cipher is determined by the key type. + */ +#define PSA_ALG_GCM ((psa_algorithm_t)0x06401002) + +/** The Chacha20-Poly1305 AEAD algorithm. + * + * The ChaCha20_Poly1305 construction is defined in RFC 7539. + * + * Implementations must support 12-byte nonces, may support 8-byte nonces, + * and should reject other sizes. + * + * Implementations must support 16-byte tags and should reject other sizes. + */ +#define PSA_ALG_CHACHA20_POLY1305 ((psa_algorithm_t)0x06001005) + +/* In the encoding of a AEAD algorithm, the bits corresponding to + * PSA_ALG_AEAD_TAG_LENGTH_MASK encode the length of the AEAD tag. + * The constants for default lengths follow this encoding. + */ +#define PSA_ALG_AEAD_TAG_LENGTH_MASK ((psa_algorithm_t)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** Macro to build a shortened AEAD algorithm. + * + * A shortened AEAD algorithm is similar to the corresponding AEAD + * algorithm, but has an authentication tag that consists of fewer bytes. + * Depending on the algorithm, the tag length may affect the calculation + * of the ciphertext. + * + * \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. + * + * \return The corresponding AEAD algorithm with the specified + * length. + * \return Unspecified if \p alg is not a supported + * AEAD algorithm or if \p tag_length is not valid + * for the specified AEAD algorithm. + */ +#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 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. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(aead_alg) \ + ( \ + 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) \ + PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH_CASE(aead_alg, PSA_ALG_CHACHA20_POLY1305) \ + 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 : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** RSA PKCS#1 v1.5 signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PKCS1-v1_5. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN(hash_alg) \ + (PSA_ALG_RSA_PKCS1V15_SIGN_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Raw PKCS#1 v1.5 signature. + * + * The input to this algorithm is the DigestInfo structure used by + * RFC 8017 (PKCS#1: RSA Cryptography Specifications), §9.2 + * steps 3–6. + */ +#define PSA_ALG_RSA_PKCS1V15_SIGN_RAW PSA_ALG_RSA_PKCS1V15_SIGN_BASE +#define PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PKCS1V15_SIGN_BASE) + +#define PSA_ALG_RSA_PSS_BASE ((psa_algorithm_t)0x10030000) +/** RSA PSS signature with hashing. + * + * This is the signature scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSASSA-PSS, with the message generation function MGF1, and with + * a salt length equal to the length of the hash. The specified + * hash algorithm is used to hash the input message, to create the + * salted hash, and for the mask generation. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_PSS(hash_alg) \ + (PSA_ALG_RSA_PSS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** ECDSA signature with hashing. + * + * This is the ECDSA signature scheme defined by ANSI X9.62, + * with a random per-message secret number (*k*). + * + * The representation of the signature as a byte string consists of + * the concatentation of the signature values *r* and *s*. Each of + * *r* and *s* is encoded as an *N*-octet string, where *N* is the length + * of the base point of the curve in octets. Each value is represented + * in big-endian order (most significant octet first). + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_ECDSA(hash_alg) \ + (PSA_ALG_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** ECDSA signature without hashing. + * + * This is the same signature scheme as #PSA_ALG_ECDSA(), but + * without specifying a hash algorithm. This algorithm may only be + * used to sign or verify a sequence of bytes that should be an + * already-calculated hash. Note that the input is padded with + * zeros on the left or truncated on the left as required to fit + * the curve size. + */ +#define PSA_ALG_ECDSA_ANY PSA_ALG_ECDSA_BASE +#define PSA_ALG_DETERMINISTIC_ECDSA_BASE ((psa_algorithm_t)0x10070000) +/** Deterministic ECDSA signature with hashing. + * + * This is the deterministic ECDSA signature scheme defined by RFC 6979. + * + * The representation of a signature is the same as with #PSA_ALG_ECDSA(). + * + * Note that when this algorithm is used for verification, signatures + * made with randomized ECDSA (#PSA_ALG_ECDSA(\p hash_alg)) with the + * same private key are accepted. In other words, + * #PSA_ALG_DETERMINISTIC_ECDSA(\p hash_alg) differs from + * #PSA_ALG_ECDSA(\p hash_alg) only for signature, not for verification. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * This includes #PSA_ALG_ANY_HASH + * when specifying the algorithm in a usage policy. + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_DETERMINISTIC_ECDSA(hash_alg) \ + (PSA_ALG_DETERMINISTIC_ECDSA_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_ECDSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#define PSA_ALG_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_ECDSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_ECDSA_DETERMINISTIC_FLAG) != 0) +#define PSA_ALG_IS_DETERMINISTIC_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) +#define PSA_ALG_IS_RANDOMIZED_ECDSA(alg) \ + (PSA_ALG_IS_ECDSA(alg) && !PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) + +/** Whether the specified algorithm is a hash-and-sign algorithm. + * + * Hash-and-sign algorithms are public-key signature algorithms structured + * in two parts: first the calculation of a hash in a way that does not + * depend on the key, then the calculation of a signature from the + * hash value and the key. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a hash-and-sign algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_HASH_AND_SIGN(alg) \ + (PSA_ALG_IS_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_ECDSA(alg)) + +/** Get the hash used by a hash-and-sign signature algorithm. + * + * A hash-and-sign algorithm is a signature algorithm which is + * composed of two phases: first a hashing phase which does not use + * the key and produces a hash of the input message, then a signing + * phase which only uses the hash and the key and not the message + * itself. + * + * \param alg A signature algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_SIGN(\p alg) is true). + * + * \return The underlying hash algorithm if \p alg is a hash-and-sign + * algorithm. + * \return 0 if \p alg is a signature algorithm that does not + * follow the hash-and-sign structure. + * \return Unspecified if \p alg is not a signature algorithm or + * if it is not supported by the implementation. + */ +#define PSA_ALG_SIGN_GET_HASH(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** RSA OAEP encryption. + * + * This is the encryption scheme defined by RFC 8017 + * (PKCS#1: RSA Cryptography Specifications) under the name + * RSAES-OAEP, with the message generation function MGF1. + * + * \param hash_alg The hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true) to use + * for MGF1. + * + * \return The corresponding RSA OAEP signature algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_RSA_OAEP(hash_alg) \ + (PSA_ALG_RSA_OAEP_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +#define PSA_ALG_IS_RSA_OAEP(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_OAEP_BASE) +#define PSA_ALG_RSA_OAEP_GET_HASH(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +#define PSA_ALG_HKDF_BASE ((psa_algorithm_t)0x20000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF using HMAC-SHA-256. + * + * This key derivation algorithm uses the following inputs: + * - #PSA_KEY_DERIVATION_INPUT_SALT is the salt used in the "extract" step. + * It is optional; if omitted, the derivation uses an empty salt. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key used in the "extract" step. + * - #PSA_KEY_DERIVATION_INPUT_INFO is the info string used in the "expand" step. + * You must pass #PSA_KEY_DERIVATION_INPUT_SALT before #PSA_KEY_DERIVATION_INPUT_SECRET. + * You may pass #PSA_KEY_DERIVATION_INPUT_INFO at any time after steup and before + * starting to generate output. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding HKDF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_HKDF(hash_alg) \ + (PSA_ALG_HKDF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +/** Whether the specified algorithm is an HKDF algorithm. + * + * HKDF is a family of key derivation algorithms that are based on a hash + * function and the HMAC construction. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an HKDF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_HKDF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_HKDF_BASE) +#define PSA_ALG_HKDF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PRF_BASE ((psa_algorithm_t)0x20000200) +/** Macro to build a TLS-1.2 PRF algorithm. + * + * TLS 1.2 uses a custom pseudorandom function (PRF) for key schedule, + * specified in Section 5 of RFC 5246. It is based on HMAC and can be + * used with either SHA-256 or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2 key expansion, the seed is the + * concatenation of ServerHello.Random + ClientHello.Random, + * and the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` represents the + * TLS 1.2 PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PRF algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PRF(hash_alg) \ + (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PRF algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PRF algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PRF(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PRF_BASE) +#define PSA_ALG_TLS12_PRF_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_TLS12_PSK_TO_MS_BASE ((psa_algorithm_t)0x20000300) +/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. + * + * In a pure-PSK handshake in TLS 1.2, the master secret is derived + * from the PreSharedKey (PSK) through the application of padding + * (RFC 4279, Section 2) and the TLS-1.2 PRF (RFC 5246, Section 5). + * The latter is based on HMAC and can be used with either SHA-256 + * or SHA-384. + * + * This key derivation algorithm uses the following inputs, which must be + * passed in the order given here: + * - #PSA_KEY_DERIVATION_INPUT_SEED is the seed. + * - #PSA_KEY_DERIVATION_INPUT_SECRET is the secret key. + * - #PSA_KEY_DERIVATION_INPUT_LABEL is the label. + * + * For the application to TLS-1.2, the seed (which is + * forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, + * and the label is "master secret" or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` represents the + * TLS-1.2 PSK to MasterSecret derivation PRF using HMAC-SHA-256. + * + * \param hash_alg A hash algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_HASH(\p hash_alg) is true). + * + * \return The corresponding TLS-1.2 PSK to MS algorithm. + * \return Unspecified if \p hash_alg is not a supported + * hash algorithm. + */ +#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ + (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) + +/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a TLS-1.2 PSK to MS algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key derivation algorithm identifier. + */ +#define PSA_ALG_IS_TLS12_PSK_TO_MS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_TLS12_PSK_TO_MS_BASE) +#define PSA_ALG_TLS12_PSK_TO_MS_GET_HASH(hkdf_alg) \ + (PSA_ALG_CATEGORY_HASH | ((hkdf_alg) & PSA_ALG_HASH_MASK)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x0803ffff) +#define PSA_ALG_KEY_AGREEMENT_MASK ((psa_algorithm_t)0x10fc0000) + +/** Macro to build a combined algorithm that chains a key agreement with + * a key derivation. + * + * \param ka_alg A key agreement algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_AGREEMENT(\p ka_alg) is true). + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p kdf_alg) is true). + * + * \return The corresponding key agreement and derivation + * algorithm. + * \return Unspecified if \p ka_alg is not a supported + * key agreement algorithm or \p kdf_alg is not a + * supported key derivation algorithm. + */ +#define PSA_ALG_KEY_AGREEMENT(ka_alg, kdf_alg) \ + ((ka_alg) | (kdf_alg)) + +#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ + (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ + (((alg) & PSA_ALG_KEY_AGREEMENT_MASK) | PSA_ALG_CATEGORY_KEY_AGREEMENT) + +/** Whether the specified algorithm is a raw key agreement algorithm. + * + * A raw key agreement algorithm is one that does not specify + * a key derivation function. + * Usually, raw key agreement algorithms are constructed directly with + * a \c PSA_ALG_xxx macro while non-raw key agreement algorithms are + * constructed with PSA_ALG_KEY_AGREEMENT(). + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a raw key agreement algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \p alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_RAW_KEY_AGREEMENT(alg) \ + (PSA_ALG_IS_KEY_AGREEMENT(alg) && \ + PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) == PSA_ALG_CATEGORY_KEY_DERIVATION) + +#define PSA_ALG_IS_KEY_DERIVATION_OR_AGREEMENT(alg) \ + ((PSA_ALG_IS_KEY_DERIVATION(alg) || PSA_ALG_IS_KEY_AGREEMENT(alg))) + +/** The finite-field Diffie-Hellman (DH) key agreement algorithm. + * + * The shared secret produced by key agreement is + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + */ +#define PSA_ALG_FFDH ((psa_algorithm_t)0x30100000) + +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes the raw finite field Diffie-Hellman algorithm as well as + * finite-field Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a finite field Diffie-Hellman algorithm, 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_FFDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_FFDH) + +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * The shared secret produced by key agreement is the x-coordinate of + * the shared secret point. It is always `ceiling(m / 8)` bytes long where + * `m` is the bit size associated with the curve, i.e. the bit size of the + * order of the curve's coordinate field. When `m` is not a multiple of 8, + * the byte containing the most significant bit of the shared secret + * is padded with zero bits. The byte order is either little-endian + * or big-endian depending on the curve type. + * + * - For Montgomery curves (curve types `PSA_ECC_CURVE_CURVEXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in little-endian byte order. + * The bit size is 448 for Curve448 and 255 for Curve25519. + * - For Weierstrass curves over prime fields (curve types + * `PSA_ECC_CURVE_SECPXXX` and `PSA_ECC_CURVE_BRAINPOOL_PXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m = ceiling(log_2(p))` for the field `F_p`. + * - For Weierstrass curves over binary fields (curve types + * `PSA_ECC_CURVE_SECTXXX`), + * the shared secret is the x-coordinate of `d_A Q_B = d_B Q_A` + * in big-endian byte order. + * The bit size is `m` for the field `F_{2^m}`. + */ +#define PSA_ALG_ECDH ((psa_algorithm_t)0x30200000) + +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes the raw elliptic curve Diffie-Hellman algorithm as well as + * elliptic curve Diffie-Hellman followed by any supporter key derivation + * algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is an elliptic curve Diffie-Hellman algorithm, + * 0 otherwise. + * This macro may return either 0 or 1 if \c alg is not a supported + * key agreement algorithm identifier. + */ +#define PSA_ALG_IS_ECDH(alg) \ + (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH) + +/** Whether the specified algorithm encoding is a wildcard. + * + * Wildcard values may only be used to set the usage algorithm field in + * a policy, not to perform an operation. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \c alg is a wildcard algorithm encoding. + * \return 0 if \c alg is a non-wildcard algorithm encoding (suitable for + * an operation). + * \return This macro may return either 0 or 1 if \c alg is not a supported + * algorithm identifier. + */ +#define PSA_ALG_IS_WILDCARD(alg) \ + (PSA_ALG_IS_HASH_AND_SIGN(alg) ? \ + PSA_ALG_SIGN_GET_HASH(alg) == PSA_ALG_ANY_HASH : \ + (alg) == PSA_ALG_ANY_HASH) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default storage area for persistent keys. + * + * A persistent key remains in storage until it is explicitly destroyed or + * until the corresponding storage area is wiped. This specification does + * not define any mechanism to wipe a storage area, but implementations may + * provide their own mechanism (for example to perform a factory reset, + * to prepare for device refurbishment, or to uninstall an application). + * + * This lifetime value is the default storage area for the calling + * application. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/** The minimum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MIN ((psa_app_key_id_t)0x00000001) +/** The maximum value for a key identifier chosen by the application. + */ +#define PSA_KEY_ID_USER_MAX ((psa_app_key_id_t)0x3fffffff) +/** The minimum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MIN ((psa_app_key_id_t)0x40000000) +/** The maximum value for a key identifier chosen by the implementation. + */ +#define PSA_KEY_ID_VENDOR_MAX ((psa_app_key_id_t)0x7fffffff) + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** Whether the key may be exported. + * + * A public key or the public part of a key pair may always be exported + * regardless of the value of this permission flag. + * + * If a key does not have export permission, implementations shall not + * allow the key to be exported in plain form from the cryptoprocessor, + * whether through psa_export_key() or through a proprietary interface. + * The key may however be exportable in a wrapped form, i.e. in a form + * where it is encrypted by another key. + */ +#define PSA_KEY_USAGE_EXPORT ((psa_key_usage_t)0x00000001) + +/** Whether the key may be copied. + * + * This flag allows the use of psa_copy_key() to make a copy of the key + * with the same policy or a more restrictive policy. + * + * For lifetimes for which the key is located in a secure element which + * enforce the non-exportability of keys, copying a key outside the secure + * element also requires the usage flag #PSA_KEY_USAGE_EXPORT. + * Copying the key inside the secure element is permitted with just + * #PSA_KEY_USAGE_COPY if the secure element supports it. + * For keys with the lifetime #PSA_KEY_LIFETIME_VOLATILE or + * #PSA_KEY_LIFETIME_PERSISTENT, the usage flag #PSA_KEY_USAGE_COPY + * is sufficient to permit the copy. + */ +#define PSA_KEY_USAGE_COPY ((psa_key_usage_t)0x00000002) + +/** Whether the key may be used to encrypt a message. + * + * This flag allows the key to be used for a symmetric encryption operation, + * for an AEAD encryption-and-authentication operation, + * or for an asymmetric encryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_ENCRYPT ((psa_key_usage_t)0x00000100) + +/** Whether the key may be used to decrypt a message. + * + * This flag allows the key to be used for a symmetric decryption operation, + * for an AEAD decryption-and-verification operation, + * or for an asymmetric decryption operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_DECRYPT ((psa_key_usage_t)0x00000200) + +/** Whether the key may be used to sign a message. + * + * This flag allows the key to be used for a MAC calculation operation + * or for an asymmetric signature operation, + * if otherwise permitted by the key's type and policy. + * + * For a key pair, this concerns the private key. + */ +#define PSA_KEY_USAGE_SIGN_HASH ((psa_key_usage_t)0x00000400) + +/** Whether the key may be used to verify a message signature. + * + * This flag allows the key to be used for a MAC verification operation + * or for an asymmetric signature verification operation, + * if otherwise permitted by by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY_HASH ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +/** \defgroup derivation Key derivation + * @{ + */ + +/** A secret input for key derivation. + * + * This should be a key of type #PSA_KEY_TYPE_DERIVE + * (passed to psa_key_derivation_input_key()) + * or the shared secret resulting from a key agreement + * (obtained via psa_key_derivation_key_agreement()). + * + * The secret can also be a direct input (passed to + * key_derivation_input_bytes()). In this case, the derivation operation + * may not be used to derive keys: the operation will only allow + * psa_key_derivation_output_bytes(), not psa_key_derivation_output_key(). + */ +#define PSA_KEY_DERIVATION_INPUT_SECRET ((psa_key_derivation_step_t)0x0101) + +/** A label for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_LABEL ((psa_key_derivation_step_t)0x0201) + +/** A salt for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SALT ((psa_key_derivation_step_t)0x0202) + +/** An information string for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_INFO ((psa_key_derivation_step_t)0x0203) + +/** A seed for key derivation. + * + * This should be a direct input. + * It can also be a key of type #PSA_KEY_TYPE_RAW_DATA. + */ +#define PSA_KEY_DERIVATION_INPUT_SEED ((psa_key_derivation_step_t)0x0204) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h new file mode 100644 index 0000000000..439dba4b70 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/error.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** + * \file psa/error.h + * \brief Standard error codes for the SPM and RoT Services + */ + +#ifndef __PSA_ERROR_H__ +#define __PSA_ERROR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* 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 + +#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) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_ERROR_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h new file mode 100644 index 0000000000..c125a4d6f4 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/initial_attestation.h @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/***************************************************************************/ +/* DRAFT UNDER REVIEW */ +/* These APIs are still evolving and are meant as a prototype for review.*/ +/* The APIs will change depending on feedback and will be firmed up */ +/* to a stable set of APIs once all the feedback has been considered. */ +/***************************************************************************/ + +#ifndef __PSA_INITIAL_ATTESTATION_H__ +#define __PSA_INITIAL_ATTESTATION_H__ + +#include +#include +#include +#include "psa/crypto.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PSA INITIAL ATTESTATION API version + * + * Initial attestation API version is: 1.0.0 + */ +#define PSA_INITIAL_ATTEST_API_VERSION_MAJOR (1) +#define PSA_INITIAL_ATTEST_API_VERSION_MINOR (0) + +/** + * The allowed size of input challenge in bytes: 32, 48, 64 + * Challenge can be a nonce from server + * or the hash of some combined data : nonce + attested data by caller. + */ +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32 (32u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48 (48u) +#define PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64 (64u) + +/** + * The maximum size of an attestation token that can be generated by the + * attestation service. Used to configure buffers for services that verify the + * produced tokens. + */ +#define PSA_INITIAL_ATTEST_MAX_TOKEN_SIZE (0x400) + +/** + * The list of fixed claims in the initial attestation token is still evolving, + * you can expect slight changes in the future. + * + * The initial attestation token is planned to be aligned with future version of + * Entity Attestation Token format: + * https://tools.ietf.org/html/draft-mandyam-eat-01 + * + * Current list of claims: + * - Challenge: Input object from caller. Can be a single nonce from server + * or hash of nonce and attested data. It is intended to provide + * freshness to reports and the caller has responsibility to + * arrange this. Allowed length: 32, 48, 64 bytes. The claim is + * modeled to be eventually represented by the EAT standard + * claim nonce. Until such a time as that standard exists, + * the claim will be represented by a custom claim. Value + * is encoded as byte string. + * + * - Instance ID: It represents the unique identifier of the instance. In the + * PSA definition it is a hash of the public attestation key + * of the instance. The claim is modeled to be eventually + * represented by the EAT standard claim UEID of type GUID. + * Until such a time as that standard exists, the claim will be + * represented by a custom claim Value is encoded as byte + * string. + * + * - Verification service indicator: Optional, recommended claim. It is used by + * a Relying Party to locate a validation service for the token. + * The value is a text string that can be used to locate the + * service or a URL specifying the address of the service. The + * claim is modeled to be eventually represented by the EAT + * standard claim origination. Until such a time as that + * standard exists, the claim will be represented by a custom + * claim. Value is encoded as text string. + * + * - Profile definition: Optional, recommended claim. It contains the name of + * a document that describes the 'profile' of the token, being + * a full description of the claims, their usage, verification + * and token signing. The document name may include versioning. + * Custom claim with a value encoded as text string. + * + * - Implementation ID: It represents the original implementation signer of the + * attestation key and identifies the contract between the + * report and verification. A verification service will use this + * claim to locate the details of the verification process. + * Custom claim with a value encoded as byte string. + * + * - Security lifecycle: It represents the current lifecycle state of the + * instance. Custom claim with a value encoded as integer that + * is divided to convey a major state and a minor state. The + * PSA state and implementation state are encoded as follows: + * - version[15:8] - PSA lifecycle state - major + * - version[7:0] - IMPLEMENTATION DEFINED state - minor + * Possible PSA lifecycle states: + * - Unknown (0x1000u), + * - PSA_RoT_Provisioning (0x2000u), + * - Secured (0x3000u), + * - Non_PSA_RoT_Debug(0x4000u), + * - Recoverable_PSA_RoT_Debug (0x5000u), + * - Decommissioned (0x6000u) + * + * - Client ID: The partition ID of that secure partition or non-secure + * thread who called the initial attestation API. Custom claim + * with a value encoded as a *signed* integer. Negative number + * represents non-secure caller, positive numbers represents + * secure callers, zero is invalid. + * + * - HW version: Optional claim. Globally unique number in EAN-13 format + * identifying the GDSII that went to fabrication, HW and ROM. + * It can be used to reference the security level of the PSA-ROT + * via a certification website. Custom claim with a value is + * encoded as text string. + + * - Boot seed: It represents a random value created at system boot time that + * will allow differentiation of reports from different system + * sessions. The size is 32 bytes. Custom claim with a value is + * encoded as byte string. + * + * - Software components: Recommended claim. It represents the software state + * of the system. The value of the claim is an array of CBOR map + * entries, with one entry per software component within the + * device. Each map contains multiple claims that describe + * evidence about the details of the software component. + * + * - Measurement type: Optional claim. It represents the role of the + * software component. Value is encoded as short(!) text + * string. + * + * - Measurement value: It represents a hash of the invariant software + * component in memory at start-up time. The value must be a + * cryptographic hash of 256 bits or stronger.Value is + * encoded as byte string. + * + * - Version: Optional claim. It represents the issued software version. + * Value is encoded as text string. + * + * - Signer ID: It represents the hash of a signing authority public key. + * Value is encoded as byte string. + * + * - Measurement description: Optional claim. It represents the way in which + * the measurement value of the software component is + * computed. Value is encoded as text string containing an + * abbreviated description (name) of the measurement method. + * + * - No software measurements: In the event that the implementation does not + * contain any software measurements then the software + * components claim above can be omitted but instead + * it is mandatory to include this claim to indicate this is a + * deliberate state. Custom claim a value is encoded as unsigned + * integer set to 1. + */ + +/** + * \brief Get initial attestation token + * + * \param[in] auth_challenge Pointer to buffer where challenge input is + * stored. Nonce and / or hash of attested data. + * Must be always + * \ref PSA_INITIAL_ATTEST_TOKEN_SIZE bytes + * long. + * \param[in] challenge_size Size of challenge object in bytes. + * \param[out] token_buf Pointer to the buffer where attestation token + * will be stored. + * \param[in] token_buf_size Size of allocated buffer for token, in bytes. + * \param[out] token_size Size of the token that has been returned, in + * bytes. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size); + +/** + * \brief Get the exact size of initial attestation token in bytes. + * + * It just returns with the size of the IAT token. It can be used if the caller + * dynamically allocates memory for the token buffer. + * + * \param[in] challenge_size Size of challenge object in bytes. This must be + * a supported challenge size (as above). + * \param[out] token_size Size of the token in bytes, which is created by + * initial attestation service. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size); + +/** + * \brief Get the initial attestation public key. + * + * \param[out] public_key Pointer to the buffer where the public key + * will be stored. + * \param[in] key_buf_size Size of allocated buffer for key, in bytes. + * \param[out] public_key_len Size of public key in bytes. + * \param[out] public_key_curve Type of the elliptic curve which the key + * belongs to. + * + * \note Currently only the ECDSA P-256 over SHA-256 algorithm is supported. + * + * \return Returns error code as specified in \ref psa_status_t + */ +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type); + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_INITIAL_ATTESTATION_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h new file mode 100644 index 0000000000..3920bc9825 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/internal_trusted_storage.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/** 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" + +#ifdef __cplusplus +extern "C" { +#endif +#define PSA_ITS_API_VERSION_MAJOR 1 /**< The major version number of the + * PSA ITS API + */ +#define PSA_ITS_API_VERSION_MINOR 0 /**< The minor version number of the + * PSA ITS API + */ +// This version of the header file is associated with 1.0 final release. + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the internal storage. + * + * \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_FLAG_WRITE_ONCE + * \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_ARGUMENT 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, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided UID + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \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 arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + */ +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `uid` as a `psa_storage_info_t` + * structure. + * + * \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 uid and its associated data from the storage + * + * Deletes the data from internal 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_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \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_STORAGE_FLAG_WRITE_ONCE + * \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/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h new file mode 100644 index 0000000000..e76205c4f1 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/protected_storage.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* 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 + +/** + * \brief PSA_PS_API_VERSION version + * + * Major and minor PSA_PS_API_VERSION numbers + */ +#define PSA_PS_API_VERSION_MAJOR 1 +#define PSA_PS_API_VERSION_MINOR 0 + +// This version of the header file is associated with 1.0 final release + +/** + * \brief Create a new, or modify an existing, uid/value pair + * + * Stores data in the protected storage. + * + * \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_FLAG_WRITE_ONCE + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one + * of the provided pointers(`p_data`) + * is invalid, for example is `NULL` or + * references memory the caller cannot + * access + * \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, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags); + +/** + * \brief Retrieve data associated with a provided uid + * + * Retrieves up to `data_size` bytes of the data associated with `uid`, starting + * at `data_offset` bytes from the beginning of the data. Upon successful + * completion, the data will be placed in the `p_data` buffer, which must be at + * least `data_size` bytes in size. The length of the data returned will be in + * `p_data_length`. If `data_size` is 0, the contents of `p_data_length` will + * be set to zero. + * + * \param[in] uid The uid value + * \param[in] data_offset The starting offset of the data requested + * \param[in] data_size The amount of data requested + * \param[out] p_data On success, the buffer where the data will + * be placed + * \param[out] p_data_length On success, this will contain size of the data + * placed in `p_data` + * + * \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 of the + * provided arguments (`p_data`, + * `p_data_length`) is invalid, for example + * is `NULL` or references memory the + * caller cannot access. In addition, this + * can also happen if `data_offset` is + * larger than the size of the data + * associated with `uid` + * \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 the data + * associated with the UID was corrupt + * \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, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length); + +/** + * \brief Retrieve the metadata about the provided uid + * + * Retrieves the metadata stored for a given `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_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 + * \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 the data + * associated with the UID was corrupt + */ +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 + * + * Removes previously stored data and any associated metadata, + * including rollback protection data. + * + * \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_INVALID_ARGUMENT The operation failed because one or more + * of the given arguments were invalid (null + * pointer, wrong flags and so on) + * \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_STORAGE_FLAG_WRITE_ONCE + * \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); + +/** + * \brief Reserves storage for the specified uid + * + * Upon success, the capacity of the storage will be capacity, and the size + * will be 0. It is only necessary to call this function for assets that will + * be written with the psa_ps_set_extended function. If only the psa_ps_set + * function is needed, calls to this function are redundant. + * + * \param[in] uid The `uid` value + * \param[in] capacity The capacity to be allocated in bytes + * \param[in] create_flags Flags indicating properties of storage + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The operation completed successfully + * \retval PSA_ERROR_STORAGE_FAILURE The operation failed because the + * physical storage has failed + * (Fatal error) + * \retval PSA_ERROR_INSUFFICIENT_STORAGE The operation failed because the + * capacity is bigger than the current + * available space + * \retval PSA_ERROR_NOT_SUPPORTED The operation failed because the + * function is not implemented or one + * or more create_flags are not + * supported. + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because uid was + * 0 or create_flags specified flags + * that are not defined in the API. + * \retval PSA_ERROR_GENERIC_ERROR The operation failed due to an + * unspecified error + * \retval PSA_ERROR_ALREADY_EXISTS Storage for the specified uid + * already exists + */ +psa_status_t psa_ps_create(psa_storage_uid_t uid, + size_t capacity, + psa_storage_create_flags_t create_flags); + +/** + * \brief Sets partial data into an asset + * + * Before calling this function, the storage must have been reserved with a call + * to psa_ps_create. It can also be used to overwrite data in an asset that was + * created with a call to psa_ps_set. Calling this function with data_length = 0 + * is permitted, which will make no change to the stored data.This function can + * overwrite existing data and/or extend it up to the capacity for the uid + * specified in psa_ps_create, but cannot create gaps. + * + * That is, it has preconditions: + * - data_offset <= size + * - data_offset + data_length <= capacity + * and postconditions: + * - size = max(size, data_offset + data_length) + * - capacity unchanged. + * + * \param[in] uid The `uid` value + * \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 + * + * \return A status indicating the success/failure of the operation + * + * \retval PSA_SUCCESS The asset exists, the input parameters + * are correct and the data is correctly + * written in the physical storage. + * \retval PSA_ERROR_STORAGE_FAILURE The data was not written correctly in + * the physical storage + * \retval PSA_ERROR_INVALID_ARGUMENT The operation failed because one or more + * of the preconditions listed above + * regarding data_offset, size, or + * data_length was violated. + * \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). + * \retval PSA_ERROR_NOT_PERMITTED The operation failed because it was + * attempted on an asset which was written + * with the flag + * PSA_STORAGE_FLAG_WRITE_ONCE + */ +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, + size_t data_offset, + size_t data_length, + const void *p_data); + +/** + * \brief Lists optional features. + * + * \return A bitmask with flags set for all of + * the optional features supported by the + * implementation.Currently defined flags + * are limited to + * PSA_STORAGE_SUPPORT_SET_EXTENDED + */ +uint32_t psa_ps_get_support(void); + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_PROTECTED_STORAGE_H */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h new file mode 100644 index 0000000000..3f901c5bf9 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa/storage_common.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* This file includes common definitions for PSA storage +*/ + +#ifndef PSA_STORAGE_COMMON_H +#define PSA_STORAGE_COMMON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef uint32_t psa_storage_create_flags_t; + +typedef uint64_t psa_storage_uid_t; + +/* Flags */ + +#define PSA_STORAGE_FLAG_NONE 0u +#define PSA_STORAGE_FLAG_WRITE_ONCE (1u << 0) +#define PSA_STORAGE_FLAG_NO_CONFIDENTIALITY (1u << 1) +#define PSA_STORAGE_FLAG_NO_REPLAY_PROTECTION (1u << 2) + +/* A container for metadata associated with a specific uid */ + +struct psa_storage_info_t { + size_t capacity; + size_t size; + psa_storage_create_flags_t flags; +}; + +#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1u << 0) + +#define PSA_ERROR_INVALID_SIGNATURE ((psa_status_t)-149) +#define PSA_ERROR_DATA_CORRUPT ((psa_status_t)-152) + +#ifdef __cplusplus +} +#endif + +#endif // PSA_STORAGE_COMMON_H diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h new file mode 100644 index 0000000000..2fc339465e --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/psa_manifest/sid.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __PSA_MANIFEST_SID_H__ +#define __PSA_MANIFEST_SID_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/******** TFM_SP_STORAGE ********/ +#define TFM_SST_SET_SID (0x00000060U) +#define TFM_SST_SET_VERSION (1U) +#define TFM_SST_GET_SID (0x00000061U) +#define TFM_SST_GET_VERSION (1U) +#define TFM_SST_GET_INFO_SID (0x00000062U) +#define TFM_SST_GET_INFO_VERSION (1U) +#define TFM_SST_REMOVE_SID (0x00000063U) +#define TFM_SST_REMOVE_VERSION (1U) +#define TFM_SST_GET_SUPPORT_SID (0x00000064U) +#define TFM_SST_GET_SUPPORT_VERSION (1U) + +/******** TFM_SP_ITS ********/ +#define TFM_ITS_SET_SID (0x00000070U) +#define TFM_ITS_SET_VERSION (1U) +#define TFM_ITS_GET_SID (0x00000071U) +#define TFM_ITS_GET_VERSION (1U) +#define TFM_ITS_GET_INFO_SID (0x00000072U) +#define TFM_ITS_GET_INFO_VERSION (1U) +#define TFM_ITS_REMOVE_SID (0x00000073U) +#define TFM_ITS_REMOVE_VERSION (1U) + +/******** TFM_SP_CRYPTO ********/ +#define TFM_CRYPTO_SID (0x00000080U) +#define TFM_CRYPTO_VERSION (1U) + +/******** TFM_SP_PLATFORM ********/ +#define TFM_SP_PLATFORM_SYSTEM_RESET_SID (0x00000040U) +#define TFM_SP_PLATFORM_SYSTEM_RESET_VERSION (1U) +#define TFM_SP_PLATFORM_IOCTL_SID (0x00000041U) +#define TFM_SP_PLATFORM_IOCTL_VERSION (1U) +#define TFM_SP_PLATFORM_NV_COUNTER_SID (0x00000042U) +#define TFM_SP_PLATFORM_NV_COUNTER_VERSION (1U) + +/******** TFM_SP_INITIAL_ATTESTATION ********/ +#define TFM_ATTEST_GET_TOKEN_SID (0x00000020U) +#define TFM_ATTEST_GET_TOKEN_VERSION (1U) +#define TFM_ATTEST_GET_TOKEN_SIZE_SID (0x00000021U) +#define TFM_ATTEST_GET_TOKEN_SIZE_VERSION (1U) +#define TFM_ATTEST_GET_PUBLIC_KEY_SID (0x00000022U) +#define TFM_ATTEST_GET_PUBLIC_KEY_VERSION (1U) + +/******** TFM_SP_CORE_TEST ********/ +#define SPM_CORE_TEST_INIT_SUCCESS_SID (0x0000F020U) +#define SPM_CORE_TEST_INIT_SUCCESS_VERSION (1U) +#define SPM_CORE_TEST_DIRECT_RECURSION_SID (0x0000F021U) +#define SPM_CORE_TEST_DIRECT_RECURSION_VERSION (1U) +#define SPM_CORE_TEST_MPU_ACCESS_SID (0x0000F022U) +#define SPM_CORE_TEST_MPU_ACCESS_VERSION (1U) +#define SPM_CORE_TEST_MEMORY_PERMISSIONS_SID (0x0000F023U) +#define SPM_CORE_TEST_MEMORY_PERMISSIONS_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_SID (0x0000F024U) +#define SPM_CORE_TEST_SS_TO_SS_VERSION (1U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_SID (0x0000F025U) +#define SPM_CORE_TEST_SS_TO_SS_BUFFER_VERSION (1U) +#define SPM_CORE_TEST_OUTVEC_WRITE_SID (0x0000F026U) +#define SPM_CORE_TEST_OUTVEC_WRITE_VERSION (1U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_SID (0x0000F027U) +#define SPM_CORE_TEST_PERIPHERAL_ACCESS_VERSION (1U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_SID (0x0000F028U) +#define SPM_CORE_TEST_GET_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_SPM_REQUEST_SID (0x0000F029U) +#define SPM_CORE_TEST_SPM_REQUEST_VERSION (1U) +#define SPM_CORE_TEST_BLOCK_SID (0x0000F02AU) +#define SPM_CORE_TEST_BLOCK_VERSION (1U) +#define SPM_CORE_TEST_NS_THREAD_SID (0x0000F02BU) +#define SPM_CORE_TEST_NS_THREAD_VERSION (1U) + +/******** TFM_SP_CORE_TEST_2 ********/ +#define SPM_CORE_TEST_2_SLAVE_SERVICE_SID (0x0000F040U) +#define SPM_CORE_TEST_2_SLAVE_SERVICE_VERSION (1U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_SID (0x0000F041U) +#define SPM_CORE_TEST_2_CHECK_CALLER_CLIENT_ID_VERSION (1U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_SID (0x0000F042U) +#define SPM_CORE_TEST_2_GET_EVERY_SECOND_BYTE_VERSION (1U) +#define SPM_CORE_TEST_2_INVERT_SID (0x0000F043U) +#define SPM_CORE_TEST_2_INVERT_VERSION (1U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_SID (0x0000F044U) +#define SPM_CORE_TEST_2_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_SID (0x0000F045U) +#define SPM_CORE_TEST_2_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_SID (0x0000F000U) +#define TFM_SECURE_CLIENT_SFN_RUN_TESTS_VERSION (1U) + +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#define IPC_SERVICE_TEST_BASIC_SID (0x0000F080U) +#define IPC_SERVICE_TEST_BASIC_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F081U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F082U) +#define IPC_SERVICE_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F083U) +#define IPC_SERVICE_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_SID (0x0000F084U) +#define IPC_SERVICE_TEST_CLIENT_PROGRAMMER_ERROR_VERSION (1U) + +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#define IPC_CLIENT_TEST_BASIC_SID (0x0000F060U) +#define IPC_CLIENT_TEST_BASIC_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_SID (0x0000F061U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_SID (0x0000F062U) +#define IPC_CLIENT_TEST_PSA_ACCESS_APP_READ_ONLY_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_SID (0x0000F063U) +#define IPC_CLIENT_TEST_APP_ACCESS_PSA_MEM_VERSION (1U) +#define IPC_CLIENT_TEST_MEM_CHECK_SID (0x0000F064U) +#define IPC_CLIENT_TEST_MEM_CHECK_VERSION (1U) + +/******** TFM_IRQ_TEST_1 ********/ +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_SID (0x0000F0A0U) +#define SPM_CORE_IRQ_TEST_1_PREPARE_TEST_SCENARIO_VERSION (1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_SID (0x0000F0A1U) +#define SPM_CORE_IRQ_TEST_1_EXECUTE_TEST_SCENARIO_VERSION (1U) + +/******** TFM_SP_SST_TEST ********/ +#define TFM_SST_TEST_PREPARE_SID (0x0000F0C0U) +#define TFM_SST_TEST_PREPARE_VERSION (1U) + +/******** TFM_SP_SECURE_CLIENT_2 ********/ +#define TFM_SECURE_CLIENT_2_SID (0x0000F0E0U) +#define TFM_SECURE_CLIENT_2_VERSION (1U) + +/******** TFM_SP_MULTI_CORE_TEST ********/ +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_SID (0x0000F100U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_0_VERSION (1U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_SID (0x0000F101U) +#define MULTI_CORE_MULTI_CLIENT_CALL_TEST_1_VERSION (1U) + +#ifdef __cplusplus +} +#endif + +#endif /* __PSA_MANIFEST_SID_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h new file mode 100644 index 0000000000..09abc399b1 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_api.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_API_H__ +#define __TFM_API_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "psa/client.h" + +#define TFM_INVALID_CLIENT_ID 0 + +/** + * \brief Checks if the provided client ID is a secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is secure. + * \retval 0 Client ID is non-secure. + */ +#define TFM_CLIENT_ID_IS_S(client_id) ((client_id)>0) + +/** + * \brief Checks if the provided client ID is a non-secure client ID. + * + * \param[in] client_id Client ID to check. + * + * \retval 1 Client ID is non-secure. + * \retval 0 Client ID is secure. + */ +#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0) + +/* The mask used for timeout values */ +#define PSA_TIMEOUT_MASK PSA_BLOCK + +/* FixMe: sort out DEBUG compile option and limit return value options + * on external interfaces */ +enum tfm_status_e +{ + TFM_SUCCESS = 0, + TFM_PARTITION_BUSY, + TFM_ERROR_SECURE_DOMAIN_LOCKED, + TFM_ERROR_INVALID_PARAMETER, + TFM_ERROR_PARTITION_NON_REENTRANT, + TFM_ERROR_NS_THREAD_MODE_CALL, + TFM_ERROR_NOT_INITIALIZED, + TFM_ERROR_NO_ACTIVE_PARTITION, + TFM_ERROR_INVALID_EXC_MODE, + TFM_SECURE_LOCK_FAILED, + TFM_SECURE_UNLOCK_FAILED, + TFM_ERROR_GENERIC = 0x1F, +}; + +/* + * Structure to package type, in_len and out_len, it is mainly used for + * psa_call. + */ +struct tfm_control_parameter_t { + int32_t type; + size_t in_len; + size_t out_len; +}; + +/********************* Secure function declarations ***************************/ + +/** + * \brief Assign client ID to the current TZ context. + * + * \param[in] ns_client_id The client ID to be assigned to the current + * context. + * \retval TFM_SUCCESS The client ID assigned successfully. + * \retval error code The client ID assignment failed, an error code + * returned according to \ref tfm_status_e. + * \note This function have to be called from handler mode. + */ +enum tfm_status_e tfm_register_client_id (int32_t ns_client_id); + +/** + * \brief Retrieve the version of the PSA Framework API that is implemented. + * + * \return The version of the PSA Framework. + */ +uint32_t tfm_psa_framework_version_veneer(void); + +/** + * \brief Return version of secure function provided by secure binary. + * + * \param[in] sid ID of secure service. + * + * \return Version number of secure function. + */ +uint32_t tfm_psa_version_veneer(uint32_t sid); + +/** + * \brief Connect to secure function. + * + * \param[in] sid ID of secure service. + * \param[in] version Version of SF requested by client. + * + * \return Returns handle to connection. + */ +psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t version); + +/** + * \brief Call a secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection. + * \param[in] ctrl_param Parameter structure, includes reuqest type, + * in_num and out_num. + * \param[in] in_vec Array of input \ref psa_invec structures. + * \param[in/out] out_vec Array of output \ref psa_outvec structures. + * + * \return Returns \ref psa_status_t status code. + */ +psa_status_t tfm_psa_call_veneer(psa_handle_t handle, + const struct tfm_control_parameter_t *ctrl_param, + const psa_invec *in_vec, + psa_outvec *out_vec); + +/** + * \brief Close connection to secure function referenced by a connection handle. + * + * \param[in] handle Handle to connection + * + * \return void + */ +void tfm_psa_close_veneer(psa_handle_t handle); + +/***************** End Secure function declarations ***************************/ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_API_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h new file mode 100644 index 0000000000..53c03ce022 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_crypto_defs.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_CRYPTO_DEFS_H__ +#define __TFM_CRYPTO_DEFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "tfm_api.h" +#include "psa/crypto.h" + +/** + * \brief This type is used to overcome a limitation in the number of maximum + * IOVECs that can be used especially in psa_aead_encrypt and + * psa_aead_decrypt. To be removed in case the AEAD APIs number of + * parameters passed gets restructured + */ +#define TFM_CRYPTO_MAX_NONCE_LENGTH (16u) +struct tfm_crypto_aead_pack_input { + uint8_t nonce[TFM_CRYPTO_MAX_NONCE_LENGTH]; + uint32_t nonce_length; +}; + +/** + * \brief Structure used to pack non-pointer types in a call + * + */ +struct tfm_crypto_pack_iovec { + uint32_t sfn_id; /*!< Secure function ID used to dispatch the + * request + */ + uint16_t step; /*!< Key derivation step */ + psa_key_handle_t key_handle; /*!< Key handle */ + psa_algorithm_t alg; /*!< Algorithm */ + uint32_t op_handle; /*!< Frontend context handle associated to a + * multipart operation + */ + size_t capacity; /*!< Key derivation capacity */ + + struct tfm_crypto_aead_pack_input aead_in; /*!< FixMe: Temporarily used for + * AEAD until the API is + * restructured + */ +}; + +/** + * \brief Define a progressive numerical value for each SID which can be used + * when dispatching the requests to the service + */ +enum { + TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID = (0u), + TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + TFM_CRYPTO_OPEN_KEY_SID, + TFM_CRYPTO_CLOSE_KEY_SID, + TFM_CRYPTO_IMPORT_KEY_SID, + TFM_CRYPTO_DESTROY_KEY_SID, + TFM_CRYPTO_EXPORT_KEY_SID, + TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + TFM_CRYPTO_COPY_KEY_SID, + TFM_CRYPTO_HASH_COMPUTE_SID, + TFM_CRYPTO_HASH_COMPARE_SID, + TFM_CRYPTO_HASH_SETUP_SID, + TFM_CRYPTO_HASH_UPDATE_SID, + TFM_CRYPTO_HASH_FINISH_SID, + TFM_CRYPTO_HASH_VERIFY_SID, + TFM_CRYPTO_HASH_ABORT_SID, + TFM_CRYPTO_HASH_CLONE_SID, + TFM_CRYPTO_MAC_COMPUTE_SID, + TFM_CRYPTO_MAC_VERIFY_SID, + TFM_CRYPTO_MAC_SIGN_SETUP_SID, + TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + TFM_CRYPTO_MAC_UPDATE_SID, + TFM_CRYPTO_MAC_SIGN_FINISH_SID, + TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + TFM_CRYPTO_MAC_ABORT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SID, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + TFM_CRYPTO_CIPHER_SET_IV_SID, + TFM_CRYPTO_CIPHER_UPDATE_SID, + TFM_CRYPTO_CIPHER_FINISH_SID, + TFM_CRYPTO_CIPHER_ABORT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SID, + TFM_CRYPTO_AEAD_DECRYPT_SID, + TFM_CRYPTO_AEAD_ENCRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_DECRYPT_SETUP_SID, + TFM_CRYPTO_AEAD_GENERATE_NONCE_SID, + TFM_CRYPTO_AEAD_SET_NONCE_SID, + TFM_CRYPTO_AEAD_SET_LENGTHS_SID, + TFM_CRYPTO_AEAD_UPDATE_AD_SID, + TFM_CRYPTO_AEAD_UPDATE_SID, + TFM_CRYPTO_AEAD_FINISH_SID, + TFM_CRYPTO_AEAD_VERIFY_SID, + TFM_CRYPTO_AEAD_ABORT_SID, + TFM_CRYPTO_SIGN_HASH_SID, + TFM_CRYPTO_VERIFY_HASH_SID, + TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + TFM_CRYPTO_GENERATE_RANDOM_SID, + TFM_CRYPTO_GENERATE_KEY_SID, + TFM_CRYPTO_SET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_GET_KEY_DOMAIN_PARAMETERS_SID, + TFM_CRYPTO_SID_MAX, +}; + +/** + * \brief Define an invalid value for an SID + * + */ +#define TFM_CRYPTO_SID_INVALID (~0x0u) + +/** + * \brief This value is used to mark an handle as invalid. + * + */ +#define TFM_CRYPTO_INVALID_HANDLE (0x0u) + +/** + * \brief The persistent key identifier that refers to the hardware unique key. + * + */ +#define TFM_CRYPTO_KEY_ID_HUK (0xFFFF815Bu) + +/** + * \brief The algorithm identifier that refers to key derivation from the + * hardware unique key. + * + */ +#define TFM_CRYPTO_ALG_HUK_DERIVATION ((psa_algorithm_t)0xB0000F00) + +/** + * \brief Define miscellaneous literal constants that are used in the service + * + */ +enum { + TFM_CRYPTO_NOT_IN_USE = 0, + TFM_CRYPTO_IN_USE = 1 +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_CRYPTO_DEFS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h new file mode 100644 index 0000000000..3d128f40b2 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_mailbox.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* + * This is header file of common mailbox objects shared by NSPE and SPE. + * Please refer to tfm_ns_mailbox.h for the definitions only used in NSPE + * mailbox library. + * Please refer to tfm_spe_mailbox.h for the SPE specific definitions and APIs. + */ + +#ifndef __TFM_MAILBOX_H__ +#define __TFM_MAILBOX_H__ + +#include +#include +#include +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#include "device_cfg.h" +#endif +#include "psa/client.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * If multiple outstanding NS PSA Client calls is enabled, multi-core platform + * should define the number of mailbox queue slots NUM_MAILBOX_QUEUE_SLOT in + * platform device_cfg.h. + * Otherwise, NUM_MAILBOX_QUEUE_SLOT is defined as 1. + */ +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +#ifndef NUM_MAILBOX_QUEUE_SLOT +#error "Error: Platform doesn't define NUM_MAILBOX_QUEUE_SLOT for mailbox queue" +#endif + +#if (NUM_MAILBOX_QUEUE_SLOT < 2) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be more than 1" +#endif + +/* + * The number of slots should be no more than the number of bits in + * mailbox_queue_status_t. + * Here the value is hardcoded. A better way is to define a sizeof() to + * calculate the bits in mailbox_queue_status_t and dump it with pragma message. + */ +#if (NUM_MAILBOX_QUEUE_SLOT > 32) +#error "Error: Invalid NUM_MAILBOX_QUEUE_SLOT. The value should be no more than 32" +#endif +#else /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ +/* Force the number of mailbox queue slots as 1. */ +#undef NUM_MAILBOX_QUEUE_SLOT +#define NUM_MAILBOX_QUEUE_SLOT (1) +#endif /* TFM_MULTI_CORE_MULTI_CLIENT_CALL */ + +/* PSA client call type value */ +#define MAILBOX_PSA_FRAMEWORK_VERSION (0x1) +#define MAILBOX_PSA_VERSION (0x2) +#define MAILBOX_PSA_CONNECT (0x3) +#define MAILBOX_PSA_CALL (0x4) +#define MAILBOX_PSA_CLOSE (0x5) + +/* Return code of mailbox APIs */ +#define MAILBOX_SUCCESS (0) +#define MAILBOX_QUEUE_FULL (INT32_MIN + 1) +#define MAILBOX_INVAL_PARAMS (INT32_MIN + 2) +#define MAILBOX_NO_PERMS (INT32_MIN + 3) +#define MAILBOX_NO_PEND_EVENT (INT32_MIN + 4) +#define MAILBOX_CHAN_BUSY (INT32_MIN + 5) +#define MAILBOX_CALLBACK_REG_ERROR (INT32_MIN + 6) +#define MAILBOX_INIT_ERROR (INT32_MIN + 7) + +/* + * This structure holds the parameters used in a PSA client call. + */ +struct psa_client_params_t { + union { + struct { + uint32_t sid; + } psa_version_params; + + struct { + uint32_t sid; + uint32_t version; + } psa_connect_params; + + struct { + psa_handle_t handle; + int32_t type; + const psa_invec *in_vec; + size_t in_len; + psa_outvec *out_vec; + size_t out_len; + } psa_call_params; + + struct { + psa_handle_t handle; + } psa_close_params; + }; +}; + +/* Mailbox message passed from NSPE to SPE to deliver a PSA client call */ +struct mailbox_msg_t { + uint32_t call_type; /* PSA client call type */ + struct psa_client_params_t params; /* Contain parameters used in PSA + * client call + */ + + int32_t client_id; /* Optional client ID of the + * non-secure caller. + * It is required to identify the + * non-secure task when NSPE OS + * enforces non-secure task isolation + */ +}; + +/* A handle to a mailbox message in use */ +typedef int32_t mailbox_msg_handle_t; + +#define MAILBOX_MSG_NULL_HANDLE ((mailbox_msg_handle_t)0) + +/* + * Mailbox reply structure in non-secure memory + * to hold the PSA client call return result from SPE + */ +struct mailbox_reply_t { + int32_t return_val; +}; + +/* A single slot structure in NSPE mailbox queue */ +struct ns_mailbox_slot_t { + struct mailbox_msg_t msg; + struct mailbox_reply_t reply; + const void *owner; /* Handle of the owner task of this + * slot + */ + bool is_woken; /* Indicate that owner task has been + * or should be woken up, after the + * replied is received. + */ +}; + +typedef uint32_t mailbox_queue_status_t; + +/* NSPE mailbox queue */ +struct ns_mailbox_queue_t { + mailbox_queue_status_t empty_slots; /* Bitmask of empty slots */ + mailbox_queue_status_t pend_slots; /* Bitmask of slots pending + * for SPE handling + */ + mailbox_queue_status_t replied_slots; /* Bitmask of active slots + * containing PSA client call + * return result + */ + + struct ns_mailbox_slot_t queue[NUM_MAILBOX_QUEUE_SLOT]; + +#ifdef TFM_MULTI_CORE_TEST + uint32_t nr_tx; /* The total number of + * submission of NS PSA Client + * calls from NS task via + * mailbox. + */ + uint32_t nr_used_slots; /* The total number of used + * mailbox queue slots each time + * NS thread requests a mailbox + * queue slot. + */ +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h new file mode 100644 index 0000000000..7999fa442d --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_multi_core_api.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_MULTI_CORE_API__ +#define __TFM_MULTI_CORE_API__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * \brief Called on the non-secure CPU. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \return Return 0 if succeeds. + * \return Otherwise, return specific error code. + */ +int32_t tfm_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Synchronisation with secure CPU, platform-specific implementation. + * Flags that the non-secure side has completed its initialization. + * Waits, if necessary, for the secure CPU to flag that it has completed + * its initialization. + * + * \retval Return 0 if succeeds. + * \retval Otherwise, return specific error code. + */ +int32_t tfm_platform_ns_wait_for_s_cpu_ready(void); + +/** + * \brief Acquire the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_acquire(void); + +/** + * \brief Release the multi-core lock for synchronizing PSA client call(s) + * The actual implementation depends on the use scenario. + * + * \return \ref TFM_SUCCESS on success + * \return \ref TFM_ERROR_GENERIC on error + */ +uint32_t tfm_ns_multi_core_lock_release(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_MULTI_CORE_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h new file mode 100644 index 0000000000..21857bed6f --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_interface.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef __TFM_NS_INTERFACE_H__ +#define __TFM_NS_INTERFACE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "tfm_api.h" + +typedef int32_t (*veneer_fn) (uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, veneer function dispatcher + * + * \details This function implements the dispatching mechanism for the + * desired veneer function, to be called with the parameters + * described from arg0 to arg3. + * + * \param[in] fn Function pointer to the veneer function desired + * \param[in] arg0 Argument 0 + * \param[in] arg1 Argument 1 + * \param[in] arg2 Argument 2 + * \param[in] arg3 Argument 3 + * + * \return Returns the same return value of the requested veneer function + */ +int32_t tfm_ns_interface_dispatch(veneer_fn fn, + uint32_t arg0, uint32_t arg1, + uint32_t arg2, uint32_t arg3); + +/** + * \brief NS interface, Initialise the NS interface + * + * \details This function needs to be called from the NS world to + * properly initialise the NS interface towards TF-M. This + * function will initialise all the objects required for + * runtime dispatching of TF-M requests to services + * + * \return A value according to \ref enum tfm_status_e + */ +enum tfm_status_e tfm_ns_interface_init(void); +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_INTERFACE_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h new file mode 100644 index 0000000000..ba902aa977 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_mailbox.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* Data types and API definitions in NSPE mailbox library */ + +#ifndef __TFM_NS_MAILBOX_H__ +#define __TFM_NS_MAILBOX_H__ + +#include +#include +#include "tfm_mailbox.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief The structure to hold the statistics result of NSPE mailbox + */ +struct ns_mailbox_stats_res_t { + uint8_t avg_nr_slots; /* The value before the decimal point + * in the average number of NSPE + * mailbox slots in use. + */ + uint8_t avg_nr_slots_tenths; /* The first digit value after the + * decimal point in the average + * number of NSPE mailbox slots in use. + */ +}; +#endif + +/** + * \brief Prepare and send PSA client request to SPE via mailbox. + * + * \param[in] call_type PSA client call type + * \param[in] params Parmaters used for PSA client call + * \param[in] client_id Optional client ID of non-secure caller. + * It is required to identify the non-secure caller + * when NSPE OS enforces non-secure task isolation. + * + * \retval >= 0 The handle to the mailbox message assigned. + * \retval < 0 Operation failed with an error code. + */ +mailbox_msg_handle_t tfm_ns_mailbox_tx_client_req(uint32_t call_type, + const struct psa_client_params_t *params, + int32_t client_id); + +/** + * \brief Fetch PSA client return result. + * + * \param[in] handle The handle to the mailbox message + * \param[out] reply The address to be written with return result. + * + * \retval MAILBOX_SUCCESS Successfully get PSA client call return result. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_rx_client_reply(mailbox_msg_handle_t handle, + int32_t *reply); + +/** + * \brief Check whether a specific mailbox message has been replied. + * + * \param[in] handle The handle to the mailbox message + * + * \retval true The PSA client call return value is replied. + * \retval false The PSA client call return value is not + * replied yet. + */ +bool tfm_ns_mailbox_is_msg_replied(mailbox_msg_handle_t handle); + +/** + * \brief NSPE mailbox initialization + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_init(struct ns_mailbox_queue_t *queue); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Get the handle of the current non-secure task executing mailbox + * functionalities + * + * \note This function should be implemented according to platform, NS OS + * and actual use scenario. + * This function can be ignored or return NULL if sleep/wake-up mechanism + * is not required in PSA Client API implementation. + * + * \return Return the handle of task. + */ +const void *tfm_ns_mailbox_get_task_handle(void); +#else +static inline const void *tfm_ns_mailbox_get_task_handle(void) +{ + return NULL; +} +#endif + +/** + * \brief Fetch the handle to the first replied mailbox message in the NSPE + * mailbox queue. + * This function is intended to be called inside platform specific + * notification IRQ handler. + * + * \note The replied status of the fetched mailbox message will be cleaned after + * the message is fetched. When this function is called again, it fetches + * the next replied mailbox message from the NSPE mailbox queue. + * + * \return Return the handle to the first replied mailbox message in the + * queue. + * Return \ref MAILBOX_MSG_NULL_HANDLE if no mailbox message is replied. + */ +mailbox_msg_handle_t tfm_ns_mailbox_fetch_reply_msg_isr(void); + +/** + * \brief Return the handle of owner task of a mailbox message according to the + * \ref mailbox_msg_handle_t + * + * \param[in] handle The handle of mailbox message. + * + * \return Return the handle value of the owner task. + */ +const void *tfm_ns_mailbox_get_msg_owner(mailbox_msg_handle_t handle); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Wait for the reply returned from SPE to the mailbox message specified + * by handle + * + * \param[in] handle The handle of mailbox message. + * + * \retval MAILBOX_SUCCESS Return from waiting successfully. + * \retval Other return code Failed to wait with an error code. + */ +int32_t tfm_ns_mailbox_wait_reply(mailbox_msg_handle_t handle); +#endif + +/** + * \brief Platform specific NSPE mailbox initialization. + * Invoked by \ref tfm_ns_mailbox_init(). + * + * \param[in] queue The base address of NSPE mailbox queue to be + * initialized. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_init(struct ns_mailbox_queue_t *queue); + +/** + * \brief Notify SPE to deal with the PSA client call sent via mailbox + * + * \note The implementation depends on platform specific hardware and use case. + * + * \retval MAILBOX_SUCCESS Operation succeeded. + * \retval Other return code Operation failed with an error code. + */ +int32_t tfm_ns_mailbox_hal_notify_peer(void); + +/** + * \brief Enter critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical(void); + +/** + * \brief Exit critical section of NSPE mailbox. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler. + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_enter_critical_isr(void); + +/** + * \brief Enter critical section of NSPE mailbox in IRQ handler + * + * \note The implementation depends on platform specific hardware and use case. + */ +void tfm_ns_mailbox_hal_exit_critical_isr(void); + +#ifdef TFM_MULTI_CORE_MULTI_CLIENT_CALL +/** + * \brief Performs platform and NS OS specific waiting mechanism to wait for + * the reply of the specified mailbox message to be returned from SPE. + * + * \note This function is implemented by platform and NS OS specific waiting + * mechanism accroding to use scenario. + * + * \param[in] handle The handle of mailbox message. + */ +void tfm_ns_mailbox_hal_wait_reply(mailbox_msg_handle_t handle); +#endif + +#ifdef TFM_MULTI_CORE_TEST +/** + * \brief Initialize the statistics module in TF-M NSPE mailbox. + * + * \note This function is only available when multi-core tests are enabled. + */ +void tfm_ns_mailbox_tx_stats_init(void); + +/** + * \brief Calculate the average number of used NS mailbox queue slots each time + * NS task requires a queue slot to submit mailbox message, which is + * recorded in NS mailbox statisitics module. + * + * \note This function is only available when multi-core tests are enabled. + * + * \param[in] stats_res The buffer to be written with + * \ref ns_mailbox_stats_res_t. + * + * \return Return the calculation result. + */ +void tfm_ns_mailbox_stats_avg_slot(struct ns_mailbox_stats_res_t *stats_res); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_MAILBOX_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h new file mode 100644 index 0000000000..def0c2f7ee --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_ns_svc.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "cmsis_compiler.h" + +#ifndef __TFM_NS_SVC_H__ +#define __TFM_NS_SVC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Include all the SVC handler headers + */ +#include "tfm_nspm_svc_handler.h" + +/** + * \brief Macro to encode an svc instruction + * + */ +#define SVC(code) __ASM volatile("svc %0" : : "I" (code)) + +/** + * \def LIST_SVC_NSPM + * + * \brief This is an X macro which lists + * the SVC interface exposed by TF-M + * for the NS OS. + * + */ +#define LIST_SVC_NSPM \ + X(SVC_TFM_NSPM_REGISTER_CLIENT_ID, tfm_nspm_svc_register_client_id) \ + +/** + * \brief Numbers associated to each SVC available + * + * \details Start from 1 as 0 is reserved by RTX + */ +enum tfm_svc_num { + SVC_INVALID = 0, + +#define X(SVC_ENUM, SVC_HANDLER) SVC_ENUM, + + /* SVC API for Services */ +#ifdef TFM_NS_CLIENT_IDENTIFICATION + LIST_SVC_NSPM +#endif + +#undef X + + /* add all the new entries above this line */ + SVC_TFM_MAX, +}; + +/* number of user SVC functions */ +#define USER_SVC_COUNT ((uint32_t)SVC_TFM_MAX - 1) + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_NS_SVC_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h new file mode 100644 index 0000000000..8c9b0db1fa --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_platform_api.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __TFM_PLATFORM_API__ +#define __TFM_PLATFORM_API__ + +#include +#include +#include +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief TFM secure partition platform API version + */ +#define TFM_PLATFORM_API_VERSION_MAJOR (0) +#define TFM_PLATFORM_API_VERSION_MINOR (3) + +#define TFM_PLATFORM_API_ID_NV_READ (1010) +#define TFM_PLATFORM_API_ID_NV_INCREMENT (1011) + +/*! + * \enum tfm_platform_err_t + * + * \brief Platform service error types + * + */ +enum tfm_platform_err_t { + TFM_PLATFORM_ERR_SUCCESS = 0, + TFM_PLATFORM_ERR_SYSTEM_ERROR, + TFM_PLATFORM_ERR_INVALID_PARAM, + TFM_PLATFORM_ERR_NOT_SUPPORTED, + + /* Following entry is only to ensure the error code of int size */ + TFM_PLATFORM_ERR_FORCE_INT_SIZE = INT_MAX +}; + +typedef int32_t tfm_platform_ioctl_req_t; + +/*! + * \brief Resets the system. + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_system_reset(void); + +/*! + * \brief Performs a platform-specific service + * + * \param[in] request Request identifier (valid values vary + * based on the platform) + * \param[in] input Input buffer to the requested service (or NULL) + * \param[in,out] output Output buffer to the requested service (or NULL) + * + * \return Returns values as specified by the \ref tfm_platform_err_t + */ +enum tfm_platform_err_t tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, + psa_outvec *output); + +/*! + * \brief Increments the given non-volatile (NV) counter by one + * + * \param[in] counter_id NV counter ID. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_increment(uint32_t counter_id); + +/*! + * \brief Reads the given non-volatile (NV) counter + * + * \param[in] counter_id NV counter ID. + * \param[in] size Size of the buffer to store NV counter value + * in bytes. + * \param[out] val Pointer to store the current NV counter value. + * + * \return TFM_PLATFORM_ERR_SUCCESS if the value is read correctly. Otherwise, + * it returns TFM_PLATFORM_ERR_SYSTEM_ERROR. + */ +enum tfm_platform_err_t +tfm_platform_nv_counter_read(uint32_t counter_id, + uint32_t size, uint8_t *val); + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_PLATFORM_API__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h new file mode 100644 index 0000000000..d2d9207ffc --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/include/tfm_veneers.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*********** WARNING: This is an auto-generated file. Do not edit! ***********/ + +#ifndef __TFM_VENEERS_H__ +#define __TFM_VENEERS_H__ + +#include "tfm_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef TFM_PARTITION_SECURE_STORAGE +/******** TFM_SP_STORAGE ********/ +psa_status_t tfm_tfm_sst_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_sst_get_support_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_SECURE_STORAGE */ + +#ifdef TFM_PARTITION_INTERNAL_TRUSTED_STORAGE +/******** TFM_SP_ITS ********/ +psa_status_t tfm_tfm_its_set_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_get_info_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_its_remove_req_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INTERNAL_TRUSTED_STORAGE */ + +#ifdef TFM_PARTITION_AUDIT_LOG +/******** TFM_SP_AUDIT_LOG ********/ +psa_status_t tfm_audit_core_retrieve_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_add_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_get_record_info_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_audit_core_delete_record_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_AUDIT_LOG */ + +#ifdef TFM_PARTITION_CRYPTO +/******** TFM_SP_CRYPTO ********/ +psa_status_t tfm_tfm_crypto_get_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_open_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_close_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_reset_key_attributes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_import_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_destroy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_export_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_copy_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_compare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_hash_clone_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_compute_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_sign_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_verify_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_mac_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_generate_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_set_iv_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_cipher_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_encrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_decrypt_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_generate_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_nonce_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_set_lengths_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_ad_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_update_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_finish_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_verify_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_aead_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_sign_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_verify_hash_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_encrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_asymmetric_decrypt_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_setup_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_get_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_set_capacity_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_input_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_bytes_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_output_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_key_derivation_abort_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_raw_key_agreement_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_random_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_tfm_crypto_generate_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_CRYPTO */ + +#ifdef TFM_PARTITION_PLATFORM +/******** TFM_SP_PLATFORM ********/ +psa_status_t tfm_platform_sp_system_reset_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_ioctl_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_read_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_platform_sp_nv_counter_increment_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_PLATFORM */ + +#ifdef TFM_PARTITION_INITIAL_ATTESTATION +/******** TFM_SP_INITIAL_ATTESTATION ********/ +psa_status_t tfm_initial_attest_get_token_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_token_size_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_initial_attest_get_public_key_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_INITIAL_ATTESTATION */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST ********/ +psa_status_t tfm_spm_core_test_sfn_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_init_success_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_sfn_direct_recursion_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_CORE +/******** TFM_SP_CORE_TEST_2 ********/ +psa_status_t tfm_spm_core_test_2_slave_service_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_sfn_invert_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_check_caller_client_id_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_get_every_second_byte_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_core_test_2_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_CORE */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_TEST_PARTITION ********/ +psa_status_t tfm_tfm_secure_client_service_sfn_run_tests_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_SERVICE_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_PARTITION_TEST_CORE_IPC +/******** TFM_SP_IPC_CLIENT_TEST ********/ +#endif /* TFM_PARTITION_TEST_CORE_IPC */ + +#ifdef TFM_ENABLE_IRQ_TEST +/******** TFM_IRQ_TEST_1 ********/ +psa_status_t tfm_spm_irq_test_1_prepare_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +psa_status_t tfm_spm_irq_test_1_execute_test_scenario_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_ENABLE_IRQ_TEST */ + +#ifdef TFM_PARTITION_TEST_SST +/******** TFM_SP_SST_TEST ********/ +psa_status_t tfm_tfm_sst_test_prepare_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SST */ + +#ifdef TFM_PARTITION_TEST_SECURE_SERVICES +/******** TFM_SP_SECURE_CLIENT_2 ********/ +psa_status_t tfm_tfm_secure_client_2_call_veneer(psa_invec *in_vec, size_t in_len, psa_outvec *out_vec, size_t out_len); +#endif /* TFM_PARTITION_TEST_SECURE_SERVICES */ + +#ifdef TFM_MULTI_CORE_TEST +/******** TFM_SP_MULTI_CORE_TEST ********/ +#endif /* TFM_MULTI_CORE_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TFM_VENEERS_H__ */ diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c new file mode 100644 index 0000000000..70b3a0dfe5 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_crypto_ipc_api.c @@ -0,0 +1,1875 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "tfm_crypto_defs.h" +#include "psa/crypto.h" +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" +#include "psa/client.h" + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) + +#define PSA_CONNECT(service) \ + psa_handle_t ipc_handle; \ + ipc_handle = psa_connect(service##_SID, service##_VERSION); \ + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { \ + return PSA_ERROR_GENERIC_ERROR; \ + } \ + +#define PSA_CLOSE() psa_close(ipc_handle) + +#define API_DISPATCH(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + out_vec, ARRAY_SIZE(out_vec)) + +#define API_DISPATCH_NO_OUTVEC(sfn_name, sfn_id) \ + psa_call(ipc_handle, PSA_IPC_CALL, \ + in_vec, ARRAY_SIZE(in_vec), \ + (psa_outvec *)NULL, 0) + +psa_status_t psa_crypto_init(void) +{ + /* Service init is performed during TFM boot up, + * so application level initialisation is empty + */ + return PSA_SUCCESS; +} + +psa_status_t psa_open_key(psa_key_id_t id, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_OPEN_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = &id, .len = sizeof(psa_key_id_t)}, + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_open_key, + TFM_CRYPTO_OPEN_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_close_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + const struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CLOSE_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_close_key, + TFM_CRYPTO_CLOSE_KEY);; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_import_key(const psa_key_attributes_t *attributes, + const uint8_t *data, + size_t data_length, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_IMPORT_KEY_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + {.base = data, .len = data_length} + }; + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_import_key, + TFM_CRYPTO_IMPORT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_destroy_key(psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_DESTROY_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_destroy_key, + TFM_CRYPTO_DESTROY_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_get_key_attributes(psa_key_handle_t handle, + psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GET_KEY_ATTRIBUTES_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_get_key_attributes, + TFM_CRYPTO_GET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +void psa_reset_key_attributes(psa_key_attributes_t *attributes) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return; +#else + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RESET_KEY_ATTRIBUTES_SID, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_handle_t ipc_handle; + ipc_handle = psa_connect(TFM_CRYPTO_SID, TFM_CRYPTO_VERSION); + if (!PSA_HANDLE_IS_VALID(ipc_handle)) { + return; + } + + (void)API_DISPATCH(tfm_crypto_reset_key_attributes, + TFM_CRYPTO_RESET_KEY_ATTRIBUTES); + PSA_CLOSE(); + + return; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_KEY_SID, + .key_handle = handle, + }; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_key, + TFM_CRYPTO_EXPORT_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_export_public_key(psa_key_handle_t handle, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_EXPORT_PUBLIC_KEY_SID, + .key_handle = handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = data, .len = data_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_export_public_key, + TFM_CRYPTO_EXPORT_PUBLIC_KEY); + + *data_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_copy_key(psa_key_handle_t source_handle, + const psa_key_attributes_t *attributes, + psa_key_handle_t *target_handle) +{ +#ifdef TFM_CRYPTO_KEY_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_COPY_KEY_SID, + .key_handle = source_handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + + }; + + psa_outvec out_vec[] = { + {.base = target_handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_copy_key, + TFM_CRYPTO_COPY_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_KEY_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation, + unsigned char *iv, + size_t iv_size, + size_t *iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_GENERATE_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = iv, .len = iv_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_generate_iv, + TFM_CRYPTO_CIPHER_GENERATE_IV); + + *iv_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation, + const unsigned char *iv, + size_t iv_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_SET_IV_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = iv, .len = iv_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_set_iv, + TFM_CRYPTO_CIPHER_SET_IV); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ENCRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_encrypt_setup, + TFM_CRYPTO_CIPHER_ENCRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_DECRYPT_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_decrypt_setup, + TFM_CRYPTO_CIPHER_DECRYPT_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_update(psa_cipher_operation_t *operation, + const uint8_t *input, + size_t input_length, + unsigned char *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_update, + TFM_CRYPTO_CIPHER_UPDATE); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_abort, + TFM_CRYPTO_CIPHER_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_CIPHER_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_CIPHER_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_cipher_finish, + TFM_CRYPTO_CIPHER_FINISH); + + *output_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_CIPHER_MODULE_DISABLED */ +} + +psa_status_t psa_hash_setup(psa_hash_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_setup, + TFM_CRYPTO_HASH_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_update(psa_hash_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_update, + TFM_CRYPTO_HASH_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_finish(psa_hash_operation_t *operation, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = hash, .len = hash_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_finish, + TFM_CRYPTO_HASH_FINISH); + + *hash_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_verify(psa_hash_operation_t *operation, + const uint8_t *hash, + size_t hash_length) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_VERIFY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_verify, + TFM_CRYPTO_HASH_VERIFY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_abort(psa_hash_operation_t *operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_abort, + TFM_CRYPTO_HASH_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation) +{ +#ifdef TFM_CRYPTO_HASH_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_HASH_CLONE_SID, + .op_handle = source_operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = target_operation, .len = sizeof(psa_hash_operation_t)}, + }; + + if (target_operation && (target_operation->handle != 0)) { + return PSA_ERROR_BAD_STATE; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_hash_clone, + TFM_CRYPTO_HASH_CLONE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_HASH_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_setup, + TFM_CRYPTO_MAC_SIGN_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_SETUP_SID, + .key_handle = handle, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_setup, + TFM_CRYPTO_MAC_VERIFY_SETUP); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_update(psa_mac_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_UPDATE_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_update, + TFM_CRYPTO_MAC_UPDATE); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_SIGN_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + {.base = mac, .len = mac_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_sign_finish, + TFM_CRYPTO_MAC_SIGN_FINISH); + + *mac_length = out_vec[1].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation, + const uint8_t *mac, + size_t mac_length) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_VERIFY_FINISH_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = mac, .len = mac_length}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_verify_finish, + TFM_CRYPTO_MAC_VERIFY_FINISH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_mac_abort(psa_mac_operation_t *operation) +{ +#ifdef TFM_CRYPTO_MAC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_MAC_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_mac_abort, + TFM_CRYPTO_MAC_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_MAC_MODULE_DISABLED */ +} + +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *plaintext, + size_t plaintext_length, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_ENCRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = plaintext, .len = plaintext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = ciphertext, .len = ciphertext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *ciphertext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *nonce, + size_t nonce_length, + const uint8_t *additional_data, + size_t additional_data_length, + const uint8_t *ciphertext, + size_t ciphertext_length, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length) +{ +#ifdef TFM_CRYPTO_AEAD_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_AEAD_DECRYPT_SID, + .key_handle = handle, + .alg = alg, + .aead_in = {.nonce = {0}, .nonce_length = nonce_length} + }; + + /* Sanitize the optional input */ + if ((additional_data == NULL) && (additional_data_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + size_t idx = 0; + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = ciphertext, .len = ciphertext_length}, + {.base = additional_data, .len = additional_data_length}, + }; + psa_outvec out_vec[] = { + {.base = plaintext, .len = plaintext_size}, + }; + + if (nonce_length > TFM_CRYPTO_MAX_NONCE_LENGTH) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + if (nonce != NULL) { + for (idx = 0; idx < nonce_length; idx++) { + iov.aead_in.nonce[idx] = nonce[idx]; + } + } + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (additional_data == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *plaintext_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_AEAD_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ + return psa_sign_hash(handle, alg, hash, hash_length, signature, signature_size, signature_length); +} + +psa_status_t psa_sign_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + uint8_t *signature, + size_t signature_size, + size_t *signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_SIGN_HASH_SID, + .key_handle = handle, + .alg = alg, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + }; + psa_outvec out_vec[] = { + {.base = signature, .len = signature_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_sign_hash, + TFM_CRYPTO_SIGN_HASH); + + *signature_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ + return psa_verify_hash(handle, alg, hash, hash_length, signature, signature_length); +} + +psa_status_t psa_verify_hash(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *hash, + size_t hash_length, + const uint8_t *signature, + size_t signature_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_VERIFY_HASH_SID, + .key_handle = handle, + .alg = alg + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = hash, .len = hash_length}, + {.base = signature, .len = signature_length} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_verify_hash, + TFM_CRYPTO_VERIFY_HASH); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_ENCRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *salt, + size_t salt_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_ASYMMETRIC_DECRYPT_SID, + .key_handle = handle, + .alg = alg + }; + + /* Sanitize the optional input */ + if ((salt == NULL) && (salt_length != 0)) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = input, .len = input_length}, + {.base = salt, .len = salt_length} + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + size_t in_len = ARRAY_SIZE(in_vec); + if (salt == NULL) { + in_len--; + } + status = psa_call(ipc_handle, PSA_IPC_CALL, in_vec, in_len, + out_vec, ARRAY_SIZE(out_vec)); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_ASYMMETRIC_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_get_capacity( + const psa_key_derivation_operation_t *operation, + size_t *capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = capacity, .len = sizeof(size_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_get_capacity, + TFM_CRYPTO_KEY_DERIVATION_GET_CAPACITY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_bytes( + psa_key_derivation_operation_t *operation, + uint8_t *output, + size_t output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_bytes, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_BYTES); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_key( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY_SID, + .key_handle = handle, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_key, + TFM_CRYPTO_KEY_DERIVATION_INPUT_KEY); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_abort( + psa_key_derivation_operation_t *operation) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_ABORT_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_abort, + TFM_CRYPTO_KEY_DERIVATION_ABORT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_key_agreement( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT_SID, + .key_handle = private_key, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_key_agreement, + TFM_CRYPTO_KEY_DERIVATION_KEY_AGREEMENT); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_random(uint8_t *output, + size_t output_size) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_RANDOM_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + if (output_size == 0) { + return PSA_SUCCESS; + } + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_random, + TFM_CRYPTO_GENERATE_RANDOM); + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_generate_key(const psa_key_attributes_t *attributes, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_GENERATE_KEY_SID, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_generate_key, + TFM_CRYPTO_GENERATE_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes, + psa_key_type_t type, + const uint8_t *data, + size_t data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_get_key_domain_parameters( + const psa_key_attributes_t *attributes, + uint8_t *data, + size_t data_size, + size_t *data_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_hash_compare(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *hash, + const size_t hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_finish(psa_aead_operation_t *operation, + uint8_t *ciphertext, + size_t ciphertext_size, + size_t *ciphertext_length, + uint8_t *tag, + size_t tag_size, + size_t *tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_verify(psa_aead_operation_t *operation, + uint8_t *plaintext, + size_t plaintext_size, + size_t *plaintext_length, + const uint8_t *tag, + size_t tag_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_abort(psa_aead_operation_t *operation) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_compute(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *mac, + size_t mac_size, + size_t *mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_mac_verify(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + const uint8_t *mac, + const size_t mac_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_encrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_cipher_decrypt(psa_key_handle_t handle, + psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_raw_key_agreement(psa_algorithm_t alg, + psa_key_handle_t private_key, + const uint8_t *peer_key, + size_t peer_key_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_RAW_KEY_AGREEMENT_SID, + .alg = alg, + .key_handle = private_key + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = peer_key, .len = peer_key_length}, + }; + + psa_outvec out_vec[] = { + {.base = output, .len = output_size}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_raw_key_agreement, + TFM_CRYPTO_RAW_KEY_AGREEMENT); + + *output_length = out_vec[0].len; + + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation, + psa_algorithm_t alg) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SETUP_SID, + .alg = alg, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + psa_outvec out_vec[] = { + {.base = &(operation->handle), .len = sizeof(uint32_t)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_setup, + TFM_CRYPTO_KEY_DERIVATION_SETUP); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_set_capacity( + psa_key_derivation_operation_t *operation, + size_t capacity) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY_SID, + .capacity = capacity, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_set_capacity, + TFM_CRYPTO_KEY_DERIVATION_SET_CAPACITY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_input_bytes( + psa_key_derivation_operation_t *operation, + psa_key_derivation_step_t step, + const uint8_t *data, + size_t data_length) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES_SID, + .step = step, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = data, .len = data_length}, + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH_NO_OUTVEC(tfm_crypto_key_derivation_input_bytes, + TFM_CRYPTO_KEY_DERIVATION_INPUT_BYTES); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_key_derivation_output_key( + const psa_key_attributes_t *attributes, + psa_key_derivation_operation_t *operation, + psa_key_handle_t *handle) +{ +#ifdef TFM_CRYPTO_GENERATOR_MODULE_DISABLED + return PSA_ERROR_NOT_SUPPORTED; +#else + psa_status_t status; + struct tfm_crypto_pack_iovec iov = { + .sfn_id = TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY_SID, + .op_handle = operation->handle, + }; + + psa_invec in_vec[] = { + {.base = &iov, .len = sizeof(struct tfm_crypto_pack_iovec)}, + {.base = attributes, .len = sizeof(psa_key_attributes_t)}, + }; + + psa_outvec out_vec[] = { + {.base = handle, .len = sizeof(psa_key_handle_t)} + }; + + PSA_CONNECT(TFM_CRYPTO); + + status = API_DISPATCH(tfm_crypto_key_derivation_output_key, + TFM_CRYPTO_KEY_DERIVATION_OUTPUT_KEY); + PSA_CLOSE(); + + return status; +#endif /* TFM_CRYPTO_GENERATOR_MODULE_DISABLED */ +} + +psa_status_t psa_hash_compute(psa_algorithm_t alg, + const uint8_t *input, + size_t input_length, + uint8_t *hash, + size_t hash_size, + size_t *hash_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation, + psa_key_handle_t handle, + psa_algorithm_t alg) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation, + uint8_t *nonce, + size_t nonce_size, + size_t *nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation, + const uint8_t *nonce, + size_t nonce_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation, + size_t ad_length, + size_t plaintext_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} + +psa_status_t psa_aead_update(psa_aead_operation_t *operation, + const uint8_t *input, + size_t input_length, + uint8_t *output, + size_t output_size, + size_t *output_length) +{ + psa_status_t status; + + status = PSA_ERROR_NOT_SUPPORTED; + + return status; +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c new file mode 100644 index 0000000000..78f9dec6f4 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_initial_attestation_ipc_api.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/initial_attestation.h" +#include "tfm_ns_interface.h" +#include "psa/client.h" +#include "psa/crypto_types.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t +psa_initial_attest_get_token(const uint8_t *auth_challenge, + size_t challenge_size, + uint8_t *token_buf, + size_t token_buf_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_invec in_vec[] = { + {auth_challenge, challenge_size} + }; + psa_outvec out_vec[] = { + {token_buf, token_buf_size} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SID, + TFM_ATTEST_GET_TOKEN_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + if (status == PSA_SUCCESS) { + *token_size = out_vec[0].len; + } + + return status; +} + +psa_status_t +psa_initial_attest_get_token_size(size_t challenge_size, + size_t *token_size) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + psa_invec in_vec[] = { + {&challenge_size, sizeof(challenge_size)} + }; + psa_outvec out_vec[] = { + {token_size, sizeof(size_t)} + }; + + handle = psa_connect(TFM_ATTEST_GET_TOKEN_SIZE_SID, + TFM_ATTEST_GET_TOKEN_SIZE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, IOVEC_LEN(in_vec), + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} + +psa_status_t +tfm_initial_attest_get_public_key(uint8_t *public_key, + size_t public_key_buf_size, + size_t *public_key_len, + psa_ecc_curve_t *elliptic_curve_type) +{ + psa_handle_t handle = PSA_NULL_HANDLE; + psa_status_t status; + + psa_outvec out_vec[] = { + {.base = public_key, .len = public_key_buf_size}, + {.base = elliptic_curve_type, .len = sizeof(*elliptic_curve_type)}, + {.base = public_key_len, .len = sizeof(*public_key_len)} + }; + + handle = psa_connect(TFM_ATTEST_GET_PUBLIC_KEY_SID, + TFM_ATTEST_GET_PUBLIC_KEY_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_HANDLE_TO_ERROR(handle); + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, + out_vec, IOVEC_LEN(out_vec)); + psa_close(handle); + + return status; +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c new file mode 100644 index 0000000000..9326f7b8e3 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_its_ipc_api.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/internal_trusted_storage.h" +#include "tfm_api.h" + +#include "psa/client.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (sizeof(x)/sizeof(x[0])) + +psa_status_t psa_its_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_ITS_SET_SID, TFM_ITS_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_ITS_GET_SID, TFM_ITS_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_its_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_ITS_GET_INFO_SID, TFM_ITS_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_its_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + handle = psa_connect(TFM_ITS_REMOVE_SID, TFM_ITS_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), NULL, 0); + + psa_close(handle); + + return status; +} diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c new file mode 100644 index 0000000000..0c1edf463f --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_platform_ipc_api.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "tfm_platform_api.h" +#include "psa_manifest/sid.h" + +enum tfm_platform_err_t tfm_platform_system_reset(void) +{ + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + handle = psa_connect(TFM_SP_PLATFORM_SYSTEM_RESET_SID, + TFM_SP_PLATFORM_SYSTEM_RESET_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + NULL, 0, NULL, 0); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } + +} + +enum tfm_platform_err_t +tfm_platform_ioctl(tfm_platform_ioctl_req_t request, + psa_invec *input, psa_outvec *output) +{ + tfm_platform_ioctl_req_t req = request; + struct psa_invec in_vec[2] = { {0} }; + size_t inlen, outlen; + psa_status_t status = PSA_ERROR_CONNECTION_REFUSED; + psa_handle_t handle = PSA_NULL_HANDLE; + + in_vec[0].base = &req; + in_vec[0].len = sizeof(req); + if (input != NULL) { + in_vec[1].base = input->base; + in_vec[1].len = input->len; + inlen = 2; + } else { + inlen = 1; + } + + if (output != NULL) { + outlen = 1; + } else { + outlen = 0; + } + + handle = psa_connect(TFM_SP_PLATFORM_IOCTL_SID, + TFM_SP_PLATFORM_IOCTL_VERSION); + if (handle <= 0) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, + in_vec, inlen, + output, outlen); + psa_close(handle); + + if (status < PSA_SUCCESS) { + return TFM_PLATFORM_ERR_SYSTEM_ERROR; + } else { + return (enum tfm_platform_err_t) status; + } +} + diff --git a/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c new file mode 100644 index 0000000000..41304281f5 --- /dev/null +++ b/features/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_TFM/TARGET_TFM_V1_0/src/tfm_sst_ipc_api.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "psa/protected_storage.h" + +#include "tfm_ns_interface.h" +#include "psa_manifest/sid.h" + +#define IOVEC_LEN(x) (uint32_t)(sizeof(x)/sizeof(x[0])) + +psa_status_t psa_ps_set(psa_storage_uid_t uid, + size_t data_length, + const void *p_data, + psa_storage_create_flags_t create_flags) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = p_data, .len = data_length }, + { .base = &create_flags, .len = sizeof(create_flags) } + }; + + handle = psa_connect(TFM_SST_SET_SID, TFM_SST_SET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + /* A parameter with a buffer pointer pointer that has data length longer + * than maximum permitted is treated as a secure violation. + * TF-M framework rejects the request with TFM_ERROR_INVALID_PARAMETER. + */ + if (status == (psa_status_t)TFM_ERROR_INVALID_PARAMETER) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + return status; +} + +psa_status_t psa_ps_get(psa_storage_uid_t uid, + size_t data_offset, + size_t data_size, + void *p_data, + size_t *p_data_length) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) }, + { .base = &data_offset, .len = sizeof(data_offset) } + }; + + psa_outvec out_vec[] = { + { .base = p_data, .len = data_size } + }; + + if (p_data_length == NULL) { + return PSA_ERROR_INVALID_ARGUMENT; + } + + handle = psa_connect(TFM_SST_GET_SID, TFM_SST_GET_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + *p_data_length = out_vec[0].len; + + return status; +} + +psa_status_t psa_ps_get_info(psa_storage_uid_t uid, + struct psa_storage_info_t *p_info) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + psa_outvec out_vec[] = { + { .base = p_info, .len = sizeof(*p_info) } + }; + + handle = psa_connect(TFM_SST_GET_INFO_SID, TFM_SST_GET_INFO_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec, + IOVEC_LEN(out_vec)); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_remove(psa_storage_uid_t uid) +{ + psa_status_t status; + psa_handle_t handle; + + psa_invec in_vec[] = { + { .base = &uid, .len = sizeof(uid) } + }; + + + handle = psa_connect(TFM_SST_REMOVE_SID, TFM_SST_REMOVE_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return PSA_ERROR_GENERIC_ERROR; + } + + status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), + NULL, 0); + + psa_close(handle); + + return status; +} + +psa_status_t psa_ps_create(psa_storage_uid_t uid, size_t size, + psa_storage_create_flags_t create_flags) +{ + (void)uid; + (void)size; + (void)create_flags; + + return PSA_ERROR_NOT_SUPPORTED; +} + +psa_status_t psa_ps_set_extended(psa_storage_uid_t uid, size_t data_offset, + size_t data_length, const void *p_data) +{ + (void)uid; + (void)data_offset; + (void)data_length; + (void)p_data; + + return PSA_ERROR_NOT_SUPPORTED; +} + +uint32_t psa_ps_get_support(void) +{ + /* Initialise support_flags to a sensible default, to avoid returning an + * uninitialised value in case the secure function fails. + */ + uint32_t support_flags = 0; + psa_handle_t handle; + + psa_outvec out_vec[] = { + { .base = &support_flags, .len = sizeof(support_flags) } + }; + + /* The PSA API does not return an error, so any error from TF-M is + * ignored. + */ + handle = psa_connect(TFM_SST_GET_SUPPORT_SID, TFM_SST_GET_SUPPORT_VERSION); + if (!PSA_HANDLE_IS_VALID(handle)) { + return support_flags; + } + + (void)psa_call(handle, PSA_IPC_CALL, NULL, 0, out_vec, IOVEC_LEN(out_vec)); + + psa_close(handle); + + return support_flags; +}