Skip to content

ukify: Support multiple PCR signing keys to sign phases separately#4279

Open
pothos wants to merge 1 commit into
systemd:mainfrom
pothos:phases
Open

ukify: Support multiple PCR signing keys to sign phases separately#4279
pothos wants to merge 1 commit into
systemd:mainfrom
pothos:phases

Conversation

@pothos
Copy link
Copy Markdown
Contributor

@pothos pothos commented Apr 21, 2026

To be able to bind a secret against a signed PCR policy so that it only unlocks in the initrd but not the final system one has to sign the policies with separate keys because that's what one actually binds to. This is supported in ukify as "phases" and ukify accepts the PCR signing keys specified multiple times together with the phase they are for. We can't extend the existing config setting for this scheme, so instead we have to add a new setting which can hold the configuration entries. Also, we need a new setting to specify which PCR pub key goes into the .pcrpkey UKI section because when we have many, ukify won't add any by default.
Add SignExpectedPcrWithPhases= as alternative to SignExpectedPcrKey=/ SignExpectedPcrCertificate=/*Source= where we can now specify the phase signing configuration one line each. A line contains KEY CERT PHASES [KEYSRC [CERTSRC]] where KEYSRC/CERTSRC defaults to "file". One can also set "-" for PHASES to omit --phases for ukify so that it chooses the defaults. Also add SignExpectedPcrUKIPublicKey= to be able to specify the key for the .pcrpkey UKI section.

Closes #4109

@pothos pothos force-pushed the phases branch 2 times, most recently from 31bd2c6 to 0d61443 Compare April 22, 2026 06:37
@pothos pothos changed the title WIP: ukify: Support multiple PCR signing keys to sign phases separately ukify: Support multiple PCR signing keys to sign phases separately Apr 22, 2026
@pothos pothos marked this pull request as ready for review April 22, 2026 07:47
Copy link
Copy Markdown
Contributor

@behrmann behrmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arghs, forgot to press the submit button

Comment thread mkosi/__init__.py Outdated
Comment thread mkosi/__init__.py Outdated
Comment thread mkosi/config.py Outdated
Comment thread mkosi/config.py Outdated
Comment thread mkosi/resources/man/mkosi.1.md Outdated
Comment thread mkosi/resources/man/mkosi.1.md Outdated
Comment thread mkosi/config.py Outdated
Comment thread mkosi/resources/man/mkosi.1.md Outdated
Comment thread mkosi/resources/man/mkosi.1.md Outdated
@pothos pothos force-pushed the phases branch 3 times, most recently from ba039eb to 1981f1e Compare April 27, 2026 01:20
To be able to bind a secret against a signed PCR policy so that it only
unlocks in the initrd but not the final system one has to sign the
policies with separate keys because that's what one actually binds to.
This is supported in ukify as "phases" and ukify accepts the PCR
signing keys specified multiple times together with the phase they are
for. We can't extend the existing config setting for this scheme, so
instead we have to add a new setting which can hold the configuration
entries. Also, we need a new setting to specify which PCR pub key goes
into the .pcrpkey UKI section because when we have many, ukify won't
add any by default.
Add SignExpectedPcrWithPhases= as alternative to SignExpectedPcrKey=/
SignExpectedPcrCertificate=/*Source= where we can now specify the
phase signing configuration one line each. A line contains
KEY CERT PHASES [KEYSRC [CERTSRC]] where KEYSRC/CERTSRC defaults to
"file". One can also set "-" for PHASES to omit --phases for ukify so
that it chooses the defaults. Also add SignExpectedPcrUKIPublicKey= to
be able to specify the key for the .pcrpkey UKI section.

Closes systemd#4109
@bluca
Copy link
Copy Markdown
Member

bluca commented Apr 27, 2026

The general feature looks ok, as long as the existing configs keep working. I'm not 100% convinced on the format of the configuration, giving semantic meaning to line breaks, but I'll leave that decision to @daandemeyer and @behrmann

@behrmann
Copy link
Copy Markdown
Contributor

I'm not 100% convinced on the format of the configuration, giving semantic meaning to line breaks

That is indeed a bit hairy, but the problem is that we're running out of separators at this interplay, since between mkosi and ukify we're already using whitespace, commas, and colons. Could this maybe be better served by an indirection putting this into the native config files for ukify and passing them to ukify from some well-known place, e.g. some mkosi.ukify?

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 22, 2026

Claude review of PR #4279 (f33f09e)

Suggestions

  • Validate consistent key sources across signersmkosi/__init__.py:1818 — When multiple signers have non-file key sources, --signing-engine/--signing-provider is emitted once per signer. Since ukify uses a single global engine/provider, inconsistent sources between signers would produce conflicting arguments with no early validation error. Consider either emitting it once or adding a check in validate_pcr_signing that all signers share the same key_source type.

Workflow run

Comment thread mkosi/__init__.py
Comment on lines +1817 to +1818
if signer.key_source.type == KeySourceType.engine:
arguments += ["--signing-engine", signer.key_source.source]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude: suggestion: Claude: When multiple signers have non-file key sources, --signing-engine/--signing-provider is emitted once per signer in the loop. Since ukify uses a single global engine/provider, passing it multiple times is redundant at best. More importantly, if different signers specify inconsistent key source types (e.g., one uses engine:pkcs11 and another uses provider:pkcs11), this would produce conflicting --signing-engine and --signing-provider arguments on the same ukify command line with no early validation error from mkosi.

The documentation notes that "it is the user's responsibility to keep sources consistent across signers," but a validation check in validate_pcr_signing (similar to the existing secure_boot_key_source consistency check) would catch misconfigurations early with a clear error message. Alternatively, emitting --signing-engine/--signing-provider only once (outside or after the loop) would make the "global" nature explicit in code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

Support for Phases= from systemd-measure

4 participants