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:
committed by
Luca Boccassi
parent
7249651bff
commit
b61efe6591
@@ -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
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user