blob: 6560a0cf85cf7af497d4f6727f9c3dc4c1713e16 [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
Ken Liu50e21092020-10-14 16:42:15 +080043 static void tfm_arch_set_secure_exception_priorities(void);
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +010044
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
Ken Liu50e21092020-10-14 16:42:15 +0800157Secure exception in the system.
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +0100158
159.. note::
160
161 The priority of PendSV Is set to be the lowest priority Secure interrupt,
162 but still higher than the maximum possible NS execution priority when
163 ``AIRCR.PRIS`` is set.
164
165NSPM
166----
167
168If the Non-secure software allows the use of multiple threads, it needs to use
169the NSPM feature of TF-M. It is expected, that all the NS context that use
170Secure services have a unique client ID, and the other contexts, that don't use
171Secure service need to have a client ID that doesn't match with any of the
172client IDs of the Secure service calling contexts.
173
174In other words, for all the *cs(0)*, *cs(1)*, ..., *cs(n)* NS contexts that use
175Secure services and for all *cn(0)*, *cn(1)*, ..., *cn(m)* NS contexts that
176don't use Secure service (where *n* > 0, *m* >= 0):
177
178- *cs(i).client_id* != *cs(j).client_id* (where 0 <= *i* < *j* <= *n*)
179- *cs(i).client_id* != *cn(j).client_id* (where 0 <= *i* <= *n* and 0 <= *j*
180 <= *m*)
181
182Entering from Non-secure to Secure
183----------------------------------
184
185The Secure code can be entered through the following gateways:
186
1871. NSPM related functions (``TZ_<operation>(...)``,
188 ``tfm_register_client_id(...)``)
189
190 These functions are expected to be called from Handler mode. The execution
191 priority, after the execution crosses the security boundary will be the same
192 as it was during NS execution. This means a malicious Non-secure application,
193 can set up Non-secure interrupt priorities in a way that it can enter one or
194 more of the NSPM APIs simultaneously.
195
196 This might leave the NSPM database in an inconsistent state, however if the
197 attacker has influence over the interrupt priorities, they can gain no
198 additional privilege by this.
199
200 .. Note::
201 The NS software is able to consume the main stack of the Secure software.
202 The Main Secure stack have to be protected by MSPLIM, to prevent stack
203 overflow. However a denial of service attack is still possible.
204
2052. PSA Client API, Library model service veneers
206
207 When a veneer is called from Non-secure, the Secure code have to check
208 whether the veneer is only entered by a single NS thread. This can be done by
209 checking the veneer stack usage. It can only contain the locals of the veneer
210 implementation. If the veneer has been entered from multiple NS threads,
211 there is at least one extra context stack frame that was created by the
212 hardware when the veneer execution had been interrupted by the NS systick.
213
214********************
215Implementation notes
216********************
217
218IPC model
219=========
220
221Save NS client ID on Secure service veneer entry
222------------------------------------------------
223
224As long as the Secure lock is in place, a single client ID have to be stored, so
225it can be done in a global variable.
226
227The caller client ID can be saved in the function
228``void tfm_psa_ipc_request_handler(uint32_t svc_ctx[])`` depending on the return
229value of the PSA API function. (Doesn't execute any Secure service code, only
Edison Aif7990c82020-07-16 18:31:48 +0800230sets signals, and triggers scheduling. If the return value is success, that
231means a scheduling is to happen, and a secure service is about to be entered.)
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +0100232
233Check client ID on Secure service return
234----------------------------------------
235
236The saved client ID can be compared with the current client ID in the function
237``tfm_core_ns_ipc_request``, after the SVC return. Before doing the comparison,
238``BASEPRI_NS`` must be set to 1.
239
240The original ``BASEPRI_NS`` value can be stored in a global variable (because of
241the single context).
242
243If the client ID's don't match, ``BASEPRI_NS`` must be reset, WFI to be issued,
244and start the checking sequence from the beginning.
245
246Library model
247=============
248
249Save NS client ID on Secure veneer entry
250----------------------------------------
251
252As long as the Secure lock is in place, only a single client ID have to be
253stored, so it can be done in a global variable.
254
255The caller client ID can be saved in the function
256``uint32_t tfm_core_partition_request_svc_handler(uint32_t *svc_args, uint32_t excReturn)``.
257
258Check client ID on SP return
259----------------------------
260
261The saved client ID can be compared with the current client ID in the function
262``tfm_core_partition_request``, after the ``tfm_core_sfn_request return``.
263
264If the client ID's don't match, WFI to be issued, and the checking sequence have
265to be started from the beginning.
266
267Common
268======
269
270Enforce single NS entry to Secure
271---------------------------------
272
273On Secure service entry (from the SVC implementation) check that (pseudocode)
274
275.. code-block:: c
276
277 svc_handler()
278 {
279 /* If there are multiple context stacked in veneer stack, hang NSPE */
280 expected_sp_top = veneer_stack_addr -
281 sizeof(svc_state_context) + sizeof(locals);
282 if (__get_PSP() != expected_sp_top) {
283 /* Multiple frames are existing, panic */
284 panic();
285 }
286 }
287
288*******
289Testing
290*******
291
292Basic scenario
293==============
294
295Basic testing of the feature is possible, by adding a new scenario to the
296existing IRQ test. The flow of the test would be something like this:
297
298============ ===================== ===========================================
299IRQ_TEST_1 prepare test scenario Do nothing
300CORE_TEST_2 prepare test scenario Do nothing
301NS prepare test scenario Initialise and start timer
302IRQ_TEST_1 execute test scenario Do nothing
303CORE_TEST_2 execute test scenario Busy wait until NS interrupt is
304 acknowledged (a flag in non Secure data is
305 set) set flag CORE_TEST_2 waits on
306NS execute test scenario Do nothing
307============ ===================== ===========================================
308
Edison Aif7990c82020-07-16 18:31:48 +0800309The test is successful if NS execute test scenario returns.
Mate Toth-Palb4d8fab2019-10-28 10:20:43 +0100310
311Advanced scenarios
312==================
313
314Testing advanced scenarios (that involves NS scheduling during secure execution,
315NS interrupting Secure interrupt, Secure interrupting NS interrupt) would
316require more advanced test framework and are not covered in this proposal.
317
318*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*