]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/boot/efi/measure.c
build-sys: use #if Y instead of #ifdef Y everywhere
[thirdparty/systemd.git] / src / boot / efi / measure.c
CommitLineData
92ed3bb4
HH
1/*
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.
6 *
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.
11 *
12 */
13
349cc4a5 14#if ENABLE_TPM
92ed3bb4
HH
15
16#include <efi.h>
17#include <efilib.h>
18#include "measure.h"
19
20#define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
21
22typedef struct _TCG_VERSION {
23 UINT8 Major;
24 UINT8 Minor;
25 UINT8 RevMajor;
26 UINT8 RevMinor;
27} TCG_VERSION;
28
29typedef struct _TCG_BOOT_SERVICE_CAPABILITY {
30 UINT8 Size;
31 struct _TCG_VERSION StructureVersion;
32 struct _TCG_VERSION ProtocolSpecVersion;
33 UINT8 HashAlgorithmBitmap;
34 BOOLEAN TPMPresentFlag;
35 BOOLEAN TPMDeactivatedFlag;
36} TCG_BOOT_SERVICE_CAPABILITY;
37
38typedef UINT32 TCG_ALGORITHM_ID;
39#define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm
40
41#define SHA1_DIGEST_SIZE 20
42
43typedef struct _TCG_DIGEST {
44 UINT8 Digest[SHA1_DIGEST_SIZE];
45} TCG_DIGEST;
46
47#define EV_IPL 13
48
49typedef struct _TCG_PCR_EVENT {
50 UINT32 PCRIndex;
51 UINT32 EventType;
52 struct _TCG_DIGEST digest;
53 UINT32 EventSize;
54 UINT8 Event[1];
55} TCG_PCR_EVENT;
56
57INTERFACE_DECL(_EFI_TCG);
58
59typedef 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);
64
65typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_ALL) (IN struct _EFI_TCG * This,
66 IN UINT8 * HashData,
67 IN UINT64 HashDataLen,
68 IN TCG_ALGORITHM_ID AlgorithmId,
69 IN OUT UINT64 * HashedDataLen, IN OUT UINT8 ** HashedDataResult);
70
71typedef 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);
74
75typedef 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);
80
81typedef 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);
88
89typedef 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;
95} EFI_TCG;
96
97#define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
98
99typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
100
101typedef struct tdEFI_TCG2_VERSION {
102 UINT8 Major;
103 UINT8 Minor;
104} EFI_TCG2_VERSION;
105
106typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP;
107typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT;
108typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP;
109
110#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001
111#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
112
113typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY {
114 UINT8 Size;
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;
126
127#define EFI_TCG2_EVENT_HEADER_VERSION 1
128
129typedef struct {
130 UINT32 HeaderSize;
131 UINT16 HeaderVersion;
132 UINT32 PCRIndex;
133 UINT32 EventType;
134} EFI_TCG2_EVENT_HEADER;
135
136typedef struct tdEFI_TCG2_EVENT {
137 UINT32 Size;
138 EFI_TCG2_EVENT_HEADER Header;
139 UINT8 Event[1];
140} EFI_TCG2_EVENT;
141
142typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_CAPABILITY) (IN EFI_TCG2_PROTOCOL * This,
143 IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY * ProtocolCapability);
144
145typedef 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);
150
151typedef EFI_STATUS(EFIAPI * EFI_TCG2_HASH_LOG_EXTEND_EVENT) (IN EFI_TCG2_PROTOCOL * This,
152 IN UINT64 Flags,
153 IN EFI_PHYSICAL_ADDRESS DataToHash,
154 IN UINT64 DataToHashLen, IN EFI_TCG2_EVENT * EfiTcgEvent);
155
156typedef 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);
160
161typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, OUT UINT32 * ActivePcrBanks);
162
163typedef EFI_STATUS(EFIAPI * EFI_TCG2_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, IN UINT32 ActivePcrBanks);
164
165typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This,
166 OUT UINT32 * OperationPresent, OUT UINT32 * Response);
167
168typedef 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;
176} EFI_TCG2;
177
178
179static 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) {
181 EFI_STATUS status;
182 TCG_PCR_EVENT *tcg_event;
183 UINT32 event_number;
184 EFI_PHYSICAL_ADDRESS event_log_last;
185 UINTN desc_len;
186
187 desc_len = (StrLen(description) + 1) * sizeof(CHAR16);
188
189 tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT));
190
191 if (tcg_event == NULL)
192 return EFI_OUT_OF_RESOURCES;
193
194 tcg_event->EventSize = desc_len;
195 CopyMem((VOID *) & tcg_event->Event[0], (VOID *) description, desc_len);
196
197 tcg_event->PCRIndex = pcrindex;
198 tcg_event->EventType = EV_IPL;
199
200 event_number = 1;
201 status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7,
a0693fc9 202 (EFI_TCG *) tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
92ed3bb4
HH
203
204 if (EFI_ERROR(status))
205 return status;
206
207 uefi_call_wrapper(BS->FreePool, 1, tcg_event);
208
209 return EFI_SUCCESS;
210}
211
59991e3f
LZ
212/*
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.
219 */
220static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg)
221{
a0693fc9 222 return uefi_call_wrapper(tcg->GetEventLog, 5, (EFI_TCG2 *) tcg,
59991e3f
LZ
223 EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL,
224 NULL, NULL);
225}
92ed3bb4
HH
226
227static 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) {
229 EFI_STATUS status;
230 EFI_TCG2_EVENT *tcg_event;
231 UINTN desc_len;
59991e3f
LZ
232 static BOOLEAN triggered = FALSE;
233
234 if (triggered == FALSE) {
235 status = trigger_tcg2_final_events_table(tcg);
236 if (EFI_ERROR(status))
237 return status;
238
239 triggered = TRUE;
240 }
92ed3bb4
HH
241
242 desc_len = StrLen(description) * sizeof(CHAR16);
243
244 tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1);
245
246 if (tcg_event == NULL)
247 return EFI_OUT_OF_RESOURCES;
248
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;
254
255 CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len);
256
a0693fc9 257 status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, (EFI_TCG2 *) tcg, 0, buffer, buffer_size, tcg_event);
92ed3bb4
HH
258
259 uefi_call_wrapper(BS->FreePool, 1, tcg_event);
260
261 if (EFI_ERROR(status))
262 return status;
263
264 return EFI_SUCCESS;
265}
266
267static EFI_TCG * tcg1_interface_check(void) {
268 EFI_GUID tpm_guid = EFI_TCG_PROTOCOL_GUID;
269 EFI_STATUS status;
270 EFI_TCG *tcg;
271 TCG_BOOT_SERVICE_CAPABILITY capability;
272 UINT32 features;
273 EFI_PHYSICAL_ADDRESS event_log_location;
274 EFI_PHYSICAL_ADDRESS event_log_last_entry;
275
276 status = LibLocateProtocol(&tpm_guid, (void **) &tcg);
277
278 if (EFI_ERROR(status))
279 return NULL;
280
281 capability.Size = (UINT8) sizeof(capability);
282 status = uefi_call_wrapper(tcg->StatusCheck, 5, tcg, &capability, &features, &event_log_location, &event_log_last_entry);
283
284 if (EFI_ERROR(status))
285 return NULL;
286
287 if (capability.TPMDeactivatedFlag)
288 return NULL;
289
290 if (!capability.TPMPresentFlag)
291 return NULL;
292
293 return tcg;
294}
295
296static EFI_TCG2 * tcg2_interface_check(void) {
297 EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
298 EFI_STATUS status;
299 EFI_TCG2 *tcg;
300 EFI_TCG2_BOOT_SERVICE_CAPABILITY capability;
301
302 status = LibLocateProtocol(&tpm2_guid, (void **) &tcg);
303
304 if (EFI_ERROR(status))
305 return NULL;
306
307 capability.Size = (UINT8) sizeof(capability);
308 status = uefi_call_wrapper(tcg->GetCapability, 2, tcg, &capability);
309
310 if (EFI_ERROR(status))
311 return NULL;
312
313 if (!capability.TPMPresentFlag)
314 return NULL;
315
316 return tcg;
317}
318
319EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
320 EFI_TCG *tpm1;
321 EFI_TCG2 *tpm2;
322
323 tpm2 = tcg2_interface_check();
324 if (tpm2)
325 return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
326
327 tpm1 = tcg1_interface_check();
328 if (tpm1)
329 return tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
330
331 /* No active TPM found, so don't return an error */
332 return EFI_SUCCESS;
333}
334
335#endif