blob: 0744064126db82232c871d32a75851eb75adc579 [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
237If you are submitting the board support upstream and cannot give Linaro
238maintainers a device, then we are going to ask you to become the maintainer for
239the device you have added. This means that you should also update the
240MAINTAINERS.md_ file accordingly. By being a maintainer for a device you are
241responsible to keep it up to date and you will be asked every quarter as part of
242the OP-TEE release schedule to test your device running the latest OP-TEE
243software.
244
245**Update build.git and manifest.git**
246
247This isn't strictly necessary, but we are trying to create and maintain OP-TEE
248developer builds that should make it easy to setup, build and deploy OP-TEE on
249various devices. We encourage all maintainers to do the same for the boards they
250are in charge of. Therefore please consider creating a new :ref:`manifest` (and
251a new ``*.mk`` in :ref:`build`) for the device you have added to OP-TEE.
252
253.. _hardware_unique_key:
254
255Hardware Unique Key
256*******************
257Most devices have some kind of Hardware Unique Key (HUK) that is mainly used to
258derive other keys. The HUK could for example be used when deriving keys used in
259secure storage etc. The important thing with the HUK is that it needs to be well
260protected and in the best case the HUK should never ever be readable directly
261from software, not even from the secure side. There are different solutions to
262this, crypto accelerator might have support for it or, it could involve another
263secure co-processor.
264
265In OP-TEE the HUK **is** just **stubbed** and you will see that in the function
266called ``tee_otp_get_hw_unique_key(...)`` in
267`core/include/kernel/tee_common_otp.h`_. In a real secure product you **must**
268replace this with something else. If your device lacks the hardware support for
269a HUK, then you must at least change this to something else than just zeroes.
270But, remember it is not good secure practice to store a key in software,
271especially not the key that is the root for everything else, so this is not
272something we recommend that you should do.
273
274Secure Clock
275************
276The Time API in GlobalPlatform Internal Core API specification defines three
277sources of time; system time, TA persistent time and REE time. The REE time is
278by nature considered as an unsecure source of time, but the other two should in
279a fully trustable hardware make use of trustable source of time, i.e., a secure
280clock. Note that from GlobalPlatform point of view it is not required to make
281use of a secure clock, i.e., it is OK to use time from REE, but the level of
282trust should be reflected by the ``gpd.tee.systemTime.protectionLevel`` property
283and the ``gpd.tee.TAPersistentTime.protectionLevel`` property (100=REE
284controlled clock, 1000=TEE controlled clock). So the functions that one needs to
285pay attention to are ``tee_time_get_sys_time(...)`` and
286``tee_time_get_ta_time(...)``. If your hardware has a secure clock, then you
287probably want to change the implementation there to instead use the secure clock
288(and then you would also need to update the property accordingly, i.e.,
289``tee_time_get_sys_time_protection_level()`` and the variable
290``ta_time_prot_lvl`` in ``tee_svc.c``).
291
292Root and Chain of Trust
293***********************
294To be able to assure that your devices are running the (untampered) binaries you
295intended to run you will need to establish some kind of trust anchor on the
296devices.
297
298The most common way of doing that is to put the root public key in some read
299only memory on the device. Quite often SoC's/OEM's stores public key(s) directly
300or the hash(es) of the public key(s) in OTP_. When the boot ROM (which indeed
301needs to be ROM) is about to load the first stage bootloader it typically reads
302the public key from the software binary itself, hash the key and compare it to
303the key in OTP_. If they are matching, then the boot ROM can be sure that the
304first stage bootloader was indeed signed with the corresponding private key.
305
306In OP-TEE you will not find any code at all related to this and this is a good
307example when it is hard for us to do this in a generic way since device
308manufacturers all tend to do this in their own unique way and they are not very
309keen on sharing their low level boot details and security implementation with
310the rest of the world. This is especially true on ARMv7-A. For ARMv8-A it looks
311bit better, since Arm in Trusted Firmware A have implemented and defined how a
312abstract the chain of trust (see auth-framework.rst_).
313We have successfully verified OP-TEE by using the authentication framework from
314Trusted Firmware A (see :ref:`secure_boot` for the details).
315
316Hardware Crypto IP
317******************
318By default OP-TEE uses a software crypto library (currently mbed TLS and
319LibTomCrypt) and you have the ability to enable Crypto Extensions that were
320introduced with ARMv8-A (if the device is capable of that). Some of the devices
321we have in our hands do have hardware crypto IP's, but due to NDA's etc it has
322not been possible to enable it. If you have a device capable of doing crypto
323operations on a dedicated crypto block and you prefer to use that in favor for
324the software implementation, then you will need to implement relevant functions
325defined in `core/include/crypto/crypto.h`_, the Crypto API, and write the low
326level driver that communicates with the device. Our
327:ref:`cryptographic_implementation` page describes in detail how the Crypto API
328is integrated. Since the communication with crypto blocks tends to be quite
329different depending on what kind of crypto IP you have, we have not written
330how that should be done. It might be that we do that in the future when get hold
331of a device where we can use the crypto block.
332
333By default OP-TEE is configured with a software PRNG. The entropy is added to
334software PRNG at various places, but unfortunately it is still quite easy to
335predict the data added as entropy. As a consequence, unless the RNG is based on
336hardware the generated random will be quite weak.
337
338Power Management / PSCI
339***********************
340In the :ref:`add_a_new_platform` section where we talked about the file
341``main.c``, we added a couple of handlers related to power management, we are
342talking about the following lines:
343
344.. code-block:: c
345
346 .cpu_on = cpu_on_handler,
347 .cpu_off = pm_do_nothing,
348 .cpu_suspend = pm_do_nothing,
349 .cpu_resume = pm_do_nothing,
350 .system_off = pm_do_nothing,
351 .system_reset = pm_do_nothing,
352
353The only function that actually does something there is the ``cpu_on`` function,
354the rest of them are stubbed. The main reason for that is because we think that
355how to suspend and resume is a device dependent thing. The code in OP-TEE is
356prepared so that callbacks etc from Trusted Firmware A will be routed to OP-TEE,
357but since the function(s) are just stubbed we will not do anything and just
358return. In a real production device, you would probably want to save and restore
359CPU states, secure hardware IPs' registers and TZASC and other memory firewall
360related setting when these callbacks are being called.
361
362Memory firewalls / TZASC
363************************
364Arm have defined a system IP / SoC peripheral called TrustZone Address Space
365Controller (TZASC, see TZC-380_ and TZC-400_). TZASC can be used to configure
366DDR memory into separate regions in the physcial address space, where each
367region can have an individual security level setting. After enabling TZASC, it
368will perform security checks on transactions to memory or peripherals. It is not
369always the case that TZASC is on a device, in some cases the SoC has developed
370something equivalent. In OP-TEE this is very well reflected, i.e., different
371platforms have different ways of protecting their memory. On ARMv8-A platforms
372we are in most of the cases using Trusted Firmware A as the boot firmware and
373there the secure bootloader is the one that configures secure vs non-secure
374memory using TZASC (see plat_arm_security_setup_ in TF-A). The takeaway here is
375that you must make sure that you have configured whatever memory firewall your
376device has such that it has a secure and a non-secure memory area.
377
378.. _core_pub_priv_keypair:
379
380Trusted Application private/public keypair
381******************************************
382By default all Trusted Applications (TA's) are signed with the pre-generated
3832048-bit RSA development key (private key). This key is located in the ``keys``
384folder (in the root of optee_os.git) and is named ``default_ta.pem``. This key
385**must** be replaced with your own key and you should **never ever** check-in
386this private key in the source code tree when in use in a real product. The
387recommended way to store private keys is to use some kind of HSM_ (Hardware
388Security Module), but an alternative would be temporary put the private key on a
389computer considered as secure when you are about to sign TA's intended to be
390used in real products. Typically it is only a few number of people having access
391to this type of key in company. The key handling in OP-TEE is currently a bit
392limited since we only support a single key which is used for all TA's. We have
393plans on extending this to make it a bit more flexible. Exactly when that will
394happen has not been decided yet.
395
396.. _core/arch/arm/plat-hikey/conf.mk: https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/plat-hikey/conf.mk
397.. _core/include/crypto/crypto.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/crypto/crypto.h
398.. _core/include/kernel/tee_common_otp.h: https://github.com/OP-TEE/optee_os/blob/master/core/include/kernel/tee_common_otp.h
399
400
401.. _auth-framework.rst: https://github.com/ARM-software/arm-trusted-firmware/blob/master/docs/auth-framework.rst
402.. _HSM: https://en.wikipedia.org/wiki/Hardware_security_module
403.. _MAINTAINERS.md: https://github.com/OP-TEE/optee_os/blob/master/MAINTAINERS
404.. _OTP: https://en.wikipedia.org/wiki/Programmable_read-only_memory
405.. _plat_arm_security_setup: https://github.com/ARM-software/arm-trusted-firmware/search?utf8=%E2%9C%93&q=plat_arm_security_setup&type=
406.. _Platform-specific configuration and flags: build_system.md#platform-specific-configuration-and-flags
407.. _TZC-380: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0431c/index.html
408.. _TZC-400: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100325_0001_02_en/index.html