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

Publish EDK's TPM eventlog that contains coreboot's entries #139

Open
wants to merge 5 commits into
base: dasharo
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 86 additions & 4 deletions DasharoModulePkg/Library/DasharoVariablesLib/DasharoVariablesLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,27 @@ MeasureVariable (
return Status;
}

/**
A comparison function for sorting an array of variable names.

@param Buffer1 Pointer to pointer of the first variable name.
@param Buffer2 Pointer to pointer of the second variable name.

@retval <0 The first variable name is less than the second one.
@retval =0 The names are equal.
@retval >0 The first variable name is greater than the second one.
**/
STATIC
INTN
EFIAPI
CompareVariableNames (
IN CONST VOID *Buffer1,
IN CONST VOID *Buffer2
)
{
return StrCmp (*(CONST CHAR16 **) Buffer1, *(CONST CHAR16 **) Buffer2);
}

/**
Measures single all existing variables with the specified GUID.

Expand All @@ -357,12 +378,25 @@ MeasureVariables (
UINTN MaxNameSize;
UINTN NameSize;
EFI_GUID Guid;
CHAR16 **Names;
UINTN NameCount;
CHAR16 SortBuf;
UINTN MaxNameCount;
UINTN Index;

MaxNameSize = 32*sizeof (CHAR16);
MaxNameSize = 32 * sizeof (CHAR16);
Name = AllocateZeroPool (MaxNameSize);
if (Name == NULL)
return EFI_OUT_OF_RESOURCES;

MaxNameCount = 32;
NameCount = 0;
Names = AllocatePool (MaxNameCount * sizeof (*Names));
if (Names == NULL) {
FreePool(Name);
return EFI_OUT_OF_RESOURCES;
}

while (TRUE) {
NameSize = MaxNameSize;
Status = gRT->GetNextVariableName (&NameSize, Name, &Guid);
Expand All @@ -373,7 +407,7 @@ MeasureVariables (
break;
}

StrnCpyS (NewBuf, NameSize/sizeof (CHAR16), Name, MaxNameSize/sizeof (CHAR16));
StrnCpyS (NewBuf, NameSize / sizeof (CHAR16), Name, MaxNameSize / sizeof (CHAR16));
FreePool (Name);

Name = NewBuf;
Expand All @@ -390,11 +424,59 @@ MeasureVariables (
if (EFI_ERROR (Status))
break;

if (CompareGuid (&Guid, Vendor))
MeasureVariable (Name, Vendor);
if (!CompareGuid (&Guid, Vendor))
continue;

if (NameCount == MaxNameCount - 1) {
Names = ReallocatePool (
MaxNameCount * sizeof (*Names),
2 * MaxNameCount * sizeof (*Names),
Names
);
if (Names == NULL) {
Status = EFI_OUT_OF_RESOURCES;
break;
}

MaxNameCount *= 2;
}

Names[NameCount] = AllocateCopyPool (NameSize, Name);
if (Names[NameCount] == NULL) {
Status = EFI_OUT_OF_RESOURCES;
break;
}

NameCount++;
}

if (Status == EFI_SUCCESS) {
//
// Achieve predictable ordering of variables by sorting them by name within
// a particular vendor.
//
QuickSort (
Names,
NameCount,
sizeof (*Names),
CompareVariableNames,
&SortBuf
);

for (Index = 0; Index < NameCount; Index++) {
Status = MeasureVariable (Names[Index], Vendor);
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_WARN, "%a(): Failed to measure variable: %g:%s.\n",
__FUNCTION__, Vendor, Name));
}
}
}

for (Index = 0; Index < NameCount; Index++)
FreePool (Names[Index]);

FreePool (Name);
FreePool (Names);
return Status;
}

Expand Down
145 changes: 145 additions & 0 deletions DasharoPayloadPkg/BlSupportPei/BlSupportPei.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "BlSupportPei.h"

#include <Coreboot.h>
#include <IndustryStandard/UefiTcgPlatform.h>

#define LEGACY_8259_MASK_REGISTER_MASTER 0x21
#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1

Expand Down Expand Up @@ -496,6 +499,139 @@ ValidateFvHeader (
return EFI_SUCCESS;
}

STATIC
EFI_STATUS
ParseAndPublishTPM1Log (
CONST struct tcpa_spec_entry *SpecEntry,
UINTN Size
)
{
UINT8 ZeroBlock[sizeof (struct tcpa_spec_entry)];
struct tcpa_log_entry *Entry;
EFI_PHYSICAL_ADDRESS Start;
EFI_PHYSICAL_ADDRESS Current;
UINTN EntrySize;

// This must hold to avoid integer overflow below.
ASSERT (Size >= sizeof (*Entry));

ZeroMem (ZeroBlock, sizeof (ZeroBlock));

Start = (EFI_PHYSICAL_ADDRESS)(UINTN) SpecEntry;
Current = Start;
while (Current - Start < Size - sizeof (*Entry) &&
CompareMem ((VOID *)(UINTN) Current, (VOID *) ZeroBlock, sizeof (ZeroBlock)) != 0) {
Entry = (VOID *)(UINTN) Current;
EntrySize = sizeof (*Entry) + Entry->event_data_size;

BuildGuidDataHob (&gTcgEventEntryHobGuid, Entry, EntrySize);
Current += EntrySize;
}

return EFI_SUCCESS;
}

STATIC
EFI_STATUS
ParseAndPublishTPM2Log (
CONST struct tcg_efi_spec_id_event *SpecEntry,
UINTN Size
)
{
UINT8 ZeroBlock[sizeof (struct tcg_pcr_event2_header)];
struct tcg_pcr_event2_header *Header;
EFI_PHYSICAL_ADDRESS Start;
EFI_PHYSICAL_ADDRESS Current;
UINTN EntrySize;
UINTN DigestsSize;
UINTN Idx;

// This must hold to avoid integer overflow below.
ASSERT (Size >= sizeof (*Header));

ZeroMem (ZeroBlock, sizeof (ZeroBlock));

DigestsSize = 0;
for (Idx = 0; Idx < SpecEntry->num_of_algorithms; ++Idx) {
DigestsSize += sizeof (UINT16) + SpecEntry->digest_sizes[Idx].digest_size;
}

Start = (EFI_PHYSICAL_ADDRESS)(UINTN) SpecEntry;

// Not adding Spec ID Event for TPM2 because Tcg2Dxe adds one, coreboot's
// event would have to be modified to be suitable due to the list of
// algorithms there.
Current = Start + sizeof (struct tcpa_log_entry) + SpecEntry->event_size;

while (Current - Start < Size - sizeof (*Header) &&
CompareMem ((VOID *)(UINTN) Current, (VOID *) ZeroBlock, sizeof (ZeroBlock)) != 0) {
Header = (VOID *)(UINTN) Current;
EntrySize = sizeof (*Header) + DigestsSize;

// Event data size field and data itself.
EntrySize += sizeof (UINT32) + *(CONST UINT32 *)(UINTN) (Current + EntrySize);

BuildGuidDataHob (&gTcgEvent2EntryHobGuid, Header, EntrySize);
Current += EntrySize;
}

return EFI_SUCCESS;
}

STATIC
EFI_STATUS
ParseAndPublishTPMLog (
VOID
)
{
RETURN_STATUS Status;
VOID *LogBase;
UINTN LogSize;

const struct tcpa_spec_entry *Tcg1Entry;
const struct tcg_efi_spec_id_event *Tcg2Entry;

Status = ParseTPMLog (&LogBase, &LogSize);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"%a: Not publishing coreboot's TPM log entries because: %r.\n",
__FUNCTION__, Status
));
return Status;
}

Tcg1Entry = LogBase;
if (AsciiStrCmp((CONST CHAR8 *)Tcg1Entry->signature, TCPA_SPEC_ID_EVENT_SIGNATURE) == 0) {
if (Tcg1Entry->spec_version_major == 1 &&
Tcg1Entry->spec_version_minor == 2 &&
Tcg1Entry->spec_errata >= 1 &&
Tcg1Entry->entry.event_type == EV_NO_ACTION) {
return ParseAndPublishTPM1Log (Tcg1Entry, LogSize);
}

DEBUG ((DEBUG_WARN, "%a: Unknown TPM1.2 log specification.\n", __FUNCTION__));
return EFI_UNSUPPORTED;
}

Tcg2Entry = LogBase;
if (AsciiStrCmp((CONST CHAR8 *)Tcg1Entry->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE) == 0) {
if (Tcg2Entry->spec_version_major == 2 &&
Tcg2Entry->spec_version_minor == 0 &&
Tcg2Entry->event_type == EV_NO_ACTION) {
return ParseAndPublishTPM2Log (Tcg2Entry, LogSize);
}

DEBUG ((DEBUG_WARN, "%a: Unknown TPM2 log specification.\n", __FUNCTION__));
return EFI_UNSUPPORTED;
}

DEBUG ((DEBUG_WARN,
"%a: Unknown TPM log specification %.*s.\n",
__FUNCTION__, (int)sizeof(Tcg2Entry->signature), (CONST CHAR8 *)Tcg2Entry->signature));
return EFI_UNSUPPORTED;
}

/**
This is the entrypoint of PEIM

Expand Down Expand Up @@ -767,6 +903,15 @@ BlPeiEntryPoint (
IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);

//
// Parse coreboot's log.
//
Status = ParseAndPublishTPMLog ();
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
return Status;
}

return EFI_SUCCESS;
}

3 changes: 3 additions & 0 deletions DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
EmbeddedPkg/EmbeddedPkg.dec
IntelFsp2Pkg/IntelFsp2Pkg.dec
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
SecurityPkg/SecurityPkg.dec
DasharoPayloadPkg/DasharoPayloadPkg.dec
UefiCpuPkg/UefiCpuPkg.dec

Expand Down Expand Up @@ -64,6 +65,8 @@
gEfiVariableGuid
gEfiAuthenticatedVariableGuid
gEdkiiNvVarStoreFormattedGuid
gTcgEventEntryHobGuid
gTcgEvent2EntryHobGuid

[Ppis]
gEfiPeiMasterBootModePpiGuid
Expand Down
64 changes: 64 additions & 0 deletions DasharoPayloadPkg/Include/Coreboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ struct cb_smmstorev2 {
UINT8 unused[3]; /* Set to zero */
};

#define CB_TAG_CBMEM_ENTRY 0x0031
#define CB_TAG_VBOOT_WORKBUF 0x0034

struct cb_cbmem_entry {
Expand Down Expand Up @@ -762,4 +763,67 @@ struct cb_range {
UINT32 range_size;
} __attribute__((packed));

#define CBMEM_ID_TCPA_TCG_LOG 0x54445041 /* TPM log per TPM 1.2 specification */
#define CBMEM_ID_TPM2_TCG_LOG 0x54504d32 /* TPM log per TPM 2.0 specification */

#define TCPA_SPEC_ID_EVENT_SIGNATURE "Spec ID Event00"
#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE "Spec ID Event03"

struct tcpa_log_entry {
UINT32 pcr;
UINT32 event_type;
UINT8 digest[20];
UINT32 event_data_size;
UINT8 event[0];
} __attribute__ ((packed));

struct tcpa_spec_entry {
struct tcpa_log_entry entry;
UINT8 signature[16];
UINT32 platform_class;
UINT8 spec_version_minor;
UINT8 spec_version_major;
UINT8 spec_errata;
UINT8 reserved;
UINT8 vendor_info_size;
UINT8 vendor_info[0];
} __attribute__ ((packed));

#define TPM2_ALG_SHA1 0x0004
#define TPM2_ALG_SHA256 0x000B
#define TPM2_ALG_SHA384 0x000C
#define TPM2_ALG_SHA512 0x000D
#define TPM2_ALG_SM3_256 0x0012

struct tcg_pcr_event2_header {
UINT32 pcr_index;
UINT32 event_type;
UINT32 digest_count;
UINT8 digests[0];
/* UINT32 event_size; */
/* UINT8 event[0]; */
} __attribute__ ((packed));

struct tpm_digest_sizes {
UINT16 alg_id;
UINT16 digest_size;
} __attribute__ ((packed));

struct tcg_efi_spec_id_event {
UINT32 pcr_index;
UINT32 event_type;
UINT8 digest[20];
UINT32 event_size;
UINT8 signature[16];
UINT32 platform_class;
UINT8 spec_version_minor;
UINT8 spec_version_major;
UINT8 spec_errata;
UINT8 uintn_size;
UINT32 num_of_algorithms;
struct tpm_digest_sizes digest_sizes[0]; /* variable number of members */
/* UINT8 vendor_info_size; */
/* UINT8 vendor_info[vendor_info_size]; */
} __attribute__ ((packed));

#endif // _COREBOOT_PEI_H_INCLUDED_
Loading