blob: a9c37590de3a4ed7edc08a9d3d4d8b4d8ffe4268 [file] [log] [blame]
Edison Ai1b7e8452019-12-16 10:03:52 +08001#######################
2Adding Secure Partition
3#######################
4
Edison Ai1b7e8452019-12-16 10:03:52 +08005***********************
6Terms and abbreviations
7***********************
8This document uses the following terms and abbreviations.
9
10.. table:: term table
11 :widths: auto
12
13 ================== ==================================
14 **Term** **Meaning**
15 ================== ==================================
16 FF Firmware Framework
17 ID Identifier
18 IPC Interprocess communication
19 IPC model The secure IPC framework
20 irqs Interrupt requests
21 Library model The secure function call framework
22 MMIO Memory Mapped I/O
23 PSA Platform Security Architecture
24 RoT Root of Trust
25 SID RoT Service ID
26 SP Secure Partition
27 SPM Secure Partition Manager
28 TF-M Trusted firmware M
29 ================== ==================================
30
31************
32Introduction
33************
34Secure Partition is an execution environment that provides the following
35functions to Root of Trust (RoT) Services:
36
37- Access to resources, protection of its own code and data.
38- Mechanisms to interact with other components in the system.
39
40Each Secure Partition is a single thread of execution and the smallest unit of
41isolation.
42
43This document mainly describes how to add a secure partition in TF-M and
44focuses on the configuration, manifest, implement rules. The actual
45source-level implementation is not included in this document.
46
47.. Note::
48 If not otherwise specified, the steps are identical for library and IPC
49 model.
50
51 The IPC model conforms the *PSA Firmware Framework (FF) v 1.0.0*. Refer to
52 `PSA Firmware Framework specification`_ for details.
53
54*******
55Process
56*******
57The main steps to add a secure partition are as follows:
58
59- `Add source folder`_
60- `Add manifest`_
61- `Add configuration`_
Edison Ai1b7e8452019-12-16 10:03:52 +080062- `Implement the RoT services`_
63
64Add source folder
65=================
Ken Liu738a4b02020-06-04 14:52:38 +080066Add a source folder under ``<TF-M base folder>/secure_fw/partitions`` for the new
Edison Ai1b7e8452019-12-16 10:03:52 +080067secure partition (Let's take EXAMPLE as the folder name):
68
69This folder should include those parts:
70
71- Manifest file: EXAMPLE.yaml
72- CMake configuration files
73- Source code files
74
75Add manifest
76============
77Each Secure Partition must have resource requirements declared in a manifest
78file. The Secure Partition Manager (SPM) uses the manifest file to assemble and
79allocate resources within the SPE. The manifest includes the following:
80
81- A Secure Partition name.
82- A list of implemented RoT Services.
83- Access to other RoT Services.
84- Memory requirements.
85- Scheduling hints.
86- Peripheral memory-mapped I/O regions and interrupts.
87
88.. Note::
89 The current manifest format in TF-M is "yaml" which is different from the
90 requirement of PSA FF.
91
92Here is a manifest reference example for the IPC model, please refer to
93`Library model support`_ for the library extend:
94
95.. code-block:: yaml
96
97 {
98 "psa_framework_version": 1.0,
99 "name": "TFM_SP_EXAMPLE",
100 "type": "PSA-ROT",
101 "priority": "HIGH",
Boris Deleticfb231172020-08-06 22:46:53 +0100102 "entry_point": "example_main",
Edison Ai1b7e8452019-12-16 10:03:52 +0800103 "stack_size": "0x0200",
104 "services" : [
105 {
106 "name": "ROT_A",
107 "sid": "0x0000F000",
108 "non_secure_clients": true,
109 "version": 1,
110 "version_policy": "STRICT"
111 }
112 ],
113 "mmio_regions": [
114 {
115 "name": "TFM_PERIPHERAL_A",
116 "permission": "READ-WRITE"
117 }
118 ],
119 "irqs": [
120 {
121 "source": "TFM_A_IRQ",
122 "signal": "SPM_CORE_A_IRQ",
123 "tfm_irq_priority": 64,
124 }
125 ],
126 "linker_pattern": {
127 "object_list": [
128 "*EXAMPLE.*"
129 ]
130 }
131 }
132
133Secure Partition ID Distribution
134--------------------------------
135Every Secure Partition has an identifier (ID). TF-M will generate a header file
136that includes definitions of the Secure Partition IDs. The header file is
137``<TF-M base folder>/interface/include/psa_manifest/pid.h``. Each definition
138uses the ``name`` attribute in the manifest as its name and the value is
139allocated by SPM.
140
141.. code-block:: c
142
143 #define name id-value
144
145Here is the Secure Partition ID table used in TF-M.
146
147.. table:: PID table
148 :widths: auto
149
150 =============================== =================
151 **Partition name** **Partition ID**
152 =============================== =================
153 Reserved 0-255
Kevin Pengc6d74502020-03-04 16:55:37 +0800154 TFM_SP_PS 256
Edison Ai1b7e8452019-12-16 10:03:52 +0800155 TFM_SP_ITS 257
156 TFM_SP_AUDIT_LOG 258
157 TFM_SP_CRYPTO 259
158 TFM_SP_PLATFORM 260
159 TFM_SP_INITIAL_ATTESTATION 261
160 TFM_SP_CORE_TEST 262
161 TFM_SP_CORE_TEST_2 263
162 TFM_SP_SECURE_TEST_PARTITION 264
163 TFM_SP_IPC_SERVICE_TEST 265
164 TFM_SP_IPC_CLIENT_TEST 266
165 TFM_IRQ_TEST_1 267
Kevin Pengc6d74502020-03-04 16:55:37 +0800166 TFM_SP_PS_TEST 268
Edison Ai1b7e8452019-12-16 10:03:52 +0800167 =============================== =================
168
169About where to add the definition, please refer to the chapter `Add
170configuration`_.
171
172RoT Service ID (SID) Distribution
173---------------------------------
174An RoT Service is identified by its RoT Service ID (SID). A SID is a 32-bit
175number that is associated with a symbolic name in the Secure Partition
176manifest. The bits [31:12] uniquely identify the vendor of the RoT Service.
177The remaining bits [11:0] can be used at the discretion of the vendor.
178
179Here is the RoT Service ID table used in TF-M.
180
181.. table:: SID table
182 :widths: auto
183
184 =========================== ====================== ========================
185 **Services** **Vendor ID(20 bits)** **Function ID(12 bits)**
186 =========================== ====================== ========================
187 audit_logging 0x00000 0x000-0x01F
188 initial_attestation 0x00000 0x020-0x03F
189 platform 0x00000 0x040-0x05F
Kevin Pengc6d74502020-03-04 16:55:37 +0800190 protected_storage 0x00000 0x060-0x07F
Edison Ai1b7e8452019-12-16 10:03:52 +0800191 crypto 0x00000 0x080-0x09F
192 internal_trusted_storage 0x00000 0x0A0-0x0BF
193 test_secure_service 0x0000F 0x000-0x01F
194 core_test 0x0000F 0x020-0x03F
195 core_test_2 0x0000F 0x040-0x05F
196 tfm_ipc_client 0x0000F 0x060-0x07F
197 tfm_ipc_service 0x0000F 0x080-0x09F
198 tfm_irq_test_service_1 0x0000F 0x0A0-0x0BF
Kevin Pengc6d74502020-03-04 16:55:37 +0800199 tfm_ps_test_service 0x0000F 0x0C0-0x0DF
Edison Ai1b7e8452019-12-16 10:03:52 +0800200 =========================== ====================== ========================
201
202mmio_regions
203------------
204This attribute is a list of MMIO region objects which the Secure Partition
205needs access to. TF-M only supports the ``named_region`` current. Please refer
206to PSA FF for more details about it. The user needs to provide a name macro to
207indicate the variable of the memory region.
208
209TF-M uses the below structure to indicate a peripheral memory.
210
211.. code-block:: c
212
213 struct tfm_spm_partition_platform_data_t {
214 uint32_t periph_start;
215 uint32_t periph_limit;
216 int16_t periph_ppc_bank;
217 int16_t periph_ppc_loc;
218 };
219
220.. Note::
221 This structure is not expected by TF-M, it's only that the current
222 implementations are using. Other peripherals that need different information
223 to create isolation need to define a different structure with the same name.
224
225Here is a example for it:
226
227.. code-block:: c
228
229 struct tfm_spm_partition_platform_data_t tfm_peripheral_A;
230 #define TFM_PERIPHERAL_A (&tfm_peripheral_A)
231
232linker_pattern
233--------------
234``linker_pattern`` is a legacy region which contains the minimum information
235required to link a Secure Partition’s compiled static objects. Now, it is
236required as 'IMPLEMENTATION DEFINED' in PSA FF 1.0.0.
237
238Library model support
239---------------------
240For the library model, the user needs to add a ``secure_functions`` item. The
241main difference between ``secure_function`` and ``services`` is the extra
242``signal`` key for secure function entry.
243
244The ``signal`` must be the upper case of the secure function name.
245
246.. code-block:: yaml
247
248 "secure_functions": [
249 {
250 "name": "TFM_EXAMPLE_A",
251 "signal": "EXAMPLE_A_FUNC",
252 "sid": "0x00000000",
253 "non_secure_clients": true,
254 "version": 1,
255 "version_policy": "STRICT"
256 },
257
258Add configuration
259=================
260The following configuration tasks are required for the newly added secure
261partition:
262
263Add CMake configure files
264-------------------------
Edison Ai1b7e8452019-12-16 10:03:52 +0800265- CMakeLists.txt, which is the compilation configuration for this module.
266
Boris Deleticfb231172020-08-06 22:46:53 +0100267The current CMake configuration should also be updated, by updating
Anton Komlevb8e3af02020-08-28 10:23:57 +0100268config_default.cmake to include the definition of the newly introduced partition
Boris Deleticfb231172020-08-06 22:46:53 +0100269and adding the relevant subdirectoy in ``secure_fw/CMakeLists.txt``.
Edison Ai1b7e8452019-12-16 10:03:52 +0800270Please refer to the source code of TF-M for more detail.
271
272Update manifest list
273--------------------
274The ``<TF-M base folder>/tools/tfm_manifest_list.yaml`` is used to collect
275necessary information of secure partition.
276
277- ``name``: The name string of the secure partition.
278- ``short_name``: should be the same as the ``name`` in the secure partition
279 manifest file.
280- ``manifest``: the relative path of the manifest file to TF-M root.
281- ``tfm_partition_ipc``: indicate if this partition is compatible with the IPC
282 model.
283- ``conditional``: Optional. Configure control macro for this partition.
284- ``version_major``: major version the partition manifest.
285- ``version_minor``: minor version the partition manifest.
286- ``pid``: Secure Partition ID value distributed in chapter `Secure Partition
287 ID Distribution`_.
288
289Reference configuration example:
290
291.. code-block:: yaml
292
293 {
294 "name": "Example Service",
295 "short_name": "TFM_SP_EXAMPLE",
Ken Liu738a4b02020-06-04 14:52:38 +0800296 "manifest": "secure_fw/partitions/EXAMPLE/tfm_example.yaml",
Edison Ai1b7e8452019-12-16 10:03:52 +0800297 "tfm_partition_ipc": true,
Boris Deleticfb231172020-08-06 22:46:53 +0100298 "conditional": "TFM_PARTITION_EXAMPLE",
Edison Ai1b7e8452019-12-16 10:03:52 +0800299 "version_major": 0,
300 "version_minor": 1,
301 "pid": 256
302 }
303
Anton Komlevb8e3af02020-08-28 10:23:57 +0100304.. Note::
305 The manifest configuration can be placed in a different external manifest
306 list. In this case, the cmake variable TFM_EXTRA_MANIFEST_LIST_PATH should be
307 set to the path of the external manifest list.
Edison Ai1b7e8452019-12-16 10:03:52 +0800308
309Implement the RoT services
310==========================
Boris Deleticfb231172020-08-06 22:46:53 +0100311To implement RoT services, the partition needs a source file which contains the
312implementations of the services, as well as the partition entry point. The user
313can create this source file under
314``<TF-M base folder>/secure_fw/partitions/EXAMPLE/EXAMPLE.c``. The linker
315detects source files according to the pattern matching defined by the
316"linker_pattern" attribute in the ``tfm_manifest_list.yaml`` file.
317
318As an example, the RoT service with SID **ROT_A** will be implemented.
319
320Entry point function
321--------------------
322This function acts as a main() function for the partition.
323On incoming signals for service calls, the entry point function handles
324signals by calling the relevant service function.
325An example entry point is given
326
327.. code-block:: c
328
329 void example_main(void)
330 {
331 psa_signal_t signals = 0;
332
333 while (1) {
334 signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
335 if (signals & ROT_A_SIGNAL) {
336 rot_A();
337 } else {
338 /* Should not come here */
339 psa_panic();
340 }
341 }
342 }
343
344Service implementation
345----------------------
346The service is implemented by the ``rot_A()`` function, which is called upon an
347incoming signal. This implementation is up to the user, however an example
348service has been included for reference. The following example sends a message
349"Hello World" when called.
350
351.. code-block:: c
352
353 static void rot_A(void)
354 {
355 const int BUFFER_LEN = 32;
356 psa_msg_t msg;
357 psa_status_t r;
358 int i;
359 uint8_t rec_buf[BUFFER_LEN];
360 uint8_t send_buf[BUFFER_LEN] = "Hello World";
361
362 psa_get(ROT_A_SIGNAL, &msg);
363 switch (msg.type) {
364 case PSA_IPC_CONNECT:
365 if (service_in_use & ROT_A_SIGNAL) {
366 r = PSA_ERROR_CONNECTION_REFUSED;
367 } else {
368 service_in_use |= ROT_A_SIGNAL;
369 r = PSA_SUCCESS;
370 }
371 psa_reply(msg.handle, r);
372 break;
373 case PSA_IPC_CALL:
374 for (i = 0; i < PSA_MAX_IOVEC; i++) {
375 if (msg.in_size[i] != 0) {
376 psa_read(msg.handle, i, rec_buf, BUFFER_LEN);
377 }
378 if (msg.out_size[i] != 0) {
379 psa_write(msg.handle, i, send_buf, BUFFER_LEN);
380 }
381 }
382 psa_reply(msg.handle, PSA_SUCCESS);
383 break;
384 case PSA_IPC_DISCONNECT:
385 assert((service_in_use & ROT_A_SIGNAL) != 0);
386 service_in_use &= ~ROT_A_SIGNAL;
387 psa_reply(msg.handle, PSA_SUCCESS);
388 break;
389 default:
390 /* cannot get here [broken SPM] */
391 psa_panic();
392 break;
393 }
394 }
395
396Test connection
397---------------
398To test that the service has been implemented correctly, the user needs to call
399it from somewhere. One option is to create a new testsuite, such as
400``<TF-M-test base folder>/test/suites/example/non_secure/example_ns_interface_testsuite.c``.
401
402.. code-block:: c
403
404 static void tfm_example_test_1001(struct test_result_t *ret)
405 {
406 char str1[] = "str1";
407 char str2[] = "str2";
408 char str3[128], str4[128];
409 struct psa_invec invecs[2] = {{str1, sizeof(str1)},
410 {str2, sizeof(str2)}};
411 struct psa_outvec outvecs[2] = {{str3, sizeof(str3)},
412 {str4, sizeof(str4)}};
413 psa_handle_t handle;
414 psa_status_t status;
415 uint32_t version;
416
417 version = psa_version(ROT_A_SID);
418 TEST_LOG("TFM service support version is %d.\r\n", version);
419 handle = psa_connect(ROT_A_SID, ROT_A_VERSION);
420 status = psa_call(handle, PSA_IPC_CALL, invecs, 2, outvecs, 2);
421 if (status >= 0) {
422 TEST_LOG("psa_call is successful!\r\n");
423 } else {
424 TEST_FAIL("psa_call is failed!\r\n");
425 return;
426 }
427
428 TEST_LOG("outvec1 is: %s\r\n", outvecs[0].base);
429 TEST_LOG("outvec2 is: %s\r\n", outvecs[1].base);
430 psa_close(handle);
431 ret->val = TEST_PASSED;
432 }
433
434Once the test and service has been implemented, the project can be built and
435executed. The user should see the "Hello World" message in the console as
436received by the testsuite.
437
438Further Notes
439-------------
Edison Ai1b7e8452019-12-16 10:03:52 +0800440
441- In the IPC model, Use PSA FF proposed memory accessing mechanism. SPM
442 provides APIs and checking between isolation boundaries, a free accessing
443 of memory can cause program panic.
444- In the IPC model, the memory checking inside partition runtime is
445 unnecessary. SPM handles the checking while memory accessing APIs are
446 called.
447- In the IPC model, the client ID had been included in the message structure
448 and secure partition can get it when calling psa_get() function. The secure
449 partition does not need to call ``tfm_core_get_caller_client_id()`` to get
450 the caller client ID anymore.
451- In the IPC model, SPM will check the security policy and partition
452 dependence between client and service. So the service does not need to
453 validate the secure caller anymore.
454
455*********
456Reference
457*********
458
459| `PSA Firmware Framework specification`_
460
461.. _PSA Firmware Framework specification: https://pages.arm.com/psa-
462 resources-ff.html?_ga=2.156169596.61580709.1542617040-1290528876.1541647333
463
464--------------
465
Kevin Pengc6d74502020-03-04 16:55:37 +0800466*Copyright (c) 2019-2020, Arm Limited. All rights reserved.*