blob: 961139f005afca4f43c06bdae7c2db7ce69c97da [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>
AKASHI Takahiro200647a2020-07-30 16:33:59 +09006 * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro
Heinrich Schuchardt9827e842020-06-22 18:10:27 +02007 */
8
Heinrich Schuchardt9827e842020-06-22 18:10:27 +02009#include <efi_loader.h>
10#include <efi_variable.h>
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +020011#include <stdlib.h>
Ilias Apalodimascc0ead72024-04-05 09:50:58 +030012#include <u-boot/crc.h>
Heinrich Schuchardt9827e842020-06-22 18:10:27 +020013
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +020014enum efi_secure_mode {
15 EFI_MODE_SETUP,
16 EFI_MODE_USER,
17 EFI_MODE_AUDIT,
18 EFI_MODE_DEPLOYED,
19};
20
Heinrich Schuchardt3a280332020-07-15 12:40:35 +020021struct efi_auth_var_name_type {
22 const u16 *name;
23 const efi_guid_t *guid;
24 const enum efi_auth_var_type type;
25};
26
Masahisa Kojima915e4272021-05-14 09:53:36 +090027const efi_guid_t efi_guid_image_security_database =
28 EFI_IMAGE_SECURITY_DATABASE_GUID;
29
Heinrich Schuchardt3a280332020-07-15 12:40:35 +020030static const struct efi_auth_var_name_type name_type[] = {
31 {u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
32 {u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
33 {u"db", &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
34 {u"dbx", &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
Heinrich Schuchardt3a280332020-07-15 12:40:35 +020035 {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
36 {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
Heinrich Schuchardt65b616f2021-08-26 04:30:24 +020037 {u"AuditMode", &efi_global_variable_guid, EFI_AUTH_MODE},
38 {u"DeployedMode", &efi_global_variable_guid, EFI_AUTH_MODE},
Heinrich Schuchardt3a280332020-07-15 12:40:35 +020039};
40
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +020041static bool efi_secure_boot;
42static enum efi_secure_mode efi_secure_mode;
43
Heinrich Schuchardt9827e842020-06-22 18:10:27 +020044/**
45 * efi_efi_get_variable() - retrieve value of a UEFI variable
46 *
47 * This function implements the GetVariable runtime service.
48 *
49 * See the Unified Extensible Firmware Interface (UEFI) specification for
50 * details.
51 *
52 * @variable_name: name of the variable
53 * @vendor: vendor GUID
54 * @attributes: attributes of the variable
55 * @data_size: size of the buffer to which the variable value is copied
56 * @data: buffer to which the variable value is copied
57 * Return: status code
58 */
59efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
60 const efi_guid_t *vendor, u32 *attributes,
61 efi_uintn_t *data_size, void *data)
62{
63 efi_status_t ret;
64
Heinrich Schuchardt282249d2022-01-16 14:15:31 +010065 EFI_ENTRY("\"%ls\" %pUs %p %p %p", variable_name, vendor, attributes,
Heinrich Schuchardt9827e842020-06-22 18:10:27 +020066 data_size, data);
67
68 ret = efi_get_variable_int(variable_name, vendor, attributes,
69 data_size, data, NULL);
70
71 /* Remove EFI_VARIABLE_READ_ONLY flag */
72 if (attributes)
73 *attributes &= EFI_VARIABLE_MASK;
74
75 return EFI_EXIT(ret);
76}
77
78/**
79 * efi_set_variable() - set value of a UEFI variable
80 *
81 * This function implements the SetVariable runtime service.
82 *
83 * See the Unified Extensible Firmware Interface (UEFI) specification for
84 * details.
85 *
86 * @variable_name: name of the variable
87 * @vendor: vendor GUID
88 * @attributes: attributes of the variable
89 * @data_size: size of the buffer with the variable value
90 * @data: buffer with the variable value
91 * Return: status code
92 */
93efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
94 const efi_guid_t *vendor, u32 attributes,
95 efi_uintn_t data_size, const void *data)
96{
97 efi_status_t ret;
98
Heinrich Schuchardt282249d2022-01-16 14:15:31 +010099 EFI_ENTRY("\"%ls\" %pUs %x %zu %p", variable_name, vendor, attributes,
Heinrich Schuchardt9827e842020-06-22 18:10:27 +0200100 data_size, data);
101
102 /* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */
Heinrich Schuchardt698cfde2024-04-03 17:33:33 +0200103 if (attributes & ~EFI_VARIABLE_MASK)
Heinrich Schuchardt9827e842020-06-22 18:10:27 +0200104 ret = EFI_INVALID_PARAMETER;
105 else
106 ret = efi_set_variable_int(variable_name, vendor, attributes,
107 data_size, data, true);
108
109 return EFI_EXIT(ret);
110}
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200111
112/**
113 * efi_get_next_variable_name() - enumerate the current variable names
114 *
115 * @variable_name_size: size of variable_name buffer in byte
116 * @variable_name: name of uefi variable's name in u16
117 * @vendor: vendor's guid
118 *
119 * See the Unified Extensible Firmware Interface (UEFI) specification for
120 * details.
121 *
122 * Return: status code
123 */
124efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
125 u16 *variable_name,
126 efi_guid_t *vendor)
127{
128 efi_status_t ret;
129
Heinrich Schuchardt282249d2022-01-16 14:15:31 +0100130 EFI_ENTRY("%p \"%ls\" %pUs", variable_name_size, variable_name, vendor);
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200131
132 ret = efi_get_next_variable_name_int(variable_name_size, variable_name,
133 vendor);
134
135 return EFI_EXIT(ret);
136}
137
138/**
139 * efi_query_variable_info() - get information about EFI variables
140 *
141 * This function implements the QueryVariableInfo() runtime service.
142 *
143 * See the Unified Extensible Firmware Interface (UEFI) specification for
144 * details.
145 *
146 * @attributes: bitmask to select variables to be
147 * queried
148 * @maximum_variable_storage_size: maximum size of storage area for the
149 * selected variable types
150 * @remaining_variable_storage_size: remaining size of storage are for the
151 * selected variable types
152 * @maximum_variable_size: maximum size of a variable of the
153 * selected type
154 * Returns: status code
155 */
156efi_status_t EFIAPI efi_query_variable_info(
157 u32 attributes, u64 *maximum_variable_storage_size,
158 u64 *remaining_variable_storage_size,
159 u64 *maximum_variable_size)
160{
161 efi_status_t ret;
162
163 EFI_ENTRY("%x %p %p %p", attributes, maximum_variable_storage_size,
164 remaining_variable_storage_size, maximum_variable_size);
165
Masami Hiramatsuaee53302021-07-01 00:49:48 +0900166 if (!maximum_variable_storage_size ||
167 !remaining_variable_storage_size ||
Masahisa Kojima1fd781f2023-02-02 22:53:35 +0900168 !maximum_variable_size)
Masami Hiramatsuaee53302021-07-01 00:49:48 +0900169 return EFI_EXIT(EFI_INVALID_PARAMETER);
170
Heinrich Schuchardt276c61d2020-06-26 17:57:48 +0200171 ret = efi_query_variable_info_int(attributes,
172 maximum_variable_storage_size,
173 remaining_variable_storage_size,
174 maximum_variable_size);
175
176 return EFI_EXIT(ret);
177}
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200178
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300179efi_status_t __efi_runtime EFIAPI
180efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
181 u32 *attributes, efi_uintn_t *data_size, void *data)
182{
183 efi_status_t ret;
184
Ilias Apalodimasde708562024-04-18 15:54:52 +0300185 ret = efi_get_variable_mem(variable_name, guid, attributes, data_size,
186 data, NULL, EFI_VARIABLE_RUNTIME_ACCESS);
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300187
188 /* Remove EFI_VARIABLE_READ_ONLY flag */
189 if (attributes)
190 *attributes &= EFI_VARIABLE_MASK;
191
192 return ret;
193}
194
195efi_status_t __efi_runtime EFIAPI
196efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
197 u16 *variable_name, efi_guid_t *guid)
198{
Ilias Apalodimasde708562024-04-18 15:54:52 +0300199 return efi_get_next_variable_name_mem(variable_name_size, variable_name,
200 guid, EFI_VARIABLE_RUNTIME_ACCESS);
Ilias Apalodimasa4d1b1b2020-07-23 15:49:49 +0300201}
202
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200203/**
204 * efi_set_secure_state - modify secure boot state variables
205 * @secure_boot: value of SecureBoot
206 * @setup_mode: value of SetupMode
207 * @audit_mode: value of AuditMode
208 * @deployed_mode: value of DeployedMode
209 *
210 * Modify secure boot status related variables as indicated.
211 *
212 * Return: status code
213 */
214static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
215 u8 audit_mode, u8 deployed_mode)
216{
217 efi_status_t ret;
218 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
219 EFI_VARIABLE_RUNTIME_ACCESS |
220 EFI_VARIABLE_READ_ONLY;
221 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
222 EFI_VARIABLE_RUNTIME_ACCESS;
223
224 efi_secure_boot = secure_boot;
225
Simon Glass90975372022-01-23 12:55:12 -0700226 ret = efi_set_variable_int(u"SecureBoot", &efi_global_variable_guid,
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200227 attributes_ro, sizeof(secure_boot),
228 &secure_boot, false);
229 if (ret != EFI_SUCCESS)
230 goto err;
231
Simon Glass90975372022-01-23 12:55:12 -0700232 ret = efi_set_variable_int(u"SetupMode", &efi_global_variable_guid,
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200233 attributes_ro, sizeof(setup_mode),
234 &setup_mode, false);
235 if (ret != EFI_SUCCESS)
236 goto err;
237
Simon Glass90975372022-01-23 12:55:12 -0700238 ret = efi_set_variable_int(u"AuditMode", &efi_global_variable_guid,
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200239 audit_mode || setup_mode ?
240 attributes_ro : attributes_rw,
241 sizeof(audit_mode), &audit_mode, false);
242 if (ret != EFI_SUCCESS)
243 goto err;
244
Simon Glass90975372022-01-23 12:55:12 -0700245 ret = efi_set_variable_int(u"DeployedMode",
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200246 &efi_global_variable_guid,
247 audit_mode || deployed_mode || setup_mode ?
248 attributes_ro : attributes_rw,
249 sizeof(deployed_mode), &deployed_mode,
250 false);
251err:
252 return ret;
253}
254
255/**
256 * efi_transfer_secure_state - handle a secure boot state transition
257 * @mode: new state
258 *
259 * Depending on @mode, secure boot related variables are updated.
260 * Those variables are *read-only* for users, efi_set_variable_int()
261 * is called here.
262 *
263 * Return: status code
264 */
265static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
266{
267 efi_status_t ret;
268
269 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
270 mode);
271
272 if (mode == EFI_MODE_DEPLOYED) {
273 ret = efi_set_secure_state(1, 0, 0, 1);
274 if (ret != EFI_SUCCESS)
275 goto err;
276 } else if (mode == EFI_MODE_AUDIT) {
Simon Glass90975372022-01-23 12:55:12 -0700277 ret = efi_set_variable_int(u"PK", &efi_global_variable_guid,
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200278 EFI_VARIABLE_BOOTSERVICE_ACCESS |
279 EFI_VARIABLE_RUNTIME_ACCESS,
280 0, NULL, false);
281 if (ret != EFI_SUCCESS)
282 goto err;
283
284 ret = efi_set_secure_state(0, 1, 1, 0);
285 if (ret != EFI_SUCCESS)
286 goto err;
287 } else if (mode == EFI_MODE_USER) {
288 ret = efi_set_secure_state(1, 0, 0, 0);
289 if (ret != EFI_SUCCESS)
290 goto err;
291 } else if (mode == EFI_MODE_SETUP) {
292 ret = efi_set_secure_state(0, 1, 0, 0);
293 if (ret != EFI_SUCCESS)
294 goto err;
295 } else {
296 return EFI_INVALID_PARAMETER;
297 }
298
299 efi_secure_mode = mode;
300
301 return EFI_SUCCESS;
302
303err:
304 /* TODO: What action should be taken here? */
305 printf("ERROR: Secure state transition failed\n");
306 return ret;
307}
308
309efi_status_t efi_init_secure_state(void)
310{
Heinrich Schuchardt3f65f812021-09-02 07:11:45 +0200311 enum efi_secure_mode mode;
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200312 u8 efi_vendor_keys = 0;
Heinrich Schuchardt3f65f812021-09-02 07:11:45 +0200313 efi_uintn_t size;
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200314 efi_status_t ret;
Heinrich Schuchardt3f65f812021-09-02 07:11:45 +0200315 u8 deployed_mode = 0;
316 u8 audit_mode = 0;
317 u8 setup_mode = 1;
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200318
Heinrich Schuchardt3f65f812021-09-02 07:11:45 +0200319 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
320 size = sizeof(deployed_mode);
321 ret = efi_get_variable_int(u"DeployedMode", &efi_global_variable_guid,
322 NULL, &size, &deployed_mode, NULL);
323 size = sizeof(audit_mode);
324 ret = efi_get_variable_int(u"AuditMode", &efi_global_variable_guid,
325 NULL, &size, &audit_mode, NULL);
326 size = 0;
327 ret = efi_get_variable_int(u"PK", &efi_global_variable_guid,
328 NULL, &size, NULL, NULL);
329 if (ret == EFI_BUFFER_TOO_SMALL) {
330 setup_mode = 0;
331 audit_mode = 0;
332 } else {
333 setup_mode = 1;
334 deployed_mode = 0;
335 }
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200336 }
Heinrich Schuchardt3f65f812021-09-02 07:11:45 +0200337 if (deployed_mode)
338 mode = EFI_MODE_DEPLOYED;
339 else if (audit_mode)
340 mode = EFI_MODE_AUDIT;
341 else if (setup_mode)
342 mode = EFI_MODE_SETUP;
343 else
344 mode = EFI_MODE_USER;
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200345
346 ret = efi_transfer_secure_state(mode);
347 if (ret != EFI_SUCCESS)
348 return ret;
349
350 /* As we do not provide vendor keys this variable is always 0. */
Simon Glass90975372022-01-23 12:55:12 -0700351 ret = efi_set_variable_int(u"VendorKeys",
Heinrich Schuchardt0f2c3332020-07-14 08:04:49 +0200352 &efi_global_variable_guid,
353 EFI_VARIABLE_BOOTSERVICE_ACCESS |
354 EFI_VARIABLE_RUNTIME_ACCESS |
355 EFI_VARIABLE_READ_ONLY,
356 sizeof(efi_vendor_keys),
357 &efi_vendor_keys, false);
358 return ret;
359}
360
361/**
362 * efi_secure_boot_enabled - return if secure boot is enabled or not
363 *
364 * Return: true if enabled, false if disabled
365 */
366bool efi_secure_boot_enabled(void)
367{
368 return efi_secure_boot;
369}
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200370
Heinrich Schuchardt1ad2f0d2021-09-09 07:12:14 +0200371enum efi_auth_var_type efi_auth_var_get_type(const u16 *name,
372 const efi_guid_t *guid)
Heinrich Schuchardt3a280332020-07-15 12:40:35 +0200373{
374 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
375 if (!u16_strcmp(name, name_type[i].name) &&
376 !guidcmp(guid, name_type[i].guid))
377 return name_type[i].type;
378 }
379 return EFI_AUTH_VAR_NONE;
380}
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200381
Heinrich Schuchardtcbd28022021-09-09 08:22:58 +0200382const efi_guid_t *efi_auth_var_get_guid(const u16 *name)
383{
384 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
385 if (!u16_strcmp(name, name_type[i].name))
386 return name_type[i].guid;
387 }
388 return &efi_global_variable_guid;
389}
390
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200391/**
392 * efi_get_var() - read value of an EFI variable
393 *
394 * @name: variable name
395 * @start: vendor GUID
396 * @size: size of allocated buffer
397 *
398 * Return: buffer with variable data or NULL
399 */
Heinrich Schuchardt1ad2f0d2021-09-09 07:12:14 +0200400void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
Ilias Apalodimasaa0f7552021-03-17 21:54:59 +0200401{
402 efi_status_t ret;
403 void *buf = NULL;
404
405 *size = 0;
406 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
407 if (ret == EFI_BUFFER_TOO_SMALL) {
408 buf = malloc(*size);
409 if (!buf)
410 return NULL;
411 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
412 }
413
414 if (ret != EFI_SUCCESS) {
415 free(buf);
416 *size = 0;
417 return NULL;
418 }
419
420 return buf;
421}
Ilias Apalodimascc0ead72024-04-05 09:50:58 +0300422
423/**
Heinrich Schuchardt3390fdd2024-04-18 04:32:02 +0200424 * efi_var_collect() - Copy EFI variables matching attributes mask
Ilias Apalodimascc0ead72024-04-05 09:50:58 +0300425 *
426 * @bufp: buffer containing variable collection
427 * @lenp: buffer length
428 * @attr_mask: mask of matched attributes
429 *
430 * Return: Status code
431 */
432efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *lenp,
433 u32 check_attr_mask)
434{
435 size_t len = EFI_VAR_BUF_SIZE;
436 struct efi_var_file *buf;
437 struct efi_var_entry *var, *old_var;
438 size_t old_var_name_length = 2;
439
440 *bufp = NULL; /* Avoid double free() */
441 buf = calloc(1, len);
442 if (!buf)
443 return EFI_OUT_OF_RESOURCES;
444 var = buf->var;
445 old_var = var;
446 for (;;) {
447 efi_uintn_t data_length, var_name_length;
448 u8 *data;
449 efi_status_t ret;
450
451 if ((uintptr_t)buf + len <=
452 (uintptr_t)var->name + old_var_name_length)
453 return EFI_BUFFER_TOO_SMALL;
454
455 var_name_length = (uintptr_t)buf + len - (uintptr_t)var->name;
456 memcpy(var->name, old_var->name, old_var_name_length);
457 guidcpy(&var->guid, &old_var->guid);
458 ret = efi_get_next_variable_name_int(
459 &var_name_length, var->name, &var->guid);
460 if (ret == EFI_NOT_FOUND)
461 break;
462 if (ret != EFI_SUCCESS) {
463 free(buf);
464 return ret;
465 }
466 old_var_name_length = var_name_length;
467 old_var = var;
468
469 data = (u8 *)var->name + old_var_name_length;
470 data_length = (uintptr_t)buf + len - (uintptr_t)data;
471 ret = efi_get_variable_int(var->name, &var->guid,
472 &var->attr, &data_length, data,
473 &var->time);
474 if (ret != EFI_SUCCESS) {
475 free(buf);
476 return ret;
477 }
478 if ((var->attr & check_attr_mask) == check_attr_mask) {
479 var->length = data_length;
480 var = (struct efi_var_entry *)ALIGN((uintptr_t)data + data_length, 8);
481 }
482 }
483
484 buf->reserved = 0;
485 buf->magic = EFI_VAR_FILE_MAGIC;
486 len = (uintptr_t)var - (uintptr_t)buf;
487 buf->crc32 = crc32(0, (u8 *)buf->var,
488 len - sizeof(struct efi_var_file));
489 buf->length = len;
490 *bufp = buf;
491 *lenp = len;
492
493 return EFI_SUCCESS;
494}