2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation; either version 2.1 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
20 #define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
22 typedef struct _TCG_VERSION
{
29 typedef struct _TCG_BOOT_SERVICE_CAPABILITY
{
31 struct _TCG_VERSION StructureVersion
;
32 struct _TCG_VERSION ProtocolSpecVersion
;
33 UINT8 HashAlgorithmBitmap
;
34 BOOLEAN TPMPresentFlag
;
35 BOOLEAN TPMDeactivatedFlag
;
36 } TCG_BOOT_SERVICE_CAPABILITY
;
38 typedef UINT32 TCG_ALGORITHM_ID
;
39 #define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm
41 #define SHA1_DIGEST_SIZE 20
43 typedef struct _TCG_DIGEST
{
44 UINT8 Digest
[SHA1_DIGEST_SIZE
];
49 typedef struct _TCG_PCR_EVENT
{
52 struct _TCG_DIGEST digest
;
57 INTERFACE_DECL(_EFI_TCG
);
59 typedef EFI_STATUS(EFIAPI
* EFI_TCG_STATUS_CHECK
) (IN
struct _EFI_TCG
* This
,
60 OUT
struct _TCG_BOOT_SERVICE_CAPABILITY
* ProtocolCapability
,
61 OUT UINT32
* TCGFeatureFlags
,
62 OUT EFI_PHYSICAL_ADDRESS
* EventLogLocation
,
63 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
);
65 typedef EFI_STATUS(EFIAPI
* EFI_TCG_HASH_ALL
) (IN
struct _EFI_TCG
* This
,
67 IN UINT64 HashDataLen
,
68 IN TCG_ALGORITHM_ID AlgorithmId
,
69 IN OUT UINT64
* HashedDataLen
, IN OUT UINT8
** HashedDataResult
);
71 typedef EFI_STATUS(EFIAPI
* EFI_TCG_LOG_EVENT
) (IN
struct _EFI_TCG
* This
,
72 IN
struct _TCG_PCR_EVENT
* TCGLogData
,
73 IN OUT UINT32
* EventNumber
, IN UINT32 Flags
);
75 typedef EFI_STATUS(EFIAPI
* EFI_TCG_PASS_THROUGH_TO_TPM
) (IN
struct _EFI_TCG
* This
,
76 IN UINT32 TpmInputParameterBlockSize
,
77 IN UINT8
* TpmInputParameterBlock
,
78 IN UINT32 TpmOutputParameterBlockSize
,
79 IN UINT8
* TpmOutputParameterBlock
);
81 typedef EFI_STATUS(EFIAPI
* EFI_TCG_HASH_LOG_EXTEND_EVENT
) (IN
struct _EFI_TCG
* This
,
82 IN EFI_PHYSICAL_ADDRESS HashData
,
83 IN UINT64 HashDataLen
,
84 IN TCG_ALGORITHM_ID AlgorithmId
,
85 IN
struct _TCG_PCR_EVENT
* TCGLogData
,
86 IN OUT UINT32
* EventNumber
,
87 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
);
89 typedef struct _EFI_TCG
{
90 EFI_TCG_STATUS_CHECK StatusCheck
;
91 EFI_TCG_HASH_ALL HashAll
;
92 EFI_TCG_LOG_EVENT LogEvent
;
93 EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTPM
;
94 EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent
;
97 #define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
99 typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL
;
101 typedef struct tdEFI_TCG2_VERSION
{
106 typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP
;
107 typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT
;
108 typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP
;
110 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001
111 #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
113 typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY
{
115 EFI_TCG2_VERSION StructureVersion
;
116 EFI_TCG2_VERSION ProtocolVersion
;
117 EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap
;
118 EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs
;
119 BOOLEAN TPMPresentFlag
;
120 UINT16 MaxCommandSize
;
121 UINT16 MaxResponseSize
;
122 UINT32 ManufacturerID
;
123 UINT32 NumberOfPCRBanks
;
124 EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks
;
125 } EFI_TCG2_BOOT_SERVICE_CAPABILITY
;
127 #define EFI_TCG2_EVENT_HEADER_VERSION 1
131 UINT16 HeaderVersion
;
134 } EFI_TCG2_EVENT_HEADER
;
136 typedef struct tdEFI_TCG2_EVENT
{
138 EFI_TCG2_EVENT_HEADER Header
;
142 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_CAPABILITY
) (IN EFI_TCG2_PROTOCOL
* This
,
143 IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY
* ProtocolCapability
);
145 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_EVENT_LOG
) (IN EFI_TCG2_PROTOCOL
* This
,
146 IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat
,
147 OUT EFI_PHYSICAL_ADDRESS
* EventLogLocation
,
148 OUT EFI_PHYSICAL_ADDRESS
* EventLogLastEntry
,
149 OUT BOOLEAN
* EventLogTruncated
);
151 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_HASH_LOG_EXTEND_EVENT
) (IN EFI_TCG2_PROTOCOL
* This
,
153 IN EFI_PHYSICAL_ADDRESS DataToHash
,
154 IN UINT64 DataToHashLen
, IN EFI_TCG2_EVENT
* EfiTcgEvent
);
156 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_SUBMIT_COMMAND
) (IN EFI_TCG2_PROTOCOL
* This
,
157 IN UINT32 InputParameterBlockSize
,
158 IN UINT8
* InputParameterBlock
,
159 IN UINT32 OutputParameterBlockSize
, IN UINT8
* OutputParameterBlock
);
161 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
, OUT UINT32
* ActivePcrBanks
);
163 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_SET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
, IN UINT32 ActivePcrBanks
);
165 typedef EFI_STATUS(EFIAPI
* EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS
) (IN EFI_TCG2_PROTOCOL
* This
,
166 OUT UINT32
* OperationPresent
, OUT UINT32
* Response
);
168 typedef struct tdEFI_TCG2_PROTOCOL
{
169 EFI_TCG2_GET_CAPABILITY GetCapability
;
170 EFI_TCG2_GET_EVENT_LOG GetEventLog
;
171 EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent
;
172 EFI_TCG2_SUBMIT_COMMAND SubmitCommand
;
173 EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks
;
174 EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks
;
175 EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks
;
179 static EFI_STATUS
tpm1_measure_to_pcr_and_event_log(const EFI_TCG
*tcg
, UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
,
180 UINTN buffer_size
, const CHAR16
*description
) {
182 TCG_PCR_EVENT
*tcg_event
;
184 EFI_PHYSICAL_ADDRESS event_log_last
;
187 desc_len
= (StrLen(description
) + 1) * sizeof(CHAR16
);
189 tcg_event
= AllocateZeroPool(desc_len
+ sizeof(TCG_PCR_EVENT
));
191 if (tcg_event
== NULL
)
192 return EFI_OUT_OF_RESOURCES
;
194 tcg_event
->EventSize
= desc_len
;
195 CopyMem((VOID
*) & tcg_event
->Event
[0], (VOID
*) description
, desc_len
);
197 tcg_event
->PCRIndex
= pcrindex
;
198 tcg_event
->EventType
= EV_IPL
;
201 status
= uefi_call_wrapper(tcg
->HashLogExtendEvent
, 7,
202 (EFI_TCG
*) tcg
, buffer
, buffer_size
, TCG_ALG_SHA
, tcg_event
, &event_number
, &event_log_last
);
204 if (EFI_ERROR(status
))
207 uefi_call_wrapper(BS
->FreePool
, 1, tcg_event
);
213 * According to TCG EFI Protocol Specification for TPM 2.0 family,
214 * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
215 * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
216 * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
217 * internal switch through calling get_event_log() in order to allow
218 * to retrieve the logs from OS runtime.
220 static EFI_STATUS
trigger_tcg2_final_events_table(const EFI_TCG2
*tcg
)
222 return uefi_call_wrapper(tcg
->GetEventLog
, 5, (EFI_TCG2
*) tcg
,
223 EFI_TCG2_EVENT_LOG_FORMAT_TCG_2
, NULL
,
227 static EFI_STATUS
tpm2_measure_to_pcr_and_event_log(const EFI_TCG2
*tcg
, UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
,
228 UINT64 buffer_size
, const CHAR16
*description
) {
230 EFI_TCG2_EVENT
*tcg_event
;
232 static BOOLEAN triggered
= FALSE
;
234 if (triggered
== FALSE
) {
235 status
= trigger_tcg2_final_events_table(tcg
);
236 if (EFI_ERROR(status
))
242 desc_len
= StrLen(description
) * sizeof(CHAR16
);
244 tcg_event
= AllocateZeroPool(sizeof(*tcg_event
) - sizeof(tcg_event
->Event
) + desc_len
+ 1);
246 if (tcg_event
== NULL
)
247 return EFI_OUT_OF_RESOURCES
;
249 tcg_event
->Size
= sizeof(EFI_TCG2_EVENT
) - sizeof(tcg_event
->Event
) + desc_len
+ 1;
250 tcg_event
->Header
.HeaderSize
= sizeof(EFI_TCG2_EVENT_HEADER
);
251 tcg_event
->Header
.HeaderVersion
= EFI_TCG2_EVENT_HEADER_VERSION
;
252 tcg_event
->Header
.PCRIndex
= pcrindex
;
253 tcg_event
->Header
.EventType
= EV_IPL
;
255 CopyMem((VOID
*) tcg_event
->Event
, (VOID
*) description
, desc_len
);
257 status
= uefi_call_wrapper(tcg
->HashLogExtendEvent
, 5, (EFI_TCG2
*) tcg
, 0, buffer
, buffer_size
, tcg_event
);
259 uefi_call_wrapper(BS
->FreePool
, 1, tcg_event
);
261 if (EFI_ERROR(status
))
267 static EFI_TCG
* tcg1_interface_check(void) {
268 EFI_GUID tpm_guid
= EFI_TCG_PROTOCOL_GUID
;
271 TCG_BOOT_SERVICE_CAPABILITY capability
;
273 EFI_PHYSICAL_ADDRESS event_log_location
;
274 EFI_PHYSICAL_ADDRESS event_log_last_entry
;
276 status
= LibLocateProtocol(&tpm_guid
, (void **) &tcg
);
278 if (EFI_ERROR(status
))
281 capability
.Size
= (UINT8
) sizeof(capability
);
282 status
= uefi_call_wrapper(tcg
->StatusCheck
, 5, tcg
, &capability
, &features
, &event_log_location
, &event_log_last_entry
);
284 if (EFI_ERROR(status
))
287 if (capability
.TPMDeactivatedFlag
)
290 if (!capability
.TPMPresentFlag
)
296 static EFI_TCG2
* tcg2_interface_check(void) {
297 EFI_GUID tpm2_guid
= EFI_TCG2_PROTOCOL_GUID
;
300 EFI_TCG2_BOOT_SERVICE_CAPABILITY capability
;
302 status
= LibLocateProtocol(&tpm2_guid
, (void **) &tcg
);
304 if (EFI_ERROR(status
))
307 capability
.Size
= (UINT8
) sizeof(capability
);
308 status
= uefi_call_wrapper(tcg
->GetCapability
, 2, tcg
, &capability
);
310 if (EFI_ERROR(status
))
313 if (!capability
.TPMPresentFlag
)
319 EFI_STATUS
tpm_log_event(UINT32 pcrindex
, const EFI_PHYSICAL_ADDRESS buffer
, UINTN buffer_size
, const CHAR16
*description
) {
323 tpm2
= tcg2_interface_check();
325 return tpm2_measure_to_pcr_and_event_log(tpm2
, pcrindex
, buffer
, buffer_size
, description
);
327 tpm1
= tcg1_interface_check();
329 return tpm1_measure_to_pcr_and_event_log(tpm1
, pcrindex
, buffer
, buffer_size
, description
);
331 /* No active TPM found, so don't return an error */