Merge patch series "ATF and OP-TEE Firewalling for K3 devices."

Manorit Chawdhry <m-chawdhry@ti.com> says:

K3 devices have firewalls that are used to prevent illegal accesses to
memory regions that are deemed secure. The series prevents the illegal
accesses to ATF and OP-TEE regions that are present in different K3
devices.

AM62X, AM62AX and AM64X are currently in hold due to some firewall
configurations that our System Controller (TIFS) needs to handle.
The devices that are not configured with the firewalling nodes will not
be affected and can continue to work fine until the firewall nodes are
added so will be a non-blocking merge.

Test Logs: https://gist.github.com/manorit2001/4cead2fb3a19eb5d19005b3f54682627
CICD Run: https://github.com/u-boot/u-boot/pull/442
This commit is contained in:
Tom Rini 2024-01-04 16:53:49 -05:00
commit 0d53be75c7
13 changed files with 854 additions and 115 deletions

View file

@ -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>;
};
};

View file

@ -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>;

View file

@ -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>;

View file

@ -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>;

View file

@ -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

View file

@ -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:
.. code-block:: bash
* U-boot build (:ref:`U-boot build <k3_rst_include_start_build_steps_spl_r5>`)
* Linux Image and Linux DTB prebuilt
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>;
description = "FIT Image description";
#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";
};
images {
[image-1]
[image-2]
[fdt-1]
[fdt-2]
}
};
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";
};
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::
2. Compile U-boot for the respective board
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>".
.. include:: k3.rst
:start-after: .. k3_rst_include_start_build_steps_uboot
:end-before: .. k3_rst_include_end_build_steps_uboot
For enabling usage of FIT signature, add the signature node to the
corresponding configuration node as follows.
* Sample Configurations
.. 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 $
mkimage -r -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K
$UBOOT_PATH/build/a72/dts/dt.dtb
For signing a secondary platform, pass the -K parameter to that DTB
.. prompt:: bash $
mkimage -f fitImage.its -k $UBOOT_PATH/board/ti/keys -K
$UBOOT_PATH/build/a72/arch/arm/dts/k3-j721e-sk.dtb
.. note::
If changing `CONFIG_DEFAULT_DEVICE_TREE` to the secondary platform,
binman changes would also be required so that correct dtb gets packaged.
.. code-block:: bash
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"
#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"
5. Rebuilt u-boot
This is required so that the modified dtb gets updated in u-boot.img
.. include:: k3.rst
:start-after: .. k3_rst_include_start_build_steps_uboot
:end-before: .. k3_rst_include_end_build_steps_uboot
6. (Optional) Enabled FIT_SIGNATURE_ENFORCED
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
This is by default enabled for devices with TI_SECURE_DEVICE enabled.
Generating the fitImage
^^^^^^^^^^^^^^^^^^^^^^^
.. 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.
For signing a secondary platform like SK boards, you'll require
additional steps
- Change the CONFIG_DEFAULT_DEVICE_TREE
For e.g
.. code-block::
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
- Change the binman nodes to package u-boot.dtb for the correct set of platform
For e.g
.. code-block::
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"
#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"
This step will embed the public key in the u-boot.dtb file that was already
built during the initial u-boot build.
.. 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.
Build u-boot again
^^^^^^^^^^^^^^^^^^
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 to
disallow fallback during testing.
Saving environment
------------------

View file

@ -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,

View file

@ -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

View file

@ -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,

View file

@ -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"""

View file

@ -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";
};
};
};

View file

@ -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";
};
};
};

View file

@ -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)