]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
ukify: add support for engine signing of PCR signatures 31274/head
authorLuca Boccassi <bluca@debian.org>
Sun, 11 Feb 2024 00:34:19 +0000 (00:34 +0000)
committerLuca Boccassi <bluca@debian.org>
Fri, 1 Mar 2024 17:32:19 +0000 (17:32 +0000)
man/ukify.xml
src/ukify/test/test_ukify.py
src/ukify/ukify.py

index 659c6ed0a3f3cc94c3dacc1be8963c489932ebfc..886e4522e414e76f5c77d98a462062dabc86232a 100644 (file)
       the n-th boot phase path set will be signed by the n-th key. This can be used to build different trust
       policies for different phases of the boot. In the config file, <varname>PCRPrivateKey=</varname>,
       <varname>PCRPublicKey=</varname>, and <varname>Phases=</varname> are grouped into separate sections,
-      describing separate boot phases.</para>
+      describing separate boot phases. If <varname>SigningEngine=</varname>/<option>--signing-engine=</option>
+      is specified, then the private keys arguments will be passed verbatim to OpenSSL as URIs, and the public
+      key arguments will be loaded as X.509 certificates, so that signing can be perfomed with an OpenSSL
+      engine.</para>
 
       <para>If a SecureBoot signing key is provided via the
       <varname>SecureBootPrivateKey=</varname>/<option>--secureboot-private-key=</option> option, the resulting
index ec466393d3a6a200defe175725c991b4b5039aeb..0e3f9328901dd2ff6a45bfd105c6cc8f69ac40ee 100755 (executable)
@@ -120,7 +120,7 @@ def test_apply_config(tmp_path):
     assert ns.sign_kernel is False
 
     assert ns._groups == ['NAME']
-    assert ns.pcr_private_keys == [pathlib.Path('some/path7')]
+    assert ns.pcr_private_keys == ['some/path7']
     assert ns.pcr_public_keys == [pathlib.Path('some/path8')]
     assert ns.phase_path_groups == [['enter-initrd:leave-initrd:sysinit:ready:shutdown:final']]
 
@@ -143,7 +143,7 @@ def test_apply_config(tmp_path):
     assert ns.sign_kernel is False
 
     assert ns._groups == ['NAME']
-    assert ns.pcr_private_keys == [pathlib.Path('some/path7')]
+    assert ns.pcr_private_keys == ['some/path7']
     assert ns.pcr_public_keys == [pathlib.Path('some/path8')]
     assert ns.phase_path_groups == [['enter-initrd:leave-initrd:sysinit:ready:shutdown:final']]
 
@@ -189,7 +189,7 @@ def test_parse_args_many_deprecated():
     assert opts.pcrpkey == pathlib.Path('PATH')
     assert opts.uname == '1.2.3'
     assert opts.stub == pathlib.Path('STUBPATH')
-    assert opts.pcr_private_keys == [pathlib.Path('PKEY1')]
+    assert opts.pcr_private_keys == ['PKEY1']
     assert opts.pcr_public_keys == [pathlib.Path('PKEY2')]
     assert opts.pcr_banks == ['SHA1', 'SHA256']
     assert opts.signing_engine == 'ENGINE'
@@ -235,7 +235,7 @@ def test_parse_args_many():
     assert opts.pcrpkey == pathlib.Path('PATH')
     assert opts.uname == '1.2.3'
     assert opts.stub == pathlib.Path('STUBPATH')
-    assert opts.pcr_private_keys == [pathlib.Path('PKEY1')]
+    assert opts.pcr_private_keys == ['PKEY1']
     assert opts.pcr_public_keys == [pathlib.Path('PKEY2')]
     assert opts.pcr_banks == ['SHA1', 'SHA256']
     assert opts.signing_engine == 'ENGINE'
@@ -342,8 +342,7 @@ def test_config_priority(tmp_path):
     assert opts.pcrpkey == pathlib.Path('PATH')
     assert opts.uname == '1.2.3'
     assert opts.stub == pathlib.Path('STUBPATH')
-    assert opts.pcr_private_keys == [pathlib.Path('PKEY1'),
-                                     pathlib.Path('some/path7')]
+    assert opts.pcr_private_keys == ['PKEY1', 'some/path7']
     assert opts.pcr_public_keys == [pathlib.Path('PKEY2'),
                                     pathlib.Path('some/path8')]
     assert opts.pcr_banks == ['SHA1', 'SHA256']
index 8ca93543b5dbeb949bc4d43254ab62124a8aa9d5..f7d08590d93a73d13ac702f1bae491cb7eb04120 100755 (executable)
@@ -449,7 +449,7 @@ def check_cert_and_keys_nonexistent(opts):
         *((priv_key, pub_key)
           for priv_key, pub_key, _ in key_path_groups(opts)))
     for path in paths:
-        if path and path.exists():
+        if path and pathlib.Path(path).exists():
             raise ValueError(f'{path} is present')
 
 
@@ -539,7 +539,11 @@ def call_systemd_measure(uki, linux, opts):
 
         for priv_key, pub_key, group in key_path_groups(opts):
             extra = [f'--private-key={priv_key}']
-            if pub_key:
+            if opts.signing_engine is not None:
+                assert pub_key
+                extra += [f'--private-key-source=engine:{opts.signing_engine}']
+                extra += [f'--certificate={pub_key}']
+            elif pub_key:
                 extra += [f'--public-key={pub_key}']
             extra += [f'--phase={phase_path}' for phase_path in group or ()]
 
@@ -728,11 +732,13 @@ def sbsign_sign(sbsign_tool, input_f, output_f, opts=None):
         sbsign_tool,
         '--key', opts.sb_key,
         '--cert', opts.sb_cert,
-        input_f,
-        '--output', output_f,
     ]
     if opts.signing_engine is not None:
         sign_invocation += ['--engine', opts.signing_engine]
+    sign_invocation += [
+        input_f,
+        '--output', output_f,
+    ]
     signer_sign(sign_invocation)
 
 def find_pesign(opts=None):
@@ -820,7 +826,7 @@ def make_uki(opts):
             pcrpkey = opts.pcr_public_keys[0]
         elif opts.pcr_private_keys and len(opts.pcr_private_keys) == 1:
             from cryptography.hazmat.primitives import serialization
-            privkey = serialization.load_pem_private_key(opts.pcr_private_keys[0].read_bytes(), password=None)
+            privkey = serialization.load_pem_private_key(pathlib.Path(opts.pcr_private_keys[0]).read_bytes(), password=None)
             pcrpkey = privkey.public_key().public_bytes(
                 encoding=serialization.Encoding.PEM,
                 format=serialization.PublicFormat.SubjectPublicKeyInfo,
@@ -1002,7 +1008,7 @@ def generate_keys(opts):
 
         print(f'Writing private key for PCR signing to {priv_key}')
         with temporary_umask(0o077):
-            priv_key.write_bytes(priv_key_pem)
+            pathlib.Path(priv_key).write_bytes(priv_key_pem)
         if pub_key:
             print(f'Writing public key for PCR signing to {pub_key}')
             pub_key.write_bytes(pub_key_pem)
@@ -1405,10 +1411,8 @@ CONFIG_ITEMS = [
     ConfigItem(
         '--pcr-private-key',
         dest = 'pcr_private_keys',
-        metavar = 'PATH',
-        type = pathlib.Path,
         action = 'append',
-        help = 'private part of the keypair for signing PCR signatures',
+        help = 'private part of the keypair or engine-specific designation for signing PCR signatures',
         config_key = 'PCRSignature:/PCRPrivateKey',
         config_push = ConfigItem.config_set_group,
     ),
@@ -1418,7 +1422,7 @@ CONFIG_ITEMS = [
         metavar = 'PATH',
         type = pathlib.Path,
         action = 'append',
-        help = 'public part of the keypair for signing PCR signatures',
+        help = 'public part of the keypair or engine-specific designation for signing PCR signatures',
         config_key = 'PCRSignature:/PCRPublicKey',
         config_push = ConfigItem.config_set_group,
     ),