diff options
-rw-r--r-- | arch/arm/dts/k3-binman.dtsi | 49 | ||||
-rw-r--r-- | arch/arm/dts/k3-j7200-binman.dtsi | 90 | ||||
-rw-r--r-- | arch/arm/dts/k3-j721e-binman.dtsi | 116 | ||||
-rw-r--r-- | arch/arm/dts/k3-j721s2-binman.dtsi | 123 | ||||
-rw-r--r-- | arch/arm/dts/k3-security.h | 58 | ||||
-rw-r--r-- | doc/board/ti/k3.rst | 313 | ||||
-rw-r--r-- | tools/binman/btool/openssl.py | 16 | ||||
-rw-r--r-- | tools/binman/etype/ti_secure.py | 95 | ||||
-rw-r--r-- | tools/binman/etype/x509_cert.py | 4 | ||||
-rw-r--r-- | tools/binman/ftest.py | 23 | ||||
-rw-r--r-- | tools/binman/test/324_ti_secure_firewall.dts | 28 | ||||
-rw-r--r-- | tools/binman/test/325_ti_secure_firewall_missing_property.dts | 28 | ||||
-rw-r--r-- | tools/dtoc/fdt.py | 2 |
13 files changed, 842 insertions, 103 deletions
diff --git a/arch/arm/dts/k3-binman.dtsi b/arch/arm/dts/k3-binman.dtsi index cd9926a016..758c8bf6ea 100644 --- a/arch/arm/dts/k3-binman.dtsi +++ b/arch/arm/dts/k3-binman.dtsi @@ -3,6 +3,8 @@ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/ */ +#include "k3-security.h" + / { binman: binman { multiple-images; @@ -437,6 +439,53 @@ }; }; }; + firewall_bg_1: template-5 { + control = <(FWCTRL_EN | FWCTRL_LOCK | + FWCTRL_BG | FWCTRL_CACHE)>; + permissions = <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>; + start_address = <0x0 0x0>; + end_address = <0xff 0xffffffff>; + }; + firewall_bg_3: template-6 { + insert-template = <&firewall_bg_1>; + permissions = <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>, + <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>, + <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>; + }; + firewall_armv8_atf_fg: template-7 { + control = <(FWCTRL_EN | FWCTRL_LOCK | + FWCTRL_CACHE)>; + permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD)>; + start_address = <0x0 0x70000000>; + end_address = <0x0 0x7001ffff>; + }; + firewall_armv8_optee_fg: template-8 { + control = <(FWCTRL_EN | FWCTRL_LOCK | + FWCTRL_CACHE)>; + permissions = <((FWPRIVID_ARMV8 << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD)>; + start_address = <0x0 0x9e800000>; + end_address = <0x0 0x9fffffff>; + }; }; diff --git a/arch/arm/dts/k3-j7200-binman.dtsi b/arch/arm/dts/k3-j7200-binman.dtsi index 38cccabaa7..06db865987 100644 --- a/arch/arm/dts/k3-j7200-binman.dtsi +++ b/arch/arm/dts/k3-j7200-binman.dtsi @@ -195,6 +195,96 @@ fit { images { + atf { + ti-secure { + auth-in-place = <0xa02>; + + firewall-257-0 { + /* cpu_0_cpu_0_msmc Background Firewall */ + insert-template = <&firewall_bg_1>; + id = <257>; + region = <0>; + }; + + firewall-257-1 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <257>; + region = <1>; + }; + + /* firewall-4760-0 { + * nb_slv0__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-4760-1 { + /* nb_slv0__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <4760>; + region = <1>; + }; + + /* firewall-4761-0 { + * nb_slv1__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-4761-1 { + /* nb_slv1__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <4761>; + region = <1>; + }; + }; + }; + + tee { + ti-secure { + auth-in-place = <0xa02>; + + /* cpu_0_cpu_0_msmc region 0 and 1 configured + * during ATF Firewalling + */ + + firewall-257-2 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <257>; + region = <2>; + }; + + firewall-4762-0 { + /* nb_slv2__mem0 Background Firewall - 0 */ + insert-template = <&firewall_bg_3>; + id = <4762>; + region = <0>; + }; + + firewall-4762-1 { + /* nb_slv2__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <4762>; + region = <1>; + }; + + firewall-4763-0 { + /* nb_slv3__mem0 Background Firewall - 0 */ + insert-template = <&firewall_bg_3>; + id = <4763>; + region = <0>; + }; + + firewall-4763-1 { + /* nb_slv3__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <4763>; + region = <1>; + }; + }; + }; dm { ti-secure { content = <&dm>; diff --git a/arch/arm/dts/k3-j721e-binman.dtsi b/arch/arm/dts/k3-j721e-binman.dtsi index dbc385a852..1bd9f96a58 100644 --- a/arch/arm/dts/k3-j721e-binman.dtsi +++ b/arch/arm/dts/k3-j721e-binman.dtsi @@ -146,6 +146,122 @@ fit { images { + atf { + ti-secure { + auth-in-place = <0xa02>; + + firewall-257-0 { + /* cpu_0_cpu_0_msmc Background Firewall */ + insert-template = <&firewall_bg_1>; + id = <257>; + region = <0>; + }; + + firewall-257-1 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <257>; + region = <1>; + }; + + firewall-284-0 { + /* dru_0_msmc Background Firewall */ + insert-template = <&firewall_bg_3>; + id = <284>; + region = <0>; + }; + + firewall-284-1 { + /* dru_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <284>; + region = <1>; + }; + + /* firewall-4760-0 { + * nb_slv0__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-4760-1 { + /* nb_slv0__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <4760>; + region = <1>; + }; + + /* firewall-4761-0 { + * nb_slv1__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-4761-1 { + /* nb_slv1__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <4761>; + region = <1>; + }; + + }; + }; + + tee { + ti-secure { + auth-in-place = <0xa02>; + + /* cpu_0_cpu_0_msmc region 0 and 1 configured + * during ATF Firewalling + */ + + firewall-257-2 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <257>; + region = <2>; + }; + + /* dru_0_msmc region 0 and 1 configured + * during ATF Firewalling + */ + + firewall-284-2 { + /* dru_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <284>; + region = <2>; + }; + + firewall-4762-0 { + /* nb_slv2__mem0 Background Firewall */ + insert-template = <&firewall_bg_3>; + id = <4762>; + region = <0>; + }; + + firewall-4762-1 { + /* nb_slv2__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <4762>; + region = <1>; + }; + + firewall-4763-0 { + /* nb_slv3__mem0 Background Firewall */ + insert-template = <&firewall_bg_3>; + id = <4763>; + region = <0>; + }; + + firewall-4763-1 { + /* nb_slv3__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <4763>; + region = <1>; + }; + }; + }; dm { ti-secure { content = <&dm>; diff --git a/arch/arm/dts/k3-j721s2-binman.dtsi b/arch/arm/dts/k3-j721s2-binman.dtsi index f17dd8e04c..7efb135bdf 100644 --- a/arch/arm/dts/k3-j721s2-binman.dtsi +++ b/arch/arm/dts/k3-j721s2-binman.dtsi @@ -159,6 +159,129 @@ fit { images { + atf { + ti-secure { + auth-in-place = <0xa02>; + + firewall-257-0 { + /* cpu_0_cpu_0_msmc Background Firewall */ + insert-template = <&firewall_bg_1>; + id = <257>; + region = <0>; + }; + + firewall-257-1 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <257>; + region = <1>; + }; + + firewall-284-0 { + /* dru_0_msmc Background Firewall */ + insert-template = <&firewall_bg_3>; + id = <284>; + region = <0>; + }; + + firewall-284-1 { + /* dru_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <284>; + region = <1>; + }; + + /* firewall-5140-0 { + * nb_slv0__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-5140-1 { + /* nb_slv0__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <5140>; + region = <1>; + }; + + /* firewall-5140-0 { + * nb_slv1__mem0 Background Firewall + * Already configured by the secure entity + * }; + */ + + firewall-5141-1 { + /* nb_slv1__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_atf_fg>; + id = <5141>; + region = <1>; + }; + + }; + }; + + tee { + ti-secure { + auth-in-place = <0xa02>; + + firewall-257-2 { + /* cpu_0_cpu_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <257>; + region = <2>; + }; + + firewall-284-2 { + /* dru_0_msmc Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <284>; + region = <2>; + }; + + firewall-5142-0 { + /* nb_slv2__mem0 Background Firewall - 0 */ + insert-template = <&firewall_bg_3>; + id = <5142>; + region = <0>; + }; + + firewall-5142-1 { + /* nb_slv2__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <5142>; + region = <1>; + }; + + firewall-5143-0 { + /* nb_slv3__mem0 Background Firewall - 0 */ + insert-template = <&firewall_bg_3>; + id = <5143>; + region = <0>; + }; + + firewall-5143-1 { + /* nb_slv3__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <5143>; + region = <1>; + }; + + firewall-5144-0 { + /* nb_slv4__mem0 Background Firewall - 0 */ + insert-template = <&firewall_bg_3>; + id = <5144>; + region = <0>; + }; + + firewall-5144-1 { + /* nb_slv4__mem0 Foreground Firewall */ + insert-template = <&firewall_armv8_optee_fg>; + id = <5144>; + region = <1>; + }; + + }; + }; dm { ti-secure { content = <&dm>; diff --git a/arch/arm/dts/k3-security.h b/arch/arm/dts/k3-security.h new file mode 100644 index 0000000000..33609caa8f --- /dev/null +++ b/arch/arm/dts/k3-security.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/ + */ + +#ifndef DTS_ARM64_TI_K3_FIREWALL_H +#define DTS_ARM64_TI_K3_FIREWALL_H + +#define FWPRIVID_ALL 0xc3 +#define FWPRIVID_ARMV8 1 +#define FWPRIVID_SHIFT 16 + +#define FWCTRL_EN 0xA +#define FWCTRL_LOCK (1 << 4) +#define FWCTRL_BG (1 << 8) +#define FWCTRL_CACHE (1 << 9) + +#define FWPERM_SECURE_PRIV_WRITE (1 << 0) +#define FWPERM_SECURE_PRIV_READ (1 << 1) +#define FWPERM_SECURE_PRIV_CACHEABLE (1 << 2) +#define FWPERM_SECURE_PRIV_DEBUG (1 << 3) + +#define FWPERM_SECURE_PRIV_RWCD (FWPERM_SECURE_PRIV_READ | \ + FWPERM_SECURE_PRIV_WRITE | \ + FWPERM_SECURE_PRIV_CACHEABLE | \ + FWPERM_SECURE_PRIV_DEBUG) + +#define FWPERM_SECURE_USER_WRITE (1 << 4) +#define FWPERM_SECURE_USER_READ (1 << 5) +#define FWPERM_SECURE_USER_CACHEABLE (1 << 6) +#define FWPERM_SECURE_USER_DEBUG (1 << 7) + +#define FWPERM_SECURE_USER_RWCD (FWPERM_SECURE_USER_READ | \ + FWPERM_SECURE_USER_WRITE | \ + FWPERM_SECURE_USER_CACHEABLE | \ + FWPERM_SECURE_USER_DEBUG) + +#define FWPERM_NON_SECURE_PRIV_WRITE (1 << 8) +#define FWPERM_NON_SECURE_PRIV_READ (1 << 9) +#define FWPERM_NON_SECURE_PRIV_CACHEABLE (1 << 10) +#define FWPERM_NON_SECURE_PRIV_DEBUG (1 << 11) + +#define FWPERM_NON_SECURE_PRIV_RWCD (FWPERM_NON_SECURE_PRIV_READ | \ + FWPERM_NON_SECURE_PRIV_WRITE | \ + FWPERM_NON_SECURE_PRIV_CACHEABLE | \ + FWPERM_NON_SECURE_PRIV_DEBUG) + +#define FWPERM_NON_SECURE_USER_WRITE (1 << 12) +#define FWPERM_NON_SECURE_USER_READ (1 << 13) +#define FWPERM_NON_SECURE_USER_CACHEABLE (1 << 14) +#define FWPERM_NON_SECURE_USER_DEBUG (1 << 15) + +#define FWPERM_NON_SECURE_USER_RWCD (FWPERM_NON_SECURE_USER_READ | \ + FWPERM_NON_SECURE_USER_WRITE | \ + FWPERM_NON_SECURE_USER_CACHEABLE | \ + FWPERM_NON_SECURE_USER_DEBUG) + +#endif diff --git a/doc/board/ti/k3.rst b/doc/board/ti/k3.rst index f19ee56f29..7dfe39c5fa 100644 --- a/doc/board/ti/k3.rst +++ b/doc/board/ti/k3.rst @@ -104,6 +104,49 @@ firmware can be loaded on the now free core in the wakeup domain. For more information on the bootup process of your SoC, consult the device specific boot flow documentation. +Secure Boot +----------- + +K3 HS-SE (High Security - Security Enforced) devices enforce an +authenticated boot flow for secure boot. HS-FS (High Security - Field +Securable) is the state of a K3 device before it has been eFused with +customer security keys. In the HS-FS state the authentication still can +function as in HS-SE but as there are no customer keys to verify the +signatures against the authentication will pass for certificates signed +with any key. + +Chain of trust +^^^^^^^^^^^^^^ + +1) Public ROM loads the tiboot3.bin (R5 SPL, TIFS) +2) R5 SPL loads tispl.bin (ATF, OP-TEE, DM, SPL) +3) SPL loads u-boot.img (U-Boot) +4) U-Boot loads fitImage (Linux and DTBs) + +Steps 1-3 are all authenticated by either the Secure ROM or TIFS as the +authenticating entity and step 4 uses U-boot standard mechanism for +authenticating. + +All the authentication that are done for ROM/TIFS are done through x509 +certificates that are signed. + +Firewalls +^^^^^^^^^ + +1) Secure ROM comes up and sets up firewalls that are needed by itself +2) TIFS will setup it's own firewalls to protect core system resources +3) R5 SPL will remove any firewalls that are leftover from the Secure ROM stage + that are no longer required. +4) Each stage beyond this: such as tispl.bin containing TFA/OPTEE uses OIDs to + set up firewalls to protect themselves (enforced by TIFS) +5) TFA/OP-TEE can configure other firewalls at runtime if required as they + are already authenticated and firewalled off from illegal access. +6) All later stages can setup or remove firewalls that have not been already + configured by previous stages, such as those created by TIFS, TFA, and OP-TEE. + +Futhur, firewalls have a lockdown bit in hardware that enforces the setting +(and cannot be over-ridden) until the full system is reset. + Software Sources ---------------- @@ -248,6 +291,8 @@ Building tiboot3.bin the final `tiboot3.bin` binary. (or the `sysfw.itb` if your device uses the split binary flow) +.. _k3_rst_include_start_build_steps_spl_r5: + .. k3_rst_include_start_build_steps_spl_r5 .. prompt:: bash $ @@ -312,6 +357,8 @@ use the `lite` option. finished, we can jump back into U-Boot again, this time running on a 64bit core in the main domain. +.. _k3_rst_include_start_build_steps_uboot: + .. k3_rst_include_start_build_steps_uboot .. prompt:: bash $ @@ -337,144 +384,212 @@ wakeup and main domain and to boot to the U-Boot prompt | `tispl.bin` for HS devices or `tispl.bin_unsigned` for GP devices | `u-boot.img` for HS devices or `u-boot.img_unsigned` for GP devices -Fit Signature Signing +FIT signature signing --------------------- -K3 Platforms have fit signature signing enabled by default on their primary -platforms. Here we'll take an example for creating fit image for J721e platform +K3 platforms have FIT signature signing enabled by default on their primary +platforms. Here we'll take an example for creating FIT Image for J721E platform and the same can be extended to other platforms -1. Describing FIT source +Pre-requisites: + +* U-boot build (:ref:`U-boot build <k3_rst_include_start_build_steps_spl_r5>`) +* Linux Image and Linux DTB prebuilt - .. code-block:: bash +Describing FIT source +^^^^^^^^^^^^^^^^^^^^^ + +FIT Image is a packed structure containing binary blobs and configurations. +The Kernel FIT Image that we have has Kernel Image, DTB and the DTBOs. It +supports packing multiple images and configurations that allow you to +choose any configuration at runtime to boot from. + +.. code-block:: /dts-v1/; / { - description = "Kernel fitImage for j721e-hs-evm"; - #address-cells = <1>; - - images { - kernel-1 { - description = "Linux kernel"; - data = /incbin/("Image"); - type = "kernel"; - arch = "arm64"; - os = "linux"; - compression = "none"; - load = <0x80080000>; - entry = <0x80080000>; - hash-1 { - algo = "sha512"; - }; - - }; - fdt-ti_k3-j721e-common-proc-board.dtb { - description = "Flattened Device Tree blob"; - data = /incbin/("k3-j721e-common-proc-board.dtb"); - type = "flat_dt"; - arch = "arm64"; - compression = "none"; - load = <0x83000000>; - hash-1 { - algo = "sha512"; - }; - - }; + description = "FIT Image description"; + #address-cells = <1>; + + images { + [image-1] + [image-2] + [fdt-1] + [fdt-2] + } + + configurations { + default = <conf-1> + [conf-1: image-1,fdt-1] + [conf-2: image-2,fdt-1] + } + } + +* Sample Images + +.. code-block:: + + kernel-1 { + description = "Linux kernel"; + data = /incbin/("linux.bin"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "gzip"; + load = <0x81000000>; + entry = <0x81000000>; + hash-1 { + algo = "sha512"; }; - - configurations { - default = "conf-ti_k3-j721e-common-proc-board.dtb"; - conf-ti_k3-j721e-common-proc-board.dtb { - description = "Linux kernel, FDT blob"; - fdt = "fdt-ti_k3-j721e-common-proc-board.dtb"; - kernel = "kernel-1"; - signature-1 { - algo = "sha512,rsa4096"; - key-name-hint = "custMpk"; - sign-images = "kernel", "fdt"; - }; - }; + }; + fdt-ti_k3-j721e-common-proc-board.dtb { + description = "Flattened Device Tree blob"; + data = /incbin/("arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x83000000>; + hash-1 { + algo = "sha512"; + }; + }; + # Optional images + fdt-ti_k3-j721e-evm-virt-mac-client.dtbo { + description = "Flattened Device Tree blob"; + data = /incbin/("arch/arm64/boot/dts/ti/k3-j721e-evm-virt-mac-client.dtbo"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x83080000>; + hash-1 { + algo = "sha512"; }; }; - You would require to change the '/incbin/' lines to point to the respective - files in your local machine and the key-name-hint also needs to be changed - if you are using some other key other than the TI dummy key that we are - using for this example. +.. note:: + + Change the path in data variables to point to the respective files in your + local machine. For e.g change "linux.bin" to "<path-to-kernel-image>". + +For enabling usage of FIT signature, add the signature node to the +corresponding configuration node as follows. -2. Compile U-boot for the respective board +* Sample Configurations -.. include:: k3.rst - :start-after: .. k3_rst_include_start_build_steps_uboot - :end-before: .. k3_rst_include_end_build_steps_uboot +.. code-block:: + + conf-ti_k3-j721e-common-proc-board.dtb { + description = "Linux kernel, FDT blob"; + fdt = "fdt-ti_k3-j721e-common-proc-board.dtb"; + kernel = "kernel-1"; + signature-1 { + algo = "sha512,rsa4096"; + key-name-hint = "custMpk"; + sign-images = "kernel", "fdt"; + }; + }; + # Optional configurations + conf-ti_k3-j721e-evm-virt-mac-client.dtbo { + description = "FDTO blob"; + fdt = "fdt-ti_k3-j721e-evm-virt-mac-client.dtbo"; + + signature-1 { + algo = "sha512,rsa4096"; + key-name-hint = "custMpk"; + sign-images = "fdt"; + }; + }; + +Specify all images you need the signature to authenticate as a part of +sign-images. The key-name-hint needs to be changed if you are using some +other key other than the TI dummy key that we are using for this example. +It should be the name of the file containing the keys. .. note:: - The changes only affect a72 binaries so the example just builds that + Generating new set of keys: -3. Sign the fit image and embed the dtb in uboot + .. prompt:: bash $ - Now once the build is done, you'll have a dtb for your board that you'll - be passing to mkimage for signing the fitImage and embedding the key in - the u-boot dtb. + mkdir keys + openssl genpkey -algorithm RSA -out keys/dev.key \ + -pkeyopt rsa_keygen_bits:4096 -pkeyopt rsa_keygen_pubexp:65537 + openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt - .. prompt:: bash $ +Generating the fitImage +^^^^^^^^^^^^^^^^^^^^^^^ - mkimage -r -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K - $UBOOT_PATH/build/a72/dts/dt.dtb +.. note:: - For signing a secondary platform, pass the -K parameter to that DTB + For signing a secondary platform like SK boards, you'll require + additional steps - .. prompt:: bash $ + - Change the CONFIG_DEFAULT_DEVICE_TREE - mkimage -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K - $UBOOT_PATH/build/a72/arch/arm/dts/k3-j721e-sk.dtb + For e.g - .. note:: + .. code-block:: - If changing `CONFIG_DEFAULT_DEVICE_TREE` to the secondary platform, - binman changes would also be required so that correct dtb gets packaged. + diff --git a/configs/j721e_evm_a72_defconfig b/configs/j721e_evm_a72_defconfig + index a5c1df7e0054..6d0126d955ef 100644 + --- a/configs/j721e_evm_a72_defconfig + +++ b/configs/j721e_evm_a72_defconfig + @@ -13,7 +13,7 @@ CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0x80480000 + CONFIG_ENV_SIZE=0x20000 + CONFIG_DM_GPIO=y + CONFIG_SPL_DM_SPI=y + -CONFIG_DEFAULT_DEVICE_TREE="k3-j721e-common-proc-board" + +CONFIG_DEFAULT_DEVICE_TREE="k3-j721e-sk" + CONFIG_SPL_TEXT_BASE=0x80080000 + CONFIG_DM_RESET=y + CONFIG_SPL_MMC=y - .. code-block:: bash + - Change the binman nodes to package u-boot.dtb for the correct set of platform - diff --git a/arch/arm/dts/k3-j721e-binman.dtsi b/arch/arm/dts/k3-j721e-binman.dtsi - index 673be646b1e3..752fa805fe8d 100644 - --- a/arch/arm/dts/k3-j721e-binman.dtsi - +++ b/arch/arm/dts/k3-j721e-binman.dtsi - @@ -299,8 +299,8 @@ - #define SPL_J721E_SK_DTB "spl/dts/k3-j721e-sk.dtb" + For e.g - #define UBOOT_NODTB "u-boot-nodtb.bin" - -#define J721E_EVM_DTB "u-boot.dtb" - -#define J721E_SK_DTB "arch/arm/dts/k3-j721e-sk.dtb" - +#define J721E_EVM_DTB "arch/arm/dts/k3-j721e-common-proc-board.dtb" - +#define J721E_SK_DTB "u-boot.dtb" + .. code-block:: -5. Rebuilt u-boot + diff --git a/arch/arm/dts/k3-j721e-binman.dtsi b/arch/arm/dts/k3-j721e-binman.dtsi + index 673be646b1e3..752fa805fe8d 100644 + --- a/arch/arm/dts/k3-j721e-binman.dtsi + +++ b/arch/arm/dts/k3-j721e-binman.dtsi + @@ -299,8 +299,8 @@ + #define SPL_J721E_SK_DTB "spl/dts/k3-j721e-sk.dtb" - This is required so that the modified dtb gets updated in u-boot.img + #define UBOOT_NODTB "u-boot-nodtb.bin" + -#define J721E_EVM_DTB "u-boot.dtb" + -#define J721E_SK_DTB "arch/arm/dts/k3-j721e-sk.dtb" + +#define J721E_EVM_DTB "arch/arm/dts/k3-j721e-common-proc-board.dtb" + +#define J721E_SK_DTB "u-boot.dtb" -.. include:: k3.rst - :start-after: .. k3_rst_include_start_build_steps_uboot - :end-before: .. k3_rst_include_end_build_steps_uboot +This step will embed the public key in the u-boot.dtb file that was already +built during the initial u-boot build. -6. (Optional) Enabled FIT_SIGNATURE_ENFORCED +.. prompt:: bash $ + + mkimage -r -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K $UBOOT_PATH/build/$ARMV8/dts/dt.dtb fitImage + +.. note:: + + If you have another set of keys then change the -k argument to point to + the folder where your keys are present, the build requires the presence + of both .key and .crt file. - By default u-boot will boot up the fit image without any authentication as - such if the public key is not embedded properly, to check if the public key - nodes are proper you can enable FIT_SIGNATURE_ENFORCED that would not rely - on the dtb for anything else then the signature node for checking the fit - image, rest other things will be enforced such as the property of - required-keys. This is not an extensive check so do manual checks also +Build u-boot again +^^^^^^^^^^^^^^^^^^ - This is by default enabled for devices with TI_SECURE_DEVICE enabled. +The updated u-boot.dtb needs to be packed in u-boot.img for authentication +so rebuild U-boot ARMV8 without changing any parameters. +Refer (:ref:`U-boot ARMV8 build <k3_rst_include_start_build_steps_uboot>`) .. note:: - The devices now also have distroboot enabled so if the fit image doesn't - work then the fallback to normal distroboot will be there on hs devices, - this will need to be explicitly disabled by changing the boot_targets. + The devices now also have distroboot enabled so if the FIT image doesn't + work then the fallback to normal distroboot will be there on HS devices. + This will need to be explicitly disabled by changing the boot_targets to + disallow fallback during testing. Saving environment ------------------ diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py index 7ee2683ab2..fe81a1f51b 100644 --- a/tools/binman/btool/openssl.py +++ b/tools/binman/btool/openssl.py @@ -82,7 +82,7 @@ imageSize = INTEGER:{len(indata)} return self.run_cmd(*args) def x509_cert_sysfw(self, cert_fname, input_fname, key_fname, sw_rev, - config_fname, req_dist_name_dict): + config_fname, req_dist_name_dict, firewall_cert_data): """Create a certificate to be booted by system firmware Args: @@ -94,6 +94,13 @@ imageSize = INTEGER:{len(indata)} req_dist_name_dict (dict): Dictionary containing key-value pairs of req_distinguished_name section extensions, must contain extensions for C, ST, L, O, OU, CN and emailAddress + firewall_cert_data (dict): + - auth_in_place (int): The Priv ID for copying as the + specific host in firewall protected region + - num_firewalls (int): The number of firewalls in the + extended certificate + - certificate (str): Extended firewall certificate with + the information for the firewall configurations. Returns: str: Tool output @@ -121,6 +128,7 @@ basicConstraints = CA:true 1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv 1.3.6.1.4.1.294.1.34 = ASN1:SEQUENCE:sysfw_image_integrity 1.3.6.1.4.1.294.1.35 = ASN1:SEQUENCE:sysfw_image_load +1.3.6.1.4.1.294.1.37 = ASN1:SEQUENCE:firewall [ swrv ] swrv = INTEGER:{sw_rev} @@ -132,7 +140,11 @@ imageSize = INTEGER:{len(indata)} [ sysfw_image_load ] destAddr = FORMAT:HEX,OCT:00000000 -authInPlace = INTEGER:2 +authInPlace = INTEGER:{hex(firewall_cert_data['auth_in_place'])} + +[ firewall ] +numFirewallRegions = INTEGER:{firewall_cert_data['num_firewalls']} +{firewall_cert_data['certificate']} ''', file=outf) args = ['req', '-new', '-x509', '-key', key_fname, '-nodes', '-outform', 'DER', '-out', cert_fname, '-config', config_fname, diff --git a/tools/binman/etype/ti_secure.py b/tools/binman/etype/ti_secure.py index d939dce571..704dcf8a38 100644 --- a/tools/binman/etype/ti_secure.py +++ b/tools/binman/etype/ti_secure.py @@ -7,9 +7,44 @@ from binman.entry import EntryArg from binman.etype.x509_cert import Entry_x509_cert +from dataclasses import dataclass from dtoc import fdt_util +@dataclass +class Firewall(): + id: int + region: int + control : int + permissions: list + start_address: str + end_address: str + + def ensure_props(self, etype, name): + missing_props = [] + for key, val in self.__dict__.items(): + if val is None: + missing_props += [key] + + if len(missing_props): + etype.Raise(f"Subnode '{name}' is missing properties: {','.join(missing_props)}") + + def get_certificate(self) -> str: + unique_identifier = f"{self.id}{self.region}" + cert = f""" +firewallID{unique_identifier} = INTEGER:{self.id} +region{unique_identifier} = INTEGER:{self.region} +control{unique_identifier} = INTEGER:{hex(self.control)} +nPermissionRegs{unique_identifier} = INTEGER:{len(self.permissions)} +""" + for index, permission in enumerate(self.permissions): + cert += f"""permissions{unique_identifier}{index} = INTEGER:{hex(permission)} +""" + cert += f"""startAddress{unique_identifier} = FORMAT:HEX,OCT:{self.start_address:02x} +endAddress{unique_identifier} = FORMAT:HEX,OCT:{self.end_address:02x} +""" + return cert + class Entry_ti_secure(Entry_x509_cert): """Entry containing a TI x509 certificate binary @@ -17,6 +52,11 @@ class Entry_ti_secure(Entry_x509_cert): - content: List of phandles to entries to sign - keyfile: Filename of file containing key to sign binary with - sha: Hash function to be used for signing + - auth-in-place: This is an integer field that contains two pieces + of information + Lower Byte - Remains 0x02 as per our use case + ( 0x02: Move the authenticated binary back to the header ) + Upper Byte - The Host ID of the core owning the firewall Output files: - input.<unique_name> - input file passed to openssl @@ -25,6 +65,35 @@ class Entry_ti_secure(Entry_x509_cert): - cert.<unique_name> - output file generated by openssl (which is used as the entry contents) + Depending on auth-in-place information in the inputs, we read the + firewall nodes that describe the configurations of firewall that TIFS + will be doing after reading the certificate. + + The syntax of the firewall nodes are as such: + + firewall-257-0 { + id = <257>; /* The ID of the firewall being configured */ + region = <0>; /* Region number to configure */ + + control = /* The control register */ + <(FWCTRL_EN | FWCTRL_LOCK | FWCTRL_BG | FWCTRL_CACHE)>; + + permissions = /* The permission registers */ + <((FWPRIVID_ALL << FWPRIVID_SHIFT) | + FWPERM_SECURE_PRIV_RWCD | + FWPERM_SECURE_USER_RWCD | + FWPERM_NON_SECURE_PRIV_RWCD | + FWPERM_NON_SECURE_USER_RWCD)>; + + /* More defines can be found in k3-security.h */ + + start_address = /* The Start Address of the firewall */ + <0x0 0x0>; + end_address = /* The End Address of the firewall */ + <0xff 0xffffffff>; + }; + + openssl signs the provided data, using the TI templated config file and writes the signature in this entry. This allows verification that the data is genuine. @@ -32,11 +101,20 @@ class Entry_ti_secure(Entry_x509_cert): def __init__(self, section, etype, node): super().__init__(section, etype, node) self.openssl = None + self.firewall_cert_data: dict = { + 'auth_in_place': 0x02, + 'num_firewalls': 0, + 'certificate': '', + } def ReadNode(self): super().ReadNode() self.key_fname = self.GetEntryArgsOrProps([ EntryArg('keyfile', str)], required=True)[0] + auth_in_place = fdt_util.GetInt(self._node, 'auth-in-place') + if auth_in_place: + self.firewall_cert_data['auth_in_place'] = auth_in_place + self.ReadFirewallNode() self.sha = fdt_util.GetInt(self._node, 'sha', 512) self.req_dist_name = {'C': 'US', 'ST': 'TX', @@ -46,6 +124,23 @@ class Entry_ti_secure(Entry_x509_cert): 'CN': 'TI Support', 'emailAddress': 'support@ti.com'} + def ReadFirewallNode(self): + self.firewall_cert_data['certificate'] = "" + self.firewall_cert_data['num_firewalls'] = 0 + for node in self._node.subnodes: + if 'firewall' in node.name: + firewall = Firewall( + fdt_util.GetInt(node, 'id'), + fdt_util.GetInt(node, 'region'), + fdt_util.GetInt(node, 'control'), + fdt_util.GetPhandleList(node, 'permissions'), + fdt_util.GetInt64(node, 'start_address'), + fdt_util.GetInt64(node, 'end_address'), + ) + firewall.ensure_props(self, node.name) + self.firewall_cert_data['num_firewalls'] += 1 + self.firewall_cert_data['certificate'] += firewall.get_certificate() + def GetCertificate(self, required): """Get the contents of this entry diff --git a/tools/binman/etype/x509_cert.py b/tools/binman/etype/x509_cert.py index fc0bb12278..29630d1b86 100644 --- a/tools/binman/etype/x509_cert.py +++ b/tools/binman/etype/x509_cert.py @@ -51,6 +51,7 @@ class Entry_x509_cert(Entry_collection): self.hashval_sysfw_data = None self.sysfw_inner_cert_ext_boot_block = None self.dm_data_ext_boot_block = None + self.firewall_cert_data = None def ReadNode(self): super().ReadNode() @@ -98,7 +99,8 @@ class Entry_x509_cert(Entry_collection): key_fname=self.key_fname, config_fname=config_fname, sw_rev=self.sw_rev, - req_dist_name_dict=self.req_dist_name) + req_dist_name_dict=self.req_dist_name, + firewall_cert_data=self.firewall_cert_data) elif type == 'rom': stdout = self.openssl.x509_cert_rom( cert_fname=output_fname, diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index a4ac520cbb..90482518f1 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -7052,6 +7052,29 @@ fdt fdtmap Extract the devicetree blob from the fdtmap entry_args=entry_args)[0] self.assertGreater(len(data), len(TI_UNSECURE_DATA)) + def testPackTiSecureFirewall(self): + """Test that an image with a TI secured binary can be created""" + keyfile = self.TestFile('key.key') + entry_args = { + 'keyfile': keyfile, + } + data_no_firewall = self._DoReadFileDtb('296_ti_secure.dts', + entry_args=entry_args)[0] + data_firewall = self._DoReadFileDtb('324_ti_secure_firewall.dts', + entry_args=entry_args)[0] + self.assertGreater(len(data_firewall),len(data_no_firewall)) + + def testPackTiSecureFirewallMissingProperty(self): + """Test that an image with a TI secured binary can be created""" + keyfile = self.TestFile('key.key') + entry_args = { + 'keyfile': keyfile, + } + with self.assertRaises(ValueError) as e: + data_firewall = self._DoReadFileDtb('325_ti_secure_firewall_missing_property.dts', + entry_args=entry_args)[0] + self.assertRegex(str(e.exception), "Node '/binman/ti-secure': Subnode 'firewall-0-2' is missing properties: id,region") + def testPackTiSecureMissingTool(self): """Test that an image with a TI secured binary (non-functional) can be created when openssl is missing""" diff --git a/tools/binman/test/324_ti_secure_firewall.dts b/tools/binman/test/324_ti_secure_firewall.dts new file mode 100644 index 0000000000..7ec407fa67 --- /dev/null +++ b/tools/binman/test/324_ti_secure_firewall.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + ti-secure { + content = <&unsecure_binary>; + auth-in-place = <0xa02>; + + firewall-0-2 { + id = <0>; + region = <2>; + control = <0x31a>; + permissions = <0xc3ffff>; + start_address = <0x0 0x9e800000>; + end_address = <0x0 0x9fffffff>; + }; + + }; + unsecure_binary: blob-ext { + filename = "ti_unsecure.bin"; + }; + }; +}; diff --git a/tools/binman/test/325_ti_secure_firewall_missing_property.dts b/tools/binman/test/325_ti_secure_firewall_missing_property.dts new file mode 100644 index 0000000000..24a0a99625 --- /dev/null +++ b/tools/binman/test/325_ti_secure_firewall_missing_property.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + ti-secure { + content = <&unsecure_binary>; + auth-in-place = <0xa02>; + + firewall-0-2 { + // id = <0>; + // region = <2>; + control = <0x31a>; + permissions = <0xc3ffff>; + start_address = <0x0 0x9e800000>; + end_address = <0x0 0x9fffffff>; + }; + + }; + unsecure_binary: blob-ext { + filename = "ti_unsecure.bin"; + }; + }; +}; diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 5963925146..991a36b987 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -782,7 +782,7 @@ class Node: for node in parent.subnodes.__reversed__(): dst = self.copy_node(node) - tout.debug(f'merge props from {parent.path} to {dst.path}') + tout.debug(f'merge props from {parent.path} to {self.path}') self.merge_props(parent, False) |