blob: 65893c26d02b8b2900e33ed4a669997d1e5c8632 [file] [log] [blame]
Joakim Bech8e5c5b32018-10-25 08:18:32 +02001.. _porting_guidelines:
2
3##################
4Porting guidelines
5##################
6This document serves a dual purpose:
7
8* Serve as a base for getting OP-TEE up and running on a new device with initial
9 xtest validation passing. This is the first part of this document (section 2).
10
11* Highlight the missing pieces if you intend to make a real secure product, that
12 is what the second part of this document is about.
13
14We are trying our best to implement full end to end security in OP-TEE in a
15generic way, but due to the nature of devices being different, NDA etc, it is
16not always possible for us to do so and in those cases, we most often try to
17write a generic API, but we will just stub the code. This porting guideline
18highlights the missing pieces that must be addressed in a real secure consumer
19device. Hopefully we will sooner or later get access to devices where we at
20least can make reference implementations publicly available to everyone for the
21missing pieces we are talking about here.
22
23.. _add_a_new_platform:
24
25Add a new platform
26******************
27The first thing you need to do after you have decided to port OP-TEE to another
28device is to add a new platform device. That can either be adding a new platform
29variant (``PLATFORM_FLAVOR``) if it is a device from a family already supported,
30or it can be a brand new platform family (``PLATFORM``). Typically this initial
31setup involve configuring UART, memory addresses etc. For simplicity let us call
32our fictive platform for "gendev" just so we have something to refer to when
33writing examples further down.
34
35core/arch/arm
36=================
37In ``core/arch/arm`` you will find all the currently supported devices. That is
38where you are supposed to add a new platform or modify an existing one.
39Typically you will find this set of files in a specific platform folder:
40
41.. code-block:: bash
42
43 $ ls
44 conf.mk main.c platform_config.h sub.mk
45
46So for the gendev platform it means that the files should be placed in this
47folder:
48
49.. code-block:: bash
50
51 core/arch/arm/plat-gendev
52
53**conf.mk**
54
55This is the device specific makefile where you define configurations unique to
Joakim Bech6f56d082024-03-11 10:40:30 +010056your platform. This mainly comprises two things:
57
58- OP-TEE configuration variables (``CFG_``), which may be assigned values in
59 two ways. ``CFG_FOO ?= bar`` should be used to provide a default value that
60 may be modified at compile time. On the other hand, variables that must be
61 set to some value and cannot be modified should be set by: ``$(call
62 force,CFG_FOO,bar)``.
63
64- Compiler flags for the TEE core, the user mode libraries and the Trusted
65 Applications, which may be added to macros used by the build system. Please
66 see :ref:`configuration_and_flags` and similar sections on that page.
Joakim Bech8e5c5b32018-10-25 08:18:32 +020067
68It is recommended to use a existing platform configuration file as a starting
69point. For instance, `core/arch/arm/plat-hikey/conf.mk`_.
70
71The platform ``conf.mk`` file should at least define the default platform flavor
72for the platform, the core configurations (architecture and number of cores),
73the main configuration directives (generic boot, arm trusted firmware support,
74generic time source, console driver, etc...) and some platform default
75configuration settings.
76
77.. code-block:: make
78
79 PLATFORM_FLAVOR ?= hikey
80
81 include core/arch/arm/cpu/cortex-armv8-0.mk
82
83 $(call force,CFG_TEE_CORE_NB_CORE,8)
84 $(call force,CFG_GENERIC_BOOT,y)
85 $(call force,CFG_PL011,y)
86 $(call force,CFG_PM_STUBS,y)
87 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
88 $(call force,CFG_WITH_ARM_TRUSTED_FW,y)
89 $(call force,CFG_WITH_LPAE,y)
90
91 ta-targets = ta_arm32
92 ta-targets += ta_arm64
93
94 CFG_NUM_THREADS ?= 8
95 CFG_CRYPTO_WITH_CE ?= y
96 CFG_WITH_STACK_CANARIES ?= y
97 CFG_CONSOLE_UART ?= 3
98 CFG_DRAM_SIZE_GB ?= 2
99
100**main.c**
101
102This platform specific file will contain power management handlers and code
103related to the UART. We will talk more about the information related to the
104handlers further down in this document. For our gendev device it could look like
105this (here we are excluding the necessary license header to save some space):
106
107.. code-block:: c
108
109 #include <console.h>
110 #include <drivers/serial8250_uart.h>
111 #include <kernel/generic_boot.h>
112 #include <kernel/panic.h>
113 #include <kernel/pm_stubs.h>
114 #include <mm/core_mmu.h>
115 #include <platform_config.h>
116 #include <stdint.h>
117 #include <tee/entry_fast.h>
118 #include <tee/entry_std.h>
119
120 static void main_fiq(void)
121 {
122 panic();
123 }
124
125 static const struct thread_handlers handlers = {
126 .std_smc = tee_entry_std,
127 .fast_smc = tee_entry_fast,
128 .nintr = main_fiq,
129 .cpu_on = cpu_on_handler,
130 .cpu_off = pm_do_nothing,
131 .cpu_suspend = pm_do_nothing,
132 .cpu_resume = pm_do_nothing,
133 .system_off = pm_do_nothing,
134 .system_reset = pm_do_nothing,
135 };
136
137 const struct thread_handlers *generic_boot_get_handlers(void)
138 {
139 return &handlers;
140 }
141
142 /*
143 * Register the physical memory area for peripherals etc. Here we are
144 * registering the UART console.
145 */
146 register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE);
147
148 static struct serial8250_uart_data console_data;
149
150 void console_init(void)
151 {
152 serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
153 CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
154 register_serial_console(&console_data.chip);
155 }
156
157**platform_config.h**
158
159This is a mandatory header file for every platform, since there are several
160files relaying upon the existence of this particular file. This file is where
161you will find the major differences between different platforms, since this is
162where you do the memory configuration, define base addresses etc. we are going
163to list a few here, but it probably makes more sense to have a look at the
164already existing ``platform_config.h`` files for the other platforms. Our
165fictive gendev could look like this:
166
167.. code-block:: c
168
169 #ifndef PLATFORM_CONFIG_H
170 #define PLATFORM_CONFIG_H
171
172 /* Make stacks aligned to data cache line length */
173 #define STACK_ALIGNMENT 64
174
175 /* 8250 UART */
176 #define CONSOLE_UART_BASE 0xcafebabe /* UART0 */
177 #define CONSOLE_BAUDRATE 115200
178 #define CONSOLE_UART_CLK_IN_HZ 19200000
179
180 /* Optional: when used with CFG_WITH_PAGER, defines the device SRAM */
181 #define TZSRAM_BASE 0x3F000000
182 #define TZSRAM_SIZE (200 * 1024)
183
184 /* Mandatory main secure RAM usually DDR */
185 #define TZDRAM_BASE 0x60000000
186 #define TZDRAM_SIZE (32 * 1024 * 1024)
187
188 /* Mandatory TEE RAM location and core load address */
189 #define TEE_RAM_START TZDRAM_BASE
190 #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE
191 #define TEE_RAM_VA_SIZE (4 * 1024 * 1024)
192 #define TEE_LOAD_ADDR (TZDRAM_BASE + 0x20000)
193
194 /* Mandatory TA RAM (external less secure RAM) */
195 #define TA_RAM_START (TZDRAM_BASE + TEE_RAM_VA_SIZE)
196 #define TA_RAM_SIZE (TZDRAM_SIZE - TEE_RAM_VA_SIZE)
197
198 /* Mandatory: for static SHM, need a hardcoded physical address */
199 #define TEE_SHMEM_START 0x08000000
200 #define TEE_SHMEM_SIZE (4 * 1024 * 1024)
201
202 #endif /* PLATFORM_CONFIG_H */
203
204This is minimal amount of information in the ``platform_config.h`` file. I.e,
205the memory layout for on-chip and external RAM. Note that parts of the DDR
206typically will need to be shared with normal world, so there is need for some
207kind of memory firewall for this (more about that further down). As you can see
208we have also added the UART configuration here, i.e., the ``DEVICE0_xyz`` part.
209
Jens Wiklander629b3352024-10-25 10:01:48 +0200210Binaries
211========
212Building OP-TEE results in a few binaries in the out directory. Which
213binaries are used depends on how OP-TEE is loaded into memory.
214
215.. list-table:: Binaries generated by default
216 :header-rows: 1
217
218 * - Name
219 - Description
220 * - tee.elf
221 - The main ELF file. All other binaries are created with this
222 as input.
223 * - tee-header_v2.bin
224 - Combined header for tee-pager_v2.bin and tee-pageable_v2.bin. Used
225 by TF-A as bl32.bin to describe bl32_extra1.bin and bl32_extra2.bin.
226 Passed to TF-A with BL32=<filename>.bin when building the FIP.
227 * - tee-pager_v2.bin
228 - Raw binary for the unpaged and init parts of OP-TEE. Used by TF-A as
229 bl32_extra1.bin, requires tee-header_v2.bin. Passed to TF-A with
230 BL32_EXTRA1=<filename>.bin
231 * - tee-pageable_v2.bin
232 - Raw binary for the paged part of OP-TEE. Used by TF-A as
233 bl32_extra2.bin, requires tee-header_v2.bin. Passed to TF-A with
234 BL32_EXTRA2=<filename>.bin. This file is empty and the parameter is
235 optional if OP-TEE is built with CFG_WITH_PAGER=n
236 * - tee.bin
237 - The original binary with a header and combined init, paged, and
238 unpaged parts
239 * - tee.dmp
240 - A dump of the ELF file using ``objdump -lxd``
241 * - tee-raw.bin
242 - Raw binary suitable to copy into physical memory where OP-TEE
243 be can executed from. Used by Hafnium to load OP-TEE, passed via
244 sp_layout.json.
245
246.. list-table:: Binaries generated only if given as targets to make
247 :header-rows: 1
248
249 * - Name
250 - Description
251 * - tee.srec
252 - Dump an SREC file from tee-raw.bin using ``objcopy -I binary -O srec``
253 * - tee-pager.bin
254 - Legacy raw binary with unpaged sections.
255 * - tee-pageable.bin
256 - Legacy raw binary with paged and init sections.
257
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200258Official board support in OP-TEE?
259=================================
260We do encourage everyone to submit their board support to the OP-TEE project
261itself, so it becomes part of the official releases and will be maintained by
262the OP-TEE community itself. If you intend to do so, then there are a few more
263things that you are supposed to do.
264
265**Update platforms supported**
266
267There is a section at the :ref:`platforms_supported` page that lists all devices
268officially supported in OP-TEE, that is where you also shall list your device.
269It should contain the name of the platform, then composite ``PLATFORM`` flag and
270whether the device is publicly available or not. If there is a product page on
271the internet for the device, please also create a link when writing the device
272name.
273
274**Update .shippable.yml**
275
276Since we are using Shippable to test pull requests etc, we would like that you
277also add your device to the `.shippable.yml
278<https://github.com/OP-TEE/optee_os/blob/master/.shippable.yml>`_ file, so that
279it will at least be built when someone is doing a pull request. Add a line at
280the end of file:
281
282.. code-block:: xml
283
284 - _make PLATFORM=<platform-name>_
285
286**Maintainer**
287
Joakim Beche58b15c2020-04-15 10:48:41 +0200288If you are submitting the board support upstream we are going to ask you to
289become the maintainer for the device you have added. This means that you should
290also update the MAINTAINERS.md_ file accordingly. By being a maintainer for a
291device you are responsible to keep it up to date and you will be asked every
292quarter as part of the OP-TEE release schedule to test your device running the
293latest OP-TEE software.
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200294
295**Update build.git and manifest.git**
296
297This isn't strictly necessary, but we are trying to create and maintain OP-TEE
298developer builds that should make it easy to setup, build and deploy OP-TEE on
299various devices. We encourage all maintainers to do the same for the boards they
300are in charge of. Therefore please consider creating a new :ref:`manifest` (and
301a new ``*.mk`` in :ref:`build`) for the device you have added to OP-TEE.
302
303.. _hardware_unique_key:
304
305Hardware Unique Key
306*******************
307Most devices have some kind of Hardware Unique Key (HUK) that is mainly used to
308derive other keys. The HUK could for example be used when deriving keys used in
309secure storage etc. The important thing with the HUK is that it needs to be well
310protected and in the best case the HUK should never ever be readable directly
311from software, not even from the secure side. There are different solutions to
312this, crypto accelerator might have support for it or, it could involve another
313secure co-processor.
314
315In OP-TEE the HUK **is** just **stubbed** and you will see that in the function
316called ``tee_otp_get_hw_unique_key(...)`` in
317`core/include/kernel/tee_common_otp.h`_. In a real secure product you **must**
318replace this with something else. If your device lacks the hardware support for
319a HUK, then you must at least change this to something else than just zeroes.
320But, remember it is not good secure practice to store a key in software,
321especially not the key that is the root for everything else, so this is not
322something we recommend that you should do.
323
324Secure Clock
325************
326The Time API in GlobalPlatform Internal Core API specification defines three
327sources of time; system time, TA persistent time and REE time. The REE time is
328by nature considered as an unsecure source of time, but the other two should in
329a fully trustable hardware make use of trustable source of time, i.e., a secure
330clock. Note that from GlobalPlatform point of view it is not required to make
331use of a secure clock, i.e., it is OK to use time from REE, but the level of
332trust should be reflected by the ``gpd.tee.systemTime.protectionLevel`` property
333and the ``gpd.tee.TAPersistentTime.protectionLevel`` property (100=REE
334controlled clock, 1000=TEE controlled clock). So the functions that one needs to
335pay attention to are ``tee_time_get_sys_time(...)`` and
336``tee_time_get_ta_time(...)``. If your hardware has a secure clock, then you
337probably want to change the implementation there to instead use the secure clock
338(and then you would also need to update the property accordingly, i.e.,
339``tee_time_get_sys_time_protection_level()`` and the variable
340``ta_time_prot_lvl`` in ``tee_svc.c``).
341
342Root and Chain of Trust
343***********************
344To be able to assure that your devices are running the (untampered) binaries you
345intended to run you will need to establish some kind of trust anchor on the
346devices.
347
348The most common way of doing that is to put the root public key in some read
349only memory on the device. Quite often SoC's/OEM's stores public key(s) directly
350or the hash(es) of the public key(s) in OTP_. When the boot ROM (which indeed
351needs to be ROM) is about to load the first stage bootloader it typically reads
352the public key from the software binary itself, hash the key and compare it to
353the key in OTP_. If they are matching, then the boot ROM can be sure that the
354first stage bootloader was indeed signed with the corresponding private key.
355
356In OP-TEE you will not find any code at all related to this and this is a good
357example when it is hard for us to do this in a generic way since device
358manufacturers all tend to do this in their own unique way and they are not very
359keen on sharing their low level boot details and security implementation with
360the rest of the world. This is especially true on ARMv7-A. For ARMv8-A it looks
361bit better, since Arm in Trusted Firmware A have implemented and defined how a
362abstract the chain of trust (see auth-framework.rst_).
363We have successfully verified OP-TEE by using the authentication framework from
364Trusted Firmware A (see :ref:`secure_boot` for the details).
365
366Hardware Crypto IP
367******************
368By default OP-TEE uses a software crypto library (currently mbed TLS and
369LibTomCrypt) and you have the ability to enable Crypto Extensions that were
370introduced with ARMv8-A (if the device is capable of that). Some of the devices
Etienne Carriere68461872023-11-10 10:10:04 +0100371supported in OP-TEE OS repository have hardware crypto capabilities. A
372framework, named drvcrypt has been designed to integrate them. The
373`drvcrypt_register_*()`` API functions allow drivers to register support for
374given cryptographic operations in OP-TEE core crypto API. Our
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200375:ref:`cryptographic_implementation` page describes in detail how the Crypto API
Etienne Carriere68461872023-11-10 10:10:04 +0100376is integrated.
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200377
Donald Chan1f59fae2022-06-15 01:05:35 +0000378Random Number Generator
379***********************
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200380By default OP-TEE is configured with a software PRNG. The entropy is added to
381software PRNG at various places, but unfortunately it is still quite easy to
382predict the data added as entropy. As a consequence, unless the RNG is based on
383hardware the generated random will be quite weak.
384
Donald Chan1f59fae2022-06-15 01:05:35 +0000385If your platform has a hardware entropy source, you should set
386``CFG_WITH_SOFTWARE_PRNG`` to ``n``, and provide an implementation for
387``hw_get_random_bytes()``, which returns multiple bytes of entropy.
388
Etienne Carriere6fede302023-01-20 10:55:54 +0100389When ``CFG_WITH_SOFTWARE_PRNG=n``, the platform can enable a PTA service for
390normal world to retrieve good quality random bytes. See configuration
391switches ``CFG_HWRNG_PTA`` and ``CFG_HWRNG_QUALITY``, from 0 to 1024.
392
393When ``CFG_WITH_SOFTWARE_PRNG=n``, the random number generator is made
394available to OP-TEE drivers and frameworks, including Trusted Applications
395(thoguh GP TEE Internal Core API) and normal world (when ``CFG_HWRNG_PTA=y``).
396
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200397Power Management / PSCI
398***********************
399In the :ref:`add_a_new_platform` section where we talked about the file
400``main.c``, we added a couple of handlers related to power management, we are
401talking about the following lines:
402
403.. code-block:: c
404
405 .cpu_on = cpu_on_handler,
406 .cpu_off = pm_do_nothing,
407 .cpu_suspend = pm_do_nothing,
408 .cpu_resume = pm_do_nothing,
409 .system_off = pm_do_nothing,
410 .system_reset = pm_do_nothing,
411
412The only function that actually does something there is the ``cpu_on`` function,
413the rest of them are stubbed. The main reason for that is because we think that
414how to suspend and resume is a device dependent thing. The code in OP-TEE is
415prepared so that callbacks etc from Trusted Firmware A will be routed to OP-TEE,
416but since the function(s) are just stubbed we will not do anything and just
417return. In a real production device, you would probably want to save and restore
418CPU states, secure hardware IPs' registers and TZASC and other memory firewall
419related setting when these callbacks are being called.
420
421Memory firewalls / TZASC
422************************
423Arm have defined a system IP / SoC peripheral called TrustZone Address Space
424Controller (TZASC, see TZC-380_ and TZC-400_). TZASC can be used to configure
425DDR memory into separate regions in the physcial address space, where each
426region can have an individual security level setting. After enabling TZASC, it
427will perform security checks on transactions to memory or peripherals. It is not
428always the case that TZASC is on a device, in some cases the SoC has developed
429something equivalent. In OP-TEE this is very well reflected, i.e., different
430platforms have different ways of protecting their memory. On ARMv8-A platforms
431we are in most of the cases using Trusted Firmware A as the boot firmware and
432there the secure bootloader is the one that configures secure vs non-secure
433memory using TZASC (see plat_arm_security_setup_ in TF-A). The takeaway here is
434that you must make sure that you have configured whatever memory firewall your
435device has such that it has a secure and a non-secure memory area.
436
437.. _core_pub_priv_keypair:
438
439Trusted Application private/public keypair
440******************************************
441By default all Trusted Applications (TA's) are signed with the pre-generated
4422048-bit RSA development key (private key). This key is located in the ``keys``
443folder (in the root of optee_os.git) and is named ``default_ta.pem``. This key
444**must** be replaced with your own key and you should **never ever** check-in
445this private key in the source code tree when in use in a real product. The
446recommended way to store private keys is to use some kind of HSM_ (Hardware
447Security Module), but an alternative would be temporary put the private key on a
448computer considered as secure when you are about to sign TA's intended to be
449used in real products. Typically it is only a few number of people having access
450to this type of key in company. The key handling in OP-TEE is currently a bit
451limited since we only support a single key which is used for all TA's. We have
452plans on extending this to make it a bit more flexible. Exactly when that will
453happen has not been decided yet.
454
Joakim Bech90b5ca12021-11-18 11:49:48 +0100455.. _platform_ports:
456
457Platform ports
458**************
459OP-TEE is a reference implementation for developers and device manufacturers.
460This also implies that there are certain configurations and settings that cannot
461be done in OP-TEE reference code. In short, there are cases when the default
462configuration hasn't enabled all necessary security features for the end
463product. There are a couple of reasons for that.
464
465- Chipmakers and Semiconductors might only share specifications telling how to
466 securely configure their devices with partners who have signed an NDA with
467 them.
468- In some cases a setting might be perfectly fine when OP-TEE is used in one
469 particular environment, but the same setting might be insecure in another
470 environment.
471
472Because of this we always urge companies and device manufacturers making the end
473product to follow the security guidelines from the chipmaker they are basing
Clement Faure4a1887d2021-11-23 11:43:57 +0100474their products on. Refer also to :ref:`platform_documentation`
Joakim Bech90b5ca12021-11-18 11:49:48 +0100475
476
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200477.. _core/arch/arm/plat-hikey/conf.mk: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-hikey/conf.mk
478.. _core/include/crypto/crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h
479.. _core/include/kernel/tee_common_otp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/kernel/tee_common_otp.h
480
481
Sean Gilligan33633892024-08-20 14:31:55 -0700482.. _auth-framework.rst: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/design/auth-framework.rst
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200483.. _HSM: https://en.wikipedia.org/wiki/Hardware_security_module
484.. _MAINTAINERS.md: https://github.com/OP-TEE/optee_os/blob/master/MAINTAINERS
485.. _OTP: https://en.wikipedia.org/wiki/Programmable_read-only_memory
486.. _plat_arm_security_setup: https://github.com/ARM-software/arm-trusted-firmware/search?utf8=%E2%9C%93&q=plat_arm_security_setup&type=
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200487.. _TZC-380: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0431c/index.html
488.. _TZC-400: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100325_0001_02_en/index.html