]> git.proxmox.com Git - efi-boot-shim.git/blame - tpm.c
Cryptlib: Update to the latest edk2 commit
[efi-boot-shim.git] / tpm.c
CommitLineData
22b58f24
MG
1#include <efi.h>
2#include <efilib.h>
3#include <string.h>
4
5#include "tpm.h"
6
7extern UINT8 in_protocol;
8
9#define perror(fmt, ...) ({ \
10 UINTN __perror_ret = 0; \
11 if (!in_protocol) \
12 __perror_ret = Print((fmt), ##__VA_ARGS__); \
13 __perror_ret; \
14 })
15
16
17EFI_GUID tpm_guid = EFI_TPM_GUID;
18EFI_GUID tpm2_guid = EFI_TPM2_GUID;
19
20static BOOLEAN tpm_present(efi_tpm_protocol_t *tpm)
21{
22 EFI_STATUS status;
23 TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
24 UINT32 flags;
25 EFI_PHYSICAL_ADDRESS eventlog, lastevent;
26
27 caps.Size = (UINT8)sizeof(caps);
28 status = uefi_call_wrapper(tpm->status_check, 5, tpm, &caps, &flags,
29 &eventlog, &lastevent);
30
31 if (status != EFI_SUCCESS || caps.TPMDeactivatedFlag
32 || !caps.TPMPresentFlag)
33 return FALSE;
34
35 return TRUE;
36}
37
38static BOOLEAN tpm2_present(efi_tpm2_protocol_t *tpm)
39{
40 EFI_STATUS status;
41 EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
94c955bb 42 TREE_BOOT_SERVICE_CAPABILITY *caps_1_0;
22b58f24
MG
43
44 caps.Size = (UINT8)sizeof(caps);
45
46 status = uefi_call_wrapper(tpm->get_capability, 2, tpm, &caps);
47
48 if (status != EFI_SUCCESS)
49 return FALSE;
50
51 if (caps.StructureVersion.Major == 1 &&
52 caps.StructureVersion.Minor == 0) {
94c955bb
LZ
53 caps_1_0 = (TREE_BOOT_SERVICE_CAPABILITY *)&caps;
54 if (caps_1_0->TrEEPresentFlag)
22b58f24
MG
55 return TRUE;
56 } else {
57 if (caps.TPMPresentFlag)
58 return TRUE;
59 }
60
61 return FALSE;
62}
63
d3884fe8
LZ
64/*
65 * According to TCG EFI Protocol Specification for TPM 2.0 family,
66 * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
67 * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
68 * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
69 * internal switch through calling get_event_log() in order to allow
70 * to retrieve the logs from OS runtime.
71 */
72static EFI_STATUS trigger_tcg2_final_events_table(efi_tpm2_protocol_t *tpm2)
73{
7bfcd708
LZ
74 EFI_PHYSICAL_ADDRESS start;
75 EFI_PHYSICAL_ADDRESS end;
76 BOOLEAN truncated;
77
d3884fe8 78 return uefi_call_wrapper(tpm2->get_event_log, 5, tpm2,
7bfcd708
LZ
79 EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, &start,
80 &end, &truncated);
d3884fe8
LZ
81}
82
22b58f24
MG
83EFI_STATUS tpm_log_event(EFI_PHYSICAL_ADDRESS buf, UINTN size, UINT8 pcr,
84 const CHAR8 *description)
85{
86 EFI_STATUS status;
87 efi_tpm_protocol_t *tpm;
88 efi_tpm2_protocol_t *tpm2;
89
90 status = LibLocateProtocol(&tpm2_guid, (VOID **)&tpm2);
91 /* TPM 2.0 */
92 if (status == EFI_SUCCESS) {
93 EFI_TCG2_EVENT *event;
94
95 if (!tpm2_present(tpm2))
96 return EFI_SUCCESS;
97
d3884fe8
LZ
98 status = trigger_tcg2_final_events_table(tpm2);
99 if (EFI_ERROR(status)) {
1ee26db0 100 perror(L"Unable to trigger tcg2 final events table: %r\n", status);
d3884fe8
LZ
101 return status;
102 }
103
22b58f24
MG
104 event = AllocatePool(sizeof(*event) + strlen(description) + 1);
105 if (!event) {
106 perror(L"Unable to allocate event structure\n");
107 return EFI_OUT_OF_RESOURCES;
108 }
109
110 event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
111 event->Header.HeaderVersion = 1;
112 event->Header.PCRIndex = pcr;
113 event->Header.EventType = 0x0d;
114 event->Size = sizeof(*event) - sizeof(event->Event) + strlen(description) + 1;
115 memcpy(event->Event, description, strlen(description) + 1);
116 status = uefi_call_wrapper(tpm2->hash_log_extend_event, 5, tpm2,
117 0, buf, (UINT64) size, event);
118 FreePool(event);
119 return status;
120 } else {
121 TCG_PCR_EVENT *event;
122 UINT32 algorithm, eventnum = 0;
123 EFI_PHYSICAL_ADDRESS lastevent;
124
125 status = LibLocateProtocol(&tpm_guid, (VOID **)&tpm);
126
127 if (status != EFI_SUCCESS)
128 return EFI_SUCCESS;
129
130 if (!tpm_present(tpm))
131 return EFI_SUCCESS;
132
133 event = AllocatePool(sizeof(*event) + strlen(description) + 1);
134
135 if (!event) {
136 perror(L"Unable to allocate event structure\n");
137 return EFI_OUT_OF_RESOURCES;
138 }
139
140 event->PCRIndex = pcr;
141 event->EventType = 0x0d;
142 event->EventSize = strlen(description) + 1;
143 algorithm = 0x00000004;
144 status = uefi_call_wrapper(tpm->log_extend_event, 7, tpm, buf,
145 (UINT64)size, algorithm, event,
146 &eventnum, &lastevent);
147 FreePool(event);
148 return status;
149 }
150
151 return EFI_SUCCESS;
152}