1 /** @file
2   This library is used by other modules to measure data to TPM.
3 
4 Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include <Uefi/UefiBaseType.h>
10 #include <Pi/PiFirmwareVolume.h>
11 
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/ReportStatusCodeLib.h>
15 #include <Library/PcdLib.h>
16 #include <Library/PrintLib.h>
17 #include <Library/TcgEventLogRecordLib.h>
18 #include <Library/TpmMeasurementLib.h>
19 
20 #include <IndustryStandard/UefiTcgPlatform.h>
21 
22 /**
23   Get the FvName from the FV header.
24 
25   Causion: The FV is untrusted input.
26 
27   @param[in]  FvBase            Base address of FV image.
28   @param[in]  FvLength          Length of FV image.
29 
30   @return FvName pointer
31   @retval NULL   FvName is NOT found
32 **/
33 VOID *
TpmMeasurementGetFvName(IN EFI_PHYSICAL_ADDRESS FvBase,IN UINT64 FvLength)34 TpmMeasurementGetFvName (
35   IN EFI_PHYSICAL_ADDRESS           FvBase,
36   IN UINT64                         FvLength
37   )
38 {
39   EFI_FIRMWARE_VOLUME_HEADER      *FvHeader;
40   EFI_FIRMWARE_VOLUME_EXT_HEADER  *FvExtHeader;
41 
42   if (FvBase >= MAX_ADDRESS) {
43     return NULL;
44   }
45   if (FvLength >= MAX_ADDRESS - FvBase) {
46     return NULL;
47   }
48   if (FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
49     return NULL;
50   }
51 
52   FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
53   if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
54     return NULL;
55   }
56   if (FvHeader->ExtHeaderOffset < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
57     return NULL;
58   }
59   if (FvHeader->ExtHeaderOffset + sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {
60     return NULL;
61   }
62   FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);
63 
64   return &FvExtHeader->FvName;
65 }
66 
67 /**
68   Measure a FirmwareBlob.
69 
70   @param[in]  PcrIndex                PcrIndex of the measurement.
71   @param[in]  Description             Description for this FirmwareBlob.
72   @param[in]  FirmwareBlobBase        Base address of this FirmwareBlob.
73   @param[in]  FirmwareBlobLength      Size in bytes of this FirmwareBlob.
74 
75   @retval EFI_SUCCESS           Operation completed successfully.
76   @retval EFI_UNSUPPORTED       TPM device not available.
77   @retval EFI_OUT_OF_RESOURCES  Out of memory.
78   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
79 **/
80 EFI_STATUS
81 EFIAPI
MeasureFirmwareBlob(IN UINT32 PcrIndex,IN CHAR8 * Description OPTIONAL,IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,IN UINT64 FirmwareBlobLength)82 MeasureFirmwareBlob (
83   IN UINT32                         PcrIndex,
84   IN CHAR8                          *Description OPTIONAL,
85   IN EFI_PHYSICAL_ADDRESS           FirmwareBlobBase,
86   IN UINT64                         FirmwareBlobLength
87   )
88 {
89   EFI_PLATFORM_FIRMWARE_BLOB        FvBlob;
90   PLATFORM_FIRMWARE_BLOB2_STRUCT    FvBlob2;
91   VOID                              *FvName;
92   UINT32                            EventType;
93   VOID                              *EventLog;
94   UINT32                            EventLogSize;
95   EFI_STATUS                        Status;
96 
97   FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength);
98 
99   if (((Description != NULL) || (FvName != NULL)) &&
100       (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {
101     if (Description != NULL) {
102       AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "%a", Description);
103     } else {
104       AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
105     }
106 
107     FvBlob2.BlobDescriptionSize = sizeof(FvBlob2.BlobDescription);
108     FvBlob2.BlobBase = FirmwareBlobBase;
109     FvBlob2.BlobLength = FirmwareBlobLength;
110 
111     EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
112     EventLog = &FvBlob2;
113     EventLogSize = sizeof(FvBlob2);
114   } else {
115     FvBlob.BlobBase = FirmwareBlobBase;
116     FvBlob.BlobLength = FirmwareBlobLength;
117 
118     EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
119     EventLog = &FvBlob;
120     EventLogSize = sizeof(FvBlob);
121   }
122 
123   Status = TpmMeasureAndLogData (
124              PcrIndex,
125              EventType,
126              EventLog,
127              EventLogSize,
128              (VOID*)(UINTN)FirmwareBlobBase,
129              FirmwareBlobLength
130              );
131 
132   return Status;
133 }
134 
135 /**
136   Measure a HandoffTable.
137 
138   @param[in]  PcrIndex                PcrIndex of the measurement.
139   @param[in]  Description             Description for this HandoffTable.
140   @param[in]  TableGuid               GUID of this HandoffTable.
141   @param[in]  TableAddress            Base address of this HandoffTable.
142   @param[in]  TableLength             Size in bytes of this HandoffTable.
143 
144   @retval EFI_SUCCESS           Operation completed successfully.
145   @retval EFI_UNSUPPORTED       TPM device not available.
146   @retval EFI_OUT_OF_RESOURCES  Out of memory.
147   @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
148 **/
149 EFI_STATUS
150 EFIAPI
MeasureHandoffTable(IN UINT32 PcrIndex,IN CHAR8 * Description OPTIONAL,IN EFI_GUID * TableGuid,IN VOID * TableAddress,IN UINTN TableLength)151 MeasureHandoffTable (
152   IN UINT32                         PcrIndex,
153   IN CHAR8                          *Description OPTIONAL,
154   IN EFI_GUID                       *TableGuid,
155   IN VOID                           *TableAddress,
156   IN UINTN                          TableLength
157   )
158 {
159   EFI_HANDOFF_TABLE_POINTERS        HandoffTables;
160   HANDOFF_TABLE_POINTERS2_STRUCT    HandoffTables2;
161   UINT32                            EventType;
162   VOID                              *EventLog;
163   UINT32                            EventLogSize;
164   EFI_STATUS                        Status;
165 
166   if ((Description != NULL) &&
167       (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {
168     AsciiSPrint((CHAR8*)HandoffTables2.TableDescription, sizeof(HandoffTables2.TableDescription), "%a", Description);
169 
170     HandoffTables2.TableDescriptionSize = sizeof(HandoffTables2.TableDescription);
171     HandoffTables2.NumberOfTables = 1;
172     CopyGuid (&(HandoffTables2.TableEntry[0].VendorGuid), TableGuid);
173     HandoffTables2.TableEntry[0].VendorTable = TableAddress;
174 
175     EventType = EV_EFI_HANDOFF_TABLES2;
176     EventLog = &HandoffTables2;
177     EventLogSize = sizeof(HandoffTables2);
178   } else {
179     HandoffTables.NumberOfTables = 1;
180     CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), TableGuid);
181     HandoffTables.TableEntry[0].VendorTable = TableAddress;
182 
183     EventType = EV_EFI_HANDOFF_TABLES;
184     EventLog = &HandoffTables;
185     EventLogSize = sizeof(HandoffTables);
186   }
187 
188   Status = TpmMeasureAndLogData (
189              PcrIndex,
190              EventType,
191              EventLog,
192              EventLogSize,
193              TableAddress,
194              TableLength
195              );
196   return Status;
197 }
198