Hi Wojciech,
On 1/20/26 9:12 AM, Wojciech Dubowik wrote:
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).
Signed-off-by: Wojciech Dubowik <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
---
tools/binman/ftest.py | 53 +++++++++++++++++++
.../binman/test/351_capsule_signed_pkcs11.dts | 22 ++++++++
2 files changed, 75 insertions(+)
create mode 100644 tools/binman/test/351_capsule_signed_pkcs11.dts
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 21ec48d86fd1..a005a167e414 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,58 @@ 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')
+ tools.write_file(softhsm2_conf, data +
+ f'\ndirectories.tokendir = \
+ {softhsm2_tokens_dir}\n'.encode("utf-8"))
+
data is already in softhsm2_conf due to calling
self._MakeInputFile(f'{prefix}softhsm2.conf', data)
you can simply do the same I did in testFitSignPKCS11Simple and append
to the file. Or you can append to data before you call _MakeInputFile().
+ p11_kit_config = configparser.ConfigParser()
+ out = tools.run('p11-kit', 'print-config')
Please create a bintool and call CheckBintool so we can skip the test if
p11-kit isn't installed. It'll be a bit awkward because there's no
--version, --help, to print the help text but not have a non-zero exit code.
+ p11_kit_config.read_string(out)
+ softhsm2_lib = p11_kit_config['softhsm2']['module']
+
We probably want to have some try..except here, or a more forgiving
.get('softhsm2', {}).get('module')
and fail the test if we don't get a path?
+ os.environ['SOFTHSM2_CONF'] = softhsm2_conf
This is wrong, you'll be messing up with the environment of all tests
being run in the same thread. You must use the "with
unittest.mock.patch.dict('os.environ'," implementation I used in
testFitSignPKCS11Simple.
+ 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')
+
+ os.environ['PKCS11_MODULE_PATH'] = softhsm2_lib
Same issue as with SOFTHSM2_CONF, you must mock the environment and not
write to it.
+ data = self._DoReadFile('351_capsule_signed_pkcs11.dts')
+
+ self._CheckCapsule(data, signed_capsule=True)
+
+ # Verify signed capsule
+ hdr = self._GetCapsuleHeaders(data)
+ monotonic_count = hdr['EFI_FIRMWARE_IMAGE_AUTH.MONOTONIC_COUNT']
+
+ with open(self._indir + '/capsule_input.bin', 'ab') as f:
Please use self._MakeInputFile() and prefix it with the name of the
method so there's no possible name clash.
+ f.write(struct.pack('<Q', int(monotonic_count, 16)))
+
+ try:
+ tools.run('openssl', 'smime', '-verify', '-inform', 'DER',
This means you depend on openssl being present. Should we maybe do
something like
openssl = bintool.Bintool.create('openssl')
self._CheckBintool(openssl)
[...]
openssl.run_cmd(['smime', ...])
to skip the test if it isn't installed?
+ '-in', tools.get_output_dir() +
'/capsule.efi-capsule.p7',
tools.get_output_filename('capsule.efi-capsule.p7')
+ '-content', self._indir + '/capsule_input.bin',
Reuse the path created by self._MakeInputFile().
+ '-CAfile', cert_file, '-no_check_time')
+ except ValueError:
+ self.assertIn('UEFI Capsule verification failed')
+
I don't think this is valid.
https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertIn
states you need 2 (or three) arguments, only one's provided here.
I'm assuming we don't need the try..except since the raised Exception
will just stop (and fail) the execution of the test but continue with
the other ones? Can you check (locally) by purposefully using the wrong
key for example?
Cheers,
Quentin