-
Notifications
You must be signed in to change notification settings - Fork 15
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
preinstall: move some extra TPM tests to only run during pre-install #340
Draft
chrisccoulson
wants to merge
9
commits into
canonical:master
Choose a base branch
from
chrisccoulson:preinstall-skip-some-tpm-tests-post-install
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
preinstall: move some extra TPM tests to only run during pre-install #340
chrisccoulson
wants to merge
9
commits into
canonical:master
from
chrisccoulson:preinstall-skip-some-tpm-tests-post-install
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This adds some checks for PCR7. 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 algorith (the optimum for this is computed earlier by another function that does a more general check of the TCG log) and the image of the initial boot loader for the current boot. As we're testing the firmware, this only checks the log up to the launch of the initial boot loader. It ignores events after this, as these are under the control of the OS and don't rely on any special firmware features such as EFI_TCG2_PROTOCOL + PE_COFF_IMAGE vs EFI_TCG_PROTOCOL in the same way that OS components measuring to PCR4 do. This ensures that secure boot is enabled, else an error is returned, as WithSecureBootPolicyProfile only generates profiles compatible with secure boot being enabled. If the version of UEFI is >= 2.5, it also makes sure that the secure boot mode is "deployed mode". If the secure boot mode is "user mode", then the "AuditMode" and "DeployedMode" values are measured to PCR7, something that WithSecureBootPolicyProfile doesn't support today. Support for "user mode" will be added in the future, although the public RunChecks API will probably require a flag to opt in to supporting user mode, as it is the less secure mode of the 2 (see the documentation for SecureBootMode in github.com/canonical/go-efilib). It also reads the "OsIndicationsSupported" variable to test for features that are not supported by WithSecureBootPolicyProfile. These are timestamp revocation (which requires an extra signature database - "dbt") and OS recovery (which requires an extra signature database - "dbr", used to control access to OsRecoveryOrder and OsRecover#### variables). Of the 2, it's likely that we might need to add support for timestamp revocation at some point. 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 be updated at runtime and might be out of data when this code runs. It uses this to detect the launch of the initial boot loader, which might not necessarily be the first EV_EFI_BOOT_SERVICES_APPLICATION event in the OS-present environment in PCR4 (eg, if Absolute is active). First of all, it iterates over the secure boot configuration in the log, making sure that the configuration is measured in the correct order, that the event data is valid, and that the measured digest is the tagged hash of the event data. It makes sure that the value of "SecureBoot" in the log is consistent with the "SecureBoot" variable (which is read-only at runtime), and it verifies that all of the signature databases are formatted correctly. It will return an error if any of these checks fail. If the pre-OS environment contains events other than EV_EFI_VARIABLE_DRIVER_CONFIG, it will return an error. This can happen if a firmware debugger is enabled, in which case PCR7 will begin with a EV_EFI_ACTION "UEFI Debug Mode" event. This case is detected by earlier firmware protection checks. If not all of the expected secure boot configuration is measured, an error is returned. Once the secure boot configuration has been measured, it looks for EV_EFI_VARIABLE_AUTHORITY events in PCR7, until it detects the launch of the initial boot loader. It verifies that each of these come from db, and if the log is in the OS-present environment, it ensures that the measured digest is the tagged hash of the event data. It doesn't do this for events in the pre-OS environment because WithSecureBootPolicyProfile just copies these to the profile. It verifies that the firmware doesn't measure a signature more than once. For each EV_EFI_VARIABLE_AUTHORITY event, it also matches the measured signature to a EFI_SIGNATURE_LIST structure in db. If the matched ESL is a X.509 certificate, it records the use of this CA in the return value. If the CA is an RSA certificate with a public modulus of <= 1024 bits, it sets a flag in the return value indicating a weak algorithm. If the matched ESL is a Authenticode digest, it sets a flag in the return value indicating that pre-OS components were verified using digests rather than signatures. This makes PCR7 fragile wrt firmware updates, because it means db needs to be updated to reflect the new components each time. If the digest being matched is SHA-1, it sets the flag in the return value indicating a weak algorithm. If any of these checks fail, an error is returned. If an event type other than EV_EFI_VARIABLE_AUTHORITY is detected, an error is returned. Upon detecting the launch of the initial boot loader in PCR4, it extracts the authenticode signatures from the supplied image, and matches these to a previously measured CA. If no match is found, an error is returned. If a match is found, it ensures that the signing certificate has an RSA public key with a modulus larger than 1024 bits, else it sets a flag in the return value indicating a weak algorithm. Once the event for the initial boot loader is complete, the function returns. If the end of the log is reached without encountering the launch of the initial boot loader, an error is returned.
This moves the code to read the current boot load option from the log into a helper function, as the same code was used both in the PCR4 and PCR7 checks.
chrisccoulson
force-pushed
the
preinstall-skip-some-tpm-tests-post-install
branch
from
October 17, 2024 10:45
0c2598b
to
e0c45dc
Compare
Hopefully this will address any outstanding review comments.
chrisccoulson
force-pushed
the
preinstall-skip-some-tpm-tests-post-install
branch
from
November 13, 2024 08:35
e0c45dc
to
e3f1bc2
Compare
CheckResult is returned from RunChecks on successful completion. It is JSON serializable and intended to be supplied later on to WithAutoTCGPCRProfile along with some user customization flags (defined by PCRProfileOptionsFlags) in order to generate an option that can be supplied to secboot_efi.AddPCRProfile. Note that some user options don't work yet because of missing PCR support, although these limitations will be addressed later. Even so, some options may still fail depending on the CheckResult flags.
RunChecks is the first main entry point for running all of the platform tests included in this package. It is considered to be quite a low level and a future PR is going to add a higher level API that is easier to use (RunChecksContext) It can be customized with the CheckFlags argument, and the caller must supply a list of images loaded during the current boot, in the correct order. On failure, it will return an error. In some cases, it fails early. In other cases, it carries on and collects individual errors which are then returned wrapped in RunChecksError. This can be obtained with the errors.As API in order to obtain individual errors. On success, it will return a CheckResult. Any errors that were encountered but are considered non-fatal based on the supplied CheckFlags will he added to the Warnings field of CheckResult. The intention is that CheckResult is persisted and then used by an API (to be added in the next PR) along with some user customization flags in order to select the most appropriate set of TCG defined PCRs to seal against. This can still fail if an appropriately secure set of PCRs cannot be selected, even if RunChecks succeeded. The future higher-level RunChecksContext API will make this case easier to handle and will also help remove the burden of deciding which set of flags to pass to RunChecks.
We were already skipping the lockout hierarchy auth value test during post-install because this doesn't make sense, but also skip similar tests for other hierarchies and also skip the lockout checkout and the test for sufficient number of NV counters.
chrisccoulson
force-pushed
the
preinstall-skip-some-tpm-tests-post-install
branch
from
November 13, 2024 19:08
e3f1bc2
to
4701bb5
Compare
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(Draft until #339 has landed)
The
RunChecks
API will support being executed post-install eventhough it's primarily a pre-install API. A use case for this is re-running
it as part of the post-recovery repair process. Not all tests makes sense
post-install, unless a motherboard (and TPM) change was the reason for
recovery, and so are skipped.
We were already skipping the lockout hierarchy auth value test during
post-install because this doesn't make sense, but also skip similar
tests for other hierarchies and also skip the lockout checkout and the
test for sufficient number of NV counters.