ukify: Add --sign-profile

Let's allow configuring which UKI profiles we generate signed PCR
measurements for since there are various types of profiles for
which we do not want to generate signed PCR measurements so that they
can not unlock the encrypted rootfs.

Fixes #36173.
This commit is contained in:
Daan De Meyer
2025-01-28 17:20:46 +00:00
committed by Luca Boccassi
parent 7249651bff
commit b61efe6591
2 changed files with 50 additions and 1 deletions
+11
View File
@@ -258,6 +258,17 @@
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--sign-profile=<replaceable>ID</replaceable></option></term>
<listitem><para>Takes a profile ID for which signed PCR measurements should be generated by ukify.
This option can be used together with <option>--join-profile=</option> when building the final
unified kernel image. If not specified, signed PCR measurements will be added for all profiles.
</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><option>--tools=<replaceable>DIRS</replaceable></option></term>
+39 -1
View File
@@ -141,6 +141,25 @@ def try_import(modname: str, name: Optional[str] = None) -> ModuleType:
raise ValueError(f'Kernel is compressed with {name or modname}, but module unavailable') from e
def read_env_file(text: str) -> dict[str, str]:
result = {}
for line in text.splitlines():
line = line.rstrip()
if not line or line.startswith('#'):
continue
if m := re.match(r'([A-Z][A-Z_0-9]+)=(.*)', line):
name, val = m.groups()
if val and val[0] in '"\'':
val = next(shlex.shlex(val, posix=True))
result[name] = val
else:
print(f'bad line {line!r}', file=sys.stderr)
return result
def get_zboot_kernel(f: IO[bytes]) -> bytes:
"""Decompress zboot efistub kernel if compressed. Return contents."""
# See linux/drivers/firmware/efi/libstub/Makefile.zboot
@@ -244,6 +263,7 @@ class UkifyConfig:
hwids: Path
initrd: list[Path]
join_profiles: list[Path]
sign_profiles: list[str]
json: Union[Literal['pretty'], Literal['short'], Literal['off']]
linux: Optional[Path]
measure: bool
@@ -1249,7 +1269,10 @@ def make_uki(opts: UkifyConfig) -> None:
# PCR measurement and signing
call_systemd_measure(uki, opts=opts)
if (opts.join_profiles or not opts.profile) and (
not opts.sign_profiles or opts.profile in opts.sign_profiles
):
call_systemd_measure(uki, opts=opts)
# UKI profiles
@@ -1298,6 +1321,13 @@ def make_uki(opts: UkifyConfig) -> None:
Section.create(n, pesection.get_data(length=pesection.Misc_VirtualSize), measure=True)
)
if opts.sign_profiles:
pesection = next(s for s in pe.sections if pe_strip_section_name(s.Name) == '.profile')
id = read_env_file(pesection.get_data(length=pesection.Misc_VirtualSize).decode()).get('ID')
if not id or id not in opts.sign_profiles:
print(f'Not signing expected PCR measurements for "{id}" profile')
continue
call_systemd_measure(uki, opts=opts, profile_start=prev_len)
# UKI creation
@@ -1807,6 +1837,14 @@ CONFIG_ITEMS = [
default=[],
help='A PE binary containing an additional profile to add to the UKI',
),
ConfigItem(
'--sign-profile',
dest='sign_profiles',
metavar='ID',
action='append',
default=[],
help='Which profiles to sign expected PCR measurements for',
),
ConfigItem(
'--efi-arch',
metavar='ARCH',