mbed-os5 only for TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Committer:
kenjiArai
Date:
Tue Dec 17 23:23:45 2019 +0000
Revision:
0:5b88d5760320
mbed-os5 only for TYBLE16

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kenjiArai 0:5b88d5760320 1 /*
kenjiArai 0:5b88d5760320 2 * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
kenjiArai 0:5b88d5760320 3 *
kenjiArai 0:5b88d5760320 4 * SPDX-License-Identifier: BSD-3-Clause
kenjiArai 0:5b88d5760320 5 *
kenjiArai 0:5b88d5760320 6 */
kenjiArai 0:5b88d5760320 7
kenjiArai 0:5b88d5760320 8 #include <stdio.h>
kenjiArai 0:5b88d5760320 9 #include <string.h>
kenjiArai 0:5b88d5760320 10 #include <stdbool.h>
kenjiArai 0:5b88d5760320 11 #include <arm_cmse.h>
kenjiArai 0:5b88d5760320 12 #include "tfm_secure_api.h"
kenjiArai 0:5b88d5760320 13 #include "tfm_nspm.h"
kenjiArai 0:5b88d5760320 14 #include "secure_utilities.h"
kenjiArai 0:5b88d5760320 15 #include "secure_fw/spm/spm_api.h"
kenjiArai 0:5b88d5760320 16 #include "region_defs.h"
kenjiArai 0:5b88d5760320 17 #include "tfm_api.h"
kenjiArai 0:5b88d5760320 18
kenjiArai 0:5b88d5760320 19 #define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
kenjiArai 0:5b88d5760320 20
kenjiArai 0:5b88d5760320 21 #ifndef TFM_LVL
kenjiArai 0:5b88d5760320 22 #error TFM_LVL is not defined!
kenjiArai 0:5b88d5760320 23 #endif
kenjiArai 0:5b88d5760320 24
kenjiArai 0:5b88d5760320 25 /* Macros to pick linker symbols and allow references to sections */
kenjiArai 0:5b88d5760320 26 #define REGION(a, b, c) a##b##c
kenjiArai 0:5b88d5760320 27 #define REGION_NAME(a, b, c) REGION(a, b, c)
kenjiArai 0:5b88d5760320 28 #define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c)
kenjiArai 0:5b88d5760320 29
kenjiArai 0:5b88d5760320 30 #ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
kenjiArai 0:5b88d5760320 31 REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
kenjiArai 0:5b88d5760320 32 REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
kenjiArai 0:5b88d5760320 33 #endif /* !defined(TFM_PSA_API) */
kenjiArai 0:5b88d5760320 34
kenjiArai 0:5b88d5760320 35 /* This is the "Big Lock" on the secure side, to guarantee single entry
kenjiArai 0:5b88d5760320 36 * to SPE
kenjiArai 0:5b88d5760320 37 */
kenjiArai 0:5b88d5760320 38 int32_t tfm_secure_lock;
kenjiArai 0:5b88d5760320 39
kenjiArai 0:5b88d5760320 40 /**
kenjiArai 0:5b88d5760320 41 * \brief Check whether a memory range is inside a memory region.
kenjiArai 0:5b88d5760320 42 *
kenjiArai 0:5b88d5760320 43 * \param[in] p The start address of the range to check
kenjiArai 0:5b88d5760320 44 * \param[in] s The size of the range to check
kenjiArai 0:5b88d5760320 45 * \param[in] region_start The start address of the region, which should
kenjiArai 0:5b88d5760320 46 * contain the range
kenjiArai 0:5b88d5760320 47 * \param[in] region_len The size of the region, which should contain the
kenjiArai 0:5b88d5760320 48 * range
kenjiArai 0:5b88d5760320 49 *
kenjiArai 0:5b88d5760320 50 * \return TFM_SUCCESS if the region contains the range,
kenjiArai 0:5b88d5760320 51 * TFM_ERROR_GENERIC otherwise.
kenjiArai 0:5b88d5760320 52 */
kenjiArai 0:5b88d5760320 53 static int32_t check_address_range(const void *p, size_t s,
kenjiArai 0:5b88d5760320 54 uintptr_t region_start, uint32_t region_len)
kenjiArai 0:5b88d5760320 55 {
kenjiArai 0:5b88d5760320 56 int32_t range_in_region;
kenjiArai 0:5b88d5760320 57
kenjiArai 0:5b88d5760320 58 /* Check for overflow in the range parameters */
kenjiArai 0:5b88d5760320 59 if ((uintptr_t)p > UINTPTR_MAX-s) {
kenjiArai 0:5b88d5760320 60 return TFM_ERROR_GENERIC;
kenjiArai 0:5b88d5760320 61 }
kenjiArai 0:5b88d5760320 62
kenjiArai 0:5b88d5760320 63 /* We trust the region parameters, and don't check for overflow */
kenjiArai 0:5b88d5760320 64
kenjiArai 0:5b88d5760320 65 /* Calculate the result */
kenjiArai 0:5b88d5760320 66 range_in_region = ((uintptr_t)p >= region_start) &&
kenjiArai 0:5b88d5760320 67 ((uintptr_t)p+s <= region_start+region_len);
kenjiArai 0:5b88d5760320 68 if (range_in_region) {
kenjiArai 0:5b88d5760320 69 return TFM_SUCCESS;
kenjiArai 0:5b88d5760320 70 } else {
kenjiArai 0:5b88d5760320 71 return TFM_ERROR_GENERIC;
kenjiArai 0:5b88d5760320 72 }
kenjiArai 0:5b88d5760320 73 }
kenjiArai 0:5b88d5760320 74
kenjiArai 0:5b88d5760320 75 /**
kenjiArai 0:5b88d5760320 76 * \brief Check whether the current partition has access to a memory range
kenjiArai 0:5b88d5760320 77 *
kenjiArai 0:5b88d5760320 78 * This function assumes, that the current MPU configuration is set for the
kenjiArai 0:5b88d5760320 79 * partition to be checked. The flags should contain information of the
kenjiArai 0:5b88d5760320 80 * execution mode of the partition code (priv/unpriv), and access type
kenjiArai 0:5b88d5760320 81 * (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
kenjiArai 0:5b88d5760320 82 * Development Tools" chapter "Address range check intrinsic"
kenjiArai 0:5b88d5760320 83 *
kenjiArai 0:5b88d5760320 84 * \param[in] p The start address of the range to check
kenjiArai 0:5b88d5760320 85 * \param[in] s The size of the range to check
kenjiArai 0:5b88d5760320 86 * \param[in] flags The flags to pass to the cmse_check_address_range func
kenjiArai 0:5b88d5760320 87 *
kenjiArai 0:5b88d5760320 88 * \return TFM_SUCCESS if the partition has access to the memory range,
kenjiArai 0:5b88d5760320 89 * TFM_ERROR_GENERIC otherwise.
kenjiArai 0:5b88d5760320 90 */
kenjiArai 0:5b88d5760320 91 static int32_t has_access_to_region(const void *p, size_t s, int flags)
kenjiArai 0:5b88d5760320 92 {
kenjiArai 0:5b88d5760320 93 int32_t range_access_allowed_by_mpu;
kenjiArai 0:5b88d5760320 94
kenjiArai 0:5b88d5760320 95 #ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
kenjiArai 0:5b88d5760320 96 uint32_t scratch_base =
kenjiArai 0:5b88d5760320 97 (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base);
kenjiArai 0:5b88d5760320 98 uint32_t scratch_limit =
kenjiArai 0:5b88d5760320 99 (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit);
kenjiArai 0:5b88d5760320 100 #endif /* !defined(TFM_PSA_API) */
kenjiArai 0:5b88d5760320 101
kenjiArai 0:5b88d5760320 102 /* Use the TT instruction to check access to the partition's regions*/
kenjiArai 0:5b88d5760320 103 range_access_allowed_by_mpu =
kenjiArai 0:5b88d5760320 104 cmse_check_address_range((void *)p, s, flags) != NULL;
kenjiArai 0:5b88d5760320 105
kenjiArai 0:5b88d5760320 106 if (range_access_allowed_by_mpu) {
kenjiArai 0:5b88d5760320 107 return TFM_SUCCESS;
kenjiArai 0:5b88d5760320 108 }
kenjiArai 0:5b88d5760320 109
kenjiArai 0:5b88d5760320 110 #ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */
kenjiArai 0:5b88d5760320 111 /* If the check for the current MPU settings fails, check for the share
kenjiArai 0:5b88d5760320 112 * region, only if the partition is secure
kenjiArai 0:5b88d5760320 113 */
kenjiArai 0:5b88d5760320 114 if ((flags & CMSE_NONSECURE) == 0) {
kenjiArai 0:5b88d5760320 115 if (check_address_range(p, s, scratch_base,
kenjiArai 0:5b88d5760320 116 scratch_limit+1-scratch_base) == TFM_SUCCESS) {
kenjiArai 0:5b88d5760320 117 return TFM_SUCCESS;
kenjiArai 0:5b88d5760320 118 }
kenjiArai 0:5b88d5760320 119 }
kenjiArai 0:5b88d5760320 120 #endif /* !defined(TFM_PSA_API) */
kenjiArai 0:5b88d5760320 121
kenjiArai 0:5b88d5760320 122 /* If all else fails, check whether the region is in the non-secure
kenjiArai 0:5b88d5760320 123 * memory
kenjiArai 0:5b88d5760320 124 */
kenjiArai 0:5b88d5760320 125 if (check_address_range(p, s, NS_CODE_START,
kenjiArai 0:5b88d5760320 126 NS_CODE_LIMIT+1-NS_CODE_START) == TFM_SUCCESS ||
kenjiArai 0:5b88d5760320 127 check_address_range(p, s, NS_DATA_START,
kenjiArai 0:5b88d5760320 128 NS_DATA_LIMIT+1-NS_DATA_START) == TFM_SUCCESS) {
kenjiArai 0:5b88d5760320 129 return TFM_SUCCESS;
kenjiArai 0:5b88d5760320 130 } else {
kenjiArai 0:5b88d5760320 131 return TFM_ERROR_GENERIC;
kenjiArai 0:5b88d5760320 132 }
kenjiArai 0:5b88d5760320 133 }
kenjiArai 0:5b88d5760320 134
kenjiArai 0:5b88d5760320 135 int32_t tfm_core_has_read_access_to_region(const void *p, size_t s,
kenjiArai 0:5b88d5760320 136 uint32_t ns_caller,
kenjiArai 0:5b88d5760320 137 uint32_t privileged)
kenjiArai 0:5b88d5760320 138 {
kenjiArai 0:5b88d5760320 139 int flags = CMSE_MPU_READ;
kenjiArai 0:5b88d5760320 140
kenjiArai 0:5b88d5760320 141 if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
kenjiArai 0:5b88d5760320 142 flags |= CMSE_MPU_UNPRIV;
kenjiArai 0:5b88d5760320 143 }
kenjiArai 0:5b88d5760320 144
kenjiArai 0:5b88d5760320 145 if (ns_caller) {
kenjiArai 0:5b88d5760320 146 flags |= CMSE_NONSECURE;
kenjiArai 0:5b88d5760320 147 }
kenjiArai 0:5b88d5760320 148
kenjiArai 0:5b88d5760320 149 return has_access_to_region(p, s, flags);
kenjiArai 0:5b88d5760320 150 }
kenjiArai 0:5b88d5760320 151
kenjiArai 0:5b88d5760320 152 int32_t tfm_core_has_write_access_to_region(void *p, size_t s,
kenjiArai 0:5b88d5760320 153 uint32_t ns_caller,
kenjiArai 0:5b88d5760320 154 uint32_t privileged)
kenjiArai 0:5b88d5760320 155 {
kenjiArai 0:5b88d5760320 156 int flags = CMSE_MPU_READWRITE;
kenjiArai 0:5b88d5760320 157
kenjiArai 0:5b88d5760320 158 if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) {
kenjiArai 0:5b88d5760320 159 flags |= CMSE_MPU_UNPRIV;
kenjiArai 0:5b88d5760320 160 }
kenjiArai 0:5b88d5760320 161
kenjiArai 0:5b88d5760320 162 if (ns_caller) {
kenjiArai 0:5b88d5760320 163 flags |= CMSE_NONSECURE;
kenjiArai 0:5b88d5760320 164 }
kenjiArai 0:5b88d5760320 165
kenjiArai 0:5b88d5760320 166 return has_access_to_region(p, s, flags);
kenjiArai 0:5b88d5760320 167 }
kenjiArai 0:5b88d5760320 168
kenjiArai 0:5b88d5760320 169 void tfm_secure_api_error_handler(void)
kenjiArai 0:5b88d5760320 170 {
kenjiArai 0:5b88d5760320 171 ERROR_MSG("Security violation when calling secure API");
kenjiArai 0:5b88d5760320 172 while (1) {
kenjiArai 0:5b88d5760320 173 ;
kenjiArai 0:5b88d5760320 174 }
kenjiArai 0:5b88d5760320 175 }
kenjiArai 0:5b88d5760320 176