Skip to content

Commit f5283a2

Browse files
committed
UefiPayloadPkg,SecurityPkg: import coreboot's TPM log
Find the log using UefiPayloadPkg/CbParseLib in UefiPayloadPkg/BlSupportPei and create HOBs like those produced by TcgPei and Tcg2Pei all of which will be picked up by TcgDxe and Tcg2Dxe. TPM1 case is quite simple: - use coreboot's Spec ID Event as EDK doesn't seem to add one of its own TPM2 case is more advanced and is more complicated: - don't create a HOB for coreboot's Spec ID Event (the first entry) because TPM2 can have multiple digests and coreboot produces at most one - when importing HOBs in Tcg2Dxe add missing hashes of OneDigest kind from TXT spec (0x01 followed by 0x00 bytes) just to not come up with some custom placeholder Signed-off-by: Sergii Dmytruk <[email protected]>
1 parent ea90d54 commit f5283a2

File tree

6 files changed

+404
-47
lines changed

6 files changed

+404
-47
lines changed

SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c

Lines changed: 91 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,55 +1057,105 @@ GetDigestListBinSize (
10571057
return TotalSize;
10581058
}
10591059

1060+
STATIC VOID *
1061+
FindHashInDigestListBin (
1062+
IN VOID *DigestListBin,
1063+
TPMI_ALG_HASH HashAlg
1064+
)
1065+
{
1066+
UINTN Index;
1067+
UINT32 Count;
1068+
TPMI_ALG_HASH Alg;
1069+
1070+
Count = ReadUnaligned32 (DigestListBin);
1071+
DigestListBin = (UINT8 *)DigestListBin + sizeof(Count);
1072+
for (Index = 0; Index < Count; Index++) {
1073+
Alg = ReadUnaligned16 (DigestListBin);
1074+
DigestListBin = (UINT8 *)DigestListBin + sizeof(Alg);
1075+
1076+
if (Alg == HashAlg)
1077+
return DigestListBin;
1078+
1079+
DigestListBin = (UINT8 *)DigestListBin + GetHashSizeFromAlgo (Alg);
1080+
}
1081+
1082+
return NULL;
1083+
}
1084+
10601085
/**
10611086
Copy TPML_DIGEST_VALUES compact binary into a buffer
10621087
10631088
@param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary.
10641089
@param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer.
10651090
@param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy.
1066-
@param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied.
10671091
10681092
@return The end of buffer to hold TPML_DIGEST_VALUES compact binary.
10691093
**/
10701094
VOID *
10711095
CopyDigestListBinToBuffer (
10721096
IN OUT VOID *Buffer,
10731097
IN VOID *DigestListBin,
1074-
IN UINT32 HashAlgorithmMask,
1075-
OUT UINT32 *HashAlgorithmMaskCopied
1098+
IN UINT32 HashAlgorithmMask
10761099
)
10771100
{
10781101
UINTN Index;
10791102
UINT16 DigestSize;
1080-
UINT32 Count;
10811103
TPMI_ALG_HASH HashAlg;
10821104
UINT32 DigestListCount;
10831105
UINT32 *DigestListCountPtr;
1106+
TPMI_ALG_HASH HashAlgs[5];
1107+
VOID *Digest;
1108+
1109+
HashAlgs[0] = TPM_ALG_SHA1;
1110+
HashAlgs[1] = TPM_ALG_SHA256;
1111+
HashAlgs[2] = TPM_ALG_SM3_256;
1112+
HashAlgs[3] = TPM_ALG_SHA384;
1113+
HashAlgs[4] = TPM_ALG_SHA512;
10841114

10851115
DigestListCountPtr = (UINT32 *) Buffer;
1116+
Buffer = (UINT8 *)Buffer + sizeof(UINT32);
1117+
10861118
DigestListCount = 0;
1087-
(*HashAlgorithmMaskCopied) = 0;
10881119

1089-
Count = ReadUnaligned32 (DigestListBin);
1090-
Buffer = (UINT8 *)Buffer + sizeof(Count);
1091-
DigestListBin = (UINT8 *)DigestListBin + sizeof(Count);
1092-
for (Index = 0; Index < Count; Index++) {
1093-
HashAlg = ReadUnaligned16 (DigestListBin);
1094-
DigestListBin = (UINT8 *)DigestListBin + sizeof(HashAlg);
1120+
//
1121+
// Make sure output buffer conforms to HashAlgorithmMask.
1122+
//
1123+
// Copy digests from the entry if they are present, otherwise add missing
1124+
// digests filled as what's called "OneDigest" in TXT Software
1125+
// Development Guide (not really related, but alternatives are zeroes or
1126+
// 0xFFs, might as well use a value documented somewhere).
1127+
//
1128+
for (Index = 0; Index < ARRAY_SIZE (HashAlgs); Index++) {
1129+
HashAlg = HashAlgs[Index];
1130+
Digest = FindHashInDigestListBin (DigestListBin, HashAlg);
10951131
DigestSize = GetHashSizeFromAlgo (HashAlg);
10961132

1097-
if (IsHashAlgSupportedInHashAlgorithmMask(HashAlg, HashAlgorithmMask)) {
1098-
CopyMem (Buffer, &HashAlg, sizeof(HashAlg));
1099-
Buffer = (UINT8 *)Buffer + sizeof(HashAlg);
1100-
CopyMem (Buffer, DigestListBin, DigestSize);
1101-
Buffer = (UINT8 *)Buffer + DigestSize;
1102-
DigestListCount++;
1103-
(*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg);
1133+
if (!(HashAlgorithmMask & GetHashMaskFromAlgo (HashAlg))) {
1134+
// Not active.
1135+
if (Digest != NULL)
1136+
DEBUG ((DEBUG_WARN, "%a(): Event log entry includes HashAlg (0x%x) unsupported by PCR bank\n",
1137+
__FUNCTION__, HashAlg));
1138+
continue;
1139+
}
1140+
1141+
CopyMem (Buffer, &HashAlg, sizeof(HashAlg));
1142+
Buffer = (UINT8 *)Buffer + sizeof(HashAlg);
1143+
1144+
if (Digest == NULL) {
1145+
// Missing, use "OneDigest".
1146+
ZeroMem (Buffer, DigestSize);
1147+
*(UINT8 *)Buffer = 1;
1148+
DEBUG ((DEBUG_WARN, "%a(): Event log entry is missing HashAlg (0x%x) supported by PCR bank\n",
1149+
__FUNCTION__, HashAlg));
11041150
} else {
1105-
DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg));
1151+
CopyMem (Buffer, Digest, DigestSize);
11061152
}
1107-
DigestListBin = (UINT8 *)DigestListBin + DigestSize;
1153+
1154+
Buffer = (UINT8 *)Buffer + DigestSize;
1155+
1156+
DigestListCount++;
11081157
}
1158+
11091159
WriteUnaligned32 (DigestListCountPtr, DigestListCount);
11101160

11111161
return Buffer;
@@ -1552,12 +1602,10 @@ SetupEventLog (
15521602
EFI_PHYSICAL_ADDRESS Lasa;
15531603
UINTN Index;
15541604
VOID *DigestListBin;
1555-
TPML_DIGEST_VALUES TempDigestListBin;
15561605
UINT32 DigestListBinSize;
15571606
UINT8 *Event;
15581607
UINT32 EventSize;
15591608
UINT32 *EventSizePtr;
1560-
UINT32 HashAlgorithmMaskCopied;
15611609
TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct;
15621610
UINT8 TempBuf[sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) + (HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8)];
15631611
TCG_PCR_EVENT_HDR SpecIdEvent;
@@ -1814,11 +1862,11 @@ SetupEventLog (
18141862
Status = EFI_SUCCESS;
18151863
while (!EFI_ERROR (Status) &&
18161864
(GuidHob.Raw = GetNextGuidHob (mTcg2EventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) {
1817-
TcgEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));
1818-
ASSERT (TcgEvent != NULL);
1819-
GuidHob.Raw = GET_NEXT_HOB (GuidHob);
18201865
switch (mTcg2EventInfo[Index].LogFormat) {
18211866
case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
1867+
TcgEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid));
1868+
ASSERT (TcgEvent != NULL);
1869+
18221870
Status = TcgDxeLogEvent (
18231871
mTcg2EventInfo[Index].LogFormat,
18241872
TcgEvent,
@@ -1828,8 +1876,15 @@ SetupEventLog (
18281876
);
18291877
break;
18301878
case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
1831-
DigestListBin = (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE);
1879+
//
1880+
// This is a storage for new header.
1881+
//
1882+
TcgEvent = AllocatePool (sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + sizeof(TPML_DIGEST_VALUES) + sizeof(UINT32));
1883+
ASSERT (TcgEvent != NULL);
1884+
1885+
DigestListBin = (UINT8 *)GET_GUID_HOB_DATA (GuidHob.Guid) + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE);
18321886
DigestListBinSize = GetDigestListBinSize (DigestListBin);
1887+
CopyMem (TcgEvent, GET_GUID_HOB_DATA (GuidHob.Guid), sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE));
18331888
//
18341889
// Save event size.
18351890
//
@@ -1838,26 +1893,18 @@ SetupEventLog (
18381893
//
18391894
// Filter inactive digest in the event2 log from PEI HOB.
18401895
//
1841-
CopyMem (&TempDigestListBin, DigestListBin, GetDigestListBinSize (DigestListBin));
18421896
EventSizePtr = CopyDigestListBinToBuffer (
1897+
TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE),
18431898
DigestListBin,
1844-
&TempDigestListBin,
1845-
mTcgDxeData.BsCap.ActivePcrBanks,
1846-
&HashAlgorithmMaskCopied
1899+
mTcgDxeData.BsCap.ActivePcrBanks
18471900
);
1848-
if (HashAlgorithmMaskCopied != mTcgDxeData.BsCap.ActivePcrBanks) {
1849-
DEBUG ((
1850-
DEBUG_ERROR,
1851-
"ERROR: The event2 log includes digest hash mask 0x%x, but required digest hash mask is 0x%x\n",
1852-
HashAlgorithmMaskCopied,
1853-
mTcgDxeData.BsCap.ActivePcrBanks
1854-
));
1855-
}
18561901
//
18571902
// Restore event size.
18581903
//
18591904
CopyMem (EventSizePtr, &EventSize, sizeof(UINT32));
1860-
DigestListBinSize = GetDigestListBinSize (DigestListBin);
1905+
DigestListBinSize = GetDigestListBinSize (TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE));
1906+
1907+
DEBUG ((DEBUG_INFO, "%a: DigestListBinSize = %d\n", __FUNCTION__, DigestListBinSize));
18611908

18621909
Status = TcgDxeLogEvent (
18631910
mTcg2EventInfo[Index].LogFormat,
@@ -1869,6 +1916,7 @@ SetupEventLog (
18691916
break;
18701917
}
18711918
FreePool (TcgEvent);
1919+
GuidHob.Raw = GET_NEXT_HOB (GuidHob);
18721920
}
18731921
}
18741922
}
@@ -2863,13 +2911,10 @@ DriverEntry (
28632911
}
28642912
}
28652913

2866-
mTcgDxeData.BsCap.SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
2867-
if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) == 0) {
2868-
//
2869-
// No need to expose TCG1.2 event log if SHA1 bank does not exist.
2870-
//
2871-
mTcgDxeData.BsCap.SupportedEventLogs &= ~EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
2872-
}
2914+
//
2915+
// Only expose TCG2 event log for TPM2.
2916+
//
2917+
mTcgDxeData.BsCap.SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
28732918

28742919
DEBUG ((EFI_D_INFO, "Tcg2.SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs));
28752920
DEBUG ((EFI_D_INFO, "Tcg2.HashAlgorithmBitmap - 0x%08x\n", mTcgDxeData.BsCap.HashAlgorithmBitmap));

UefiPayloadPkg/BlSupportPei/BlSupportPei.c

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
88
**/
99
#include "BlSupportPei.h"
1010

11+
#include <Coreboot.h>
12+
#include <IndustryStandard/UefiTcgPlatform.h>
13+
1114
#define LEGACY_8259_MASK_REGISTER_MASTER 0x21
1215
#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1
1316

@@ -495,6 +498,140 @@ ValidateFvHeader (
495498
return EFI_SUCCESS;
496499
}
497500

501+
STATIC
502+
EFI_STATUS
503+
ParseAndPublishTPM1Log (
504+
CONST struct tcpa_spec_entry *SpecEntry,
505+
UINTN Size
506+
)
507+
{
508+
UINT8 ZeroBlock[sizeof (struct tcpa_spec_entry)];
509+
struct tcpa_log_entry *Entry;
510+
EFI_PHYSICAL_ADDRESS Start;
511+
EFI_PHYSICAL_ADDRESS Current;
512+
UINTN EntrySize;
513+
514+
// This must hold to avoid integer overflow below.
515+
ASSERT (Size >= sizeof (*Entry));
516+
517+
ZeroMem (ZeroBlock, sizeof (ZeroBlock));
518+
519+
Start = (EFI_PHYSICAL_ADDRESS)(UINTN) SpecEntry;
520+
Current = Start;
521+
while (Current - Start < Size - sizeof (*Entry) &&
522+
CompareMem ((VOID *)(UINTN) Current, (VOID *) ZeroBlock, sizeof (ZeroBlock)) != 0) {
523+
Entry = (VOID *)(UINTN) Current;
524+
EntrySize = sizeof (*Entry) + Entry->event_data_size;
525+
526+
BuildGuidDataHob (&gTcgEventEntryHobGuid, Entry, EntrySize);
527+
Current += EntrySize;
528+
}
529+
530+
return EFI_SUCCESS;
531+
}
532+
533+
STATIC
534+
EFI_STATUS
535+
ParseAndPublishTPM2Log (
536+
CONST struct tcg_efi_spec_id_event *SpecEntry,
537+
UINTN Size
538+
)
539+
{
540+
UINT8 ZeroBlock[sizeof (struct tcg_pcr_event2_header)];
541+
struct tcg_pcr_event2_header *Header;
542+
EFI_PHYSICAL_ADDRESS Start;
543+
EFI_PHYSICAL_ADDRESS Current;
544+
UINTN EntrySize;
545+
UINTN DigestsSize;
546+
UINTN Idx;
547+
548+
// This must hold to avoid integer overflow below.
549+
ASSERT (Size >= sizeof (*Header));
550+
551+
ZeroMem (ZeroBlock, sizeof (ZeroBlock));
552+
553+
DigestsSize = 0;
554+
for (Idx = 0; Idx < SpecEntry->num_of_algorithms; ++Idx) {
555+
DigestsSize += sizeof (UINT16) + SpecEntry->digest_sizes[Idx].digest_size;
556+
}
557+
558+
Start = (EFI_PHYSICAL_ADDRESS)(UINTN) SpecEntry;
559+
560+
// Not adding Spec ID Event for TPM2 because Tcg2Dxe adds one, coreboot's
561+
// event would have to be modified to be suitable due to the list of
562+
// algorithms there.
563+
Current = Start + sizeof (struct tcpa_log_entry) + SpecEntry->event_size;
564+
565+
while (Current - Start < Size - sizeof (*Header) &&
566+
CompareMem ((VOID *)(UINTN) Current, (VOID *) ZeroBlock, sizeof (ZeroBlock)) != 0) {
567+
Header = (VOID *)(UINTN) Current;
568+
EntrySize = sizeof (*Header) + DigestsSize;
569+
570+
// Event data size field and data itself.
571+
EntrySize += sizeof (UINT32) + *(CONST UINT32 *)(UINTN) (Current + EntrySize);
572+
573+
BuildGuidDataHob (&gTcgEvent2EntryHobGuid, Header, EntrySize);
574+
Current += EntrySize;
575+
}
576+
577+
return EFI_SUCCESS;
578+
}
579+
580+
STATIC
581+
EFI_STATUS
582+
ParseAndPublishTPMLog (
583+
VOID
584+
)
585+
{
586+
RETURN_STATUS Status;
587+
VOID *LogBase;
588+
UINTN LogSize;
589+
590+
const struct tcpa_spec_entry *Tcg1Entry;
591+
const struct tcg_efi_spec_id_event *Tcg2Entry;
592+
593+
Status = ParseTPMLog (&LogBase, &LogSize);
594+
if (EFI_ERROR (Status)) {
595+
DEBUG ((
596+
DEBUG_INFO,
597+
"%a: Not publishing coreboot's TPM log entries because: %r.\n",
598+
__FUNCTION__, Status
599+
));
600+
return Status;
601+
}
602+
603+
Tcg1Entry = LogBase;
604+
if (AsciiStrCmp((CONST CHAR8 *)Tcg1Entry->signature, TCPA_SPEC_ID_EVENT_SIGNATURE) == 0) {
605+
if (Tcg1Entry->spec_version_major == 1 &&
606+
Tcg1Entry->spec_version_minor == 2 &&
607+
Tcg1Entry->spec_errata >= 1 &&
608+
Tcg1Entry->entry.event_type == EV_NO_ACTION) {
609+
return ParseAndPublishTPM1Log (Tcg1Entry, LogSize);
610+
}
611+
612+
DEBUG ((DEBUG_WARN, "%a: Unknown TPM1.2 log specification.\n", __FUNCTION__));
613+
return EFI_UNSUPPORTED;
614+
}
615+
616+
Tcg2Entry = LogBase;
617+
if (AsciiStrCmp((CONST CHAR8 *)Tcg1Entry->signature, TCG_EFI_SPEC_ID_EVENT_SIGNATURE) == 0) {
618+
if (Tcg2Entry->spec_version_major == 2 &&
619+
Tcg2Entry->spec_version_minor == 0 &&
620+
Tcg2Entry->event_type == EV_NO_ACTION) {
621+
return ParseAndPublishTPM2Log (Tcg2Entry, LogSize);
622+
}
623+
624+
DEBUG ((DEBUG_WARN, "%a: Unknown TPM2 log specification.\n", __FUNCTION__));
625+
return EFI_UNSUPPORTED;
626+
}
627+
628+
DEBUG ((DEBUG_WARN,
629+
"%a: Unknown TPM log specification %.*s.\n",
630+
__FUNCTION__, (int)sizeof(Tcg2Entry->signature), (CONST CHAR8 *)Tcg2Entry->signature));
631+
return EFI_UNSUPPORTED;
632+
}
633+
634+
498635
/**
499636
This is the entrypoint of PEIM
500637
@@ -757,6 +894,15 @@ BlPeiEntryPoint (
757894
IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
758895
IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
759896

897+
//
898+
// Parse coreboot's log.
899+
//
900+
Status = ParseAndPublishTPMLog ();
901+
if (EFI_ERROR (Status)) {
902+
DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
903+
return Status;
904+
}
905+
760906
return EFI_SUCCESS;
761907
}
762908

0 commit comments

Comments
 (0)