blob: 83479dd142aa8e359e191478acd79d350a68b64d [file] [log] [blame]
Heinrich Schuchardtf2d2b3a2020-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 Takahirodd92aad2020-07-30 16:33:59 +09006 * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +02007 */
8
9#include <common.h>
10#include <efi_loader.h>
11#include <efi_variable.h>
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +020012#include <stdlib.h>
Heinrich Schuchardtf2d2b3a2020-06-22 18:10:27 +020013
Heinrich Schuchardt012c56a2020-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 Schuchardt99bfab82020-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 Kojimaf6081a82021-05-14 09:53:36 +090027const efi_guid_t efi_guid_image_security_database =
28 EFI_IMAGE_SECURITY_DATABASE_GUID;
29
Heinrich Schuchardt99bfab82020-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},
35 /* not used yet
36 {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
37 {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
38 */
39};
40
Heinrich Schuchardt012c56a2020-07-14 08:04:49 +020041static bool efi_secure_boot;
42static enum efi_secure_mode efi_secure_mode;
43
Heinrich Schuchardtf2d2b3a2020-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
65 EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
66 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
99 EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
100 data_size, data);
101
102 /* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */
103 if (attributes & ~(u32)EFI_VARIABLE_MASK)
104 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 Schuchardt01df8cf2020-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
130 EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
131
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
166 ret = efi_query_variable_info_int(attributes,
167 maximum_variable_storage_size,
168 remaining_variable_storage_size,
169 maximum_variable_size);
170
171 return EFI_EXIT(ret);
172}
Heinrich Schuchardt012c56a2020-07-14 08:04:49 +0200173
Ilias Apalodimase01aed42020-07-23 15:49:49 +0300174efi_status_t __efi_runtime EFIAPI
175efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
176 u32 *attributes, efi_uintn_t *data_size, void *data)
177{
178 efi_status_t ret;
179
180 ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
181
182 /* Remove EFI_VARIABLE_READ_ONLY flag */
183 if (attributes)
184 *attributes &= EFI_VARIABLE_MASK;
185
186 return ret;
187}
188
189efi_status_t __efi_runtime EFIAPI
190efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
191 u16 *variable_name, efi_guid_t *guid)
192{
193 return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
194}
195
Heinrich Schuchardt012c56a2020-07-14 08:04:49 +0200196/**
197 * efi_set_secure_state - modify secure boot state variables
198 * @secure_boot: value of SecureBoot
199 * @setup_mode: value of SetupMode
200 * @audit_mode: value of AuditMode
201 * @deployed_mode: value of DeployedMode
202 *
203 * Modify secure boot status related variables as indicated.
204 *
205 * Return: status code
206 */
207static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
208 u8 audit_mode, u8 deployed_mode)
209{
210 efi_status_t ret;
211 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
212 EFI_VARIABLE_RUNTIME_ACCESS |
213 EFI_VARIABLE_READ_ONLY;
214 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
215 EFI_VARIABLE_RUNTIME_ACCESS;
216
217 efi_secure_boot = secure_boot;
218
219 ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
220 attributes_ro, sizeof(secure_boot),
221 &secure_boot, false);
222 if (ret != EFI_SUCCESS)
223 goto err;
224
225 ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
226 attributes_ro, sizeof(setup_mode),
227 &setup_mode, false);
228 if (ret != EFI_SUCCESS)
229 goto err;
230
231 ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
232 audit_mode || setup_mode ?
233 attributes_ro : attributes_rw,
234 sizeof(audit_mode), &audit_mode, false);
235 if (ret != EFI_SUCCESS)
236 goto err;
237
238 ret = efi_set_variable_int(L"DeployedMode",
239 &efi_global_variable_guid,
240 audit_mode || deployed_mode || setup_mode ?
241 attributes_ro : attributes_rw,
242 sizeof(deployed_mode), &deployed_mode,
243 false);
244err:
245 return ret;
246}
247
248/**
249 * efi_transfer_secure_state - handle a secure boot state transition
250 * @mode: new state
251 *
252 * Depending on @mode, secure boot related variables are updated.
253 * Those variables are *read-only* for users, efi_set_variable_int()
254 * is called here.
255 *
256 * Return: status code
257 */
258static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
259{
260 efi_status_t ret;
261
262 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
263 mode);
264
265 if (mode == EFI_MODE_DEPLOYED) {
266 ret = efi_set_secure_state(1, 0, 0, 1);
267 if (ret != EFI_SUCCESS)
268 goto err;
269 } else if (mode == EFI_MODE_AUDIT) {
270 ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
271 EFI_VARIABLE_BOOTSERVICE_ACCESS |
272 EFI_VARIABLE_RUNTIME_ACCESS,
273 0, NULL, false);
274 if (ret != EFI_SUCCESS)
275 goto err;
276
277 ret = efi_set_secure_state(0, 1, 1, 0);
278 if (ret != EFI_SUCCESS)
279 goto err;
280 } else if (mode == EFI_MODE_USER) {
281 ret = efi_set_secure_state(1, 0, 0, 0);
282 if (ret != EFI_SUCCESS)
283 goto err;
284 } else if (mode == EFI_MODE_SETUP) {
285 ret = efi_set_secure_state(0, 1, 0, 0);
286 if (ret != EFI_SUCCESS)
287 goto err;
288 } else {
289 return EFI_INVALID_PARAMETER;
290 }
291
292 efi_secure_mode = mode;
293
294 return EFI_SUCCESS;
295
296err:
297 /* TODO: What action should be taken here? */
298 printf("ERROR: Secure state transition failed\n");
299 return ret;
300}
301
302efi_status_t efi_init_secure_state(void)
303{
304 enum efi_secure_mode mode = EFI_MODE_SETUP;
305 u8 efi_vendor_keys = 0;
306 efi_uintn_t size = 0;
307 efi_status_t ret;
308
309 ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
310 NULL, &size, NULL, NULL);
311 if (ret == EFI_BUFFER_TOO_SMALL) {
312 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
313 mode = EFI_MODE_USER;
314 }
315
316 ret = efi_transfer_secure_state(mode);
317 if (ret != EFI_SUCCESS)
318 return ret;
319
320 /* As we do not provide vendor keys this variable is always 0. */
321 ret = efi_set_variable_int(L"VendorKeys",
322 &efi_global_variable_guid,
323 EFI_VARIABLE_BOOTSERVICE_ACCESS |
324 EFI_VARIABLE_RUNTIME_ACCESS |
325 EFI_VARIABLE_READ_ONLY,
326 sizeof(efi_vendor_keys),
327 &efi_vendor_keys, false);
328 return ret;
329}
330
331/**
332 * efi_secure_boot_enabled - return if secure boot is enabled or not
333 *
334 * Return: true if enabled, false if disabled
335 */
336bool efi_secure_boot_enabled(void)
337{
338 return efi_secure_boot;
339}
Heinrich Schuchardt99bfab82020-07-15 12:40:35 +0200340
341enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
342{
343 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
344 if (!u16_strcmp(name, name_type[i].name) &&
345 !guidcmp(guid, name_type[i].guid))
346 return name_type[i].type;
347 }
348 return EFI_AUTH_VAR_NONE;
349}
Ilias Apalodimas37c3ca52021-03-17 21:54:59 +0200350
351/**
352 * efi_get_var() - read value of an EFI variable
353 *
354 * @name: variable name
355 * @start: vendor GUID
356 * @size: size of allocated buffer
357 *
358 * Return: buffer with variable data or NULL
359 */
360void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
361{
362 efi_status_t ret;
363 void *buf = NULL;
364
365 *size = 0;
366 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
367 if (ret == EFI_BUFFER_TOO_SMALL) {
368 buf = malloc(*size);
369 if (!buf)
370 return NULL;
371 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
372 }
373
374 if (ret != EFI_SUCCESS) {
375 free(buf);
376 *size = 0;
377 return NULL;
378 }
379
380 return buf;
381}