Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #337 from chrisccoulson/preinstall-add-check-pcr7
preinstall: Add checks for PCR7. 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 < 256 bytes, 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 at least as large as 256 bytes, 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.
- Loading branch information