Commit Graph
36 Commits
Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek d1c345a079 pcrextend: convert to VERB_COMMAND and add --introspect-cli
The custom help() is replaced by a COMMAND() description, and
--introspect-cli is added. The man page is adjusted to match.
2026-08-17 13:21:31 +02:00
Chris Coulson f0f3687700 tpm2: Improve how NvPCR protection works.
NV indexes created in the storage hierarchy can be undefined and
redefined with TPM owner auth. Because of this, NvPCRs need some way
to prevent them from being redfined in a way that allows spoof
measurements to be replayed.

The current approach requires knowledge of a secret ("anchor secret")
in order to derive the initial NvPCR measurement and to derive a
measurement to an existing PCR (9). The credential is protected by the
TPM with a PCR policy. Without access to the credential, it's not
possible to replay measurements to a newly defined NvPCR without
breaking the binding with the measurement in PCR 9. However, this
approach has a couple of issues:

- The credential is currently only protected by PCR11. As it's not
  protected by the rest of the boot chain, it's possible to boot other
  operating systems in order to replay the PCR11 measurements and
  recover the secret. Note that as the NvPCR anchoring happens in early
  boot, the credential is stored in the ESP.
- Someone with privileged access to a system can just create a new
  credential containing a known secret and store this in /var/lib and
  the ESP. The NvPCRs are anchored with this known secret on subsequent
  boots, and therefore the measurements can no longer be trusted.
  Imagine the scenario where privileged access is theoretically possible
  as a result of some vulnerability. After upgrading the system to fix
  this vulnerability, the system should be able to attest that it is
  now in a good state. However, if an adversary were able to use their
  priviliges to replace the credential, they are able to obtain
  persistence and the NvPCR measurements are no longer trustworthy.

This PR changes things to take a different approach. Instead of
requiring knowledge of a secret, the NvPCRs are now created in a way
that requires a policy to be satisfied for writing. The write policy has
2 branches:
- TPM2_PolicyNvWritten(true), which can be satisified without any
  further authorization if the NvPCR has already been extended.
- TPM2_PolicyAuthorize(pcrPubKey, SHA256("nvpcr-init")) which can be
  satisfied with a signed PCR policy, and must be used to perform the
  initial extend to a NvPCR.

The intention here is that the signed PCR policy that can be used to
authorize the initial extend to the NvPCR can only be satisfied during
early boot. During later boot phases, this signed PCR policy must not be
valid. This means that if a NvPCR is undefined and redefined, it won't
be possible to satisfy its write policy in order to able to perform the
initial extend.

In order to anchor the NvPCRs and prevent them from being undefined and
then redefined with a different policy that does allow them to be
extended, the names of the NvPCRs are measured to PCR9. Verifiers must
check that the names of attested NvPCRs match the measurements in PCR9.

This uses the PCR signing key from the currently booted UKI to create
the NvPCRs. If this changes between boots, then tpm2-setup automatically
recreates new NvPCRs with an updated write policy to reflect this. I've
tried to be careful to not undefine arbitrary NV indexes in this case,
so it checks that the existing NV index looks like a NvPCR (ie, it has
the expected attributes) before undefining it.

I did originally try to preserve the old behaviour for existing systems,
but it makes things a lot more complicated. As the new implementation
already creates new NvPCRs when the PCR signing key changes, I ended up
just automatically upgrading the old NvPCRs as well. Again, I check here
that any existing NV index looks like an old style NvPCR (ie, it has the
expected attributes) before undefining it.

I did notice that the initial NvPCR measurement isn't going into the
log. I don't know if that was an intentional choice, but I've preserved
that behaviour in this PR.

This also adds a new option to ukify (--sign-initrd-pcrs) which creates
signed policies (one per PCR bank) that can only be satisfied from the
initrd. These policies are used for initializing the NvPCRs, but can also
be used for protecting TPM2 keyslots enrolled with systemd-cryptenroll
(by using the --tpm2-public-key-policyref=initrd option).

There is one outstanding issue. The NvPCR definitions support different
algorithms, but the use of PolicyAuthorize means that they can only support
SHA-256 for now. This is because the signed policy algorithm must match
the name algorithm, and some additional work is required to support
signed PCR policies for algorithms other than SHA256. I've left a note in
tpm2_nvpcr_initialize that details what's required, and I'll take a look
at that in a subsequent PR.
2026-07-28 08:35:39 +02:00
Ronan Pigott c7e1fe094d man: correct a few manpage references 2026-06-06 10:47:10 +01:00
Lennart Poettering e32209c69c pcrextend: add support for measuring a user record, to be executed on first login of the user
This is supposed to be useful to mark an interactive user login as a
"break glass" event in the measurement logs, i.e. as in many typically
headless scenerios this indicates debug access or similar.
2026-05-22 12:15:12 +02:00
Antonio Alvarez Feijoo d2983ba6e7 man: fix typos in some binary names 2026-03-31 09:47:27 +01:00
Lennart Poettering 7c27f9f594 pcrextend: measure another separator at boot
This has been requested previously for PCR 7 (#40567), but let's do that
for all firmware owned PCRs, since some firmwares forget to measure
their own separator. Let's hence measure our own guranteed one.

Fixes: #40567
2026-03-26 16:11:34 +01:00
Lennart Poettering 45c305f9b8 man: add pcrproduct to man page header, too 2025-11-14 22:22:39 +01:00
Lennart Poettering 867e64737a units: measure a separator event into PCR 9 after completing NvPCR initialization
We do this in a separate service (rather than inside of
systemd-tpm2-setup), since we want failures of this measurement to
result in an instant reboot, like for most our measurements.

Failures to initialize nvpcrs, or allocate an SRK are somewhat OK (and
more likely), as long as this separator communicates clearly where they
have to have taken place, if they worked.
2025-11-14 22:22:39 +01:00
Lennart Poettering 86dc140b9f pcrextend: allow setting the event type for the event log on the command line
This makes the tool more powerful as we can invoke it for any type of
measurement correctly
2025-11-14 22:04:58 +01:00
Lennart Poettering 0196abbd10 pcrextend: automatically measure SMBIOS product ID at boot
Now that PCRs are not that expensive anymore, let's use them to measure
the SMBIOS product ID to one.
2025-11-02 21:14:35 +01:00
Lennart Poettering 2b90bf1730 pcrextend: make use new nvindex-based PCRs 2025-11-02 21:14:35 +01:00
Zbigniew Jędrzejewski-Szmek b082968d19 man: better tags, more links, minor grammar and formatting improvements
Closes https://github.com/systemd/systemd/issues/35751.
2025-05-28 15:35:53 +02:00
Jan Engelhardt c592ebdf4f man: grammar fixes for introductory adverbs/phrases 2024-12-25 17:24:38 +01:00
MaxHearnden bd96d63787 Use the correct name of CEL
It's Canonical Event Format, not Common
2024-05-08 13:34:07 +02:00
Sam Leonard 9bfabe14e5 man: fix incorrect XML in man page 2024-04-15 10:40:11 +02:00
Zbigniew Jędrzejewski-Szmek ec3cf73f30 meson/man: allow man pages to use multiple conditions
This way the man pages are installed only when the corresponding binary is
installed. The conditions in man pages and man/rules/meson.build are adjusted to
match the conditions for units in units/meson.build.
2024-03-06 09:55:01 +00:00
David Tardon eea10b26f7 man: use same version in public and system ident. 2023-12-25 15:51:47 +01:00
David Tardon 13a69c120b man: use <simplelist> for 'See also' sections
This is just a slight markup improvement; there should be no difference
in rendering.
2023-12-23 08:28:57 +01:00
Lennart Poettering 4c376e58da markdown: add document listing TPM2 PCR measurements we make comprehensively
This is useful to write TPM event log decoders.
2023-10-04 15:38:48 +02:00
Abderrahim Kitouni 2de0bb2fad man: add a couple missing version annotations
These were discovered by the newly added checks
2023-10-01 11:54:29 +01:00
Lennart Poettering 9551aa707d tpm2: move measurement log to /run/log/ (from /var/log/)
I have no idea what went on in my mind when I used a path in /var/ for
the tpm2 event log we now keep for userspace measurements. The
measurements are only valid for the current boot, hence should not be
persisted (in particular as they cannot be rotated, hence should not
grow without bounds).

Fix that, simply move from /var/log/ to /run/log/.
2023-09-29 14:35:56 +02:00
Lennart Poettering 75174a5de9 man: briefly document that we are now keeping an event log in userspace for out measurements 2023-09-25 17:17:20 +02:00
Lennart Poettering b0d00ec60a pcrextend: make PCR index configurable
Let's make the tool a tiny bit more generic by allowing the PCR index to
measure into to be configurable.
2023-09-25 17:17:20 +02:00
Lennart Poettering 32295fa08f pcrphase: rename binary to pcrextend
The tool initially just measured the boot phase, but was subsequently
extended to measure file system and machine IDs, too. At AllSystemsGo
there were request to add more, and make the tool generically
accessible.

Hence, let's rename the binary (but not the pcrphase services), to make
clear the tool is not just measureing the boot phase, but a lot of other
things too.

The tool is located in /usr/lib/ and still relatively new, hence let's
just rename the binary and be done with it, while keeping the unit names
stable.

While we are at it, also move the tool out of src/boot/ and into its own
src/pcrextend/ dir, since it's not really doing boot related stuff
anymore.
2023-09-25 17:17:20 +02:00
Abderrahim Kitouni ec07c3c80b man: add version info
This tries to add information about when each option was added. It goes
back to version 183.

The version info is included from a separate file to allow generating it,
which would allow more control on the formatting of the final output.
2023-08-29 14:07:24 +01:00
Zbigniew Jędrzejewski-Szmek 8fb350049b man: fixes for assorted issues reported by the manpage-l10n project
Fixes #26761.
2023-05-17 12:25:01 +02:00
Jan Janssen dfca5587cf tree-wide: Drop gnu-efi
This drops all mentions of gnu-efi and its manual build machinery. A
future commit will bring bootloader builds back. A new bootloader meson
option is now used to control whether to build sd-boot and its userspace
tooling.
2023-03-10 11:41:03 +01:00
Zbigniew Jędrzejewski-Szmek f37f0f35cd man: fix links to man pages
Done using linkchecker as usual.
2023-02-09 14:30:43 +01:00
Simon Brand 45ab6f2a37 man: correct path for systemd-pcrphase 2023-02-03 12:51:57 +09:00
Lennart Poettering 2bd33c909c man: document new machine-id/fs measurement options 2023-01-17 09:42:16 +01:00
Zbigniew Jędrzejewski-Szmek 86a066157e man: reword "string is extended into PCR"
Originally, people used "extend a PCR with a measurement" or
"measure some blob into the PCR". In our docs those uses got merged
into "extend a string into a PCR". The meaning is clear to developers, but
it's a very jargony syntax that wouldn't make any sense to somebody who encounters
it the first time. Let's return to the more natural original phrasing.

Also, change various "this is supposed to act as" to "this acts as". If it
doesn't work, we have a bug to fix. This indirection is not useful.

Also, "boot path" → "phase path" and other smaller cleanups.
2023-01-11 17:13:05 +01:00
Zbigniew Jędrzejewski-Szmek 8b9f092112 man: fix issues reported by the manpage-l10n project
Fixes #25780.

> Man page: crypttab.5
> Issue 1:  Missing fullstop
> Issue 2:  I<cipher=>, I<hash=>, I<size=> → B<cipher=>, B<hash=>, B<size=>
>
> "Force LUKS mode\\&. When this mode is used, the following options are "
> "ignored since they are provided by the LUKS header on the device: "
> "I<cipher=>, I<hash=>, I<size=>"

Seems OK to me. The full stop is there and has been for at least a few years. And we use <option> for the markup, which is appropriate here.

> Man page: crypttab.5
> Issue 1:  Missing fullstop
> Issue 2:  I<cipher=>, I<hash=>, I<keyfile-offset=>, I<keyfile-size=>, I<size=> → B<cipher=>, B<hash=>, B<keyfile-offset=>, B<keyfile-size=>, B<size=>
>
> "Use TrueCrypt encryption mode\\&. When this mode is used, the following "
> "options are ignored since they are provided by the TrueCrypt header on the "
> "device or do not apply: I<cipher=>, I<hash=>, I<keyfile-offset=>, I<keyfile-"
> "size=>, I<size=>"

Same.

> Man page: journalctl.1
> Issue 1:  make be → may be

Fixed.

> Issue 2:  below\\&. → below:

Fixed.

> Man page: journalctl.1
> Issue:    Colon at the end?
>
> "The following commands are understood\\&. If none is specified the default "
> "is to display journal records\\&."
> msgstr ""
> "Die folgenden Befehle werden verstanden\\&. Falls keiner festgelegt ist, ist "
> "die Anzeige von Journal-Datensätzen die Vorgabe\\&."

This is a bit awkward, but I'm not sure how to fix it.

> Man page: kernel-install.8
> Issue:    methods a fallback → methods fallback

It was correct, but I added a comma to make the sense clearer.

> Man page: loader.conf.5
> Issue 1:  secure boot variables → Secure Boot variables
> Issue 2:  one → one for (multiple times)
>
> "Supported secure boot variables are one database for authorized images, one "
> "key exchange key (KEK) and one platform key (PK)\\&. For more information, "
> "refer to the \\m[blue]B<UEFI specification>\\m[]\\&\\s-2\\u[2]\\d\\s+2, "
> "under Secure Boot and Driver Signing\\&. Another resource that describe the "
> "interplay of the different variables is the \\m[blue]B<EDK2 "
> "documentation>\\m[]\\&\\s-2\\u[3]\\d\\s+2\\&."

"one of" would sound strange. "One this and one that" is OK.

> Man page: loader.conf.5
> Issue:    systemd-boot → B<systemd-boot>(7)

Fixed.

> Man page: logind.conf.5
> Issue:    systemd-logind → B<systemd-logind>(8)

We use <filename>systemd-logind</> on subsequent references… I think that's good enough.

> Man page: nss-myhostname.8
> Issue:    B<getent> → B<getent>(1)

Fixed.

> Man page: nss-resolve.8
> Issue:    B<systemd-resolved> → B<systemd-resolved>(8)

The first reference does this, subsequent are shorter.

> Man page: os-release.5
> Issue:    Portable Services → Portable Services Documentation?

Updated.

> Man page: pam_systemd_home.8
> Issue:    auth and account use "reason", while session and password do not?

Reworded.

> Man page: portablectl.1
> Issue:    In systemd-portabled.service(8): Portable Services Documentation

Updated.

> Man page: repart.d.5
> Issue:    The partition → the partition

Fixed.

> Man page: repart.d.5
> Issue:    B<systemd-repart> → B<systemd-repart>(8)

The first reference does this. I also change this one, because it's pretty far down in the text.

> Man page: systemd.1
> Issue:    kernel command line twice?
>
> "Takes a boolean argument\\&. If false disables importing credentials from "
> "the kernel command line, qemu_fw_cfg subsystem or the kernel command line\\&."

Apparently this was fixed already.

> Man page: systemd-boot.7
> Issue:    enrollement → enrollment

Fixed.

> Man page: systemd-cryptenroll.1
> Issue:    multiple cases: any specified → the specified

Reworded.

> Man page: systemd-cryptenroll.1
> Issue:    If this this → If this

Fixed tree-wide.

> Man page: systemd-cryptsetup-generator.8
> Issue:    and the initrd → and in the initrd

"Is honoured by the initrd" is OK, because we often speak about the initrd as a single unit. But in the same paragraph we also used "in the initrd", which makes the other use look sloppy. I changed it to "in the initrd" everywhere in that file.

> Man page: systemd.directives.7
> Issue:    Why are these two quoted (but not others)?
>
> "B<\\*(Aqh\\*(Aq>"
>
> B<\\*(Aqs\\*(Aq>"
>
> "B<\\*(Aqy\\*(Aq>"

This is autogenerated from files… We use slightly different markup in different files, and it's just too hard to make it consistent. We gave up on this.

> Man page: systemd.exec.5
> Issue 1:  B<at>(1p) → B<at>(1)
> Issue 2:  B<crontab>(1p) → B<crontab>(1)

Fixed.

> Man page: systemd.exec.5
> Issue:    B<select()> → B<select>(2)

Fixed.

> Man page: systemd.exec.5
> Issue:   qemu → B<qemu>(1)

The man page doesn't seem to be in any of the canonical places on the web.
I added a link to online docs.

> Man page: systemd.exec.5
> Issue:    variable → variables

Seems to be fixed already.

> Man page: systemd-integritysetup-generator.8
> Issue:    systemd-integritysetup-generator → B<systemd-integritysetup-generator>

I changed <filename> to <command>.

> Man page: systemd-integritysetup-generator.8
> Issue:    superfluous comma at the end

Already fixed.

> Man page: systemd-measure.1
> Issue:    (see B<--pcr-bank=>) below → (see B<--pcr-bank=> below)

Reworded.

> Man page: systemd-measure.1
> Issue:    =PATH> → =>I<PATH>

Fixed.

> Man page: systemd-measure.1.po
> Issue:    B<--bank=DIGEST> → B<--bank=>I<DIGEST>

Fixed.

> Man page: systemd.netdev.5
> Issue:    os the → on the

Appears to have been fixed already.

> Man page: systemd.netdev.5
> Issue:    Onboard → On-board (as in previous string)

Updated.

> Man page: systemd.network.5
> Issue:    B<systemd-networkd> -> B<systemd-networkd>(8)

First reference does this, subsequent do not.

> Man page: systemd.network.5
> Issue:    B<netlabelctl> → B<netlabelctl>(8)

First reference does this, subsequent do not.

> Man page: systemd.network.5
> Issue:    Missing verb (aquired? configured?) in the half sentence starting with "or by a "

I dropped the comma.

> Man page: systemd-nspawn.1
> Issue:    All host users outside of that range → All other host users

Reworded.

> # FIXME no effect → no effect\\&.
> #. type: Plain text
> #: archlinux debian-unstable fedora-rawhide mageia-cauldron opensuse-tumbleweed
> msgid ""
> "Whichever ID mapping option is used, the same mapping will be used for users "
> "and groups IDs\\&. If B<rootidmap> is used, the group owning the bind "
> "mounted directory will have no effect"

A period is added. Not sure if there's some other issue.

> Man page: systemd-oomd.service.8
> Issue:    B<systemd> → B<systemd>(1)

Done.

> Man page: systemd.path.5
> Issue 1:  B<systemd.exec>(1) → B<systemd.exec>(5)
> Issue 2:  This section does not (yet?) exist

Fixed.

> Man page: systemd-pcrphase.service.8
> Issue 1:  indicate phases into TPM2 PCR 11 ??
> Issue 2: Colon at the end of the paragraph?

Fixed.

> Man page: systemd-pcrphase.service.8
> Issue:    final boot phase → final shutdown phase?

Updated.

> Man page: systemd-pcrphase.service.8
> Issue:    for the the → for the

Fixed tree-wide.

> Man page: systemd-portabled.service.8
> Issue:    In systemd-portabled.service(8): Portable Services Documentation

Updated.

> Man page: systemd-pstore.service.8
> Issue:    Here and the following paragraphs: . → \\&. // Upstream: What does this comment mean? // You normally write \\&. for a full dot (full stop etc.); here you write only "." (i.e. a plain dot).
>
> "and we look up \"localhost\", nss-dns will send the following queries to "
> "systemd-resolved listening on 127.0.0.53:53: first \"localhost.foobar.com\", "
> "then \"localhost.barbar.com\", and finally \"localhost\". If (hopefully) the "
> "first two queries fail, systemd-resolved will synthesize an answer for the "
> "third query."

Looks all OK to me.

> Man page: systemd.resource-control.5
> Issue:    Missing closing bracket after link to Control Groups version 1

Fixed.

> Man page: systemd-sysext.8
> Issue:    In systemd-portabled.service(8): Portable Services Documentation

Updated.

> Man page: systemd.timer.5
> Issue 1:  B<systemd.exec>(1) → B<systemd.exec>(5)
> Issue 2:  This section does not (yet?) exist

Fixed.

> Man page: systemd.unit.5
> Issue:    that is → that are

Fixed.

> Man page: systemd-veritysetup-generator.8
> Issue:    systemd-veritysetup-generator → B<systemd-veritysetup-generator>
>
 > "systemd-veritysetup-generator implements B<systemd.generator>(7)\\&."
>
> "systemd-veritysetup-generator understands the following kernel command line "
> "parameters:"

Updated.

> Man page: systemd-volatile-root.service.8
> Issue:    initrdyes → Initrd

Fixed.

> Man page: sysupdate.d.5
> Issue:    : → \\&. (As above in TRANSFER)

Updated.

> Man page: sysupdate.d.5
> Issue:    some → certain

Updated.

> Man page: sysupdate.d.5
> Issue 1:  i\\&.e\\& → I\\&.e\\&

Fixed.

> Issue 2:  the image → the system

"image" seems correct.

> Man page: tmpfiles.d.5
> Issue:    systemd-tmpfiles → B<systemd-tmpfiles>(8)

Updated.
2023-01-11 17:12:54 +01:00
Lennart Poettering 0318d54539 pcrphase: gracefully exit if TPM2 support is incomplete
If everything points to the fact that TPM2 should work, but then the
driver fails to initialize we should handle this gracefully and not
cause failing services all over the place.

Fixes: #25700
2022-12-15 22:20:54 +01:00
Lennart Poettering 15f9a1525f man: add missing reference to systemd-pcrphase-sysinit.service 2022-10-17 17:12:45 +02:00
Lennart Poettering 047273e6e8 pcrphase: add two additional phases
This adds two more phases to the PCR boot phase logic: "sysinit" +
"final".

The "sysinit" one is placed between sysinit.target and basic.target.
It's good to have a milestone in this place, since this is after all
file systems/LUKS volumes are in place (which sooner or later should
result in measurements of their own) and before services are started
(where we should be able to rely on them to be complete).

This is particularly useful to make certain secrets available for
mounting secondary file systems, but making them unavailable later.

This breaks API in a way (as measurements during runtime will change),
but given that the pcrphase stuff wasn't realeased yet should be OK.
2022-10-17 12:09:43 +02:00
Lennart Poettering 708d752479 boot: add new pcrphase tool to measure barrier strings into PCR 11 2022-09-22 16:52:06 +02:00