[PATCH v2] binman: x509_cert: add PKCS#11/HSM signing support
Simon Glass
sjg at chromium.org
Wed Apr 22 02:14:48 CEST 2026
Hi Sergio,
On 2026-04-21T13:36:46, Sergio Prado <sergio.prado at e-labworks.com> wrote:
> binman: x509_cert: add PKCS#11/HSM signing support
>
> Allow X509 certificates used for K3/TI secure boot to be signed via an
> HSM using the PKCS#11 standard.
>
> Two new make variables are introduced:
>
> - BINMAN_PKCS11_URI PKCS#11 URI identifying the signing key on the HSM
> - BINMAN_PKCS11_MODULE Path to the PKCS#11 shared library (.so)
>
> When BINMAN_PKCS11_URI is set, it is passed to binman as the pkcs11-uri
> entry argument, which overrides the keyfile property at signing time.
>
> The openssl bintool gains three helper methods:
>
> - _pkcs11_use_provider() detects whether the pkcs11 provider (OpenSSL
> >= 3.1) or the legacy pkcs11 engine (libp11) is available.
>
> - _build_key_args() builds the appropriate -key/-provider/-engine
> arguments for the openssl command line, appending ?pin-value=<pin>
> [...]
>
> Makefile | 2 +
> tools/binman/binman.rst | 18 +++++++
> tools/binman/btool/openssl.py | 106 ++++++++++++++++++++++++++++++++++------
> tools/binman/etype/x509_cert.py | 47 ++++++++++++++++--
> tools/binman/ftest.py | 96 ++++++++++++++++++++++++++++++++++++
> 5 files changed, 249 insertions(+), 20 deletions(-)
> diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py
> @@ -35,18 +36,83 @@ class Bintoolopenssl(bintool.Bintool):
> + if key_fname.startswith('pkcs11:'):
> + pin = os.environ.get('PKCS11_PIN')
> + if pin:
> + key_fname = f'{key_fname}?pin-value={pin}'
This assumes the URI has no existing query parameters. It might be
worth using '&' instead of '?' if the URI already contains '?'
> diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py
> @@ -35,18 +36,83 @@ class Bintoolopenssl(bintool.Bintool):
> + def _run_cmd_pkcs11(self, pkcs11_module, *args):
> + if pkcs11_module:
> + os.environ['PKCS11_MODULE_PATH'] = pkcs11_module
> + os.environ['PKCS11_PROVIDER_MODULE'] = pkcs11_module
> + return self.run_cmd(*args)
Setting os.environ directly pollutes the global environment. This
could cause issues if binman signs multiple images with different
module paths in a single run. It would be cleaner to pass the env to
run_cmd() explicitly. What do you think?
Also, the environment variables persist even if pkcs11_module is None
on a subsequent call.
> diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
> @@ -6884,6 +6884,102 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
> + def testX509CertPkcs11(self):
> + """Test X509 certificate creation using a PKCS#11 URI instead of a key file"""
> + PKCS11_URI = 'pkcs11:token=test;object=mykey;type=private'
> + PKCS11_MODULE = '/usr/lib/pkcs11/libsofthsm2.so'
> + original = bintool.Bintool.run_cmd
> +
> + def fake_openssl(self_tool, *args, binary=False):
> + if self_tool.name != 'openssl':
> + return original(self_tool, *args, binary=binary)
> + arg_list = list(args)
> + if arg_list == ['list', '-providers']:
> + return 'pkcs11 provider'
> + if '-out' in arg_list:
> + tools.write_file(arg_list[arg_list.index('-out') + 1],
> + b'\x00' * 32)
> + return ''
The test only confirms the code path runs without error. You could
also add assertions that check the args contain '-provider pkcs11' and
that PKCS11_URI is passed as the key argument.
Reviewed-by: Simon Glass <sjg at chromium.org>
Regards,
Simon
More information about the U-Boot
mailing list