blob: 453cbce5c83ab2a9a62f385ea61f68d92d34f624 [file] [log] [blame]
Heinrich Schuchardt9827e842020-06-22 18:10:27 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * UEFI runtime variable services
4 *
5 * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
6 */
7
8#include <common.h>
9#include <efi_loader.h>
10#include <efi_variable.h>
11
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +020012enum efi_secure_mode {
13 EFI_MODE_SETUP,
14 EFI_MODE_USER,
15 EFI_MODE_AUDIT,
16 EFI_MODE_DEPLOYED,
17};
18
Heinrich Schuchardt3a280332020-07-15 12:40:35 +020019struct efi_auth_var_name_type {
20 const u16 *name;
21 const efi_guid_t *guid;
22 const enum efi_auth_var_type type;
23};
24
25static const struct efi_auth_var_name_type name_type[] = {
26 {u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
27 {u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
28 {u"db", &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
29 {u"dbx", &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
30 /* not used yet
31 {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
32 {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
33 */
34};
35
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +020036static bool efi_secure_boot;
37static enum efi_secure_mode efi_secure_mode;
38
Heinrich Schuchardt9827e842020-06-22 18:10:27 +020039/**
40 * efi_efi_get_variable() - retrieve value of a UEFI variable
41 *
42 * This function implements the GetVariable runtime service.
43 *
44 * See the Unified Extensible Firmware Interface (UEFI) specification for
45 * details.
46 *
47 * @variable_name: name of the variable
48 * @vendor: vendor GUID
49 * @attributes: attributes of the variable
50 * @data_size: size of the buffer to which the variable value is copied
51 * @data: buffer to which the variable value is copied
52 * Return: status code
53 */
54efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
55 const efi_guid_t *vendor, u32 *attributes,
56 efi_uintn_t *data_size, void *data)
57{
58 efi_status_t ret;
59
60 EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
61 data_size, data);
62
63 ret = efi_get_variable_int(variable_name, vendor, attributes,
64 data_size, data, NULL);
65
66 /* Remove EFI_VARIABLE_READ_ONLY flag */
67 if (attributes)
68 *attributes &= EFI_VARIABLE_MASK;
69
70 return EFI_EXIT(ret);
71}
72
73/**
74 * efi_set_variable() - set value of a UEFI variable
75 *
76 * This function implements the SetVariable runtime service.
77 *
78 * See the Unified Extensible Firmware Interface (UEFI) specification for
79 * details.
80 *
81 * @variable_name: name of the variable
82 * @vendor: vendor GUID
83 * @attributes: attributes of the variable
84 * @data_size: size of the buffer with the variable value
85 * @data: buffer with the variable value
86 * Return: status code
87 */
88efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
89 const efi_guid_t *vendor, u32 attributes,
90 efi_uintn_t data_size, const void *data)
91{
92 efi_status_t ret;
93
94 EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
95 data_size, data);
96
97 /* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */
98 if (attributes & ~(u32)EFI_VARIABLE_MASK)
99 ret = EFI_INVALID_PARAMETER;
100 else
101 ret = efi_set_variable_int(variable_name, vendor, attributes,
102 data_size, data, true);
103
104 return EFI_EXIT(ret);
105}
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200106
107/**
108 * efi_get_next_variable_name() - enumerate the current variable names
109 *
110 * @variable_name_size: size of variable_name buffer in byte
111 * @variable_name: name of uefi variable's name in u16
112 * @vendor: vendor's guid
113 *
114 * See the Unified Extensible Firmware Interface (UEFI) specification for
115 * details.
116 *
117 * Return: status code
118 */
119efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
120 u16 *variable_name,
121 efi_guid_t *vendor)
122{
123 efi_status_t ret;
124
125 EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
126
127 ret = efi_get_next_variable_name_int(variable_name_size, variable_name,
128 vendor);
129
130 return EFI_EXIT(ret);
131}
132
133/**
134 * efi_query_variable_info() - get information about EFI variables
135 *
136 * This function implements the QueryVariableInfo() runtime service.
137 *
138 * See the Unified Extensible Firmware Interface (UEFI) specification for
139 * details.
140 *
141 * @attributes: bitmask to select variables to be
142 * queried
143 * @maximum_variable_storage_size: maximum size of storage area for the
144 * selected variable types
145 * @remaining_variable_storage_size: remaining size of storage are for the
146 * selected variable types
147 * @maximum_variable_size: maximum size of a variable of the
148 * selected type
149 * Returns: status code
150 */
151efi_status_t EFIAPI efi_query_variable_info(
152 u32 attributes, u64 *maximum_variable_storage_size,
153 u64 *remaining_variable_storage_size,
154 u64 *maximum_variable_size)
155{
156 efi_status_t ret;
157
158 EFI_ENTRY("%x %p %p %p", attributes, maximum_variable_storage_size,
159 remaining_variable_storage_size, maximum_variable_size);
160
161 ret = efi_query_variable_info_int(attributes,
162 maximum_variable_storage_size,
163 remaining_variable_storage_size,
164 maximum_variable_size);
165
166 return EFI_EXIT(ret);
167}
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200168
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300169efi_status_t __efi_runtime EFIAPI
170efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
171 u32 *attributes, efi_uintn_t *data_size, void *data)
172{
173 efi_status_t ret;
174
175 ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
176
177 /* Remove EFI_VARIABLE_READ_ONLY flag */
178 if (attributes)
179 *attributes &= EFI_VARIABLE_MASK;
180
181 return ret;
182}
183
184efi_status_t __efi_runtime EFIAPI
185efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
186 u16 *variable_name, efi_guid_t *guid)
187{
188 return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
189}
190
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200191/**
192 * efi_set_secure_state - modify secure boot state variables
193 * @secure_boot: value of SecureBoot
194 * @setup_mode: value of SetupMode
195 * @audit_mode: value of AuditMode
196 * @deployed_mode: value of DeployedMode
197 *
198 * Modify secure boot status related variables as indicated.
199 *
200 * Return: status code
201 */
202static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
203 u8 audit_mode, u8 deployed_mode)
204{
205 efi_status_t ret;
206 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
207 EFI_VARIABLE_RUNTIME_ACCESS |
208 EFI_VARIABLE_READ_ONLY;
209 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
210 EFI_VARIABLE_RUNTIME_ACCESS;
211
212 efi_secure_boot = secure_boot;
213
214 ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
215 attributes_ro, sizeof(secure_boot),
216 &secure_boot, false);
217 if (ret != EFI_SUCCESS)
218 goto err;
219
220 ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
221 attributes_ro, sizeof(setup_mode),
222 &setup_mode, false);
223 if (ret != EFI_SUCCESS)
224 goto err;
225
226 ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
227 audit_mode || setup_mode ?
228 attributes_ro : attributes_rw,
229 sizeof(audit_mode), &audit_mode, false);
230 if (ret != EFI_SUCCESS)
231 goto err;
232
233 ret = efi_set_variable_int(L"DeployedMode",
234 &efi_global_variable_guid,
235 audit_mode || deployed_mode || setup_mode ?
236 attributes_ro : attributes_rw,
237 sizeof(deployed_mode), &deployed_mode,
238 false);
239err:
240 return ret;
241}
242
243/**
244 * efi_transfer_secure_state - handle a secure boot state transition
245 * @mode: new state
246 *
247 * Depending on @mode, secure boot related variables are updated.
248 * Those variables are *read-only* for users, efi_set_variable_int()
249 * is called here.
250 *
251 * Return: status code
252 */
253static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
254{
255 efi_status_t ret;
256
257 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
258 mode);
259
260 if (mode == EFI_MODE_DEPLOYED) {
261 ret = efi_set_secure_state(1, 0, 0, 1);
262 if (ret != EFI_SUCCESS)
263 goto err;
264 } else if (mode == EFI_MODE_AUDIT) {
265 ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
266 EFI_VARIABLE_BOOTSERVICE_ACCESS |
267 EFI_VARIABLE_RUNTIME_ACCESS,
268 0, NULL, false);
269 if (ret != EFI_SUCCESS)
270 goto err;
271
272 ret = efi_set_secure_state(0, 1, 1, 0);
273 if (ret != EFI_SUCCESS)
274 goto err;
275 } else if (mode == EFI_MODE_USER) {
276 ret = efi_set_secure_state(1, 0, 0, 0);
277 if (ret != EFI_SUCCESS)
278 goto err;
279 } else if (mode == EFI_MODE_SETUP) {
280 ret = efi_set_secure_state(0, 1, 0, 0);
281 if (ret != EFI_SUCCESS)
282 goto err;
283 } else {
284 return EFI_INVALID_PARAMETER;
285 }
286
287 efi_secure_mode = mode;
288
289 return EFI_SUCCESS;
290
291err:
292 /* TODO: What action should be taken here? */
293 printf("ERROR: Secure state transition failed\n");
294 return ret;
295}
296
297efi_status_t efi_init_secure_state(void)
298{
299 enum efi_secure_mode mode = EFI_MODE_SETUP;
300 u8 efi_vendor_keys = 0;
301 efi_uintn_t size = 0;
302 efi_status_t ret;
303
304 ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
305 NULL, &size, NULL, NULL);
306 if (ret == EFI_BUFFER_TOO_SMALL) {
307 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
308 mode = EFI_MODE_USER;
309 }
310
311 ret = efi_transfer_secure_state(mode);
312 if (ret != EFI_SUCCESS)
313 return ret;
314
315 /* As we do not provide vendor keys this variable is always 0. */
316 ret = efi_set_variable_int(L"VendorKeys",
317 &efi_global_variable_guid,
318 EFI_VARIABLE_BOOTSERVICE_ACCESS |
319 EFI_VARIABLE_RUNTIME_ACCESS |
320 EFI_VARIABLE_READ_ONLY,
321 sizeof(efi_vendor_keys),
322 &efi_vendor_keys, false);
323 return ret;
324}
325
326/**
327 * efi_secure_boot_enabled - return if secure boot is enabled or not
328 *
329 * Return: true if enabled, false if disabled
330 */
331bool efi_secure_boot_enabled(void)
332{
333 return efi_secure_boot;
334}
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200335
336enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
337{
338 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
339 if (!u16_strcmp(name, name_type[i].name) &&
340 !guidcmp(guid, name_type[i].guid))
341 return name_type[i].type;
342 }
343 return EFI_AUTH_VAR_NONE;
344}