From: Wojciech Dubowik Date: Fri, 20 Feb 2026 09:15:16 +0000 (+0100) Subject: test: binman: Add test for pkcs11 signed capsule X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e73443167be055c646dfd7d5a79bc30ac33e31d5;p=thirdparty%2Fu-boot.git test: binman: Add test for pkcs11 signed capsule Test pkcs11 URI support for UEFI capsule generation. Both public certificate and private key are used over pkcs11 protocol. Pkcs11-tool has been introduced as softhsm tool doesn't have functionality to import certificates in commonly distributed version (only in the latest). Signed-off-by: Wojciech Dubowik Reviewed-by: Simon Glass --- diff --git a/tools/binman/btool/p11_kit.py b/tools/binman/btool/p11_kit.py new file mode 100644 index 00000000000..9d8d5d848b4 --- /dev/null +++ b/tools/binman/btool/p11_kit.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright 2026 Mettler Toledo Technologies GmbH +# +"""Bintool implementation for p11-kit""" + +from binman import bintool + + +class Bintoolp11_kit(bintool.Bintool): + """p11-kit -- support tool for pkcs#11 libraries""" + def __init__(self, name): + super().__init__('p11-kit', + 'Pkcs11 library modules tool', + version_args='list modules') + + def fetch(self, method): + """Install p11-kit via APT """ + if method != bintool.FETCH_BIN: + return None + + return self.apt_install('p11-kit') diff --git a/tools/binman/btool/pkcs11_tool.py b/tools/binman/btool/pkcs11_tool.py new file mode 100644 index 00000000000..673c0ea0ac3 --- /dev/null +++ b/tools/binman/btool/pkcs11_tool.py @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright 2026 Mettler Toledo Technologies GmbH +# +"""Bintool implementation for pkcs11-tool""" + +from binman import bintool + + +class Bintoolpkcs11_tool(bintool.Bintool): + """pkcs11-tool -- support tool for managing pkcs#11 tokens""" + def __init__(self, name): + super().__init__('pkcs11-tool', + 'PKCS #11 tokens managing tool', + version_args='--show-info') + + def fetch(self, method): + """Install opensc via APT """ + if method != bintool.FETCH_BIN: + return None + + return self.apt_install('opensc') diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 9cc1a97f95c..ca5149ee654 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -7,6 +7,7 @@ # python -m unittest func_test.TestFunctional.testHelp import collections +import configparser import glob import gzip import hashlib @@ -7532,6 +7533,78 @@ fdt fdtmap Extract the devicetree blob from the fdtmap self._CheckCapsule(data, signed_capsule=True) + def testPkcs11SignedCapsuleGen(self): + """Test generation of EFI capsule (with PKCS11)""" + data = tools.read_file(self.TestFile("security/key.key")) + private_key = self._MakeInputFile("key.key", data) + data = tools.read_file(self.TestFile("security/key.pem")) + cert_file = self._MakeInputFile("key.crt", data) + + softhsm2_util = bintool.Bintool.create('softhsm2_util') + self._CheckBintool(softhsm2_util) + + pkcs11_tool = bintool.Bintool.create('pkcs11-tool') + self._CheckBintool(pkcs11_tool) + + prefix = "testPkcs11SignedCapsuleGen." + # Configure SoftHSMv2 + data = tools.read_file(self.TestFile('fit/softhsm2.conf')) + softhsm2_conf = self._MakeInputFile(f'{prefix}softhsm2.conf', data) + softhsm2_tokens_dir = self._MakeInputDir(f'{prefix}softhsm2.tokens') + + with open(softhsm2_conf, 'a') as f: + f.write(f'directories.tokendir = {softhsm2_tokens_dir}\n') + + # Find the path to softhsm2 library + p11_kit = bintool.Bintool.create('p11-kit') + self._CheckBintool(p11_kit) + + p11_kit_config = configparser.ConfigParser() + out = tools.run('p11-kit', 'print-config') + p11_kit_config.read_string(out) + softhsm2_lib = p11_kit_config.get('softhsm2', 'module', + fallback=None) + self.assertIsNotNone(softhsm2_lib) + + with unittest.mock.patch.dict('os.environ', + {'SOFTHSM2_CONF': softhsm2_conf, + 'PKCS11_MODULE_PATH': softhsm2_lib}): + tools.run('softhsm2-util', '--init-token', '--free', '--label', + 'U-Boot token', '--pin', '1111', '--so-pin', + '222222') + tools.run('pkcs11-tool', '--module', softhsm2_lib, + '--write-object', cert_file, '--pin', '1111', + '--type', 'cert', '--id', '999999', '--label', + 'test_cert', '--login') + tools.run('softhsm2-util', '--import', private_key, '--token', + 'U-Boot token', '--label', 'test_key', '--id', '999999', + '--pin', '1111') + data = self._DoReadFile('capsule/signed_pkcs11.dts') + + self._CheckCapsule(data, signed_capsule=True) + + hdr = self._GetCapsuleHeaders(data) + monotonic_count = hdr['EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT'] + + # UEFI standard requires that signature is checked over payload followed + # by a monotonic count as little endian 64-bit integer. + sig_input = self._MakeInputFile("sig_input", EFI_CAPSULE_DATA) + with open(sig_input, 'ab') as f: + f.write(struct.pack('; + /* Image GUID for testing capsule update */ + image-guid = "binman-test"; + hardware-instance = <0x0>; + monotonic-count = <0x1>; + dump-signature; + private-key = "pkcs11:token=U-Boot%20token;object=test_key;type=private;pin-value=1111"; + public-key-cert = "pkcs11:token=U-Boot%20token;object=test_cert;type=cert;pin-value=1111"; + + blob { + filename = "capsule_input.bin"; + }; + }; + }; +};