]>
Commit | Line | Data |
---|---|---|
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 |
14 | static 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 |
48 | static 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 |
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), | |
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 | 112 | static 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 | 141 | bool tpm_present(void) { |
a87e9cd7 JJ |
142 | return tcg2_interface_check() || tcg1_interface_check(); |
143 | } | |
144 | ||
8d5e4d59 | 145 | EFI_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 | ||
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; | |
188 | ||
189 | if (description) | |
190 | c = xstra_to_str(description); | |
191 | ||
192 | return tpm_log_event(pcrindex, buffer, buffer_size, c, ret_measured); | |
92ed3bb4 HH |
193 | } |
194 | ||
8d5e4d59 LP |
195 | EFI_STATUS tpm_log_load_options(const char16_t *load_options, bool *ret_measured) { |
196 | int measured = -1; | |
e6e24af5 LP |
197 | EFI_STATUS err; |
198 | ||
199 | /* Measures a load options string into the TPM2, i.e. the kernel command line */ | |
200 | ||
4d32507f | 201 | for (UINTN i = 0; i < 2; i++) { |
db4122d1 | 202 | uint32_t pcr = i == 0 ? TPM_PCR_INDEX_KERNEL_PARAMETERS : TPM_PCR_INDEX_KERNEL_PARAMETERS_COMPAT; |
8d5e4d59 LP |
203 | bool m; |
204 | ||
205 | if (pcr == UINT32_MAX) /* Skip this one, if it's invalid, so that our 'measured' return value is not corrupted by it */ | |
206 | continue; | |
4d32507f | 207 | |
8d5e4d59 | 208 | err = tpm_log_event(pcr, POINTER_TO_PHYSICAL_ADDRESS(load_options), strsize16(load_options), load_options, &m); |
2a5e4fe4 | 209 | if (err != EFI_SUCCESS) |
4d32507f | 210 | return log_error_status_stall(err, L"Unable to add load options (i.e. kernel command) line measurement to PCR %u: %r", pcr, err); |
8d5e4d59 LP |
211 | |
212 | measured = measured < 0 ? m : (measured && m); | |
4d32507f | 213 | } |
e6e24af5 | 214 | |
8d5e4d59 LP |
215 | if (ret_measured) |
216 | *ret_measured = measured < 0 ? false : measured; | |
217 | ||
e6e24af5 LP |
218 | return EFI_SUCCESS; |
219 | } | |
220 | ||
92ed3bb4 | 221 | #endif |