aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Hu <david.hu@arm.com>2019-08-06 14:16:51 +0800
committerKen Liu <ken.liu@arm.com>2019-08-13 10:32:30 +0000
commit326f397d8453c31a1d57e2ef4d25cada97c57ec7 (patch)
treeff9dbd4d785c1417fa663dc0aa3000fed21db270
parentcb05d972ca8711bfdb3af88c65150fdd5b26a26b (diff)
downloadtrusted-firmware-m-326f397d8453c31a1d57e2ef4d25cada97c57ec7.tar.gz
Core: Split memory access check from tfm_secure_api.c/.h
Diverse topologies require different memory access check implementations. Split single Armv8-M memory access functions and API definitions from common TF-M secure operations. Thus different topologies can continue sharing the same TF-M secure operations in tfm_secure_api.c and implement own memory access functionalities. Change-Id: I789e712a5d0e3b4127e6710846f2a2b0f612dba7 Signed-off-by: David Hu <david.hu@arm.com>
-rw-r--r--secure_fw/core/CMakeLists.inc1
-rw-r--r--secure_fw/core/ipc/CMakeLists.inc1
-rw-r--r--secure_fw/core/tfm_core_mem_check.c116
-rw-r--r--secure_fw/core/tfm_core_mem_check.h53
-rw-r--r--secure_fw/core/tfm_func_api.c2
-rw-r--r--secure_fw/core/tfm_secure_api.c144
-rw-r--r--secure_fw/core/tfm_secure_api.h45
-rw-r--r--secure_fw/spm/spm_api_ipc.c1
8 files changed, 190 insertions, 173 deletions
diff --git a/secure_fw/core/CMakeLists.inc b/secure_fw/core/CMakeLists.inc
index 22a742a68..8603ab892 100644
--- a/secure_fw/core/CMakeLists.inc
+++ b/secure_fw/core/CMakeLists.inc
@@ -39,6 +39,7 @@ set (SS_CORE_C_SRC
"${SS_CORE_DIR}/tfm_nspm.c"
"${SS_CORE_DIR}/tfm_boot_data.c"
"${SS_CORE_DIR}/tfm_utils.c"
+ "${SS_CORE_DIR}/tfm_core_mem_check.c"
)
#Append all our source files to global lists.
diff --git a/secure_fw/core/ipc/CMakeLists.inc b/secure_fw/core/ipc/CMakeLists.inc
index c2e385a64..027a88298 100644
--- a/secure_fw/core/ipc/CMakeLists.inc
+++ b/secure_fw/core/ipc/CMakeLists.inc
@@ -47,6 +47,7 @@ elseif (TFM_PSA_API)
"${SS_IPC_DIR}/../tfm_handler.c"
"${SS_IPC_DIR}/../tfm_nspm.c"
"${SS_IPC_DIR}/../tfm_boot_data.c"
+ "${SS_IPC_DIR}/../tfm_core_mem_check.c"
)
endif()
diff --git a/secure_fw/core/tfm_core_mem_check.c b/secure_fw/core/tfm_core_mem_check.c
new file mode 100644
index 000000000..d6d735432
--- /dev/null
+++ b/secure_fw/core/tfm_core_mem_check.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <arm_cmse.h>
+#include "region_defs.h"
+#include "secure_fw/spm/spm_api.h"
+#include "tfm_api.h"
+
+#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
+/* 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)
+
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
+#endif /* !defined(TFM_PSA_API) */
+
+/**
+ * \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 enum tfm_status_e 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) == 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) == TFM_SUCCESS) ||
+ (check_address_range(p, s, NS_DATA_START,
+ NS_DATA_LIMIT) == TFM_SUCCESS)) {
+ return TFM_SUCCESS;
+ } else {
+ return TFM_ERROR_GENERIC;
+ }
+}
+
+enum tfm_status_e 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);
+}
+
+enum tfm_status_e tfm_core_has_write_access_to_region(const 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);
+}
diff --git a/secure_fw/core/tfm_core_mem_check.h b/secure_fw/core/tfm_core_mem_check.h
new file mode 100644
index 000000000..b90c43941
--- /dev/null
+++ b/secure_fw/core/tfm_core_mem_check.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_CORE_MEM_CHECK_H__
+#define __TFM_CORE_MEM_CHECK_H__
+
+#include "tfm_api.h"
+
+/**
+ * \brief Check whether the current partition has read access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is non-secure
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
+ uint32_t ns_caller,
+ uint32_t privileged);
+
+/**
+ * \brief Check whether the current partition has write access to a memory range
+ *
+ * This function assumes, that the current MPU configuration is set for the
+ * partition to be checked.
+ *
+ * \param[in] p The start address of the range to check
+ * \param[in] s The size of the range to check
+ * \param[in] ns_caller Whether the current partition is non-secure
+ * \param[in] privileged Privileged mode or unprivileged mode:
+ * \ref TFM_PARTITION_UNPRIVILEGED_MODE
+ * \ref TFM_PARTITION_PRIVILEGED_MODE
+ *
+ * \return TFM_SUCCESS if the partition has access to the memory range,
+ * TFM_ERROR_GENERIC otherwise.
+ */
+enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s,
+ uint32_t ns_caller,
+ uint32_t privileged);
+
+#endif /* __TFM_CORE_MEM_CHECK_H__ */
diff --git a/secure_fw/core/tfm_func_api.c b/secure_fw/core/tfm_func_api.c
index 8f0850860..6d067c14e 100644
--- a/secure_fw/core/tfm_func_api.c
+++ b/secure_fw/core/tfm_func_api.c
@@ -10,7 +10,6 @@
#include <stdint.h>
#include <stdbool.h>
#include <arm_cmse.h>
-#include "tfm_secure_api.h"
#include "tfm_nspm.h"
#include "secure_utilities.h"
#include "uart_stdout.h"
@@ -21,6 +20,7 @@
#include "platform/include/tfm_spm_hal.h"
#include "tfm_irq_list.h"
#include "psa/service.h"
+#include "tfm_core_mem_check.h"
#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
#define EXC_RETURN_SECURE_HANDLER 0xFFFFFFF1
diff --git a/secure_fw/core/tfm_secure_api.c b/secure_fw/core/tfm_secure_api.c
index 6555fcb86..f713b0345 100644
--- a/secure_fw/core/tfm_secure_api.c
+++ b/secure_fw/core/tfm_secure_api.c
@@ -5,32 +5,9 @@
*
*/
-#include <stdio.h>
-#include <string.h>
#include <stdbool.h>
-#include <arm_cmse.h>
+#include "secure_utilities.h"
#include "tfm_secure_api.h"
-#include "tfm_nspm.h"
-#include "uart_stdout.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
@@ -52,27 +29,14 @@ bool tfm_is_one_bit_set(uint32_t n)
return ((n && !(n & (n-1))) ? true : false);
}
-/**
- * \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 enum tfm_status_e check_address_range(const void *p, size_t s,
- uintptr_t region_start,
- uint32_t region_len)
+enum tfm_status_e check_address_range(const void *p, size_t s,
+ uintptr_t region_start,
+ uintptr_t region_limit)
{
int32_t range_in_region;
/* Check for overflow in the range parameters */
- if ((uintptr_t)p > UINTPTR_MAX-s) {
+ if ((uintptr_t)p > UINTPTR_MAX - s) {
return TFM_ERROR_GENERIC;
}
@@ -80,7 +44,7 @@ static enum tfm_status_e check_address_range(const void *p, size_t s,
/* Calculate the result */
range_in_region = ((uintptr_t)p >= region_start) &&
- ((uintptr_t)p+s <= region_start+region_len);
+ ((uintptr_t)(p + s - 1) <= region_limit);
if (range_in_region) {
return TFM_SUCCESS;
} else {
@@ -88,101 +52,6 @@ static enum tfm_status_e check_address_range(const void *p, size_t s,
}
}
-/**
- * \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 enum tfm_status_e 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;
- }
-}
-
-enum tfm_status_e 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);
-}
-
-enum tfm_status_e tfm_core_has_write_access_to_region(const 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");
@@ -190,4 +59,3 @@ void tfm_secure_api_error_handler(void)
;
}
}
-
diff --git a/secure_fw/core/tfm_secure_api.h b/secure_fw/core/tfm_secure_api.h
index c626df137..68df628f4 100644
--- a/secure_fw/core/tfm_secure_api.h
+++ b/secure_fw/core/tfm_secure_api.h
@@ -91,44 +91,21 @@ int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr);
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
/**
- * \brief Check whether the current partition has read access to a memory range
+ * \brief Check whether a memory range is inside a memory region.
*
- * This function assumes, that the current MPU configuration is set for the
- * partition to be checked.
+ * \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_limit The end address of the region, which should contain
+ * the range
*
- * \param[in] p The start address of the range to check
- * \param[in] s The size of the range to check
- * \param[in] ns_caller Whether the current partition is a non-secure one
- * \param[in] privileged Privileged mode or unprivileged mode:
- * \ref TFM_PARTITION_UNPRIVILEGED_MODE
- * \ref TFM_PARTITION_PRIVILEGED_MODE
- *
- * \return TFM_SUCCESS if the partition has access to the memory range,
- * TFM_ERROR_GENERIC otherwise.
- */
-enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s,
- uint32_t ns_caller,
- uint32_t privileged);
-
-/**
- * \brief Check whether the current partition has write access to a memory range
- *
- * This function assumes, that the current MPU configuration is set for the
- * partition to be checked.
- *
- * \param[in] p The start address of the range to check
- * \param[in] s The size of the range to check
- * \param[in] ns_caller Whether the current partition is a non-secure one
- * \param[in] privileged Privileged mode or unprivileged mode:
- * \ref TFM_PARTITION_UNPRIVILEGED_MODE
- * \ref TFM_PARTITION_PRIVILEGED_MODE
- *
- * \return TFM_SUCCESS if the partition has access to the memory range,
+ * \return TFM_SUCCESS if the region contains the range,
* TFM_ERROR_GENERIC otherwise.
*/
-enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s,
- uint32_t ns_caller,
- uint32_t privileged);
+enum tfm_status_e check_address_range(const void *p, size_t s,
+ uintptr_t region_start,
+ uintptr_t region_limit);
void tfm_enable_irq(psa_signal_t irq_signal);
void tfm_disable_irq(psa_signal_t irq_signal);
diff --git a/secure_fw/spm/spm_api_ipc.c b/secure_fw/spm/spm_api_ipc.c
index 24fd179a9..b05ec81b4 100644
--- a/secure_fw/spm/spm_api_ipc.c
+++ b/secure_fw/spm/spm_api_ipc.c
@@ -17,6 +17,7 @@
#include "tfm_spm_hal.h"
#include "spm_api.h"
#include "spm_db.h"
+#include "tfm_core_mem_check.h"
#include "tfm_internal_defines.h"
#include "tfm_wait.h"
#include "tfm_message_queue.h"