1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #include "macro-fundamental.h"
11 #include "missing_efi.h"
14 static EFI_STATUS
tpm1_measure_to_pcr_and_event_log(
17 EFI_PHYSICAL_ADDRESS buffer
,
19 const char16_t
*description
) {
21 _cleanup_free_ TCG_PCR_EVENT
*tcg_event
= NULL
;
22 EFI_PHYSICAL_ADDRESS event_log_last
;
23 uint32_t event_number
= 1;
29 desc_len
= strsize16(description
);
30 tcg_event
= xmalloc(offsetof(TCG_PCR_EVENT
, Event
) + desc_len
);
31 memset(tcg_event
, 0, offsetof(TCG_PCR_EVENT
, Event
) + desc_len
);
32 *tcg_event
= (TCG_PCR_EVENT
) {
33 .EventSize
= desc_len
,
37 memcpy(tcg_event
->Event
, description
, desc_len
);
39 return tcg
->HashLogExtendEvent(
48 static EFI_STATUS
tpm2_measure_to_pcr_and_event_log(
51 EFI_PHYSICAL_ADDRESS buffer
,
53 const char16_t
*description
) {
55 _cleanup_free_ EFI_TCG2_EVENT
*tcg_event
= NULL
;
61 desc_len
= strsize16(description
);
62 tcg_event
= xmalloc(offsetof(EFI_TCG2_EVENT
, Event
) + desc_len
);
63 memset(tcg_event
, 0, offsetof(EFI_TCG2_EVENT
, Event
) + desc_len
);
64 *tcg_event
= (EFI_TCG2_EVENT
) {
65 .Size
= offsetof(EFI_TCG2_EVENT
, Event
) + desc_len
,
66 .Header
.HeaderSize
= sizeof(EFI_TCG2_EVENT_HEADER
),
67 .Header
.HeaderVersion
= EFI_TCG2_EVENT_HEADER_VERSION
,
68 .Header
.PCRIndex
= pcrindex
,
69 .Header
.EventType
= EV_IPL
,
72 memcpy(tcg_event
->Event
, description
, desc_len
);
74 return tcg
->HashLogExtendEvent(
81 static EFI_TCG
*tcg1_interface_check(void) {
82 EFI_PHYSICAL_ADDRESS event_log_location
, event_log_last_entry
;
83 TCG_BOOT_SERVICE_CAPABILITY capability
= {
84 .Size
= sizeof(capability
),
90 err
= BS
->LocateProtocol((EFI_GUID
*) EFI_TCG_GUID
, NULL
, (void **) &tcg
);
91 if (err
!= EFI_SUCCESS
)
94 err
= tcg
->StatusCheck(
99 &event_log_last_entry
);
100 if (err
!= EFI_SUCCESS
)
103 if (capability
.TPMDeactivatedFlag
)
106 if (!capability
.TPMPresentFlag
)
112 static EFI_TCG2
* tcg2_interface_check(void) {
113 EFI_TCG2_BOOT_SERVICE_CAPABILITY capability
= {
114 .Size
= sizeof(capability
),
119 err
= BS
->LocateProtocol((EFI_GUID
*) EFI_TCG2_GUID
, NULL
, (void **) &tcg
);
120 if (err
!= EFI_SUCCESS
)
123 err
= tcg
->GetCapability(tcg
, &capability
);
124 if (err
!= EFI_SUCCESS
)
127 if (capability
.StructureVersion
.Major
== 1 &&
128 capability
.StructureVersion
.Minor
== 0) {
129 TCG_BOOT_SERVICE_CAPABILITY
*caps_1_0
=
130 (TCG_BOOT_SERVICE_CAPABILITY
*) &capability
;
131 if (caps_1_0
->TPMPresentFlag
)
135 if (!capability
.TPMPresentFlag
)
141 bool tpm_present(void) {
142 return tcg2_interface_check() || tcg1_interface_check();
145 EFI_STATUS
tpm_log_event(uint32_t pcrindex
, EFI_PHYSICAL_ADDRESS buffer
, UINTN buffer_size
, const char16_t
*description
, bool *ret_measured
) {
151 /* If EFI_SUCCESS is returned, will initialize ret_measured to true if we actually measured
152 * something, or false if measurement was turned off. */
154 if (pcrindex
== UINT32_MAX
) { /* PCR disabled? */
156 *ret_measured
= false;
161 tpm2
= tcg2_interface_check();
163 err
= tpm2_measure_to_pcr_and_event_log(tpm2
, pcrindex
, buffer
, buffer_size
, description
);
167 tpm1
= tcg1_interface_check();
169 err
= tpm1_measure_to_pcr_and_event_log(tpm1
, pcrindex
, buffer
, buffer_size
, description
);
171 /* No active TPM found, so don't return an error */
174 *ret_measured
= false;
180 if (err
== EFI_SUCCESS
&& ret_measured
)
181 *ret_measured
= true;
186 EFI_STATUS
tpm_log_event_ascii(uint32_t pcrindex
, EFI_PHYSICAL_ADDRESS buffer
, UINTN buffer_size
, const char *description
, bool *ret_measured
) {
187 _cleanup_free_ char16_t
*c
= NULL
;
190 c
= xstr8_to_16(description
);
192 return tpm_log_event(pcrindex
, buffer
, buffer_size
, c
, ret_measured
);
195 EFI_STATUS
tpm_log_load_options(const char16_t
*load_options
, bool *ret_measured
) {
196 bool measured
= false;
199 /* Measures a load options string into the TPM2, i.e. the kernel command line */
202 TPM_PCR_INDEX_KERNEL_PARAMETERS
,
203 POINTER_TO_PHYSICAL_ADDRESS(load_options
),
204 strsize16(load_options
),
207 if (err
!= EFI_SUCCESS
)
208 return log_error_status_stall(
210 L
"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r",
211 TPM_PCR_INDEX_KERNEL_PARAMETERS
,
215 *ret_measured
= measured
;