1 /*
2  * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <string.h>
9 #include <stdint.h>
10 #include "aapcs_local.h"
11 #include "config_spm.h"
12 #include "interrupt.h"
13 #include "internal_status_code.h"
14 #include "memory_symbols.h"
15 #include "spm.h"
16 #include "svc_num.h"
17 #include "tfm_arch.h"
18 #include "tfm_svcalls.h"
19 #include "tfm_boot_data.h"
20 #include "tfm_hal_platform.h"
21 #include "tfm_hal_isolation.h"
22 #include "tfm_hal_spm_logdev.h"
23 #include "tfm_core_trustzone.h"
24 #include "utilities.h"
25 #include "ffm/backend.h"
26 #include "ffm/psa_api.h"
27 #include "load/spm_load_api.h"
28 #include "load/partition_defs.h"
29 #include "psa/client.h"
30 
31 #define INVALID_PSP_VALUE 0xFFFFFFFFU
32 
33 #ifdef PLATFORM_SVC_HANDLERS
34 extern int32_t platform_svc_handlers(uint8_t svc_number,
35                                      uint32_t *ctx, uint32_t lr);
36 #endif
37 
38 #if TFM_ISOLATION_LEVEL > 1
39 
40 /*
41  * TODO: To be updated after secure context management is going to implemented.
42  * The variables are used to save PSP, PSPLimit and the EXC_RETURN payload because
43  * they will be changed when preparing to Thread mode to run the PSA API functions.
44  * Later they will be restored when returning from the functions.
45  */
46 static uint32_t saved_psp = INVALID_PSP_VALUE;
47 static uint32_t saved_psp_limit;
48 static uint32_t saved_exc_return;
49 
50 typedef psa_status_t (*psa_api_svc_func_t)(uint32_t p0, uint32_t p1, uint32_t p2, uint32_t p3);
51 
52 /* The order of the functions must match the SVC number index defined in svc_num.h */
53 static const psa_api_svc_func_t psa_api_svc_func_table[] = {
54     /* Client APIs */
55     (psa_api_svc_func_t)tfm_spm_client_psa_framework_version,
56     (psa_api_svc_func_t)tfm_spm_client_psa_version,
57     (psa_api_svc_func_t)tfm_spm_client_psa_call,
58     (psa_api_svc_func_t)tfm_spm_client_psa_connect,
59     (psa_api_svc_func_t)tfm_spm_client_psa_close,
60     /* Secure Partition APIs */
61     (psa_api_svc_func_t)tfm_spm_partition_psa_wait,
62     (psa_api_svc_func_t)tfm_spm_partition_psa_get,
63     (psa_api_svc_func_t)tfm_spm_partition_psa_set_rhandle,
64     (psa_api_svc_func_t)tfm_spm_partition_psa_read,
65     (psa_api_svc_func_t)tfm_spm_partition_psa_skip,
66     (psa_api_svc_func_t)tfm_spm_partition_psa_write,
67     (psa_api_svc_func_t)tfm_spm_partition_psa_reply,
68     (psa_api_svc_func_t)tfm_spm_partition_psa_notify,
69     (psa_api_svc_func_t)tfm_spm_partition_psa_clear,
70     (psa_api_svc_func_t)tfm_spm_partition_psa_eoi,
71     (psa_api_svc_func_t)tfm_spm_partition_psa_panic,
72     (psa_api_svc_func_t)tfm_spm_get_lifecycle_state,
73     (psa_api_svc_func_t)tfm_spm_partition_psa_irq_enable,
74     (psa_api_svc_func_t)tfm_spm_partition_psa_irq_disable,
75     (psa_api_svc_func_t)tfm_spm_partition_psa_reset_signal,
76     (psa_api_svc_func_t)tfm_spm_agent_psa_call,
77     (psa_api_svc_func_t)tfm_spm_agent_psa_connect,
78     (psa_api_svc_func_t)tfm_spm_agent_psa_close,
79 };
80 
thread_mode_spm_return(uint32_t result)81 static uint32_t thread_mode_spm_return(uint32_t result)
82 {
83     fih_int fih_rc = FIH_FAILURE;
84     FIH_RET_TYPE(bool) fih_bool;
85     const struct partition_t *p_part_next = GET_CURRENT_COMPONENT();
86     struct tfm_state_context_t *p_tctx = (struct tfm_state_context_t *)saved_psp;
87 
88     FIH_CALL(tfm_hal_boundary_need_switch, fih_bool, get_spm_boundary(), p_part_next->boundary);
89     if (fih_not_eq(fih_bool, fih_int_encode(false))) {
90         FIH_CALL(tfm_hal_activate_boundary, fih_rc,
91                  p_part_next->p_ldinf, p_part_next->boundary);
92         if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
93             tfm_core_panic();
94         }
95     }
96 
97     backend_abi_leaving_spm(result);
98 
99     ARCH_STATE_CTX_SET_R0(p_tctx, result);
100 
101     tfm_arch_set_psplim(saved_psp_limit);
102     __set_PSP(saved_psp);
103 
104     /* Invalidate saved_psp */
105     saved_psp = INVALID_PSP_VALUE;
106 
107     return saved_exc_return;
108 }
109 
init_spm_func_context(psa_api_svc_func_t svc_func,uint32_t * ctx)110 static void init_spm_func_context(psa_api_svc_func_t svc_func, uint32_t *ctx)
111 {
112     AAPCS_DUAL_U32_T sp_info;
113     struct tfm_state_context_t *p_statctx;
114     uint32_t sp = __get_PSP();
115     uint32_t sp_limit = tfm_arch_get_psplim();
116     const uint32_t stack_alloc_size = (sizeof(*p_statctx) + 7UL) & ~0x7UL;
117 
118     saved_psp       = sp;
119     saved_psp_limit = sp_limit;
120 
121     sp_info.u64_val = backend_abi_entering_spm();
122     /* SPM SP is saved in R0 */
123     if (sp_info.u32_regs.r0 != 0) {
124         sp       = sp_info.u32_regs.r0;
125         sp_limit = sp_info.u32_regs.r1;
126     }
127 
128     /* Check if there is enough space on stack. */
129     if ((sp_limit + stack_alloc_size) > sp) {
130         tfm_core_panic();
131     }
132 
133     /* Allocate memory for p_statctx on the stack. */
134     sp -= stack_alloc_size;
135 
136     p_statctx = (struct tfm_state_context_t *)sp;
137     ARCH_CTXCTRL_EXCRET_PATTERN(p_statctx, ctx[0], ctx[1], ctx[2], ctx[3],
138                                 svc_func, tfm_svc_thread_mode_spm_return);
139 
140     arch_update_process_sp(sp, sp_limit);
141 }
142 
prepare_to_thread_mode_spm(uint8_t svc_number,uint32_t * ctx,uint32_t exc_return)143 static int32_t prepare_to_thread_mode_spm(uint8_t svc_number, uint32_t *ctx, uint32_t exc_return)
144 {
145     fih_int fih_rc = FIH_FAILURE;
146     FIH_RET_TYPE(bool) fih_bool;
147     const struct partition_t *p_curr_sp;
148     psa_api_svc_func_t svc_func = NULL;
149     uint8_t svc_idx = svc_number & TFM_SVC_NUM_INDEX_MSK;
150 
151     if (TFM_SVC_IS_HANDLER_MODE(svc_number)) {
152         /* PSA APIs are not allowed to be called from Handler mode */
153         tfm_core_panic();
154     }
155 
156     if (svc_idx >= (sizeof(psa_api_svc_func_table)/sizeof(psa_api_svc_func_t))) {
157         ERROR_RAW("Invalid PSA API SVC requested: 0x%08x\n", svc_number);
158         ctx[0] = (uint32_t)PSA_ERROR_GENERIC_ERROR;
159         return exc_return;
160     }
161 
162     svc_func = psa_api_svc_func_table[svc_idx];
163     if (!svc_func) {
164         ERROR_RAW("Corresponding SVC function is not included for number 0x%08x\n", svc_number);
165         ctx[0] = (uint32_t)PSA_ERROR_GENERIC_ERROR;
166         return exc_return;
167     }
168 
169     saved_exc_return = exc_return;
170 
171     p_curr_sp = GET_CURRENT_COMPONENT();
172     FIH_CALL(tfm_hal_boundary_need_switch, fih_bool, p_curr_sp->boundary, get_spm_boundary());
173     if (fih_not_eq(fih_bool, fih_int_encode(false))) {
174         FIH_CALL(tfm_hal_activate_boundary, fih_rc, NULL, get_spm_boundary());
175         if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
176             tfm_core_panic();
177         }
178     }
179 
180     init_spm_func_context(svc_func, ctx);
181 
182     ctx[0] = (uint32_t)PSA_SUCCESS;
183 
184     return EXC_RETURN_THREAD_PSP;
185 }
186 
tfm_svc_thread_mode_spm_active(void)187 bool tfm_svc_thread_mode_spm_active(void)
188 {
189     return saved_psp != INVALID_PSP_VALUE;
190 }
191 #endif
192 
handle_spm_svc_requests(uint32_t svc_number,uint32_t exc_return,uint32_t * svc_args,uint32_t * msp)193 static uint32_t handle_spm_svc_requests(uint32_t svc_number, uint32_t exc_return,
194                                         uint32_t *svc_args, uint32_t *msp)
195 {
196 #if TFM_SP_LOG_RAW_ENABLED
197     struct partition_t *curr_partition;
198     fih_int fih_rc = FIH_FAILURE;
199 #endif
200 
201     switch (svc_number) {
202     case TFM_SVC_SPM_INIT:
203         exc_return = tfm_spm_init();
204         tfm_arch_check_msp_sealing();
205         /* The following call does not return */
206         tfm_arch_free_msp_and_exc_ret(SPM_BOOT_STACK_BOTTOM, exc_return);
207         break;
208     case TFM_SVC_GET_BOOT_DATA:
209         tfm_core_get_boot_data_handler(svc_args);
210         break;
211 #if (TFM_ISOLATION_LEVEL != 1) && (CONFIG_TFM_FLIH_API == 1)
212     case TFM_SVC_PREPARE_DEPRIV_FLIH:
213         exc_return = tfm_flih_prepare_depriv_flih((struct partition_t *)svc_args[0],
214                                                   (uintptr_t)svc_args[1]);
215         break;
216     case TFM_SVC_FLIH_FUNC_RETURN:
217         exc_return = tfm_flih_return_to_isr(svc_args[0], (struct context_flih_ret_t *)msp);
218         break;
219 #endif
220 #if TFM_SP_LOG_RAW_ENABLED
221     case TFM_SVC_OUTPUT_UNPRIV_STRING:
222         /* Protect PRoT data from unauthorised access from ARoT partition.
223          * This fixes the TFMV-7 vulnerability
224          */
225         curr_partition = GET_CURRENT_COMPONENT();
226         FIH_CALL(tfm_hal_memory_check, fih_rc, curr_partition->boundary, (uintptr_t)svc_args[0],
227                 svc_args[1], TFM_HAL_ACCESS_READABLE);
228         if (fih_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) {
229             svc_args[0] = tfm_hal_output_spm_log((const char *)svc_args[0], svc_args[1]);
230         } else {
231             tfm_core_panic();
232         }
233         break;
234 #endif
235 #if TFM_ISOLATION_LEVEL > 1
236     case TFM_SVC_THREAD_MODE_SPM_RETURN:
237         exc_return = thread_mode_spm_return(svc_args[0]);
238         break;
239 #endif
240     default:
241         ERROR_RAW("Unknown SPM SVC requested: 0x%08x\n", svc_number);
242         svc_args[0] = (uint32_t)PSA_ERROR_GENERIC_ERROR;
243     }
244 
245     return exc_return;
246 }
247 
spm_svc_handler(uint32_t * msp,uint32_t exc_return,uint32_t * psp)248 uint32_t spm_svc_handler(uint32_t *msp, uint32_t exc_return, uint32_t *psp)
249 {
250     uint8_t svc_number = TFM_SVC_PSA_FRAMEWORK_VERSION;
251     uint32_t *svc_args = msp;
252 
253     if ((exc_return & EXC_RETURN_MODE) && (exc_return & EXC_RETURN_SPSEL)) {
254         /* Use PSP when both EXC_RETURN.MODE and EXC_RETURN.SPSEL are set */
255         svc_args = psp;
256     }
257 
258     if (is_return_secure_stack(exc_return)) {
259         if (is_default_stacking_rules_apply(exc_return) == false) {
260             /* In this case offset the svc_args and only use
261              * the caller-saved registers
262              */
263             svc_args = &svc_args[10];
264         }
265 
266         /* SV called directly from secure context. Check instruction for
267          * svc_number
268          */
269         svc_number = ((uint8_t *)svc_args[6])[-2];
270     } else {
271         /* Secure SV executing with NS return.
272          * NS cannot directly trigger S SVC so this should not happen. This is
273          * an unrecoverable error.
274          */
275         tfm_core_panic();
276     }
277 
278     if (!!(exc_return & EXC_RETURN_MODE) == TFM_SVC_IS_HANDLER_MODE(svc_number)) {
279         /* Mode of caller does match mode of the target SVC */
280         tfm_core_panic();
281     }
282 
283     if (TFM_SVC_IS_SPM(svc_number)) {
284         /* SPM SVC */
285         return handle_spm_svc_requests(svc_number, exc_return, svc_args, msp);
286     }
287 
288 #if TFM_ISOLATION_LEVEL > 1
289     if (TFM_SVC_IS_PSA_API(svc_number)) {
290         if (((uint32_t)&REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit) - (uint32_t)msp) > 0) {
291             /* The Main Stack has contents, not calling from Partition thread */
292             tfm_core_panic();
293         }
294 
295         return prepare_to_thread_mode_spm(svc_number, svc_args, exc_return);
296     }
297 #endif
298 
299 #ifdef PLATFORM_SVC_HANDLERS
300     if (TFM_SVC_IS_PLATFORM(svc_number)) {
301         svc_args[0] = (platform_svc_handlers(svc_number, svc_args, exc_return));
302         return exc_return;
303     }
304 #endif
305 
306     ERROR_RAW("Unknown SVC number requested: 0x%08x\n", svc_number);
307     svc_args[0] = (uint32_t)PSA_ERROR_GENERIC_ERROR;
308 
309     return exc_return;
310 }
311 
312 __attribute__((naked))
tfm_svc_thread_mode_spm_return(psa_status_t result)313 void tfm_svc_thread_mode_spm_return(psa_status_t result)
314 {
315     __ASM volatile("SVC "M2S(TFM_SVC_THREAD_MODE_SPM_RETURN)"           \n");
316 }
317