1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
21 #define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
23 typedef struct _TCG_VERSION
{
30 typedef struct tdEFI_TCG2_VERSION
{
35 typedef struct _TCG_BOOT_SERVICE_CAPABILITY
{
37 struct _TCG_VERSION StructureVersion
;
38 struct _TCG_VERSION ProtocolSpecVersion
;
39 UINT8 HashAlgorithmBitmap
;
40 BOOLEAN TPMPresentFlag
;
41 BOOLEAN TPMDeactivatedFlag
;
42 } TCG_BOOT_SERVICE_CAPABILITY
;
44 typedef struct tdTREE_BOOT_SERVICE_CAPABILITY
{
46 EFI_TCG2_VERSION StructureVersion
;
47 EFI_TCG2_VERSION ProtocolVersion
;
48 UINT32 HashAlgorithmBitmap
;
49 UINT32 SupportedEventLogs
;
50 BOOLEAN TrEEPresentFlag
;
51 UINT16 MaxCommandSize
;
52 UINT16 MaxResponseSize
;
53 UINT32 ManufacturerID
;
54 } TREE_BOOT_SERVICE_CAPABILITY
;
56 typedef UINT32 TCG_ALGORITHM_ID
;
57 #define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm
59 #define SHA1_DIGEST_SIZE 20
61 typedef struct _TCG_DIGEST
{
62 UINT8 Digest
[SHA1_DIGEST_SIZE
];
67 typedef struct _TCG_PCR_EVENT
{
70 struct _TCG_DIGEST digest
;
75 INTERFACE_DECL(_EFI_TCG
);
77 typedef EFI_STATUS(EFIAPI
* EFI_TCG_STATUS_CHECK
) (IN
struct _EFI_TCG
* This
,
78 OUT
struct _TCG_BOOT_SERVICE_CAPABILITY
* ProtocolCapability
,
79 OUT UINT32
* TCGFeatureFlags
,
80 OUT EFI_PHYSICAL_ADDRESS
* EventLogLocation
,
81 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
);
83 typedef EFI_STATUS(EFIAPI
* EFI_TCG_HASH_ALL
) (IN
struct _EFI_TCG
* This
,
85 IN UINT64 HashDataLen
,
86 IN TCG_ALGORITHM_ID AlgorithmId
,
87 IN OUT UINT64
* HashedDataLen
, IN OUT UINT8
** HashedDataResult
);
89 typedef EFI_STATUS(EFIAPI
* EFI_TCG_LOG_EVENT
) (IN
struct _EFI_TCG
* This
,
90 IN
struct _TCG_PCR_EVENT
* TCGLogData
,
91 IN OUT UINT32
* EventNumber
, IN UINT32 Flags
);
93 typedef EFI_STATUS(EFIAPI
* EFI_TCG_PASS_THROUGH_TO_TPM
) (IN
struct _EFI_TCG
* This
,
94 IN UINT32 TpmInputParameterBlockSize
,
95 IN UINT8
* TpmInputParameterBlock
,
96 IN UINT32 TpmOutputParameterBlockSize
,
97 IN UINT8
* TpmOutputParameterBlock
);
99 typedef EFI_STATUS(EFIAPI
* EFI_TCG_HASH_LOG_EXTEND_EVENT
) (IN
struct _EFI_TCG
* This
,
100 IN EFI_PHYSICAL_ADDRESS HashData
,
101 IN UINT64 HashDataLen
,
102 IN TCG_ALGORITHM_ID AlgorithmId
,
103 IN
struct _TCG_PCR_EVENT
* TCGLogData
,
104 IN OUT UINT32
* EventNumber
,
105 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
);
107 typedef struct _EFI_TCG
{
108 EFI_TCG_STATUS_CHECK StatusCheck
;
109 EFI_TCG_HASH_ALL HashAll
;
110 EFI_TCG_LOG_EVENT LogEvent
;
111 EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTPM
;
112 EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent
;
115 #define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
117 typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL
;
119 typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP
;
120 typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT
;
121 typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP
;
123 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001
124 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
126 typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY
{
128 EFI_TCG2_VERSION StructureVersion
;
129 EFI_TCG2_VERSION ProtocolVersion
;
130 EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap
;
131 EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs
;
132 BOOLEAN TPMPresentFlag
;
133 UINT16 MaxCommandSize
;
134 UINT16 MaxResponseSize
;
135 UINT32 ManufacturerID
;
136 UINT32 NumberOfPCRBanks
;
137 EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks
;
138 } EFI_TCG2_BOOT_SERVICE_CAPABILITY
;
140 #define EFI_TCG2_EVENT_HEADER_VERSION 1
144 UINT16 HeaderVersion
;
147 } __attribute__ ((packed
)) EFI_TCG2_EVENT_HEADER
;
149 typedef struct tdEFI_TCG2_EVENT
{
151 EFI_TCG2_EVENT_HEADER Header
;
153 } __attribute__ ((packed
)) EFI_TCG2_EVENT
;
155 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_CAPABILITY
) (IN EFI_TCG2_PROTOCOL
* This
,
156 IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY
* ProtocolCapability
);
158 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_EVENT_LOG
) (IN EFI_TCG2_PROTOCOL
* This
,
159 IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat
,
160 OUT EFI_PHYSICAL_ADDRESS
* EventLogLocation
,
161 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
,
162 OUT BOOLEAN
* EventLogTruncated
);
164 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_HASH_LOG_EXTEND_EVENT
) (IN EFI_TCG2_PROTOCOL
* This
,
166 IN EFI_PHYSICAL_ADDRESS DataToHash
,
167 IN UINT64 DataToHashLen
, IN EFI_TCG2_EVENT
* EfiTcgEvent
);
169 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_SUBMIT_COMMAND
) (IN EFI_TCG2_PROTOCOL
* This
,
170 IN UINT32 InputParameterBlockSize
,
171 IN UINT8
* InputParameterBlock
,
172 IN UINT32 OutputParameterBlockSize
, IN UINT8
* OutputParameterBlock
);
174 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
, OUT UINT32
* ActivePcrBanks
);
176 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_SET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
, IN UINT32 ActivePcrBanks
);
178 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
,
179 OUT UINT32
* OperationPresent
, OUT UINT32
* Response
);
181 typedef struct tdEFI_TCG2_PROTOCOL
{
182 EFI_TCG2_GET_CAPABILITY GetCapability
;
183 EFI_TCG2_GET_EVENT_LOG GetEventLog
;
184 EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent
;
185 EFI_TCG2_SUBMIT_COMMAND SubmitCommand
;
186 EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks
;
187 EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks
;
188 EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks
;
192 static EFI_STATUS
tpm1_measure_to_pcr_and_event_log(const EFI_TCG
*tcg
, UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
,
193 UINTN buffer_size
, const CHAR16
*description
) {
195 TCG_PCR_EVENT
*tcg_event
;
197 EFI_PHYSICAL_ADDRESS event_log_last
;
200 desc_len
= (StrLen(description
) + 1) * sizeof(CHAR16
);
202 tcg_event
= AllocateZeroPool(desc_len
+ sizeof(TCG_PCR_EVENT
));
205 return EFI_OUT_OF_RESOURCES
;
207 tcg_event
->EventSize
= desc_len
;
208 CopyMem((VOID
*) & tcg_event
->Event
[0], (VOID
*) description
, desc_len
);
210 tcg_event
->PCRIndex
= pcrindex
;
211 tcg_event
->EventType
= EV_IPL
;
214 status
= uefi_call_wrapper(tcg
->HashLogExtendEvent
, 7,
215 (EFI_TCG
*) tcg
, buffer
, buffer_size
, TCG_ALG_SHA
, tcg_event
, &event_number
, &event_log_last
);
217 if (EFI_ERROR(status
))
220 uefi_call_wrapper(BS
->FreePool
, 1, tcg_event
);
226 * According to TCG EFI Protocol Specification for TPM 2.0 family,
227 * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
228 * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
229 * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
230 * internal switch through calling get_event_log() in order to allow
231 * to retrieve the logs from OS runtime.
233 static EFI_STATUS
trigger_tcg2_final_events_table(const EFI_TCG2
*tcg
, EFI_TCG2_EVENT_LOG_FORMAT log_fmt
)
235 return uefi_call_wrapper(tcg
->GetEventLog
, 5, (EFI_TCG2
*) tcg
,
239 static EFI_STATUS
tpm2_measure_to_pcr_and_event_log(const EFI_TCG2
*tcg
, UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
,
240 UINT64 buffer_size
, const CHAR16
*description
, EFI_TCG2_EVENT_LOG_FORMAT log_fmt
) {
242 EFI_TCG2_EVENT
*tcg_event
;
244 static BOOLEAN triggered
= FALSE
;
246 if (triggered
== FALSE
) {
247 status
= trigger_tcg2_final_events_table(tcg
, log_fmt
);
248 if (EFI_ERROR(status
))
254 desc_len
= StrLen(description
) * sizeof(CHAR16
);
256 tcg_event
= AllocateZeroPool(sizeof(*tcg_event
) - sizeof(tcg_event
->Event
) + desc_len
+ 1);
259 return EFI_OUT_OF_RESOURCES
;
261 tcg_event
->Size
= sizeof(*tcg_event
) - sizeof(tcg_event
->Event
) + desc_len
+ 1;
262 tcg_event
->Header
.HeaderSize
= sizeof(EFI_TCG2_EVENT_HEADER
);
263 tcg_event
->Header
.HeaderVersion
= EFI_TCG2_EVENT_HEADER_VERSION
;
264 tcg_event
->Header
.PCRIndex
= pcrindex
;
265 tcg_event
->Header
.EventType
= EV_IPL
;
267 CopyMem((VOID
*) tcg_event
->Event
, (VOID
*) description
, desc_len
);
269 status
= uefi_call_wrapper(tcg
->HashLogExtendEvent
, 5, (EFI_TCG2
*) tcg
, 0, buffer
, (UINT64
) buffer_size
, tcg_event
);
271 uefi_call_wrapper(BS
->FreePool
, 1, tcg_event
);
273 if (EFI_ERROR(status
))
279 static EFI_TCG
* tcg1_interface_check(void) {
280 EFI_GUID tpm_guid
= EFI_TCG_PROTOCOL_GUID
;
283 TCG_BOOT_SERVICE_CAPABILITY capability
;
285 EFI_PHYSICAL_ADDRESS event_log_location
;
286 EFI_PHYSICAL_ADDRESS event_log_last_entry
;
288 status
= LibLocateProtocol(&tpm_guid
, (void **) &tcg
);
290 if (EFI_ERROR(status
))
293 capability
.Size
= (UINT8
) sizeof(capability
);
294 status
= uefi_call_wrapper(tcg
->StatusCheck
, 5, tcg
, &capability
, &features
, &event_log_location
, &event_log_last_entry
);
296 if (EFI_ERROR(status
))
299 if (capability
.TPMDeactivatedFlag
)
302 if (!capability
.TPMPresentFlag
)
308 static EFI_TCG2
* tcg2_interface_check(EFI_TCG2_BOOT_SERVICE_CAPABILITY
*caps
) {
309 EFI_GUID tpm2_guid
= EFI_TCG2_PROTOCOL_GUID
;
313 status
= LibLocateProtocol(&tpm2_guid
, (void **) &tcg
);
315 if (EFI_ERROR(status
))
318 caps
->Size
= (UINT8
) sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY
);
319 status
= uefi_call_wrapper(tcg
->GetCapability
, 2, tcg
, caps
);
321 if (EFI_ERROR(status
))
324 if (caps
->StructureVersion
.Major
== 1 &&
325 caps
->StructureVersion
.Minor
== 0) {
326 TCG_BOOT_SERVICE_CAPABILITY
*caps_1_0
;
327 caps_1_0
= (TCG_BOOT_SERVICE_CAPABILITY
*)caps
;
328 if (caps_1_0
->TPMPresentFlag
)
332 if (!caps
->TPMPresentFlag
)
338 EFI_STATUS
tpm_log_event(UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
, UINTN buffer_size
, const CHAR16
*description
) {
341 EFI_TCG2_BOOT_SERVICE_CAPABILITY caps
;
343 tpm2
= tcg2_interface_check(&caps
);
345 EFI_TCG2_EVENT_LOG_BITMAP supported_logs
;
346 EFI_TCG2_EVENT_LOG_FORMAT log_fmt
;
348 if (caps
.StructureVersion
.Major
== 1 &&
349 caps
.StructureVersion
.Minor
== 0)
350 supported_logs
= ((TREE_BOOT_SERVICE_CAPABILITY
*)&caps
)->SupportedEventLogs
;
352 supported_logs
= caps
.SupportedEventLogs
;
354 if (supported_logs
& EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
)
355 log_fmt
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
;
357 log_fmt
= EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2
;
359 uefi_call_wrapper(BS
->Stall
, 1, 2000 * 1000);
360 return tpm2_measure_to_pcr_and_event_log(tpm2
, pcrindex
, buffer
, buffer_size
, description
, log_fmt
);
363 tpm1
= tcg1_interface_check();
365 return tpm1_measure_to_pcr_and_event_log(tpm1
, pcrindex
, buffer
, buffer_size
, description
);
367 /* No active TPM found, so don't return an error */