return cc;
}
-static EFI_TCG2_PROTOCOL *tcg2_interface_check(void) {
+static EFI_TCG2_PROTOCOL* tcg2_interface_check(EFI_TCG2_VERSION *ret_version) {
EFI_STATUS err;
EFI_TCG2_PROTOCOL *tcg;
assert(capability.Size >= endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, Size));
- if (capability.Size < endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag))
+ /* This is a paranoia check, given these fields existed from day one of the spec. But the spec also
+ * suggests checking the structure size before accessing any fields, hence let's do so, for extra
+ * paranoia. */
+ if (capability.Size < CONST_MAX(endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, TPMPresentFlag),
+ endoffsetof_field(EFI_TCG2_BOOT_SERVICE_CAPABILITY, ProtocolVersion)))
return NULL;
if (!capability.TPMPresentFlag)
return NULL;
+ if (ret_version)
+ *ret_version = capability.ProtocolVersion;
+
return tcg;
}
bool tpm_present(void) {
- return tcg2_interface_check();
+ return tcg2_interface_check(/* ret_version= */ NULL);
}
uint32_t tpm_get_active_pcr_banks(void) {
- uint32_t active_pcr_banks = 0;
- EFI_TCG2_PROTOCOL *tpm2;
EFI_STATUS err;
- tpm2 = tcg2_interface_check();
+ EFI_TCG2_PROTOCOL *tpm2;
+ EFI_TCG2_VERSION version;
+ tpm2 = tcg2_interface_check(&version);
if (!tpm2)
return 0;
+ /* GetActivePcrBanks() was added only in version 1.1 of the spec */
+ if (version.Major < 1 || (version.Major == 1 && version.Minor < 1)) {
+ log_debug("TCG protocol too old for GetActivePcrBanks(), claiming no active banks.");
+ return 0;
+ }
+
+ uint32_t active_pcr_banks = 0;
err = tpm2->GetActivePcrBanks(tpm2, &active_pcr_banks);
if (err != EFI_SUCCESS) {
log_warning_status(err, "Failed to get TPM2 active PCR banks, assuming none: %m");
assert(ret_measured);
- tpm2 = tcg2_interface_check();
+ tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
if (!tpm2) {
*ret_measured = false;
return EFI_SUCCESS;
/* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
* something, or false if measurement was turned off. */
- tpm2 = tcg2_interface_check();
+ tpm2 = tcg2_interface_check(/* ret_version= */ NULL);
if (!tpm2 || pcrindex == UINT32_MAX) { /* PCR disabled? */
if (ret_measured)
*ret_measured = false;