[PATCH v5 6/6] test: binman: Add test for pkcs11 signed capsule
Wojciech Dubowik
Wojciech.Dubowik at mt.com
Wed Jan 28 09:05:13 CET 2026
Test pkcs11 URI support for UEFI capsule generation. For
simplicity only private key is defined in binman section
as softhsm tool doesn't support certificate import (yet).
Add bintool support for p11-kit as it's needed in the test
to find library path for softhsm2 module.
Signed-off-by: Wojciech Dubowik <Wojciech.Dubowik at mt.com>
Reviewed-by: Simon Glass <simon.glass at canonical.com>
---
tools/binman/btool/p11_kit.py | 21 ++++++
tools/binman/ftest.py | 66 +++++++++++++++++++
.../binman/test/351_capsule_signed_pkcs11.dts | 22 +++++++
3 files changed, 109 insertions(+)
create mode 100644 tools/binman/btool/p11_kit.py
create mode 100644 tools/binman/test/351_capsule_signed_pkcs11.dts
diff --git a/tools/binman/btool/p11_kit.py b/tools/binman/btool/p11_kit.py
new file mode 100644
index 000000000000..9d8d5d848b44
--- /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/ftest.py b/tools/binman/ftest.py
index 21ec48d86fd1..a66030c7a56f 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,71 @@ 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("key.key"))
+ private_key = self._MakeInputFile("key.key", data)
+ data = tools.read_file(self.TestFile("key.pem"))
+ cert_file = self._MakeInputFile("key.crt", data)
+
+ softhsm2_util = bintool.Bintool.create('softhsm2_util')
+ self._CheckBintool(softhsm2_util)
+
+ prefix = "testPkcs11SignedCapsuleGen."
+ # Configure SoftHSMv2
+ data = tools.read_file(self.TestFile('340_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('softhsm2-util', '--import', private_key, '--token',
+ 'U-Boot token', '--label', 'test_key', '--id', '999999',
+ '--pin', '1111')
+ data = self._DoReadFile('351_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('<Q', int(monotonic_count, 16)))
+
+ # Verify dumped capsule signature dumped by meficapsule during
+ # generation
+ openssl = bintool.Bintool.create('openssl')
+ self._CheckBintool(openssl)
+ openssl_args = ['smime', '-verify', '-inform', 'DER',
+ '-in', tools.get_output_filename('capsule.efi-capsule.p7'),
+ '-content', sig_input, '-CAfile', cert_file,
+ '-no_check_time',
+ '-out', tools.get_output_filename('decoded-capsule.bin')]
+ result = openssl.run_cmd_result(*openssl_args)
+ self.assertIsNotNone(result.stdout)
+ self.assertIn('Verification successful', result.stderr)
+
def testCapsuleGenVersionSupport(self):
"""Test generation of EFI capsule with version support"""
data = self._DoReadFile('313_capsule_version.dts')
diff --git a/tools/binman/test/351_capsule_signed_pkcs11.dts b/tools/binman/test/351_capsule_signed_pkcs11.dts
new file mode 100644
index 000000000000..ae93bf83936f
--- /dev/null
+++ b/tools/binman/test/351_capsule_signed_pkcs11.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+ binman {
+ efi-capsule {
+ image-index = <0x1>;
+ /* 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 = "key.crt";
+
+ blob {
+ filename = "capsule_input.bin";
+ };
+ };
+ };
+};
--
2.47.3
More information about the U-Boot
mailing list