mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Revision:
0:5b88d5760320
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c	Tue Dec 17 23:23:45 2019 +0000
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <arm_cmse.h>
+#include "tfm_secure_api.h"
+#include "tfm_nspm.h"
+#include "secure_utilities.h"
+#include "secure_fw/spm/spm_api.h"
+#include "region_defs.h"
+#include "tfm_api.h"
+
+#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
+
+#ifndef TFM_LVL
+#error TFM_LVL is not defined!
+#endif
+
+/* Macros to pick linker symbols and allow references to sections */
+#define REGION(a, b, c) a##b##c
+#define REGION_NAME(a, b, c) REGION(a, b, c)
+#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
+
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif /* !defined(TFM_PSA_API) */
+
+/* This is the "Big Lock" on the secure side, to guarantee single entry
+ * to SPE
+ */
+int32_t tfm_secure_lock;
+
+/**
+ * \brief Check whether a memory range is inside a memory region.
+ *
+ * \param[in] p             The start address of the range to check
+ * \param[in] s             The size of the range to check
+ * \param[in] region_start  The start address of the region, which should
+ *                          contain the range
+ * \param[in] region_len    The size of the region, which should contain the
+ *                          range
+ *
+ * \return TFM_SUCCESS if the region contains the range,
+ *         TFM_ERROR_GENERIC otherwise.
+ */
+static int32_t check_address_range(const void *p, size_t s,
+                                   uintptr_t region_start, uint32_t region_len)
+{
+    int32_t range_in_region;
+
+    /* Check for overflow in the range parameters */
+    if ((uintptr_t)p > UINTPTR_MAX-s) {
+        return TFM_ERROR_GENERIC;
+    }
+
+    /* We trust the region parameters, and don't check for overflow */
+
+    /* Calculate the result */
+    range_in_region = ((uintptr_t)p >= region_start) &&
+                      ((uintptr_t)p+s <= region_start+region_len);
+    if (range_in_region) {
+        return TFM_SUCCESS;
+    } else {
+        return TFM_ERROR_GENERIC;
+    }
+}
+
+/**
+ * \brief Check whether the current partition has access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked. The flags should contain information of the
+ * execution mode of the partition code (priv/unpriv), and access type
+ * (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
+ * Development Tools" chapter "Address range check intrinsic"
+ *
+ * \param[in] p      The start address of the range to check
+ * \param[in] s      The size of the range to check
+ * \param[in] flags  The flags to pass to the cmse_check_address_range func
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ *         TFM_ERROR_GENERIC otherwise.
+ */
+static int32_t has_access_to_region(const void *p, size_t s, int flags)
+{
+    int32_t range_access_allowed_by_mpu;
+
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
+    uint32_t scratch_base =
+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+    uint32_t scratch_limit =
+        (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif /* !defined(TFM_PSA_API) */
+
+    /* Use the TT instruction to check access to the partition's regions*/
+    range_access_allowed_by_mpu =
+                          cmse_check_address_range((void *)p, s, flags) != NULL;
+
+    if (range_access_allowed_by_mpu) {
+        return TFM_SUCCESS;
+    }
+
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
+    /* If the check for the current MPU settings fails, check for the share
+     * region, only if the partition is secure
+     */
+    if ((flags & CMSE_NONSECURE) == 0) {
+        if (check_address_range(p, s, scratch_base,
+                                scratch_limit+1-scratch_base) == TFM_SUCCESS) {
+            return TFM_SUCCESS;
+        }
+    }
+#endif /* !defined(TFM_PSA_API) */
+
+    /* If all else fails, check whether the region is in the non-secure
+     * memory
+     */
+    if (check_address_range(p, s, NS_CODE_START,
+                            NS_CODE_LIMIT+1-NS_CODE_START) == TFM_SUCCESS ||
+        check_address_range(p, s, NS_DATA_START,
+                            NS_DATA_LIMIT+1-NS_DATA_START) == TFM_SUCCESS) {
+        return TFM_SUCCESS;
+    } else {
+        return TFM_ERROR_GENERIC;
+    }
+}
+
+int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
+                                           uint32_t ns_caller,
+                                           uint32_t privileged)
+{
+    int flags = CMSE_MPU_READ;
+
+    if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+        flags |= CMSE_MPU_UNPRIV;
+    }
+
+    if (ns_caller) {
+        flags |= CMSE_NONSECURE;
+    }
+
+    return has_access_to_region(p, s, flags);
+}
+
+int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
+                                            uint32_t ns_caller,
+                                            uint32_t privileged)
+{
+    int flags = CMSE_MPU_READWRITE;
+
+    if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
+        flags |= CMSE_MPU_UNPRIV;
+    }
+
+    if (ns_caller) {
+        flags |= CMSE_NONSECURE;
+    }
+
+    return has_access_to_region(p, s, flags);
+}
+
+void tfm_secure_api_error_handler(void)
+{
+    ERROR_MSG("Security violation when calling secure API");
+    while (1) {
+        ;
+    }
+}
+