Merge tag 'backlight-next-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/lee...
[linux-2.6-microblaze.git] / drivers / firmware / efi / libstub / tpm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * TPM handling.
4  *
5  * Copyright (C) 2016 CoreOS, Inc
6  * Copyright (C) 2017 Google, Inc.
7  *     Matthew Garrett <mjg59@google.com>
8  *     Thiebaud Weksteen <tweek@google.com>
9  */
10 #include <linux/efi.h>
11 #include <linux/tpm_eventlog.h>
12 #include <asm/efi.h>
13
14 #include "efistub.h"
15
16 #ifdef CONFIG_RESET_ATTACK_MITIGATION
17 static const efi_char16_t efi_MemoryOverWriteRequest_name[] =
18         L"MemoryOverwriteRequestControl";
19
20 #define MEMORY_ONLY_RESET_CONTROL_GUID \
21         EFI_GUID(0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 0xd4, 0x98, 0x29)
22
23 /*
24  * Enable reboot attack mitigation. This requests that the firmware clear the
25  * RAM on next reboot before proceeding with boot, ensuring that any secrets
26  * are cleared. If userland has ensured that all secrets have been removed
27  * from RAM before reboot it can simply reset this variable.
28  */
29 void efi_enable_reset_attack_mitigation(void)
30 {
31         u8 val = 1;
32         efi_guid_t var_guid = MEMORY_ONLY_RESET_CONTROL_GUID;
33         efi_status_t status;
34         unsigned long datasize = 0;
35
36         status = get_efi_var(efi_MemoryOverWriteRequest_name, &var_guid,
37                              NULL, &datasize, NULL);
38
39         if (status == EFI_NOT_FOUND)
40                 return;
41
42         set_efi_var(efi_MemoryOverWriteRequest_name, &var_guid,
43                     EFI_VARIABLE_NON_VOLATILE |
44                     EFI_VARIABLE_BOOTSERVICE_ACCESS |
45                     EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val);
46 }
47
48 #endif
49
50 void efi_retrieve_tpm2_eventlog(void)
51 {
52         efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
53         efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
54         efi_status_t status;
55         efi_physical_addr_t log_location = 0, log_last_entry = 0;
56         struct linux_efi_tpm_eventlog *log_tbl = NULL;
57         struct efi_tcg2_final_events_table *final_events_table = NULL;
58         unsigned long first_entry_addr, last_entry_addr;
59         size_t log_size, last_entry_size;
60         efi_bool_t truncated;
61         int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
62         efi_tcg2_protocol_t *tcg2_protocol = NULL;
63         int final_events_size = 0;
64
65         status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
66                              (void **)&tcg2_protocol);
67         if (status != EFI_SUCCESS)
68                 return;
69
70         status = efi_call_proto(tcg2_protocol, get_event_log, version,
71                                 &log_location, &log_last_entry, &truncated);
72
73         if (status != EFI_SUCCESS || !log_location) {
74                 version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
75                 status = efi_call_proto(tcg2_protocol, get_event_log, version,
76                                         &log_location, &log_last_entry,
77                                         &truncated);
78                 if (status != EFI_SUCCESS || !log_location)
79                         return;
80
81         }
82
83         first_entry_addr = (unsigned long) log_location;
84
85         /*
86          * We populate the EFI table even if the logs are empty.
87          */
88         if (!log_last_entry) {
89                 log_size = 0;
90         } else {
91                 last_entry_addr = (unsigned long) log_last_entry;
92                 /*
93                  * get_event_log only returns the address of the last entry.
94                  * We need to calculate its size to deduce the full size of
95                  * the logs.
96                  */
97                 if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
98                         /*
99                          * The TCG2 log format has variable length entries,
100                          * and the information to decode the hash algorithms
101                          * back into a size is contained in the first entry -
102                          * pass a pointer to the final entry (to calculate its
103                          * size) and the first entry (so we know how long each
104                          * digest is)
105                          */
106                         last_entry_size =
107                                 __calc_tpm2_event_size((void *)last_entry_addr,
108                                                     (void *)(long)log_location,
109                                                     false);
110                 } else {
111                         last_entry_size = sizeof(struct tcpa_event) +
112                            ((struct tcpa_event *) last_entry_addr)->event_size;
113                 }
114                 log_size = log_last_entry - log_location + last_entry_size;
115         }
116
117         /* Allocate space for the logs and copy them. */
118         status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
119                              sizeof(*log_tbl) + log_size, (void **)&log_tbl);
120
121         if (status != EFI_SUCCESS) {
122                 efi_err("Unable to allocate memory for event log\n");
123                 return;
124         }
125
126         /*
127          * Figure out whether any events have already been logged to the
128          * final events structure, and if so how much space they take up
129          */
130         if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
131                 final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
132         if (final_events_table && final_events_table->nr_events) {
133                 struct tcg_pcr_event2_head *header;
134                 int offset;
135                 void *data;
136                 int event_size;
137                 int i = final_events_table->nr_events;
138
139                 data = (void *)final_events_table;
140                 offset = sizeof(final_events_table->version) +
141                         sizeof(final_events_table->nr_events);
142
143                 while (i > 0) {
144                         header = data + offset + final_events_size;
145                         event_size = __calc_tpm2_event_size(header,
146                                                    (void *)(long)log_location,
147                                                    false);
148                         final_events_size += event_size;
149                         i--;
150                 }
151         }
152
153         memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
154         log_tbl->size = log_size;
155         log_tbl->final_events_preboot_size = final_events_size;
156         log_tbl->version = version;
157         memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
158
159         status = efi_bs_call(install_configuration_table,
160                              &linux_eventlog_guid, log_tbl);
161         if (status != EFI_SUCCESS)
162                 goto err_free;
163         return;
164
165 err_free:
166         efi_bs_call(free_pool, log_tbl);
167 }