[PATCH v2] binman: x509_cert: add PKCS#11/HSM signing support

Sergio Prado sergio.prado at e-labworks.com
Tue Apr 21 15:36:46 CEST 2026


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>
  from the PKCS11_PIN environment variable when set.

- _run_cmd_pkcs11() exports PKCS11_MODULE_PATH and PKCS11_PROVIDER_MODULE
  before invoking openssl when a module path is provided.

Existing behavior is unchanged when neither BINMAN_PKCS11_URI nor
BINMAN_PKCS11_MODULE is set.

Tested with SoftHSM2 and a Yubikey using the verdin-am62_a53_defconfig
configuration.

Signed-off-by: Sergio Prado <sergio.prado at e-labworks.com>
---
Changes in v2:
- Add tests for _build_key_args() (PEM path, PKCS#11 provider, PKCS#11 engine,
  PIN appending), _pkcs11_use_provider() (caching), _run_cmd_pkcs11() (with and
  without module path), and end-to-end x509_cert signing with a PKCS#11 URI
  (testX509CertPkcs11), making sure btool/openssl.py and etype/x509_cert.py has
  100% test coverage.

 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/Makefile b/Makefile
index dfc95d314ddd..8d6c584b2731 100644
--- a/Makefile
+++ b/Makefile
@@ -1701,6 +1701,8 @@ cmd_binman = $(srctree)/tools/binman/binman $(if $(BINMAN_DEBUG),-D) \
 		-a vpl-dtb=$(CONFIG_VPL_OF_REAL) \
 		-a pre-load-key-path=${PRE_LOAD_KEY_PATH} \
 		-a of-spl-remove-props=$(CONFIG_OF_SPL_REMOVE_PROPS) \
+		$(if $(BINMAN_PKCS11_URI),-a pkcs11-uri="$(BINMAN_PKCS11_URI)") \
+		$(if $(BINMAN_PKCS11_MODULE),-a pkcs11-module="$(BINMAN_PKCS11_MODULE)") \
 		$(BINMAN_$(@F))
 
 OBJCOPYFLAGS_u-boot.ldr.hex := -I binary -O ihex
diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst
index 3f725868c8bb..ea91199b1e22 100644
--- a/tools/binman/binman.rst
+++ b/tools/binman/binman.rst
@@ -2165,6 +2165,24 @@ BINMAN_INDIRS
     Sets the search path for input files used by binman by adding one or more
     `-I` arguments. See :ref:`External blobs`.
 
+BINMAN_PKCS11_URI
+    PKCS#11 URI used to sign boot artifacts via an HSM instead of a PEM key
+    file on disk. When set, it is passed as ``-a pkcs11-uri=<uri>`` to binman,
+    which overrides the ``keyfile`` entry argument for all signing operations.
+    Example::
+
+        make BINMAN_PKCS11_URI="pkcs11:token=mytoken;object=mykey;type=private"
+
+BINMAN_PKCS11_MODULE
+    Path to the PKCS#11 shared library (.so) for HSM signing. When set, it is
+    passed as ``-a pkcs11-module=<path>`` to binman. Only needed when the
+    module is not already configured via ``openssl.cnf`` or the
+    ``PKCS11_MODULE_PATH`` environment variable. Typically used together with
+    ``BINMAN_PKCS11_URI``::
+
+        make BINMAN_PKCS11_URI="pkcs11:token=mytoken;object=mykey;type=private" \
+             BINMAN_PKCS11_MODULE="/usr/lib/pkcs11/libsofthsm2.so"
+
 BINMAN_TOOLPATHS
     Sets the search path for external tool used by binman by adding one or more
     `--toolpath` arguments. See :ref:`External tools`.
diff --git a/tools/binman/btool/openssl.py b/tools/binman/btool/openssl.py
index b26f087c4470..550f318fade6 100644
--- a/tools/binman/btool/openssl.py
+++ b/tools/binman/btool/openssl.py
@@ -11,6 +11,7 @@ Source code is at https://www.openssl.org/
 """
 
 import hashlib
+import os
 
 from binman import bintool
 from u_boot_pylib import tools
@@ -35,18 +36,83 @@ class Bintoolopenssl(bintool.Bintool):
         super().__init__(
             name, 'openssl cryptography toolkit',
             version_regex=r'OpenSSL (.*) \(', version_args='version')
+        self._use_provider = None
+
+    def _pkcs11_use_provider(self):
+        """Return True if the provider API should be used for PKCS#11 signing.
+
+        Checks whether the pkcs11 provider is available by running
+        'openssl list -providers'. The result is cached after the first call
+        to avoid spawning a subprocess on every signing operation.
+
+        Returns:
+            bool: True if provider should be used, False if engine should be used
+        """
+        if self._use_provider is None:
+            out = self.run_cmd('list', '-providers') or ''
+            self._use_provider = 'pkcs11' in out
+        return self._use_provider
+
+    def _build_key_args(self, key_fname):
+        """Build openssl CLI arguments for the signing key.
+
+        Always add '-key key_fname', and for a PKCS#11 URI (pkcs11:...),
+        prepends either '-provider default -provider pkcs11' (if provider API
+        is available) or '-engine pkcs11 -keyform engine' (legacy fallback).
+        If the PKCS11_PIN environment variable is set, appends ?pin-value=<pin>
+        to the URI.
+
+        Args:
+            key_fname (str): Filename of .pem file or PKCS#11 URI
+
+        Returns:
+            list: openssl arguments for the key selection
+        """
+        if key_fname.startswith('pkcs11:'):
+            pin = os.environ.get('PKCS11_PIN')
+            if pin:
+                key_fname = f'{key_fname}?pin-value={pin}'
+            if self._pkcs11_use_provider():
+                args = ['-provider', 'default', '-provider', 'pkcs11', '-key', key_fname]
+            else:
+                args = ['-engine', 'pkcs11', '-keyform', 'engine', '-key', key_fname]
+        else:
+            args = ['-key', key_fname]
+        return args
+
+    def _run_cmd_pkcs11(self, pkcs11_module, *args):
+        """Run an openssl command, optionally setting the PKCS#11 module env vars.
+
+        When pkcs11_module is set, both PKCS11_MODULE_PATH (engine) and
+        PKCS11_PROVIDER_MODULE (provider) are exported before invoking openssl.
+        If already configured via openssl.cnf or the calling environment,
+        pkcs11_module can be None.
+
+        Args:
+            pkcs11_module (str or None): Path to the PKCS#11 shared library
+            *args: Arguments forwarded to run_cmd
+
+        Returns:
+            str: openssl output
+        """
+        if pkcs11_module:
+            os.environ['PKCS11_MODULE_PATH'] = pkcs11_module
+            os.environ['PKCS11_PROVIDER_MODULE'] = pkcs11_module
+        return self.run_cmd(*args)
 
     def x509_cert(self, cert_fname, input_fname, key_fname, cn, revision,
-                  config_fname):
+                  config_fname, pkcs11_module=None):
         """Create a certificate
 
         Args:
             cert_fname (str): Filename of certificate to create
             input_fname (str): Filename containing data to sign
-            key_fname (str): Filename of .pem file
+            key_fname (str): Filename of .pem file or PKCS#11 URI
             cn (str): Common name
             revision (int): Revision number
             config_fname (str): Filename to write fconfig into
+            pkcs11_module (str or None): Path to PKCS#11 shared library, or
+                None if already configured via openssl.cnf or the environment
 
         Returns:
             str: Tool output
@@ -76,19 +142,20 @@ shaType                = OID:2.16.840.1.101.3.4.2.3
 shaValue               = FORMAT:HEX,OCT:{hashval}
 imageSize              = INTEGER:{len(indata)}
 ''', file=outf)
-        args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
+        args = ['req', '-new', '-x509', *self._build_key_args(key_fname), '-nodes',
                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
                 '-sha512']
-        return self.run_cmd(*args)
+        return self._run_cmd_pkcs11(pkcs11_module, *args)
 
     def x509_cert_sysfw(self, cert_fname, input_fname, key_fname, sw_rev,
-                  config_fname, req_dist_name_dict, firewall_cert_data):
+                  config_fname, req_dist_name_dict, firewall_cert_data,
+                  pkcs11_module=None):
         """Create a certificate to be booted by system firmware
 
         Args:
             cert_fname (str): Filename of certificate to create
             input_fname (str): Filename containing data to sign
-            key_fname (str): Filename of .pem file
+            key_fname (str): Filename of .pem file or PKCS#11 URI
             sw_rev (int): Software revision
             config_fname (str): Filename to write fconfig into
             req_dist_name_dict (dict): Dictionary containing key-value pairs of
@@ -101,6 +168,8 @@ imageSize              = INTEGER:{len(indata)}
                 extended certificate
               - certificate (str): Extended firewall certificate with
                 the information for the firewall configurations.
+            pkcs11_module (str or None): Path to PKCS#11 shared library, or
+                None if already configured via openssl.cnf or the environment
 
         Returns:
             str: Tool output
@@ -146,20 +215,20 @@ authInPlace = INTEGER:{hex(firewall_cert_data['auth_in_place'])}
 numFirewallRegions = INTEGER:{firewall_cert_data['num_firewalls']}
 {firewall_cert_data['certificate']}
 ''', file=outf)
-        args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
+        args = ['req', '-new', '-x509', *self._build_key_args(key_fname), '-nodes',
                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
                 '-sha512']
-        return self.run_cmd(*args)
+        return self._run_cmd_pkcs11(pkcs11_module, *args)
 
     def x509_cert_rom(self, cert_fname, input_fname, key_fname, sw_rev,
                   config_fname, req_dist_name_dict, cert_type, bootcore,
-                  bootcore_opts, load_addr, sha, debug):
+                  bootcore_opts, load_addr, sha, debug, pkcs11_module=None):
         """Create a certificate
 
         Args:
             cert_fname (str): Filename of certificate to create
             input_fname (str): Filename containing data to sign
-            key_fname (str): Filename of .pem file
+            key_fname (str): Filename of .pem file or PKCS#11 URI
             sw_rev (int): Software revision
             config_fname (str): Filename to write fconfig into
             req_dist_name_dict (dict): Dictionary containing key-value pairs of
@@ -170,6 +239,8 @@ numFirewallRegions = INTEGER:{firewall_cert_data['num_firewalls']}
             bootcore_opts(int): Booting core option, lockstep (0) or split (2) mode
             load_addr (int): Load address of image
             sha (int): Hash function
+            pkcs11_module (str or None): Path to PKCS#11 shared library, or
+                None if already configured via openssl.cnf or the environment
 
         Returns:
             str: Tool output
@@ -231,10 +302,10 @@ emailAddress           = {req_dist_name_dict['emailAddress']}
  coreDbgEn = INTEGER:0
  coreDbgSecEn = INTEGER:0
 ''', file=outf)
-        args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
+        args = ['req', '-new', '-x509', *self._build_key_args(key_fname), '-nodes',
                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
                 '-sha512']
-        return self.run_cmd(*args)
+        return self._run_cmd_pkcs11(pkcs11_module, *args)
 
     def x509_cert_rom_combined(self, cert_fname, input_fname, key_fname, sw_rev,
                   config_fname, req_dist_name_dict, load_addr, sha, total_size, num_comps,
@@ -242,13 +313,14 @@ emailAddress           = {req_dist_name_dict['emailAddress']}
                   imagesize_sbl, hashval_sbl, load_addr_sysfw, imagesize_sysfw,
                   hashval_sysfw, load_addr_sysfw_data, imagesize_sysfw_data,
                   hashval_sysfw_data, sysfw_inner_cert_ext_boot_block,
-                  dm_data_ext_boot_block, bootcore_opts, debug):
+                  dm_data_ext_boot_block, bootcore_opts, debug,
+                  pkcs11_module=None):
         """Create a certificate
 
         Args:
             cert_fname (str): Filename of certificate to create
             input_fname (str): Filename containing data to sign
-            key_fname (str): Filename of .pem file
+            key_fname (str): Filename of .pem file or PKCS#11 URI
             sw_rev (int): Software revision
             config_fname (str): Filename to write fconfig into
             req_dist_name_dict (dict): Dictionary containing key-value pairs of
@@ -259,6 +331,8 @@ emailAddress           = {req_dist_name_dict['emailAddress']}
             load_addr (int): Load address of image
             sha (int): Hash function
             bootcore_opts (int): Booting core option, lockstep (0) or split (2) mode
+            pkcs11_module (str or None): Path to PKCS#11 shared library, or
+                None if already configured via openssl.cnf or the environment
 
         Returns:
             str: Tool output
@@ -342,10 +416,10 @@ coreDbgSecEn = INTEGER:0
 
 {dm_data_ext_boot_block}
         ''', file=outf)
-        args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
+        args = ['req', '-new', '-x509', *self._build_key_args(key_fname), '-nodes',
                 '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
                 '-sha512']
-        return self.run_cmd(*args)
+        return self._run_cmd_pkcs11(pkcs11_module, *args)
 
     def fetch(self, method):
         """Fetch handler for openssl
diff --git a/tools/binman/etype/x509_cert.py b/tools/binman/etype/x509_cert.py
index b6e8b0b4fb09..cdeff1a227a1 100644
--- a/tools/binman/etype/x509_cert.py
+++ b/tools/binman/etype/x509_cert.py
@@ -19,6 +19,18 @@ class Entry_x509_cert(Entry_collection):
 
     Properties / Entry arguments:
         - content: List of phandles to entries to sign
+        - keyfile: Filename of the PEM key file used to sign the binary
+        - pkcs11-uri: PKCS#11 URI for signing via an HSM, e.g.
+            ``pkcs11:token=mytoken;object=mykey;type=private``. When provided
+            via ``-a pkcs11-uri=...`` on the binman command line (or via the
+            ``BINMAN_PKCS11_URI`` make variable), it overrides ``keyfile`` for
+            the signing operation.
+        - pkcs11-module: Path to the PKCS#11 shared library (.so), e.g.
+            ``/usr/lib/pkcs11/libsofthsm2.so``. Only needed when signing via
+            HSM and the module is not already configured via ``openssl.cnf`` or
+            the ``PKCS11_MODULE_PATH`` environment variable. Provided via
+            ``-a pkcs11-module=...`` or the ``BINMAN_PKCS11_MODULE`` make
+            variable.
 
     Output files:
         - input.<unique_name> - input file passed to openssl
@@ -27,6 +39,16 @@ class Entry_x509_cert(Entry_collection):
 
     openssl signs the provided data, writing the signature in this entry. This
     allows verification that the data is genuine
+
+    To sign with an HSM, pass the PKCS#11 URI and optionally the module path
+    at build time::
+
+        make BINMAN_PKCS11_URI="pkcs11:token=mytoken;object=mykey;type=private" \\
+             BINMAN_PKCS11_MODULE="/usr/lib/pkcs11/libsofthsm2.so" \\
+             PKCS11_PIN="1234"
+
+    The ``PKCS11_PIN`` environment variable is used by the openssl bintool to
+    append ``?pin-value=<pin>`` to the URI when required.
     """
     def __init__(self, section, etype, node):
         super().__init__(section, etype, node)
@@ -53,6 +75,8 @@ class Entry_x509_cert(Entry_collection):
         self.dm_data_ext_boot_block = None
         self.firewall_cert_data = None
         self.debug = False
+        self.pkcs11_uri = None
+        self.pkcs11_module = None
 
     def ReadNode(self):
         super().ReadNode()
@@ -61,6 +85,10 @@ class Entry_x509_cert(Entry_collection):
         self.key_fname = self.GetEntryArgsOrProps([
             EntryArg('keyfile', str)], required=True)[0]
         self.sw_rev = fdt_util.GetInt(self._node, 'sw-rev', 1)
+        self.pkcs11_uri = self.GetEntryArgsOrProps([
+            EntryArg('pkcs11-uri', str)], required=False)[0]
+        self.pkcs11_module = self.GetEntryArgsOrProps([
+            EntryArg('pkcs11-module', str)], required=False)[0]
 
     def GetCertificate(self, required, type='generic'):
         """Get the contents of this entry
@@ -80,6 +108,13 @@ class Entry_x509_cert(Entry_collection):
         if input_data is None:
             return None
 
+        # Override keyfile with the PKCS#11 URI if provided. This must be
+        # done here rather than in ReadNode(), because subclasses (e.g.
+        # ti_secure_rom, ti_secure) call super().ReadNode() and then
+        # overwrite self.key_fname with the DTS 'keyfile' property.
+        if self.pkcs11_uri:
+            self.key_fname = self.pkcs11_uri
+
         uniq = self.GetUniqueName()
         output_fname = tools.get_output_filename('cert.%s' % uniq)
         input_fname = tools.get_output_filename('input.%s' % uniq)
@@ -93,7 +128,8 @@ class Entry_x509_cert(Entry_collection):
                 key_fname=self.key_fname,
                 cn=self._cert_ca,
                 revision=self._cert_rev,
-                config_fname=config_fname)
+                config_fname=config_fname,
+                pkcs11_module=self.pkcs11_module)
         elif type == 'sysfw':
             stdout = self.openssl.x509_cert_sysfw(
                 cert_fname=output_fname,
@@ -102,7 +138,8 @@ class Entry_x509_cert(Entry_collection):
                 config_fname=config_fname,
                 sw_rev=self.sw_rev,
                 req_dist_name_dict=self.req_dist_name,
-                firewall_cert_data=self.firewall_cert_data)
+                firewall_cert_data=self.firewall_cert_data,
+                pkcs11_module=self.pkcs11_module)
         elif type == 'rom':
             stdout = self.openssl.x509_cert_rom(
                 cert_fname=output_fname,
@@ -116,7 +153,8 @@ class Entry_x509_cert(Entry_collection):
                 bootcore_opts=self.bootcore_opts,
                 load_addr=self.load_addr,
                 sha=self.sha,
-                debug=self.debug
+                debug=self.debug,
+                pkcs11_module=self.pkcs11_module
             )
         elif type == 'rom-combined':
             stdout = self.openssl.x509_cert_rom_combined(
@@ -143,7 +181,8 @@ class Entry_x509_cert(Entry_collection):
                 sysfw_inner_cert_ext_boot_block=self.sysfw_inner_cert_ext_boot_block,
                 dm_data_ext_boot_block=self.dm_data_ext_boot_block,
                 bootcore_opts=self.bootcore_opts,
-                debug=self.debug
+                debug=self.debug,
+                pkcs11_module=self.pkcs11_module
             )
         if stdout is not None:
             data = tools.read_file(output_fname)
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index ca5149ee654a..e74120ba3f8f 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6884,6 +6884,102 @@ fdt         fdtmap                Extract the devicetree blob from the fdtmap
         err = stderr.getvalue()
         self.assertRegex(err, "Image 'image'.*missing bintools.*: openssl")
 
+    def testOpenSslBuildKeyArgsPem(self):
+        """Test _build_key_args with a regular PEM key file"""
+        openssl = bintool.Bintool.create('openssl')
+        args = openssl._build_key_args('/path/to/key.pem')
+        self.assertEqual(['-key', '/path/to/key.pem'], args)
+
+    def testOpenSslBuildKeyArgsPkcs11Provider(self):
+        """Test _build_key_args with a PKCS#11 URI when provider API is available"""
+        uri = 'pkcs11:token=mytoken;object=mykey'
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.object(openssl, 'run_cmd',
+                                        return_value='pkcs11 provider'):
+            args = openssl._build_key_args(uri)
+        self.assertEqual(['-provider', 'default', '-provider', 'pkcs11',
+                          '-key', uri], args)
+
+    def testOpenSslBuildKeyArgsPkcs11Engine(self):
+        """Test _build_key_args with a PKCS#11 URI when only engine API is available"""
+        uri = 'pkcs11:token=mytoken;object=mykey'
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.object(openssl, 'run_cmd', return_value=''):
+            args = openssl._build_key_args(uri)
+        self.assertEqual(['-engine', 'pkcs11', '-keyform', 'engine',
+                          '-key', uri], args)
+
+    def testOpenSslBuildKeyArgsPkcs11Pin(self):
+        """Test _build_key_args appends pin-value to URI when PKCS11_PIN is set"""
+        uri = 'pkcs11:token=mytoken;object=mykey'
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.dict('os.environ', {'PKCS11_PIN': '1234'}):
+            with unittest.mock.patch.object(openssl, 'run_cmd',
+                                            return_value='pkcs11'):
+                args = openssl._build_key_args(uri)
+        self.assertIn(f'{uri}?pin-value=1234', args)
+
+    def testOpenSslPkcs11UseProviderCached(self):
+        """Test that _pkcs11_use_provider caches its result after the first call"""
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.object(openssl, 'run_cmd',
+                                        return_value='pkcs11') as mock_cmd:
+            result1 = openssl._pkcs11_use_provider()
+            result2 = openssl._pkcs11_use_provider()
+        self.assertTrue(result1)
+        self.assertTrue(result2)
+        mock_cmd.assert_called_once_with('list', '-providers')
+
+    def testOpenSslRunCmdPkcs11NoModule(self):
+        """Test _run_cmd_pkcs11 without a module just forwards to run_cmd"""
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.object(openssl, 'run_cmd',
+                                        return_value='output') as mock_cmd:
+            result = openssl._run_cmd_pkcs11(None, 'version')
+        mock_cmd.assert_called_once_with('version')
+        self.assertEqual('output', result)
+
+    def testOpenSslRunCmdPkcs11WithModule(self):
+        """Test _run_cmd_pkcs11 sets PKCS#11 module env vars when a path is given"""
+        module = '/usr/lib/pkcs11/libsofthsm2.so'
+        openssl = bintool.Bintool.create('openssl')
+        with unittest.mock.patch.object(openssl, 'run_cmd',
+                                        return_value='output'):
+            with unittest.mock.patch.dict('os.environ', {}, clear=False):
+                openssl._run_cmd_pkcs11(module, 'version')
+                self.assertEqual(module, os.environ.get('PKCS11_MODULE_PATH'))
+                self.assertEqual(module, os.environ.get('PKCS11_PROVIDER_MODULE'))
+
+    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 ''
+
+        entry_args = {
+            'keyfile': self.TestFile('security/key.key'),
+            'pkcs11-uri': PKCS11_URI,
+            'pkcs11-module': PKCS11_MODULE,
+        }
+        with unittest.mock.patch.dict('os.environ', {}, clear=False):
+            with unittest.mock.patch.object(bintool.Bintool, 'run_cmd',
+                                            new=fake_openssl):
+                data = self._DoReadFileDtb('security/x509_cert.dts',
+                                           entry_args=entry_args)[0]
+        self.assertGreater(len(data), len(U_BOOT_DATA))
+        self.assertEqual(U_BOOT_DATA, data[-4:])
+
     def testPackRockchipTpl(self):
         """Test that an image with a Rockchip TPL binary can be created"""
         data = self._DoReadFile('vendor/rockchip_tpl.dts')
-- 
2.34.1



More information about the U-Boot mailing list