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 4 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
144 changes: 144 additions & 0 deletions DasharoPayloadPkg/BlSupportPei/BlSupportPei.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent

**/
#include "BlSupportPei.h"
#include <Coreboot.h>
#include <IndustryStandard/UefiTcgPlatform.h>

#define PEI_MEM_SIZE SIZE_64MB

Expand Down Expand Up @@ -497,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 @@ -763,6 +898,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 @@ -783,4 +784,67 @@ struct lb_efi_fw_info {
UINT32 fw_size; /* Size of firmware in bytes */
} __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_
20 changes: 20 additions & 0 deletions DasharoPayloadPkg/Include/Library/BlParseLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,26 @@ ParseTPMPPIInfo (
OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo
);

/**
Find TPM log in TCG format if any.

The caller is expected to parse the first event of the log to determine its
version.

@param Base Pointer the start of the log
@param Size Size of the log

@retval RETURN_SUCCESS Successfully found TPM log.
@retval RETURN_NOT_FOUND Failed to find TPM log.

**/
RETURN_STATUS
EFIAPI
ParseTPMLog (
OUT VOID **Base,
OUT UINTN *Size
);

/**
Acquire Vboot recovery information from coreboot

Expand Down
79 changes: 79 additions & 0 deletions DasharoPayloadPkg/Library/CbParseLib/CbParseLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,42 @@ FindCbTag (
}


/**
Find location and size of a coreboot record of the given type.

@param Tag The tag id to be found
@param Size Optionally (if not NULL) set to size of the tag

@retval NULL The Tag is not found.
@retval Others The pointer to the record found.

**/
STATIC
struct cb_cbmem_entry *
FindCbEntry (
IN UINT32 Id
)
{
struct cb_header *Header;
struct cb_cbmem_entry *Entry;
UINT8 *TmpPtr;
UINTN Idx;

Header = (struct cb_header *) GetParameterBase ();

TmpPtr = (UINT8 *)Header + Header->header_bytes;
for (Idx = 0; Idx < Header->table_entries; Idx++) {
Entry = (struct cb_cbmem_entry *)TmpPtr;
if (Entry->tag == CB_TAG_CBMEM_ENTRY && Entry->id == Id) {
return Entry;
}
TmpPtr += Entry->size;
}

return NULL;
}


/**
Find the given table with TableId from the given coreboot memory Root.

Expand Down Expand Up @@ -693,6 +729,49 @@ ParseTPMPPIInfo (
return RETURN_SUCCESS;
}

/**
Find TPM log in TCG format if any.

The caller is expected to parse the first event of the log to determine its
version.

@param Base Pointer the start of the log
@param Size Size of the log

@retval RETURN_SUCCESS Successfully found TPM log.
@retval RETURN_NOT_FOUND Failed to find TPM log.

**/
RETURN_STATUS
EFIAPI
ParseTPMLog (
OUT VOID **Base,
OUT UINTN *Size
)
{
struct cb_cbmem_entry *Entry;

//
// TPM2 format is the more capable "agile" format, so start with it like some
// other parts of EDK test for TPM2 before testing for TPM1.
//
// Could return log version, but the caller should probably validate that the
// buffer isn't empty and checking for correct Spec ID Event is a good way of
// going about it.
//

Entry = FindCbEntry (CBMEM_ID_TPM2_TCG_LOG);
if (Entry == NULL)
Entry = FindCbEntry (CBMEM_ID_TCPA_TCG_LOG);

if (Entry == NULL)
return RETURN_NOT_FOUND;

*Base = (void *)(UINTN) Entry->address;
*Size = Entry->entry_size;
return RETURN_SUCCESS;
}

STATIC
CONST CHAR8 *
GetRecoveryReasonString(
Expand Down
Loading
Loading