Skip to content

Commit 9896354

Browse files
committed
DasharoPayloadPkg,SecurityPkg: import coreboot's TPM log
Find the log using DasharoPayloadPkg/CbParseLib in DasharoPayloadPkg/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 26f855c commit 9896354

File tree

7 files changed

+401
-47
lines changed

7 files changed

+401
-47
lines changed

DasharoPayloadPkg/BlSupportPei/BlSupportPei.c

Lines changed: 145 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

@@ -496,6 +499,139 @@ ValidateFvHeader (
496499
return EFI_SUCCESS;
497500
}
498501

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

906+
//
907+
// Parse coreboot's log.
908+
//
909+
Status = ParseAndPublishTPMLog ();
910+
if (EFI_ERROR (Status)) {
911+
DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));
912+
return Status;
913+
}
914+
770915
return EFI_SUCCESS;
771916
}
772917

DasharoPayloadPkg/BlSupportPei/BlSupportPei.inf

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
EmbeddedPkg/EmbeddedPkg.dec
3535
IntelFsp2Pkg/IntelFsp2Pkg.dec
3636
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
37+
SecurityPkg/SecurityPkg.dec
3738
DasharoPayloadPkg/DasharoPayloadPkg.dec
3839
UefiCpuPkg/UefiCpuPkg.dec
3940

@@ -64,6 +65,8 @@
6465
gEfiVariableGuid
6566
gEfiAuthenticatedVariableGuid
6667
gEdkiiNvVarStoreFormattedGuid
68+
gTcgEventEntryHobGuid
69+
gTcgEvent2EntryHobGuid
6770

6871
[Ppis]
6972
gEfiPeiMasterBootModePpiGuid

DasharoPayloadPkg/Include/Coreboot.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ struct cb_smmstorev2 {
264264
UINT8 unused[3]; /* Set to zero */
265265
};
266266

267+
#define CB_TAG_CBMEM_ENTRY 0x0031
267268
#define CB_TAG_VBOOT_WORKBUF 0x0034
268269

269270
struct cb_cbmem_entry {
@@ -762,4 +763,67 @@ struct cb_range {
762763
UINT32 range_size;
763764
} __attribute__((packed));
764765

766+
#define CBMEM_ID_TCPA_TCG_LOG 0x54445041 /* TPM log per TPM 1.2 specification */
767+
#define CBMEM_ID_TPM2_TCG_LOG 0x54504d32 /* TPM log per TPM 2.0 specification */
768+
769+
#define TCPA_SPEC_ID_EVENT_SIGNATURE "Spec ID Event00"
770+
#define TCG_EFI_SPEC_ID_EVENT_SIGNATURE "Spec ID Event03"
771+
772+
struct tcpa_log_entry {
773+
UINT32 pcr;
774+
UINT32 event_type;
775+
UINT8 digest[20];
776+
UINT32 event_data_size;
777+
UINT8 event[0];
778+
} __attribute__ ((packed));
779+
780+
struct tcpa_spec_entry {
781+
struct tcpa_log_entry entry;
782+
UINT8 signature[16];
783+
UINT32 platform_class;
784+
UINT8 spec_version_minor;
785+
UINT8 spec_version_major;
786+
UINT8 spec_errata;
787+
UINT8 reserved;
788+
UINT8 vendor_info_size;
789+
UINT8 vendor_info[0];
790+
} __attribute__ ((packed));
791+
792+
#define TPM2_ALG_SHA1 0x0004
793+
#define TPM2_ALG_SHA256 0x000B
794+
#define TPM2_ALG_SHA384 0x000C
795+
#define TPM2_ALG_SHA512 0x000D
796+
#define TPM2_ALG_SM3_256 0x0012
797+
798+
struct tcg_pcr_event2_header {
799+
UINT32 pcr_index;
800+
UINT32 event_type;
801+
UINT32 digest_count;
802+
UINT8 digests[0];
803+
/* UINT32 event_size; */
804+
/* UINT8 event[0]; */
805+
} __attribute__ ((packed));
806+
807+
struct tpm_digest_sizes {
808+
UINT16 alg_id;
809+
UINT16 digest_size;
810+
} __attribute__ ((packed));
811+
812+
struct tcg_efi_spec_id_event {
813+
UINT32 pcr_index;
814+
UINT32 event_type;
815+
UINT8 digest[20];
816+
UINT32 event_size;
817+
UINT8 signature[16];
818+
UINT32 platform_class;
819+
UINT8 spec_version_minor;
820+
UINT8 spec_version_major;
821+
UINT8 spec_errata;
822+
UINT8 uintn_size;
823+
UINT32 num_of_algorithms;
824+
struct tpm_digest_sizes digest_sizes[0]; /* variable number of members */
825+
/* UINT8 vendor_info_size; */
826+
/* UINT8 vendor_info[vendor_info_size]; */
827+
} __attribute__ ((packed));
828+
765829
#endif // _COREBOOT_PEI_H_INCLUDED_

DasharoPayloadPkg/Include/Library/BlParseLib.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,26 @@ ParseTPMPPIInfo (
153153
OUT TCG_PHYSICAL_PRESENCE_INFO *PPIInfo
154154
);
155155

156+
/**
157+
Find TPM log in TCG format if any.
158+
159+
The caller is expected to parse the first event of the log to determine its
160+
version.
161+
162+
@param Base Pointer the start of the log
163+
@param Size Size of the log
164+
165+
@retval RETURN_SUCCESS Successfully found TPM log.
166+
@retval RETURN_NOT_FOUND Failed to find TPM log.
167+
168+
**/
169+
RETURN_STATUS
170+
EFIAPI
171+
ParseTPMLog (
172+
OUT VOID **Base,
173+
OUT UINTN *Size
174+
);
175+
156176
/**
157177
Acquire Vboot recovery information from coreboot
158178

DasharoPayloadPkg/Library/CbParseLib/CbParseLib.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,42 @@ FindCbTag (
239239
}
240240

241241

242+
/**
243+
Find location and size of a coreboot record of the given type.
244+
245+
@param Tag The tag id to be found
246+
@param Size Optionally (if not NULL) set to size of the tag
247+
248+
@retval NULL The Tag is not found.
249+
@retval Others The pointer to the record found.
250+
251+
**/
252+
STATIC
253+
struct cb_cbmem_entry *
254+
FindCbEntry (
255+
IN UINT32 Id
256+
)
257+
{
258+
struct cb_header *Header;
259+
struct cb_cbmem_entry *Entry;
260+
UINT8 *TmpPtr;
261+
UINTN Idx;
262+
263+
Header = (struct cb_header *) GetParameterBase ();
264+
265+
TmpPtr = (UINT8 *)Header + Header->header_bytes;
266+
for (Idx = 0; Idx < Header->table_entries; Idx++) {
267+
Entry = (struct cb_cbmem_entry *)TmpPtr;
268+
if (Entry->tag == CB_TAG_CBMEM_ENTRY && Entry->id == Id) {
269+
return Entry;
270+
}
271+
TmpPtr += Entry->size;
272+
}
273+
274+
return NULL;
275+
}
276+
277+
242278
/**
243279
Find the given table with TableId from the given coreboot memory Root.
244280
@@ -693,6 +729,49 @@ ParseTPMPPIInfo (
693729
return RETURN_SUCCESS;
694730
}
695731

732+
/**
733+
Find TPM log in TCG format if any.
734+
735+
The caller is expected to parse the first event of the log to determine its
736+
version.
737+
738+
@param Base Pointer the start of the log
739+
@param Size Size of the log
740+
741+
@retval RETURN_SUCCESS Successfully found TPM log.
742+
@retval RETURN_NOT_FOUND Failed to find TPM log.
743+
744+
**/
745+
RETURN_STATUS
746+
EFIAPI
747+
ParseTPMLog (
748+
OUT VOID **Base,
749+
OUT UINTN *Size
750+
)
751+
{
752+
struct cb_cbmem_entry *Entry;
753+
754+
//
755+
// TPM2 format is the more capable "agile" format, so start with it like some
756+
// other parts of EDK test for TPM2 before testing for TPM1.
757+
//
758+
// Could return log version, but the caller should probably validate that the
759+
// buffer isn't empty and checking for correct Spec ID Event is a good way of
760+
// going about it.
761+
//
762+
763+
Entry = FindCbEntry (CBMEM_ID_TPM2_TCG_LOG);
764+
if (Entry == NULL)
765+
Entry = FindCbEntry (CBMEM_ID_TCPA_TCG_LOG);
766+
767+
if (Entry == NULL)
768+
return RETURN_NOT_FOUND;
769+
770+
*Base = (void *)(UINTN) Entry->address;
771+
*Size = Entry->entry_size;
772+
return RETURN_SUCCESS;
773+
}
774+
696775
STATIC
697776
CONST CHAR8 *
698777
GetRecoveryReasonString(

0 commit comments

Comments
 (0)