]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/boot/efi/measure.c
boot: Use printf for error logging
[thirdparty/systemd.git] / src / boot / efi / measure.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
92ed3bb4 2
349cc4a5 3#if ENABLE_TPM
92ed3bb4
HH
4
5#include <efi.h>
6#include <efilib.h>
7d2ebb6f 7
aa323c09 8#include "tpm-pcr.h"
508df915 9#include "macro-fundamental.h"
92ed3bb4 10#include "measure.h"
b4f25c64 11#include "missing_efi.h"
ff3aa8d1 12#include "util.h"
92ed3bb4 13
ff3aa8d1
LP
14static EFI_STATUS tpm1_measure_to_pcr_and_event_log(
15 const EFI_TCG *tcg,
db4122d1 16 uint32_t pcrindex,
ff3aa8d1
LP
17 EFI_PHYSICAL_ADDRESS buffer,
18 UINTN buffer_size,
3639d1b0 19 const char16_t *description) {
ff3aa8d1 20
93521e55 21 _cleanup_free_ TCG_PCR_EVENT *tcg_event = NULL;
92ed3bb4 22 EFI_PHYSICAL_ADDRESS event_log_last;
db4122d1 23 uint32_t event_number = 1;
92ed3bb4
HH
24 UINTN desc_len;
25
508df915
JJ
26 assert(tcg);
27 assert(description);
28
60c2af56 29 desc_len = strsize16(description);
0af26643
JJ
30 tcg_event = xmalloc(offsetof(TCG_PCR_EVENT, Event) + desc_len);
31 memset(tcg_event, 0, offsetof(TCG_PCR_EVENT, Event) + desc_len);
ff3aa8d1
LP
32 *tcg_event = (TCG_PCR_EVENT) {
33 .EventSize = desc_len,
34 .PCRIndex = pcrindex,
35 .EventType = EV_IPL,
36 };
bbc1f2ea 37 memcpy(tcg_event->Event, description, desc_len);
ff3aa8d1 38
12f32748 39 return tcg->HashLogExtendEvent(
ff3aa8d1
LP
40 (EFI_TCG *) tcg,
41 buffer, buffer_size,
42 TCG_ALG_SHA,
43 tcg_event,
44 &event_number,
45 &event_log_last);
92ed3bb4
HH
46}
47
ff3aa8d1
LP
48static EFI_STATUS tpm2_measure_to_pcr_and_event_log(
49 EFI_TCG2 *tcg,
db4122d1 50 uint32_t pcrindex,
ff3aa8d1 51 EFI_PHYSICAL_ADDRESS buffer,
db4122d1 52 uint64_t buffer_size,
3639d1b0 53 const char16_t *description) {
ff3aa8d1 54
93521e55 55 _cleanup_free_ EFI_TCG2_EVENT *tcg_event = NULL;
92ed3bb4
HH
56 UINTN desc_len;
57
508df915
JJ
58 assert(tcg);
59 assert(description);
60
60c2af56 61 desc_len = strsize16(description);
0af26643
JJ
62 tcg_event = xmalloc(offsetof(EFI_TCG2_EVENT, Event) + desc_len);
63 memset(tcg_event, 0, offsetof(EFI_TCG2_EVENT, Event) + desc_len);
ff3aa8d1 64 *tcg_event = (EFI_TCG2_EVENT) {
7700e9ba 65 .Size = offsetof(EFI_TCG2_EVENT, Event) + desc_len,
ff3aa8d1
LP
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,
70 };
71
bbc1f2ea 72 memcpy(tcg_event->Event, description, desc_len);
ff3aa8d1 73
12f32748 74 return tcg->HashLogExtendEvent(
ff3aa8d1
LP
75 tcg,
76 0,
77 buffer, buffer_size,
78 tcg_event);
92ed3bb4
HH
79}
80
ff3aa8d1
LP
81static 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),
85 };
8599bdb6 86 EFI_STATUS err;
db4122d1 87 uint32_t features;
ff3aa8d1 88 EFI_TCG *tcg;
92ed3bb4 89
8599bdb6 90 err = BS->LocateProtocol((EFI_GUID *) EFI_TCG_GUID, NULL, (void **) &tcg);
2a5e4fe4 91 if (err != EFI_SUCCESS)
92ed3bb4
HH
92 return NULL;
93
8599bdb6 94 err = tcg->StatusCheck(
ff3aa8d1
LP
95 tcg,
96 &capability,
97 &features,
98 &event_log_location,
99 &event_log_last_entry);
2a5e4fe4 100 if (err != EFI_SUCCESS)
92ed3bb4
HH
101 return NULL;
102
103 if (capability.TPMDeactivatedFlag)
104 return NULL;
105
106 if (!capability.TPMPresentFlag)
107 return NULL;
108
109 return tcg;
110}
111
ee851229 112static EFI_TCG2 * tcg2_interface_check(void) {
ff3aa8d1
LP
113 EFI_TCG2_BOOT_SERVICE_CAPABILITY capability = {
114 .Size = sizeof(capability),
115 };
8599bdb6 116 EFI_STATUS err;
92ed3bb4 117 EFI_TCG2 *tcg;
92ed3bb4 118
8599bdb6 119 err = BS->LocateProtocol((EFI_GUID *) EFI_TCG2_GUID, NULL, (void **) &tcg);
2a5e4fe4 120 if (err != EFI_SUCCESS)
92ed3bb4
HH
121 return NULL;
122
8599bdb6 123 err = tcg->GetCapability(tcg, &capability);
2a5e4fe4 124 if (err != EFI_SUCCESS)
92ed3bb4
HH
125 return NULL;
126
f8e54bf3
JR
127 if (capability.StructureVersion.Major == 1 &&
128 capability.StructureVersion.Minor == 0) {
ff3aa8d1
LP
129 TCG_BOOT_SERVICE_CAPABILITY *caps_1_0 =
130 (TCG_BOOT_SERVICE_CAPABILITY*) &capability;
bfdf8c3b
HH
131 if (caps_1_0->TPMPresentFlag)
132 return tcg;
133 }
134
f8e54bf3 135 if (!capability.TPMPresentFlag)
92ed3bb4
HH
136 return NULL;
137
138 return tcg;
139}
140
e5a1b8f9 141bool tpm_present(void) {
a87e9cd7
JJ
142 return tcg2_interface_check() || tcg1_interface_check();
143}
144
8d5e4d59 145EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const char16_t *description, bool *ret_measured) {
92ed3bb4 146 EFI_TCG2 *tpm2;
8d5e4d59 147 EFI_STATUS err;
bfdf8c3b 148
508df915
JJ
149 assert(description);
150
8d5e4d59
LP
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. */
153
154 if (pcrindex == UINT32_MAX) { /* PCR disabled? */
155 if (ret_measured)
156 *ret_measured = false;
157
4d32507f 158 return EFI_SUCCESS;
8d5e4d59 159 }
4d32507f 160
f8e54bf3 161 tpm2 = tcg2_interface_check();
38cd55b0 162 if (tpm2)
8d5e4d59
LP
163 err = tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
164 else {
165 EFI_TCG *tpm1;
92ed3bb4 166
8d5e4d59
LP
167 tpm1 = tcg1_interface_check();
168 if (tpm1)
169 err = tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
170 else {
171 /* No active TPM found, so don't return an error */
92ed3bb4 172
8d5e4d59
LP
173 if (ret_measured)
174 *ret_measured = false;
175
176 return EFI_SUCCESS;
177 }
178 }
179
180 if (err == EFI_SUCCESS && ret_measured)
181 *ret_measured = true;
182
183 return err;
184}
185
186EFI_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;
188
189 if (description)
aee515bb 190 c = xstr8_to_16(description);
8d5e4d59
LP
191
192 return tpm_log_event(pcrindex, buffer, buffer_size, c, ret_measured);
92ed3bb4
HH
193}
194
8d5e4d59 195EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured) {
d84bdadb 196 bool measured = false;
e6e24af5
LP
197 EFI_STATUS err;
198
199 /* Measures a load options string into the TPM2, i.e. the kernel command line */
200
d84bdadb
JJ
201 err = tpm_log_event(
202 TPM_PCR_INDEX_KERNEL_PARAMETERS,
203 POINTER_TO_PHYSICAL_ADDRESS(load_options),
204 strsize16(load_options),
205 load_options,
206 &measured);
207 if (err != EFI_SUCCESS)
c2c62035 208 return log_error_status(
d84bdadb 209 err,
c2c62035
JJ
210 "Unable to add load options (i.e. kernel command) line measurement to PCR %u: %m",
211 TPM_PCR_INDEX_KERNEL_PARAMETERS);
e6e24af5 212
8d5e4d59 213 if (ret_measured)
d84bdadb 214 *ret_measured = measured;
8d5e4d59 215
e6e24af5
LP
216 return EFI_SUCCESS;
217}
218
92ed3bb4 219#endif