]>
Commit | Line | Data |
---|---|---|
22b58f24 MG |
1 | #include <efi.h> |
2 | #include <efilib.h> | |
3 | #include <string.h> | |
4 | ||
5 | #include "tpm.h" | |
6 | ||
7 | extern 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 | ||
17 | EFI_GUID tpm_guid = EFI_TPM_GUID; | |
18 | EFI_GUID tpm2_guid = EFI_TPM2_GUID; | |
19 | ||
20 | static 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 | ||
38 | static 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 *)∩︀ |
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 | */ | |
72 | static 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 |
83 | EFI_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 | } |