[PATCH 2/7] test: py: Generate capsule keys prior to building u-boot

Sughosh Ganu
2023-06-13T10:39:29Z

Currently, the keys and the EFI Signature List(ESL) file used for
capsule authentication can be generated after the u-boot image has
been built. The ESL file is then manually embedded into the platform's
dtb for capsule authentication.

This flow has been changed through an earlier commit, which embeds the
ESL file into the platform's dtb(s) as part of the u-boot build. This
requires generating the keys and the ESL file prior to invoking the
u-boot build.

Bring about the same sequence of generating these files prior to
invoking the u-boot build while testing.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
configs/sandbox_defconfig | 1 +
configs/sandbox_flattree_defconfig | 1 +
test/py/conftest.py | 64 ++++++++++++++++++++
test/py/tests/test_efi_capsule/conftest.py | 38 +++---------
test/py/tests/test_efi_capsule/signature.dts | 10 ---
5 files changed, 74 insertions(+), 40 deletions(-)
delete mode 100644 test/py/tests/test_efi_capsule/signature.dts

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 1ec44d5b33..d8a2386bb0 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -339,6 +339,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl"
CONFIG_EFI_SECURE_BOOT=y
CONFIG_TEST_FDTDEC=y
CONFIG_UNIT_TEST=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index e7657d40dc..8d60744771 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -226,6 +226,7 @@ CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
CONFIG_EFI_CAPSULE_ON_DISK=y
CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_ESL_FILE="/tmp/capsules/SIGNER.esl"
CONFIG_UNIT_TEST=y
CONFIG_UT_TIME=y
CONFIG_UT_DM=y
diff --git a/test/py/conftest.py b/test/py/conftest.py
index fc9dd3a83f..b7166508d4 100644
--- a/test/py/conftest.py
+++ b/test/py/conftest.py
@@ -80,6 +80,65 @@ def pytest_addoption(parser):
help='Run sandbox under gdbserver. The argument is the channel '+
'over which gdbserver should communicate, e.g. localhost:1234')

+def setup_capsule_auth_build(source_dir, build_dir, board_type, log):
+ """Setup the platform's build for capsule authenticate
+
+ This generates the signatures needed for signing the capsules along
+ with the EFI Signature List(ESL) file, with the capsule
+ authentication feature enabled.
+
+ The ESL file is subsequently embedded into the platform's
+ dtb during the u-boot build, to be used for capsule
+ authentication.
+
+ Two sets of signatures are generated, namely SIGNER and SIGNER2.
+ The SIGNER2 key pair is used as a malicious key for testing the
+ the capsule authentication functionality.
+
+ Args:
+ soruce_dir (str): Directory containing source code
+ build_dir (str): Directory to build in
+ board_type (str): board_type parameter (e.g. 'sandbox')
+ log (Logfile): Log file to use
+
+ Returns:
+ Nothing.
+ """
+ def run_command(name, cmd, source_dir):
+ with log.section(name):
+ if isinstance(cmd, str):
+ cmd = cmd.split()
+ runner = log.get_runner(name, None)
+ runner.run(cmd, cwd=source_dir)
+ runner.close()
+ log.status_pass('OK')
+
+ capsule_sig_dir = '/tmp/capsules/'
+ sig_name = 'SIGNER'
+ mkdir_p(capsule_sig_dir)
+ name = 'openssl'
+ cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
+ '-subj /CN=TEST_SIGNER/ -keyout %s%s.key '
+ '-out %s%s.crt -nodes -days 365'
+ % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name)
+ )
+ run_command(name, cmd, source_dir)
+
+ name = 'cert-to-efi-sig-list'
+ cmd = ( 'cert-to-efi-sig-list %s%s.crt %s%s.esl'
+ % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name)
+ )
+ run_command(name, cmd, source_dir)
+
+ sig_name = 'SIGNER2'
+ name = 'openssl'
+ cmd = ( 'openssl req -x509 -sha256 -newkey rsa:2048 '
+ '-subj /CN=TEST_SIGNER/ -keyout %s%s.key '
+ '-out %s%s.crt -nodes -days 365'
+ % (capsule_sig_dir, sig_name, capsule_sig_dir, sig_name)
+ )
+ run_command(name, cmd, source_dir)
+
def run_build(config, source_dir, build_dir, board_type, log):
"""run_build: Build U-Boot

@@ -102,6 +161,11 @@ def run_build(config, source_dir, build_dir, board_type, log):
o_opt = 'O=%s' % build_dir
else:
o_opt = ''
+
+ capsule_auth_boards = ( 'sandbox', 'sandbox_flattree' )
+ if board_type in capsule_auth_boards:
+ setup_capsule_auth_build(source_dir, build_dir, board_type, log)
+
cmds = (
['make', o_opt, '-s', board_type + '_defconfig'],
['make', o_opt, '-s', '-j{}'.format(os.cpu_count())],
diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
index a337e62936..4269c41a74 100644
--- a/test/py/tests/test_efi_capsule/conftest.py
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -32,36 +32,6 @@ def efi_capsule_data(request, u_boot_config):
check_call('mkdir -p %s' % data_dir, shell=True)
check_call('mkdir -p %s' % install_dir, shell=True)

- capsule_auth_enabled = u_boot_config.buildconfig.get(
- 'config_efi_capsule_authenticate')
- if capsule_auth_enabled:
- # Create private key (SIGNER.key) and certificate (SIGNER.crt)
- check_call('cd %s; '
- 'openssl req -x509 -sha256 -newkey rsa:2048 '
- '-subj /CN=TEST_SIGNER/ -keyout SIGNER.key '
- '-out SIGNER.crt -nodes -days 365'
- % data_dir, shell=True)
- check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl'
- % (data_dir, EFITOOLS_PATH), shell=True)
-
- # Update dtb adding capsule certificate
- check_call('cd %s; '
- 'cp %s/test/py/tests/test_efi_capsule/signature.dts .'
- % (data_dir, u_boot_config.source_dir), shell=True)
- check_call('cd %s; '
- 'dtc -@ -I dts -O dtb -o signature.dtbo signature.dts; '
- 'fdtoverlay -i %s/arch/sandbox/dts/test.dtb '
- '-o test_sig.dtb signature.dtbo'
- % (data_dir, u_boot_config.build_dir), shell=True)
-
- # Create *malicious* private key (SIGNER2.key) and certificate
- # (SIGNER2.crt)
- check_call('cd %s; '
- 'openssl req -x509 -sha256 -newkey rsa:2048 '
- '-subj /CN=TEST_SIGNER/ -keyout SIGNER2.key '
- '-out SIGNER2.crt -nodes -days 365'
- % data_dir, shell=True)
-
# Create capsule files
# two regions: one for u-boot.bin and the other for u-boot.env
check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old > u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
@@ -88,7 +58,14 @@ def efi_capsule_data(request, u_boot_config):
(data_dir, u_boot_config.build_dir),
shell=True)

+ capsule_auth_enabled = u_boot_config.buildconfig.get(
+ 'config_efi_capsule_authenticate')
if capsule_auth_enabled:
+ capsules_path_dir = '/tmp/capsules/'
+ check_call('mv %s/* %s ' %(capsules_path_dir, data_dir), shell=True)
+ check_call('cp %s/arch/sandbox/dts/test.dtb %s/test_sig.dtb' %
+ (u_boot_config.build_dir, data_dir), shell=True)
+
# raw firmware signed with proper key
check_call('cd %s; '
'%s/tools/mkeficapsule --index 1 --monotonic-count 1 '
@@ -138,4 +115,5 @@ def efi_capsule_data(request, u_boot_config):
finally:
call('rm -rf %s' % mnt_point, shell=True)
call('rm -f %s' % image_path, shell=True)
+ call('rm -rf %s' % capsules_path_dir, shell=True)
call('rm -f ./spi.bin', shell=True)
diff --git a/test/py/tests/test_efi_capsule/signature.dts b/test/py/tests/test_efi_capsule/signature.dts
deleted file mode 100644
index 078cfc76c9..0000000000
--- a/test/py/tests/test_efi_capsule/signature.dts
+++ /dev/null
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
- signature {
- capsule-key = /incbin/("SIGNER.esl");
- };
-};
--
2.34.1