mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c@0:5b88d5760320, 2019-12-17 (annotated)
- 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?
User | Revision | Line number | New 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)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); |
kenjiArai | 0:5b88d5760320 | 98 | uint32_t scratch_limit = |
kenjiArai | 0:5b88d5760320 | 99 | (uint32_t)®ION_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 |