blob: 0be444e5bc194f4e9553ee013ea88560a18b2810 [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
56your platform. This mainly comprises two things: - OP-TEE configuration
57variables (``CFG_``), which may be assigned values in two ways. ``CFG_FOO ?=
58bar`` should be used to provide a default value that may be modified at compile
59time. On the other hand, variables that must be set to some value and cannot be
60modified should be set by: ``$(call force,CFG_FOO,bar)``. - Compiler flags for
61the TEE core, the user mode libraries and the Trusted Applications, which may be
62added to macros used by the build system. Please see `Platform-specific
63configuration and flags`_ in the build system documentation.
64
65It is recommended to use a existing platform configuration file as a starting
66point. For instance, `core/arch/arm/plat-hikey/conf.mk`_.
67
68The platform ``conf.mk`` file should at least define the default platform flavor
69for the platform, the core configurations (architecture and number of cores),
70the main configuration directives (generic boot, arm trusted firmware support,
71generic time source, console driver, etc...) and some platform default
72configuration settings.
73
74.. code-block:: make
75
76 PLATFORM_FLAVOR ?= hikey
77
78 include core/arch/arm/cpu/cortex-armv8-0.mk
79
80 $(call force,CFG_TEE_CORE_NB_CORE,8)
81 $(call force,CFG_GENERIC_BOOT,y)
82 $(call force,CFG_PL011,y)
83 $(call force,CFG_PM_STUBS,y)
84 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
85 $(call force,CFG_WITH_ARM_TRUSTED_FW,y)
86 $(call force,CFG_WITH_LPAE,y)
87
88 ta-targets = ta_arm32
89 ta-targets += ta_arm64
90
91 CFG_NUM_THREADS ?= 8
92 CFG_CRYPTO_WITH_CE ?= y
93 CFG_WITH_STACK_CANARIES ?= y
94 CFG_CONSOLE_UART ?= 3
95 CFG_DRAM_SIZE_GB ?= 2
96
97**main.c**
98
99This platform specific file will contain power management handlers and code
100related to the UART. We will talk more about the information related to the
101handlers further down in this document. For our gendev device it could look like
102this (here we are excluding the necessary license header to save some space):
103
104.. code-block:: c
105
106 #include <console.h>
107 #include <drivers/serial8250_uart.h>
108 #include <kernel/generic_boot.h>
109 #include <kernel/panic.h>
110 #include <kernel/pm_stubs.h>
111 #include <mm/core_mmu.h>
112 #include <platform_config.h>
113 #include <stdint.h>
114 #include <tee/entry_fast.h>
115 #include <tee/entry_std.h>
116
117 static void main_fiq(void)
118 {
119 panic();
120 }
121
122 static const struct thread_handlers handlers = {
123 .std_smc = tee_entry_std,
124 .fast_smc = tee_entry_fast,
125 .nintr = main_fiq,
126 .cpu_on = cpu_on_handler,
127 .cpu_off = pm_do_nothing,
128 .cpu_suspend = pm_do_nothing,
129 .cpu_resume = pm_do_nothing,
130 .system_off = pm_do_nothing,
131 .system_reset = pm_do_nothing,
132 };
133
134 const struct thread_handlers *generic_boot_get_handlers(void)
135 {
136 return &handlers;
137 }
138
139 /*
140 * Register the physical memory area for peripherals etc. Here we are
141 * registering the UART console.
142 */
143 register_phys_mem(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, SERIAL8250_UART_REG_SIZE);
144
145 static struct serial8250_uart_data console_data;
146
147 void console_init(void)
148 {
149 serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
150 CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
151 register_serial_console(&console_data.chip);
152 }
153
154**platform_config.h**
155
156This is a mandatory header file for every platform, since there are several
157files relaying upon the existence of this particular file. This file is where
158you will find the major differences between different platforms, since this is
159where you do the memory configuration, define base addresses etc. we are going
160to list a few here, but it probably makes more sense to have a look at the
161already existing ``platform_config.h`` files for the other platforms. Our
162fictive gendev could look like this:
163
164.. code-block:: c
165
166 #ifndef PLATFORM_CONFIG_H
167 #define PLATFORM_CONFIG_H
168
169 /* Make stacks aligned to data cache line length */
170 #define STACK_ALIGNMENT 64
171
172 /* 8250 UART */
173 #define CONSOLE_UART_BASE 0xcafebabe /* UART0 */
174 #define CONSOLE_BAUDRATE 115200
175 #define CONSOLE_UART_CLK_IN_HZ 19200000
176
177 /* Optional: when used with CFG_WITH_PAGER, defines the device SRAM */
178 #define TZSRAM_BASE 0x3F000000
179 #define TZSRAM_SIZE (200 * 1024)
180
181 /* Mandatory main secure RAM usually DDR */
182 #define TZDRAM_BASE 0x60000000
183 #define TZDRAM_SIZE (32 * 1024 * 1024)
184
185 /* Mandatory TEE RAM location and core load address */
186 #define TEE_RAM_START TZDRAM_BASE
187 #define TEE_RAM_PH_SIZE TEE_RAM_VA_SIZE
188 #define TEE_RAM_VA_SIZE (4 * 1024 * 1024)
189 #define TEE_LOAD_ADDR (TZDRAM_BASE + 0x20000)
190
191 /* Mandatory TA RAM (external less secure RAM) */
192 #define TA_RAM_START (TZDRAM_BASE + TEE_RAM_VA_SIZE)
193 #define TA_RAM_SIZE (TZDRAM_SIZE - TEE_RAM_VA_SIZE)
194
195 /* Mandatory: for static SHM, need a hardcoded physical address */
196 #define TEE_SHMEM_START 0x08000000
197 #define TEE_SHMEM_SIZE (4 * 1024 * 1024)
198
199 #endif /* PLATFORM_CONFIG_H */
200
201This is minimal amount of information in the ``platform_config.h`` file. I.e,
202the memory layout for on-chip and external RAM. Note that parts of the DDR
203typically will need to be shared with normal world, so there is need for some
204kind of memory firewall for this (more about that further down). As you can see
205we have also added the UART configuration here, i.e., the ``DEVICE0_xyz`` part.
206
207Official board support in OP-TEE?
208=================================
209We do encourage everyone to submit their board support to the OP-TEE project
210itself, so it becomes part of the official releases and will be maintained by
211the OP-TEE community itself. If you intend to do so, then there are a few more
212things that you are supposed to do.
213
214**Update platforms supported**
215
216There is a section at the :ref:`platforms_supported` page that lists all devices
217officially supported in OP-TEE, that is where you also shall list your device.
218It should contain the name of the platform, then composite ``PLATFORM`` flag and
219whether the device is publicly available or not. If there is a product page on
220the internet for the device, please also create a link when writing the device
221name.
222
223**Update .shippable.yml**
224
225Since we are using Shippable to test pull requests etc, we would like that you
226also add your device to the `.shippable.yml
227<https://github.com/OP-TEE/optee_os/blob/master/.shippable.yml>`_ file, so that
228it will at least be built when someone is doing a pull request. Add a line at
229the end of file:
230
231.. code-block:: xml
232
233 - _make PLATFORM=<platform-name>_
234
235**Maintainer**
236
Joakim Beche58b15c2020-04-15 10:48:41 +0200237If you are submitting the board support upstream we are going to ask you to
238become the maintainer for the device you have added. This means that you should
239also update the MAINTAINERS.md_ file accordingly. By being a maintainer for a
240device you are responsible to keep it up to date and you will be asked every
241quarter as part of the OP-TEE release schedule to test your device running the
242latest OP-TEE software.
Joakim Bech8e5c5b32018-10-25 08:18:32 +0200243
244**Update build.git and manifest.git**
245
246This isn't strictly necessary, but we are trying to create and maintain OP-TEE
247developer builds that should make it easy to setup, build and deploy OP-TEE on
248various devices. We encourage all maintainers to do the same for the boards they
249are in charge of. Therefore please consider creating a new :ref:`manifest` (and
250a new ``*.mk`` in :ref:`build`) for the device you have added to OP-TEE.
251
252.. _hardware_unique_key:
253
254Hardware Unique Key
255*******************
256Most devices have some kind of Hardware Unique Key (HUK) that is mainly used to
257derive other keys. The HUK could for example be used when deriving keys used in
258secure storage etc. The important thing with the HUK is that it needs to be well
259protected and in the best case the HUK should never ever be readable directly
260from software, not even from the secure side. There are different solutions to
261this, crypto accelerator might have support for it or, it could involve another
262secure co-processor.
263
264In OP-TEE the HUK **is** just **stubbed** and you will see that in the function
265called ``tee_otp_get_hw_unique_key(...)`` in
266`core/include/kernel/tee_common_otp.h`_. In a real secure product you **must**
267replace this with something else. If your device lacks the hardware support for
268a HUK, then you must at least change this to something else than just zeroes.
269But, remember it is not good secure practice to store a key in software,
270especially not the key that is the root for everything else, so this is not
271something we recommend that you should do.
272
273Secure Clock
274************
275The Time API in GlobalPlatform Internal Core API specification defines three
276sources of time; system time, TA persistent time and REE time. The REE time is
277by nature considered as an unsecure source of time, but the other two should in
278a fully trustable hardware make use of trustable source of time, i.e., a secure
279clock. Note that from GlobalPlatform point of view it is not required to make
280use of a secure clock, i.e., it is OK to use time from REE, but the level of
281trust should be reflected by the ``gpd.tee.systemTime.protectionLevel`` property
282and the ``gpd.tee.TAPersistentTime.protectionLevel`` property (100=REE
283controlled clock, 1000=TEE controlled clock). So the functions that one needs to
284pay attention to are ``tee_time_get_sys_time(...)`` and
285``tee_time_get_ta_time(...)``. If your hardware has a secure clock, then you
286probably want to change the implementation there to instead use the secure clock
287(and then you would also need to update the property accordingly, i.e.,
288``tee_time_get_sys_time_protection_level()`` and the variable
289``ta_time_prot_lvl`` in ``tee_svc.c``).
290
291Root and Chain of Trust
292***********************
293To be able to assure that your devices are running the (untampered) binaries you
294intended to run you will need to establish some kind of trust anchor on the
295devices.
296
297The most common way of doing that is to put the root public key in some read
298only memory on the device. Quite often SoC's/OEM's stores public key(s) directly
299or the hash(es) of the public key(s) in OTP_. When the boot ROM (which indeed
300needs to be ROM) is about to load the first stage bootloader it typically reads
301the public key from the software binary itself, hash the key and compare it to
302the key in OTP_. If they are matching, then the boot ROM can be sure that the
303first stage bootloader was indeed signed with the corresponding private key.
304
305In OP-TEE you will not find any code at all related to this and this is a good
306example when it is hard for us to do this in a generic way since device
307manufacturers all tend to do this in their own unique way and they are not very
308keen on sharing their low level boot details and security implementation with
309the rest of the world. This is especially true on ARMv7-A. For ARMv8-A it looks
310bit better, since Arm in Trusted Firmware A have implemented and defined how a
311abstract the chain of trust (see auth-framework.rst_).
312We have successfully verified OP-TEE by using the authentication framework from
313Trusted Firmware A (see :ref:`secure_boot` for the details).
314
315Hardware Crypto IP
316******************
317By default OP-TEE uses a software crypto library (currently mbed TLS and
318LibTomCrypt) and you have the ability to enable Crypto Extensions that were
319introduced with ARMv8-A (if the device is capable of that). Some of the devices
320we have in our hands do have hardware crypto IP's, but due to NDA's etc it has
321not been possible to enable it. If you have a device capable of doing crypto
322operations on a dedicated crypto block and you prefer to use that in favor for
323the software implementation, then you will need to implement relevant functions
324defined in `core/include/crypto/crypto.h`_, the Crypto API, and write the low
325level driver that communicates with the device. Our
326:ref:`cryptographic_implementation` page describes in detail how the Crypto API
327is integrated. Since the communication with crypto blocks tends to be quite
328different depending on what kind of crypto IP you have, we have not written
329how that should be done. It might be that we do that in the future when get hold
330of a device where we can use the crypto block.
331
332By default OP-TEE is configured with a software PRNG. The entropy is added to
333software PRNG at various places, but unfortunately it is still quite easy to
334predict the data added as entropy. As a consequence, unless the RNG is based on
335hardware the generated random will be quite weak.
336
337Power Management / PSCI
338***********************
339In the :ref:`add_a_new_platform` section where we talked about the file
340``main.c``, we added a couple of handlers related to power management, we are
341talking about the following lines:
342
343.. code-block:: c
344
345 .cpu_on = cpu_on_handler,
346 .cpu_off = pm_do_nothing,
347 .cpu_suspend = pm_do_nothing,
348 .cpu_resume = pm_do_nothing,
349 .system_off = pm_do_nothing,
350 .system_reset = pm_do_nothing,
351
352The only function that actually does something there is the ``cpu_on`` function,
353the rest of them are stubbed. The main reason for that is because we think that
354how to suspend and resume is a device dependent thing. The code in OP-TEE is
355prepared so that callbacks etc from Trusted Firmware A will be routed to OP-TEE,
356but since the function(s) are just stubbed we will not do anything and just
357return. In a real production device, you would probably want to save and restore
358CPU states, secure hardware IPs' registers and TZASC and other memory firewall
359related setting when these callbacks are being called.
360
361Memory firewalls / TZASC
362************************
363Arm have defined a system IP / SoC peripheral called TrustZone Address Space
364Controller (TZASC, see TZC-380_ and TZC-400_). TZASC can be used to configure
365DDR memory into separate regions in the physcial address space, where each
366region can have an individual security level setting. After enabling TZASC, it
367will perform security checks on transactions to memory or peripherals. It is not
368always the case that TZASC is on a device, in some cases the SoC has developed
369something equivalent. In OP-TEE this is very well reflected, i.e., different
370platforms have different ways of protecting their memory. On ARMv8-A platforms
371we are in most of the cases using Trusted Firmware A as the boot firmware and
372there the secure bootloader is the one that configures secure vs non-secure
373memory using TZASC (see plat_arm_security_setup_ in TF-A). The takeaway here is
374that you must make sure that you have configured whatever memory firewall your
375device has such that it has a secure and a non-secure memory area.
376
377.. _core_pub_priv_keypair:
378
379Trusted Application private/public keypair
380******************************************
381By default all Trusted Applications (TA's) are signed with the pre-generated
3822048-bit RSA development key (private key). This key is located in the ``keys``
383folder (in the root of optee_os.git) and is named ``default_ta.pem``. This key
384**must** be replaced with your own key and you should **never ever** check-in
385this private key in the source code tree when in use in a real product. The
386recommended way to store private keys is to use some kind of HSM_ (Hardware
387Security Module), but an alternative would be temporary put the private key on a
388computer considered as secure when you are about to sign TA's intended to be
389used in real products. Typically it is only a few number of people having access
390to this type of key in company. The key handling in OP-TEE is currently a bit
391limited since we only support a single key which is used for all TA's. We have
392plans on extending this to make it a bit more flexible. Exactly when that will
393happen has not been decided yet.
394
395.. _core/arch/arm/plat-hikey/conf.mk: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-hikey/conf.mk
396.. _core/include/crypto/crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h
397.. _core/include/kernel/tee_common_otp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/kernel/tee_common_otp.h
398
399
400.. _auth-framework.rst: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/auth-framework.rst
401.. _HSM: https://en.wikipedia.org/wiki/Hardware_security_module
402.. _MAINTAINERS.md: https://github.com/OP-TEE/optee_os/blob/master/MAINTAINERS
403.. _OTP: https://en.wikipedia.org/wiki/Programmable_read-only_memory
404.. _plat_arm_security_setup: https://github.com/ARM-software/arm-trusted-firmware/search?utf8=%E2%9C%93&q=plat_arm_security_setup&type=
405.. _Platform-specific configuration and flags: build_system.md#platform-specific-configuration-and-flags
406.. _TZC-380: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0431c/index.html
407.. _TZC-400: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100325_0001_02_en/index.html