Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WithBootManagerCodeProfile needs changes to accommodate TCG PFP spec v1.06 #308

Open
chrisccoulson opened this issue May 31, 2024 · 0 comments

Comments

@chrisccoulson
Copy link
Collaborator

chrisccoulson commented May 31, 2024

Previous versions of the TCG PFP spec describe a EV_EFI_ACTION event "Calling EFI Application from Boot Option" optionally measured to PCR4 before the first launch event. If this exists in the current log, we copy it to the computed profile.

v1.06 of this spec adds an additional EV_EFI_ACTION event - "Booting to <Boot####> Option". Whilst the current WithBootManagerCodeProfile will also copy this event to the computed profile if it exists in the current log, there needs to be an API to specify which boot entry will be used to boot a specific path so that we predict the correct PCR values, rather than just blindly copying the entry in the log, which might contain the wrong boot number. This needs coordinating with whatever is writing to BootXXXX, BootOrder and BootNext variables.

Right now, the pre-install checks I'm working on will detect this and disable support for WithBootManagerCodeProfile, but we need to fix this fairly urgently

chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 12, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option. Any other event type at this stage is rejected
as an error, as it would result in an invalid policy being generated by
the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of the
first 2 EV_EFI_BOOT_SERVICES_APPLICATION events are verified. This
ensures that if the IBL loads the SBL outside of the LoadImage service
(ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to
properly measure the Authenticode digest of the SBL (ie, grub).

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 13, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 13, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 13, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 14, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 14, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 14, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Aug 17, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot.

First of all, in the pre-OS environment, it checks that the log only
contains either a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single
EV_EFI_ACTION "Calling EFI Application from Boot Option" event (after
which, it expects to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

Before processing the OS-present part of the log, it reads the
BootCurrent EFI variable and matches this to a EFI_LOAD_OPTION from the
TCG log - it uses the log as load options can be updated at runtime and
might be out of date when this code runs.

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader, and it expects the path of this to match the previously
discovered load option - note that it doesn't expect a complete match.
See how path matching works in efi.DevicePath.Matches. Any other event
type at this stage is rejected as an error, as it would result in an invalid
policy being generated by the code in efi/fw_load_handler.go. If the first
EV_EFI_BOOT_SERVICES_APPLICATION event is not the initial boot loader, it
checks to see if it is part of Absolute, in which case it skips it and
looks for the next event. Note that Absolute will be copied to the computed
policy if it is present by efi/fw_load_handler.go, altohugh it's
recommended that this is disabled instead. The next event must be the
initial boot loader, matched to the EFI_LOAD_OPTION that the BootCurrent
EFI variable points to, else an error is returned. It verifies that the
digest in the log matches the Authenticode digest of the first boot file
supplied to the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package takes
this into account). For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION),
it verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, but the function does require that the digests of
at least one EV_EFI_BOOT_SERVICES_APPLICATION event other than the IBL is
verified. This ensures that if the IBL loads the SBL outside of the LoadImage
service (ie, how shim loads grub), that the EFI_TCG2_PROTOCOL interface is
properly supported by the firmware to allow the IBL (ie, shim) to properly
measure the Authenticode digest of the SBL (ie, grub). This isn't a test
against OS components, which is is now what these tests are for - it's a
test against firmware behaviour and firmware features.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 2, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 2, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 3, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 3, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 3, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit to chrisccoulson/secboot that referenced this issue Oct 4, 2024
This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event). It also permits
EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS environment if the
BootOptionSupport EFI variable indicates that system preparation
applications are supported, although these must be before the previously
mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (canonical#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
chrisccoulson added a commit that referenced this issue Oct 7, 2024
preinstall: Add checks for PCR4.

This adds checks some checks for PCR4.

The caller supplies a context.Context to which an EFI variable backend
is attached, a internal_efi.HostEnvironment implementation, a TCG log, a
PCR digest algorithm (the optimum for this is computed earlier by
another function that does a more general check of the TCG log) and a
list of boot images related to the current boot. These are used to
verify the digests in the EV_EFI_BOOT_SERVICES_APPLICATION events.

It reads the BootCurrent EFI variable and matches this to the
EFI_LOAD_OPTION associated with the current boot from the TCG log - it
uses the log as BootXXXX EFI variables can updated at runtime and might
be out of date when this code runs.

In the pre-OS environment, it checks that the log only contains either
a single EV_OMIT_BOOT_DEVICE_EVENTS event or a single EV_EFI_ACTION
"Calling EFI Application from Boot Option" event (after which, it expects
to see the EV_SEPARATOR event to signal the transition to OS-present). It
also permits EV_EFI_BOOT_SERVICES_APPLICATION events in the pre-OS
environment if the BootOptionSupport EFI variable indicates that system
preparation applications are supported, although these must be before the
previously mentioned EV_EFI_ACTION event. The profile generating code in
efi/fw_load_handler.go copies these pre-OS events (including sysprep
applications to the final policy).

Note that firmware that implements v1.06 of the TCG PC-Client PFP spec
implements another EV_EFI_ACTION event that indicates the number of the
Boot option that the load occurred from - this code will need to include
support for that quite soon. There is a corresponding github issue for
this (#308).

When processing the initial part of the OS-present section of the log,
it expects to find the EV_EFI_BOOT_SERVICES_APPLICATION for the initial
boot loader (IBL), and it expects the path of this to match the previously
discovered load option associated with the current boot - note that it
doesn't expect a complete match. See how path matching works in
efi.DevicePath.Matches. Any other event type at this stage is rejected as
an error, as it would result in an invalid policy being generated by the
code in efi/fw_load_handler.go. If the first EV_EFI_BOOT_SERVICES_APPLICATION
event is not the IBL, it checks to see if it is part of Absolute, in which
case it skips it and looks for the next event. Note that Absolute will be
copied to the computed policy by efi/fw_load_handler.go, if it is present,
although it's recommended that this is disabled instead. The next event
must be the IBL, else an error is returned. It verifies that the digest in
the log matches the Authenticode digest of the first boot file supplied to
the function.

It then continues to process EV_EFI_BOOT_SERVICE_APPLICATION events in
the log (permitting, but ignoring other event types - it's expected that
if other OS boot code uses other event types in the log, the policy
generation code for that OS component in the secboot efi package emits
these. For each launch event (EV_EFI_BOOT_SERVICES_APPLICATION), it
verifies that the digest in the log matches the Authenticode digest of
the next boot file supplied. Note that it is not mandatory to verify every
one of these events, so it's not mandatory to supply every boot
component to the function.

Some OS components may not rely on the boot services LoadImage API for
loading subsequent stages (eg, shim). For the
EV_EFI_BOOT_SERVICES_APPLICATION digests to be correct, these components
rely on the existence of the EFI_TCG2_PROTOCOL with the PE_COFF_IMAGE
flag. There isn't a direct way to test for this, so for this reason, the
function does have to verify the digest of the
EV_EFI_BOOT_SERVICES_APPLICATION event associated with the secondary
boot loader (SBL), if there is one. This image must be supplied to this
function, else an error will be returned.

On success, the function will return a set of flags indicating whether
system preparation applications were detected to be running, whether
Absolute was detected to be running, or whether it wasn't able to verify
all EV_EFI_BOOT_SERVICES_APPLICATION event digests because not all paths
to every component for the current boot were supplied. What happens with
these flags will be customizable with flags supplied to the higher level
RunChecks API.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant