blob: 3b0b143b275645dcaf7401c1b21085e8b60657b1 [file] [log] [blame]
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +01001#############################
2Non-Secure Interrupt Handling
3#############################
4
5:Author: Mate Toth-Pal
6:Organization: Arm Limited
7:Contact: Mate Toth-Pal <mate.toth-pal@arm.com>
8:Status: Accepted
9
10
11*****
12Terms
13*****
14
15========== ================================================
16Term Meaning
17========== ================================================
18AIRCR Application Interrupt and Reset Control Register
19AIRCR.PRIS PRIoritize Secure exceptions
20ISR Interrupt Service Routine
21NS Non-Secure
22NSPM Non-Secure Partition Manager
23SAU Security Attribution Unit
24SPM Secure Partition Manager
25TF-M Trusted Firmware-M
26========== ================================================
27
28************
29Introduction
30************
31
32In the current design it is possible to use Non-secure interrupts, however the
33Non-secure interrupts cannot pre-empt Secure service execution. TF-M core
34achieves this by making the following configurations:
35
361. ``AIRCR.PRIS`` is set to 1 during TF-M core initialisation. This
37 de-prioritizes Non-secure exceptions compared to Secure exceptions, so that
Edison Aif7990c82020-07-16 18:31:48 +080038 they cannot interrupt Secure Handler mode. the ``AIRCR.PRIS`` bit remains set
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +010039 during TF-M run. The bit is set in the function
40
41.. code-block:: c
42
43 static int32_t tfm_core_set_secure_exception_priorities(void);
44
45.. Note::
46
47 Setting ``AIRCR.PRIS`` in itself doesn't prevent NS interrupts to pre-empt
48 Secure Thread mode when it runs on normal priority i.e., 256.
49
502. On Secure service entry ``PRIMASK_NS`` is set, to boost the Non-secure
51 execution priority so that all NS interrupts are masked. This is done in the
52 ``TFM_NS_EXC_DISABLE()`` macro called from
53
54.. code-block:: c
55
56 static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
57
58.. Note::
59
60 '2.' is only in Library model.
61
62In the below chapters a design is proposed to enable Non-secure interrupts to
63pre-empt Secure Thread mode.
64
65**********************************
66Limitations of the proposed design
67**********************************
68
69Library model
70=============
71
72The proposed design keeps the Secure lock in place, which means Non-secure code
73can do a single Secure service call, all further calls to Secure services will
74be rejected until the first Secure service call returns.
75
76IPC model
77=========
78
79The PSA client API can only be entered once. All the functions in the client API
80(``psa_framework_version``, ``psa_version``, ``psa_connect``, ``psa_call``,
81``psa_close``) are part of the same critical section.
82
83Non-secure software
84===================
85
86The Non-secure API functions that wraps the Secure service veneers (either
87Library or IPC model) should continue to use the NS locking mechanism currently
88implemented by calling ``tfm_ns_lock_dispatch(...)``.
89
90If any of the Non-secure software decides to bypass the locking mechanism, then
91concurrent access of veneer functions is detected by TF-M, and NS software
92execution is halted.
93
94.. Note::
95
96 This makes denial of service attack possible by a malicious NS application
97
98***************************************************
99Enabling NS interrupts to pre-empt Secure execution
100***************************************************
101
102To enable NS interrupts, 2) described in chapter 'Current design' must be turned
103off. (For details see implementation notes)
104
105When a Non-secure interrupt is triggered during Secure code execution, and the
106ISR have to be executed based on the priority settings, the hardware saves the
107current execution context on the current Secure stack, and clears the general
108purpose registers, to prevents data leakage. After that the NS ISR starts
109execution.
110
111When the Non-secure ISR returns with the EXC_RETURN value provided to it in the
112link register, the context is fetched from the Secure stack, and the Secure code
113continues execution.
114
115If TF-M is used with a single threaded NS software, the mechanisms provided by
116the HW is enough to maintain the consistency of the system, and keep the
117secrets.
118
119However if the NS software is allowed to change execution context during an
120interrupt (e.g an NS operating system schedules another thread during a SysTick
121interrupt), then the Secure code can return execution to an NS thread, with the
122context of a different thread. So extra measures needs to be introduced in TF-M
123to prevent this.
124
125For IPC model
126=============
127
128In the current implementation there is no locking mechanism on the Secure side
129that would prevent the Non-secure code to enter psa_client functions multiple
130times. (For the Library model the ``tfm_secure_lock global`` variable is used
131for this purpose). Note, that the ``tfm_ns_lock_dispatch(...)`` function that
132is used by the NS service API implementations to prevent Secure services to be
133called simultaneously can be bypassed by a malicious Non-secure application, so
134a Secure side locking mechanism have to be implemented.
135
136When an NS client calls a PSA client API function, the client ID of the calling
137NS context have to be saved, and execution can only return to NS if the current
138scheduled NS thread is the one that did the call.
139
140For Library model
141=================
142
143As currently there is no scheduling in the Library model, the calls follow each
144other just like in an ordinary function call scheme. Then when the original
145Secure service that was called from the NS code is about to return, it has to
146check for the current NS client ID, and only return if it is the same as the one
147saved on Secure service entry from NS. If the ID's don't match, the Secure side
148waits so that NS OS can do context switch.
149
150Common measures
151===============
152
153Exception priorities
154--------------------
155
156The priority of the Secure SVC and the Secure faults must be higher than any
157Secure exception in the system. Once this is done, the following fixme can be
158removed from ``secure_fw\core\tfm_core.c``:
159``tfm_core_set_secure_exception_priorities``:
160
161.. code-block:: c
162
163 /* FixMe: Explicitly set secure fault and Secure SVC priority to highest */
164
165.. note::
166
167 The priority of PendSV Is set to be the lowest priority Secure interrupt,
168 but still higher than the maximum possible NS execution priority when
169 ``AIRCR.PRIS`` is set.
170
171NSPM
172----
173
174If the Non-secure software allows the use of multiple threads, it needs to use
175the NSPM feature of TF-M. It is expected, that all the NS context that use
176Secure services have a unique client ID, and the other contexts, that don't use
177Secure service need to have a client ID that doesn't match with any of the
178client IDs of the Secure service calling contexts.
179
180In other words, for all the *cs(0)*, *cs(1)*, ..., *cs(n)* NS contexts that use
181Secure services and for all *cn(0)*, *cn(1)*, ..., *cn(m)* NS contexts that
182don't use Secure service (where *n* > 0, *m* >= 0):
183
184- *cs(i).client_id* != *cs(j).client_id* (where 0 <= *i* < *j* <= *n*)
185- *cs(i).client_id* != *cn(j).client_id* (where 0 <= *i* <= *n* and 0 <= *j*
186 <= *m*)
187
188Entering from Non-secure to Secure
189----------------------------------
190
191The Secure code can be entered through the following gateways:
192
1931. NSPM related functions (``TZ_<operation>(...)``,
194 ``tfm_register_client_id(...)``)
195
196 These functions are expected to be called from Handler mode. The execution
197 priority, after the execution crosses the security boundary will be the same
198 as it was during NS execution. This means a malicious Non-secure application,
199 can set up Non-secure interrupt priorities in a way that it can enter one or
200 more of the NSPM APIs simultaneously.
201
202 This might leave the NSPM database in an inconsistent state, however if the
203 attacker has influence over the interrupt priorities, they can gain no
204 additional privilege by this.
205
206 .. Note::
207 The NS software is able to consume the main stack of the Secure software.
208 The Main Secure stack have to be protected by MSPLIM, to prevent stack
209 overflow. However a denial of service attack is still possible.
210
2112. PSA Client API, Library model service veneers
212
213 When a veneer is called from Non-secure, the Secure code have to check
214 whether the veneer is only entered by a single NS thread. This can be done by
215 checking the veneer stack usage. It can only contain the locals of the veneer
216 implementation. If the veneer has been entered from multiple NS threads,
217 there is at least one extra context stack frame that was created by the
218 hardware when the veneer execution had been interrupted by the NS systick.
219
220********************
221Implementation notes
222********************
223
224IPC model
225=========
226
227Save NS client ID on Secure service veneer entry
228------------------------------------------------
229
230As long as the Secure lock is in place, a single client ID have to be stored, so
231it can be done in a global variable.
232
233The caller client ID can be saved in the function
234``void tfm_psa_ipc_request_handler(uint32_t svc_ctx[])`` depending on the return
235value of the PSA API function. (Doesn't execute any Secure service code, only
Edison Aif7990c82020-07-16 18:31:48 +0800236sets signals, and triggers scheduling. If the return value is success, that
237means a scheduling is to happen, and a secure service is about to be entered.)
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +0100238
239Check client ID on Secure service return
240----------------------------------------
241
242The saved client ID can be compared with the current client ID in the function
243``tfm_core_ns_ipc_request``, after the SVC return. Before doing the comparison,
244``BASEPRI_NS`` must be set to 1.
245
246The original ``BASEPRI_NS`` value can be stored in a global variable (because of
247the single context).
248
249If the client ID's don't match, ``BASEPRI_NS`` must be reset, WFI to be issued,
250and start the checking sequence from the beginning.
251
252Library model
253=============
254
255Save NS client ID on Secure veneer entry
256----------------------------------------
257
258As long as the Secure lock is in place, only a single client ID have to be
259stored, so it can be done in a global variable.
260
261The caller client ID can be saved in the function
262``uint32_t tfm_core_partition_request_svc_handler(uint32_t *svc_args, uint32_t excReturn)``.
263
264Check client ID on SP return
265----------------------------
266
267The saved client ID can be compared with the current client ID in the function
268``tfm_core_partition_request``, after the ``tfm_core_sfn_request return``.
269
270If the client ID's don't match, WFI to be issued, and the checking sequence have
271to be started from the beginning.
272
273Common
274======
275
276Enforce single NS entry to Secure
277---------------------------------
278
279On Secure service entry (from the SVC implementation) check that (pseudocode)
280
281.. code-block:: c
282
283 svc_handler()
284 {
285 /* If there are multiple context stacked in veneer stack, hang NSPE */
286 expected_sp_top = veneer_stack_addr -
287 sizeof(svc_state_context) + sizeof(locals);
288 if (__get_PSP() != expected_sp_top) {
289 /* Multiple frames are existing, panic */
290 panic();
291 }
292 }
293
294*******
295Testing
296*******
297
298Basic scenario
299==============
300
301Basic testing of the feature is possible, by adding a new scenario to the
302existing IRQ test. The flow of the test would be something like this:
303
304============ ===================== ===========================================
305IRQ_TEST_1 prepare test scenario Do nothing
306CORE_TEST_2 prepare test scenario Do nothing
307NS prepare test scenario Initialise and start timer
308IRQ_TEST_1 execute test scenario Do nothing
309CORE_TEST_2 execute test scenario Busy wait until NS interrupt is
310 acknowledged (a flag in non Secure data is
311 set) set flag CORE_TEST_2 waits on
312NS execute test scenario Do nothing
313============ ===================== ===========================================
314
Edison Aif7990c82020-07-16 18:31:48 +0800315The test is successful if NS execute test scenario returns.
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +0100316
317Advanced scenarios
318==================
319
320Testing advanced scenarios (that involves NS scheduling during secure execution,
321NS interrupting Secure interrupt, Secure interrupting NS interrupt) would
322require more advanced test framework and are not covered in this proposal.
323
324*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*