From b6f94dbeacfc6f0a507413096189304c58dbe66c Mon Sep 17 00:00:00 2001 From: Mathieu Trudel-Lapierre Date: Wed, 13 Sep 2017 12:09:40 -0700 Subject: New upstream version 13~git1505328970.9c1c35c5 --- tpm.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 227 insertions(+), 23 deletions(-) (limited to 'tpm.c') diff --git a/tpm.c b/tpm.c index c37cc484..05b3c6fb 100644 --- a/tpm.c +++ b/tpm.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "tpm.h" @@ -14,6 +15,16 @@ extern UINT8 in_protocol; }) +typedef struct { + CHAR16 *VariableName; + EFI_GUID *VendorGuid; + VOID *Data; + UINTN Size; +} VARIABLE_RECORD; + +UINTN measuredcount = 0; +VARIABLE_RECORD *measureddata = NULL; + EFI_GUID tpm_guid = EFI_TPM_GUID; EFI_GUID tpm2_guid = EFI_TPM2_GUID; @@ -108,27 +119,60 @@ static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2, &start, &end, &truncated); } -EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, - const CHAR8 *description) +static EFI_STATUS tpm_locate_protocol(efi_tpm_protocol_t **tpm, + efi_tpm2_protocol_t **tpm2, + BOOLEAN *old_caps_p, + EFI_TCG2_BOOT_SERVICE_CAPABILITY *capsp) { EFI_STATUS status; - efi_tpm_protocol_t *tpm; - efi_tpm2_protocol_t *tpm2; - status = LibLocateProtocol(&tpm2_guid, (VOID **)&tpm2); + *tpm = NULL; + *tpm2 = NULL; + status = LibLocateProtocol(&tpm2_guid, (VOID **)tpm2); /* TPM 2.0 */ if (status == EFI_SUCCESS) { BOOLEAN old_caps; - EFI_TCG2_EVENT *event; EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; - EFI_TCG2_EVENT_LOG_BITMAP supported_logs; - status = tpm2_get_caps(tpm2, &caps, &old_caps); - if (status != EFI_SUCCESS) + status = tpm2_get_caps(*tpm2, &caps, &old_caps); + if (EFI_ERROR(status)) + return status; + + if (tpm2_present(&caps, old_caps)) { + if (old_caps_p) + *old_caps_p = old_caps; + if (capsp) + memcpy(capsp, &caps, sizeof(caps)); return EFI_SUCCESS; + } + } else { + status = LibLocateProtocol(&tpm_guid, (VOID **)tpm); + if (EFI_ERROR(status)) + return status; - if (!tpm2_present(&caps, old_caps)) + if (tpm_present(*tpm)) return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +static EFI_STATUS tpm_log_event_raw(EFI_PHYSICAL_ADDRESS buf, UINTN size, + UINT8 pcr, const CHAR8 *log, UINTN logsize, + UINT32 type, CHAR8 *hash) +{ + EFI_STATUS status; + efi_tpm_protocol_t *tpm; + efi_tpm2_protocol_t *tpm2; + BOOLEAN old_caps; + EFI_TCG2_BOOT_SERVICE_CAPABILITY caps; + + status = tpm_locate_protocol(&tpm, &tpm2, &old_caps, &caps); + if (EFI_ERROR(status)) { + return status; + } else if (tpm2) { + EFI_TCG2_EVENT *event; + EFI_TCG2_EVENT_LOG_BITMAP supported_logs; supported_logs = tpm2_get_supported_logs(tpm2, &caps, old_caps); @@ -138,7 +182,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, return status; } - event = AllocatePool(sizeof(*event) + strlen(description) + 1); + event = AllocatePool(sizeof(*event) + logsize); if (!event) { perror(L"Unable to allocate event structure\n"); return EFI_OUT_OF_RESOURCES; @@ -147,14 +191,24 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER); event->Header.HeaderVersion = 1; event->Header.PCRIndex = pcr; - event->Header.EventType = EV_IPL; - event->Size = sizeof(*event) - sizeof(event->Event) + strlen(description) + 1; - memcpy(event->Event, description, strlen(description) + 1); - status = uefi_call_wrapper(tpm2->hash_log_extend_event, 5, tpm2, - 0, buf, (UINT64) size, event); + event->Header.EventType = type; + event->Size = sizeof(*event) - sizeof(event->Event) + logsize + 1; + CopyMem(event->Event, (VOID *)log, logsize); + if (hash) { + /* TPM 2 systems will generate the appropriate hash + themselves if we pass PE_COFF_IMAGE + */ + status = uefi_call_wrapper(tpm2->hash_log_extend_event, + 5, tpm2, PE_COFF_IMAGE, buf, + (UINT64) size, event); + } else { + status = uefi_call_wrapper(tpm2->hash_log_extend_event, + 5, tpm2, 0, buf, + (UINT64) size, event); + } FreePool(event); return status; - } else { + } else if (tpm) { TCG_PCR_EVENT *event; UINT32 eventnum = 0; EFI_PHYSICAL_ADDRESS lastevent; @@ -167,7 +221,7 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, if (!tpm_present(tpm)) return EFI_SUCCESS; - event = AllocatePool(sizeof(*event) + strlen(description) + 1); + event = AllocatePool(sizeof(*event) + logsize); if (!event) { perror(L"Unable to allocate event structure\n"); @@ -175,14 +229,164 @@ EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, } event->PCRIndex = pcr; - event->EventType = EV_IPL; - event->EventSize = strlen(description) + 1; - status = uefi_call_wrapper(tpm->log_extend_event, 7, tpm, buf, - (UINT64)size, TPM_ALG_SHA, event, - &eventnum, &lastevent); + event->EventType = type; + event->EventSize = logsize; + CopyMem(event->Event, (VOID *)log, logsize); + if (hash) { + /* TPM 1.2 devices require us to pass the Authenticode + hash rather than allowing the firmware to attempt + to calculate it */ + CopyMem(event->digest, hash, sizeof(event->digest)); + status = uefi_call_wrapper(tpm->log_extend_event, 7, + tpm, 0, 0, TPM_ALG_SHA, + event, &eventnum, + &lastevent); + } else { + status = uefi_call_wrapper(tpm->log_extend_event, 7, + tpm, buf, (UINT64)size, + TPM_ALG_SHA, event, + &eventnum, &lastevent); + } FreePool(event); return status; } return EFI_SUCCESS; } + +EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr, + const CHAR8 *description) +{ + return tpm_log_event_raw(buf, size, pcr, description, + strlen(description) + 1, 0xd, NULL); +} + +EFI_STATUS tpm_log_pe(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 *sha1hash, + UINT8 pcr) +{ + EFI_IMAGE_LOAD_EVENT ImageLoad; + + // All of this is informational and forces us to do more parsing before + // we can generate it, so let's just leave it out for now + ImageLoad.ImageLocationInMemory = 0; + ImageLoad.ImageLengthInMemory = 0; + ImageLoad.ImageLinkTimeAddress = 0; + ImageLoad.LengthOfDevicePath = 0; + + return tpm_log_event_raw(buf, size, pcr, (CHAR8 *)&ImageLoad, + sizeof(ImageLoad), + EV_EFI_BOOT_SERVICES_APPLICATION, sha1hash); +} + +typedef struct { + EFI_GUID VariableName; + UINT64 UnicodeNameLength; + UINT64 VariableDataLength; + CHAR16 UnicodeName[1]; + INT8 VariableData[1]; +} EFI_VARIABLE_DATA_TREE; + +static BOOLEAN tpm_data_measured(CHAR16 *VarName, EFI_GUID VendorGuid, UINTN VarSize, VOID *VarData) +{ + UINTN i; + + for (i=0; iUnicodeName) - + sizeof (VarLog->VariableData)); + + VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize); + if (VarLog == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (&VarLog->VariableName, &VendorGuid, + sizeof(VarLog->VariableName)); + VarLog->UnicodeNameLength = VarNameLength; + VarLog->VariableDataLength = VarSize; + CopyMem (VarLog->UnicodeName, VarName, + VarNameLength * sizeof (*VarName)); + CopyMem ((CHAR16 *)VarLog->UnicodeName + VarNameLength, VarData, + VarSize); + + Status = tpm_log_event_raw((EFI_PHYSICAL_ADDRESS)(intptr_t)VarLog, + VarLogSize, 7, (CHAR8 *)VarLog, VarLogSize, + EV_EFI_VARIABLE_AUTHORITY, NULL); + + FreePool(VarLog); + + if (Status != EFI_SUCCESS) + return Status; + + return tpm_record_data_measurement(VarName, VendorGuid, VarSize, + VarData); +} + +EFI_STATUS +fallback_should_prefer_reset(void) +{ + EFI_STATUS status; + efi_tpm_protocol_t *tpm; + efi_tpm2_protocol_t *tpm2; + + status = tpm_locate_protocol(&tpm, &tpm2, NULL, NULL); + if (EFI_ERROR(status)) + return EFI_NOT_FOUND; + return EFI_SUCCESS; +} -- cgit v1.2.3