From 6ac9131702768343bec150894daac7208963b440 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 28 Feb 2023 19:19:11 +0100 Subject: iot2050: Update firmware layout The latest version of the binary-only firmware parts come in a combined form of FSBL and sysfw containers. This implies some layout changes to the generated firmware image but also makes handling of artifacts much simpler (4 files less). The env locations will not change, just the space reserved for U-Boot will shrink from 4 to 3 MB - still plenty of space left in practice. Adjust configuration and documentation accordingly. Along this change, add a new reservation for update commands of the user-controlled OTP part. A specific userspace tool will fill it, and the FSBL will evaluate it during boot. This reservation will use 64K of the former sysfw section. Signed-off-by: Jan Kiszka --- tools/binman/missing-blob-help | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'tools') diff --git a/tools/binman/missing-blob-help b/tools/binman/missing-blob-help index f3a44d08acc..5fdb22c88c8 100644 --- a/tools/binman/missing-blob-help +++ b/tools/binman/missing-blob-help @@ -21,13 +21,7 @@ Please read the section on SCP firmware in board/sunxi/README.sunxi64 iot2050-seboot: See the documentation for IOT2050 board. Your image is missing SEBoot which is mandatory for board startup. Prebuilt SEBoot located at -meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/tiboot3.bin. - -iot2050-sysfw: -See the documentation for IOT2050 board. Your image is missing system -firmware which is mandatory for board startup. Prebuilt system firmware -located at meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/ -with sysfw prefix. +meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/seboot_pg*.bin. k3-rti-wdt-firmware: If CONFIG_WDT_K3_RTI_LOAD_FW is enabled, a firmware image is needed for -- cgit v1.3.1 From 75c89069f0cbf887c12f96db7529430c3932fb81 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 28 Feb 2023 19:19:16 +0100 Subject: tools: Add script for converting public key into device tree include Allows to create a public key device tree dtsi for inclusion into U-Boot SPL and proper during first build already. This can be achieved via CONFIG_DEVICE_TREE_INCLUDES. Signed-off-by: Jan Kiszka --- tools/key2dtsi.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100755 tools/key2dtsi.py (limited to 'tools') diff --git a/tools/key2dtsi.py b/tools/key2dtsi.py new file mode 100755 index 00000000000..1dbb2cc94bf --- /dev/null +++ b/tools/key2dtsi.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-only +# +# Public key to dtsi converter. +# +# Copyright (c) Siemens AG, 2022 +# + +from argparse import ArgumentParser, FileType +from os.path import basename, splitext +from Cryptodome.PublicKey import RSA +from Cryptodome.Util.number import inverse + +def int_to_bytestr(n, length=None): + if not length: + length = (n.bit_length() + 7) // 8 + byte_array = n.to_bytes(length, 'big') + return ' '.join(['{:02x}'.format(byte) for byte in byte_array]) + +ap = ArgumentParser(description='Public key to dtsi converter') + +ap.add_argument('--hash', '-H', default='sha256', + help='hash to be used with key (default: sha256)') +ap.add_argument('--required-conf', '-c', action='store_true', + help='mark key required for configuration') +ap.add_argument('--required-image', '-i', action='store_true', + help='mark key required for image') +ap.add_argument('--spl', '-s', action='store_true', + help='mark key for usage in SPL') +ap.add_argument('key_file', metavar='KEY_FILE', type=FileType('r'), + help='key file (formats: X.509, PKCS#1, OpenSSH)') +ap.add_argument('dtsi_file', metavar='DTSI_FILE', type=FileType('w'), + help='dtsi output file') + +args = ap.parse_args() + +key_name, _ = splitext(basename(args.key_file.name)) + +key_data = args.key_file.read() +key = RSA.importKey(key_data) + +r_squared = (2**key.size_in_bits())**2 % key.n +n0_inverse = 2**32 - inverse(key.n, 2**32) + +out = args.dtsi_file +out.write('/ {\n') +out.write('\tsignature {\n') +out.write('\t\tkey-{} {{\n'.format(key_name)) +out.write('\t\t\tkey-name-hint = "{}";\n'.format(key_name)) +out.write('\t\t\talgo = "{},rsa{}";\n'.format(args.hash, key.size_in_bits())) +out.write('\t\t\trsa,num-bits = <{}>;\n'.format(key.size_in_bits())) +out.write('\t\t\trsa,modulus = [{}];\n'.format(int_to_bytestr(key.n))) +out.write('\t\t\trsa,exponent = [{}];\n'.format(int_to_bytestr(key.e, 8))) +out.write('\t\t\trsa,r-squared = [{}];\n'.format(int_to_bytestr(r_squared))) +out.write('\t\t\trsa,n0-inverse = <0x{:x}>;\n'.format(n0_inverse)) +if args.required_conf: + out.write('\t\t\trequired = "conf";\n') +elif args.required_image: + out.write('\t\t\trequired = "image";\n') +if args.spl: + out.write('\t\t\tu-boot,dm-spl;\n') +out.write('\t\t};\n') +out.write('\t};\n') +out.write('};\n') -- cgit v1.3.1 From 033ab460d0930e4f7d365279f1c39d914b5e88a4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 28 Feb 2023 19:19:17 +0100 Subject: iot2050: Add script for signing artifacts There are many ways to get a signed firmware for the IOT2050 devices, namely for the parts under user-control. This script documents one way of doing it, given a signing key. Augment the board documentation with the required procedure around it. Signed-off-by: Jan Kiszka --- doc/board/siemens/iot2050.rst | 52 +++++++++++++++++++++++++++++++++++++++++++ tools/iot2050-sign-fw.sh | 51 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100755 tools/iot2050-sign-fw.sh (limited to 'tools') diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index 26972e20ae9..4e0925c72c9 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -79,3 +79,55 @@ Via external programmer Dediprog SF100 or SF600: .. code-block:: text $ dpcmd --vcc 2 -v -u flash.bin + +Signing (optional) +------------------ + +To enable verified boot for the firmware artifacts after the Siemens-managed +first-stage loader (seboot_pg*.bin), the following steps need to be taken +before and after the build: + +Generate dtsi holding the public key +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + tools/key2dtsi.py -c -s key.pem public-key.dtsi + +This will be used to embed the public key into U-Boot SPL and main so that each +step can validate signatures of the succeeding one. + +Adjust U-Boot configuration +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Enabled at least the following options in U-Boot: + +.. code-block:: text + + CONFIG_SPL_FIT_SIGNATURE=y + CONFIG_DEVICE_TREE_INCLUDES="/path/to/public-key.dtsi" + CONFIG_RSA=y + +Note that there are more configuration changes needed in order to lock-down +the command line and the boot process of U-Boot for secure scenarios. These are +not in scope here. + +Build U-Boot +^^^^^^^^^^^^ + +See related section above. + +Sign flash.bin +^^^^^^^^^^^^^^ + +In the build folder still containing artifacts from step 3, invoke: + +.. code-block:: text + + tools/iot2050-sign-fw.sh /path/to/key.pem + +Flash signed flash.bin +^^^^^^^^^^^^^^^^^^^^^^ + +The signing has happen in-place in flash.bin, thus the flashing procedure +described above. diff --git a/tools/iot2050-sign-fw.sh b/tools/iot2050-sign-fw.sh new file mode 100755 index 00000000000..4d1d79498c2 --- /dev/null +++ b/tools/iot2050-sign-fw.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +if [ -z "$1" ]; then + echo "Usage: $0 KEY" + exit 1 +fi + +TEMP_X509=$(mktemp XXXXXXXX.temp) + +REVISION=${2:-0} +SHA_VAL=$(openssl dgst -sha512 -hex tispl.bin | sed -e "s/^.*= //g") +BIN_SIZE=$(stat -c %s tispl.bin) + +cat <$TEMP_X509 +[ req ] +distinguished_name = req_distinguished_name +x509_extensions = v3_ca +prompt = no +dirstring_type = nobmp + +[ req_distinguished_name ] +CN = IOT2050 Firmware Signature + +[ v3_ca ] +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 + +[ swrv ] +swrv = INTEGER:$REVISION + +[ sysfw_image_integrity ] +shaType = OID:2.16.840.1.101.3.4.2.3 +shaValue = FORMAT:HEX,OCT:$SHA_VAL +imageSize = INTEGER:$BIN_SIZE +EOF + +CERT_X509=$(mktemp XXXXXXXX.crt) + +openssl req -new -x509 -key $1 -nodes -outform DER -out $CERT_X509 -config $TEMP_X509 -sha512 +cat $CERT_X509 tispl.bin > tispl.bin_signed +# currently broken in upstream +#source/tools/binman/binman replace -i flash.bin -f tispl.bin_signed blob@0x180000 +dd if=tispl.bin_signed of=flash.bin bs=$((0x1000)) seek=$((0x180000/0x1000)) conv=notrunc + +rm $TEMP_X509 $CERT_X509 + +tools/mkimage -G $1 -r -o sha256,rsa4096 -F fit@0x380000.fit +# currently broken in upstream +#source/tools/binman/binman replace -i flash.bin -f fit@0x380000.fit fit@0x380000 +dd if=fit@0x380000.fit of=flash.bin bs=$((0x1000)) seek=$((0x380000/0x1000)) conv=notrunc -- cgit v1.3.1 From 367b1bf2ceb320e8862c6014b7138fa126268161 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Tue, 28 Feb 2023 19:19:18 +0100 Subject: arm: dts: iot2050: Optionally embed OTP programming data into image Use external blob otpcmd.bin to replace the 0xff filled OTP programming command block to create a firmware image that provisions the OTP on first boot. This otpcmd.bin is generated from the customer keys using steps described in the meta-iot2050 integration layer for the device. Based on original patch by Baocheng Su. Signed-off-by: Jan Kiszka --- arch/arm/dts/k3-am65-iot2050-boot-image.dtsi | 9 +++++++++ board/siemens/iot2050/Kconfig | 7 +++++++ doc/board/siemens/iot2050.rst | 8 ++++++++ tools/binman/missing-blob-help | 8 ++++++++ 4 files changed, 32 insertions(+) (limited to 'tools') diff --git a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi index 9082a79a034..a2fc8bbc123 100644 --- a/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi +++ b/arch/arm/dts/k3-am65-iot2050-boot-image.dtsi @@ -111,10 +111,19 @@ }; /* OTP update command block */ +#if CONFIG_IOT2050_EMBED_OTPCMD + blob-ext@0x6c0000 { + offset = <0x6c0000>; + size = <0x010000>; + filename = "otpcmd.bin"; + missing-msg = "iot2050-otpcmd"; + }; +#else fill@0x6c0000 { offset = <0x6c0000>; size = <0x010000>; fill-byte = [ff]; }; +#endif }; }; diff --git a/board/siemens/iot2050/Kconfig b/board/siemens/iot2050/Kconfig index a2b40881d11..e66b2427d95 100644 --- a/board/siemens/iot2050/Kconfig +++ b/board/siemens/iot2050/Kconfig @@ -49,4 +49,11 @@ config IOT2050_BOOT_SWITCH bool "Disable eMMC boot via USER button (Advanced version only)" default y +config IOT2050_EMBED_OTPCMD + bool "Embed OTP programming data" + help + Embed signed OTP programming data 'otpcmd.bin' into the firmware + image. This data will be evaluated and executed on first boot of the + device. + endif diff --git a/doc/board/siemens/iot2050.rst b/doc/board/siemens/iot2050.rst index 4e0925c72c9..cb49a0e36bf 100644 --- a/doc/board/siemens/iot2050.rst +++ b/doc/board/siemens/iot2050.rst @@ -27,6 +27,14 @@ The following binaries from that source need to be present in the build folder: - seboot_pg1.bin - seboot_pg2.bin +For building an image containing the OTP key provisioning data, below binary +needs to be present in the build folder: + + - otpcmd.bin + +Regarding how to generating this otpcmd.bin, please refer to: +https://github.com/siemens/meta-iot2050/tree/master/recipes-bsp/secure-boot-otp-provisioning/files/make-otpcmd.sh + Building -------- diff --git a/tools/binman/missing-blob-help b/tools/binman/missing-blob-help index 5fdb22c88c8..f013367ac36 100644 --- a/tools/binman/missing-blob-help +++ b/tools/binman/missing-blob-help @@ -23,6 +23,14 @@ See the documentation for IOT2050 board. Your image is missing SEBoot which is mandatory for board startup. Prebuilt SEBoot located at meta-iot2050/tree/master/recipes-bsp/u-boot/files/prebuild/seboot_pg*.bin. +iot2050-otpcmd: +See the documentation for IOT2050 board. Your image is missing OTP command data +block which is used for provisioning the customer keys to the board. +Please refer to +meta-iot2050/tree/master/recipes-bsp/secure-boot-otp-provisioning/files/make-otpcmd.sh +for how to generate this binary. If you are not using secure boot or do not +intend to provision the keys, disable CONFIG_IOT2050_EMBED_OTPCMD. + k3-rti-wdt-firmware: If CONFIG_WDT_K3_RTI_LOAD_FW is enabled, a firmware image is needed for the R5F core(s) to trigger the system reset. One possible source is -- cgit v1.3.1