Skip to content

Commit b51594c

Browse files
authored
Merge pull request #2899 from OSInside/s390_attestation_request_data
Add support for s390 UV-attestation
2 parents 888b565 + 0313b7b commit b51594c

File tree

6 files changed

+171
-6
lines changed

6 files changed

+171
-6
lines changed

.github/workflows/ci-code-style.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1616

1717
steps:
1818
- uses: actions/checkout@v3

.github/workflows/ci-units-types.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
15+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1616

1717
steps:
1818
- uses: actions/checkout@v3

kiwi/bootloader/config/zipl.py

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import os
1919
import copy
2020
import logging
21+
import shutil
2122
from string import Template
2223
from typing import Dict
2324

@@ -123,7 +124,8 @@ def setup_loader(self, target: str) -> None:
123124
)
124125
Command.run(genprotimg_host_key_check)
125126
os.unlink(f'{root_dir}/{cc_boot_image}')
126-
# final call
127+
128+
# generate secure execution image
127129
genprotimg = genprotimg_init
128130
genprotimg.append('--no-verify')
129131
for host_key_certificate in host_key_certificates:
@@ -135,6 +137,73 @@ def setup_loader(self, target: str) -> None:
135137
genprotimg.append(host_crl)
136138
Command.run(genprotimg)
137139

140+
# extract secure execution header
141+
secure_execution_header = 'secure_execution_header.bin'
142+
Command.run(
143+
[
144+
'chroot', root_dir, 'pvextract-hdr',
145+
'-o', secure_execution_header,
146+
cc_boot_image
147+
]
148+
)
149+
shutil.move(
150+
os.sep.join([root_dir, secure_execution_header]),
151+
os.sep.join(
152+
[
153+
self.custom_args['target_dir'],
154+
'{0}.{1}-{2}.{3}'.format(
155+
self.xml_state.xml_data.get_name(),
156+
self.arch,
157+
self.xml_state.get_image_version(),
158+
secure_execution_header
159+
)
160+
]
161+
)
162+
)
163+
164+
# generate attestation request binary and response key
165+
attestation_request = 'attestation_request.bin'
166+
attestation_response_key = 'attestation_response.key'
167+
pvattest = [
168+
'chroot', root_dir, 'pvattest', 'create',
169+
'--no-verify', '--verbose',
170+
'-o', attestation_request,
171+
'--arpk', attestation_response_key
172+
]
173+
for host_key_certificate in host_key_certificates:
174+
for host_key in host_key_certificate.get('hkd_cert'):
175+
pvattest.append('-k')
176+
pvattest.append(host_key)
177+
Command.run(pvattest)
178+
shutil.move(
179+
os.sep.join([root_dir, attestation_request]),
180+
os.sep.join(
181+
[
182+
self.custom_args['target_dir'],
183+
'{0}.{1}-{2}.{3}'.format(
184+
self.xml_state.xml_data.get_name(),
185+
self.arch,
186+
self.xml_state.get_image_version(),
187+
attestation_request
188+
)
189+
]
190+
)
191+
)
192+
shutil.move(
193+
os.sep.join([root_dir, attestation_response_key]),
194+
os.sep.join(
195+
[
196+
self.custom_args['target_dir'],
197+
'{0}.{1}-{2}.{3}'.format(
198+
self.xml_state.xml_data.get_name(),
199+
self.arch,
200+
self.xml_state.get_image_version(),
201+
attestation_response_key
202+
)
203+
]
204+
)
205+
)
206+
138207
self.custom_args['secure_linux'] = True
139208
self.custom_args['secure_image_file'] = cc_boot_image
140209
os.unlink(f'{root_dir}/{self.custom_args["kernel"]}')

kiwi/builder/disk.py

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ def __init__(
166166
self.luks = xml_state.get_luks_credentials()
167167
self.use_disk_password = \
168168
xml_state.get_build_type_bootloader_use_disk_password()
169+
self.host_key_certificates = xml_state.get_host_key_certificates()
169170
self.integrity = xml_state.build_type.get_standalone_integrity()
170171
self.integrity_legacy_hmac = \
171172
xml_state.build_type.get_integrity_legacy_hmac()
@@ -419,7 +420,64 @@ def create_disk(self) -> Result:
419420
compress=compression,
420421
shasum=True
421422
)
422-
423+
if self.host_key_certificates and 's390' in self.arch:
424+
self.result.add(
425+
key='secure_execution_header',
426+
filename=os.path.normpath(
427+
os.sep.join(
428+
[
429+
self.target_dir,
430+
'{0}.{1}-{2}.{3}'.format(
431+
self.xml_state.xml_data.get_name(),
432+
self.arch,
433+
self.xml_state.get_image_version(),
434+
'secure_execution_header.bin'
435+
)
436+
]
437+
)
438+
),
439+
use_for_bundle=True,
440+
compress=False,
441+
shasum=False
442+
)
443+
self.result.add(
444+
key='attestation_response_key',
445+
filename=os.path.normpath(
446+
os.sep.join(
447+
[
448+
self.target_dir,
449+
'{0}.{1}-{2}.{3}'.format(
450+
self.xml_state.xml_data.get_name(),
451+
self.arch,
452+
self.xml_state.get_image_version(),
453+
'attestation_response.key'
454+
)
455+
]
456+
)
457+
),
458+
use_for_bundle=True,
459+
compress=False,
460+
shasum=False
461+
)
462+
self.result.add(
463+
key='attestation_request',
464+
filename=os.path.normpath(
465+
os.sep.join(
466+
[
467+
self.target_dir,
468+
'{0}.{1}-{2}.{3}'.format(
469+
self.xml_state.xml_data.get_name(),
470+
self.arch,
471+
self.xml_state.get_image_version(),
472+
'attestation_request.bin'
473+
)
474+
]
475+
)
476+
),
477+
use_for_bundle=True,
478+
compress=False,
479+
shasum=False
480+
)
423481
# create image root metadata
424482
self.result.add(
425483
key='image_packages',
@@ -557,7 +615,9 @@ def _bootloader_instance(self, disk: Disk) -> BootLoaderConfigBase:
557615
'boot_is_crypto':
558616
self.boot_is_crypto,
559617
'config_options':
560-
self.xml_state.get_bootloader_config_options()
618+
self.xml_state.get_bootloader_config_options(),
619+
'target_dir':
620+
self.target_dir
561621
}
562622
if self.bootloader.startswith('grub'):
563623
custom_args.update(

test/unit/bootloader/config/zipl_test.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def setup(self, mock_FirmWare):
3939
self.bootloader.custom_args['initrd'] = None
4040
self.bootloader.custom_args['boot_options'] = {}
4141
self.bootloader.custom_args['targetbase'] = '/dev/disk'
42+
self.bootloader.custom_args['target_dir'] = 'target_dir'
4243
self.bootloader.sys_mount = Mock(
4344
mountpoint='sys_mount'
4445
)
@@ -63,6 +64,7 @@ def test_setup_loader_raises_invalid_target(self, mock_os_unlink):
6364
with raises(KiwiBootLoaderTargetError):
6465
self.bootloader.setup_loader('iso')
6566

67+
@patch('shutil.move')
6668
@patch('os.unlink')
6769
@patch('os.path.exists')
6870
@patch('kiwi.bootloader.config.zipl.BootImageBase.get_boot_names')
@@ -79,7 +81,7 @@ def test_setup_loader(
7981
mock_write_config_file, mock_Temporary_new_file,
8082
mock_BootLoaderTemplateZipl, mock_Command_run,
8183
mock_Path_create, mock_Path_wipe, mock_BootImageBase_get_boot_names,
82-
mock_os_path_exists, mock_os_unlink
84+
mock_os_path_exists, mock_os_unlink, mock_shutil_move
8385
):
8486
temporary = Mock()
8587
temporary.name = 'system_root_mount/kiwi_zipl.conf_'
@@ -146,6 +148,22 @@ def test_setup_loader(
146148
'--crl', '/path/to/revocation-list.crl',
147149
]
148150
),
151+
call(
152+
[
153+
'chroot', 'system_root_mount', 'pvextract-hdr',
154+
'-o', 'secure_execution_header.bin',
155+
'bootpath/kernel-filename.cc'
156+
]
157+
),
158+
call(
159+
[
160+
'chroot', 'system_root_mount', 'pvattest', 'create',
161+
'--no-verify', '--verbose',
162+
'-o', 'attestation_request.bin',
163+
'--arpk', 'attestation_response.key',
164+
'-k', '/path/to/host.crt'
165+
]
166+
),
149167
call(
150168
[
151169
'chroot', 'system_root_mount', 'zipl',
@@ -156,6 +174,23 @@ def test_setup_loader(
156174
]
157175
)
158176
]
177+
assert mock_shutil_move.call_args_list == [
178+
call(
179+
'system_root_mount/secure_execution_header.bin',
180+
'target_dir/image-name.x86_64-image-version.'
181+
'secure_execution_header.bin'
182+
),
183+
call(
184+
'system_root_mount/attestation_request.bin',
185+
'target_dir/image-name.x86_64-image-version.'
186+
'attestation_request.bin'
187+
),
188+
call(
189+
'system_root_mount/attestation_response.key',
190+
'target_dir/image-name.x86_64-image-version.'
191+
'attestation_response.key'
192+
)
193+
]
159194
assert mock_os_unlink.call_args_list == [
160195
call('system_root_mount/bootpath/kernel-filename.cc'),
161196
call('system_root_mount/bootpath/kernel-filename'),

test/unit/builder/disk_test.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,7 @@ def test_create_disk_standard_root_s390_boot(
12051205
mock_Disk.return_value.__enter__.return_value = \
12061206
self._get_disk_instance()
12071207
self.disk_builder.arch = 's390x'
1208+
self.disk_builder.host_key_certificates = Mock()
12081209
bootloader_config = Mock()
12091210
bootloader_config.get_boot_cmdline = Mock(
12101211
return_value='boot_cmdline'

0 commit comments

Comments
 (0)