1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * UEFI runtime variable services
4 *
5 * Copyright (c) 2020, Heinrich Schuchardt <xypron.glpk@gmx.de>
6 * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro
7 */
8
9 #include <common.h>
10 #include <efi_loader.h>
11 #include <efi_variable.h>
12 #include <stdlib.h>
13
14 enum efi_secure_mode {
15 EFI_MODE_SETUP,
16 EFI_MODE_USER,
17 EFI_MODE_AUDIT,
18 EFI_MODE_DEPLOYED,
19 };
20
21 struct 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
27 const efi_guid_t efi_guid_image_security_database =
28 EFI_IMAGE_SECURITY_DATABASE_GUID;
29
30 static 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 {u"dbt", &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
36 {u"dbr", &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
37 {u"AuditMode", &efi_global_variable_guid, EFI_AUTH_MODE},
38 {u"DeployedMode", &efi_global_variable_guid, EFI_AUTH_MODE},
39 };
40
41 static bool efi_secure_boot;
42 static enum efi_secure_mode efi_secure_mode;
43
44 /**
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 */
efi_get_variable(u16 * variable_name,const efi_guid_t * vendor,u32 * attributes,efi_uintn_t * data_size,void * data)59 efi_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\" %pUs %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 */
efi_set_variable(u16 * variable_name,const efi_guid_t * vendor,u32 attributes,efi_uintn_t data_size,const void * data)93 efi_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\" %pUs %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 }
111
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 */
efi_get_next_variable_name(efi_uintn_t * variable_name_size,u16 * variable_name,efi_guid_t * vendor)124 efi_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\" %pUs", 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 */
efi_query_variable_info(u32 attributes,u64 * maximum_variable_storage_size,u64 * remaining_variable_storage_size,u64 * maximum_variable_size)156 efi_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 if (!maximum_variable_storage_size ||
167 !remaining_variable_storage_size ||
168 !maximum_variable_size)
169 return EFI_EXIT(EFI_INVALID_PARAMETER);
170
171 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 }
178
179 efi_status_t __efi_runtime EFIAPI
efi_get_variable_runtime(u16 * variable_name,const efi_guid_t * guid,u32 * attributes,efi_uintn_t * data_size,void * data)180 efi_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
185 ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
186
187 /* Remove EFI_VARIABLE_READ_ONLY flag */
188 if (attributes)
189 *attributes &= EFI_VARIABLE_MASK;
190
191 return ret;
192 }
193
194 efi_status_t __efi_runtime EFIAPI
efi_get_next_variable_name_runtime(efi_uintn_t * variable_name_size,u16 * variable_name,efi_guid_t * guid)195 efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
196 u16 *variable_name, efi_guid_t *guid)
197 {
198 return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
199 }
200
201 /**
202 * efi_set_secure_state - modify secure boot state variables
203 * @secure_boot: value of SecureBoot
204 * @setup_mode: value of SetupMode
205 * @audit_mode: value of AuditMode
206 * @deployed_mode: value of DeployedMode
207 *
208 * Modify secure boot status related variables as indicated.
209 *
210 * Return: status code
211 */
efi_set_secure_state(u8 secure_boot,u8 setup_mode,u8 audit_mode,u8 deployed_mode)212 static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
213 u8 audit_mode, u8 deployed_mode)
214 {
215 efi_status_t ret;
216 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
217 EFI_VARIABLE_RUNTIME_ACCESS |
218 EFI_VARIABLE_READ_ONLY;
219 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
220 EFI_VARIABLE_RUNTIME_ACCESS;
221
222 efi_secure_boot = secure_boot;
223
224 ret = efi_set_variable_int(u"SecureBoot", &efi_global_variable_guid,
225 attributes_ro, sizeof(secure_boot),
226 &secure_boot, false);
227 if (ret != EFI_SUCCESS)
228 goto err;
229
230 ret = efi_set_variable_int(u"SetupMode", &efi_global_variable_guid,
231 attributes_ro, sizeof(setup_mode),
232 &setup_mode, false);
233 if (ret != EFI_SUCCESS)
234 goto err;
235
236 ret = efi_set_variable_int(u"AuditMode", &efi_global_variable_guid,
237 audit_mode || setup_mode ?
238 attributes_ro : attributes_rw,
239 sizeof(audit_mode), &audit_mode, false);
240 if (ret != EFI_SUCCESS)
241 goto err;
242
243 ret = efi_set_variable_int(u"DeployedMode",
244 &efi_global_variable_guid,
245 audit_mode || deployed_mode || setup_mode ?
246 attributes_ro : attributes_rw,
247 sizeof(deployed_mode), &deployed_mode,
248 false);
249 err:
250 return ret;
251 }
252
253 /**
254 * efi_transfer_secure_state - handle a secure boot state transition
255 * @mode: new state
256 *
257 * Depending on @mode, secure boot related variables are updated.
258 * Those variables are *read-only* for users, efi_set_variable_int()
259 * is called here.
260 *
261 * Return: status code
262 */
efi_transfer_secure_state(enum efi_secure_mode mode)263 static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
264 {
265 efi_status_t ret;
266
267 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
268 mode);
269
270 if (mode == EFI_MODE_DEPLOYED) {
271 ret = efi_set_secure_state(1, 0, 0, 1);
272 if (ret != EFI_SUCCESS)
273 goto err;
274 } else if (mode == EFI_MODE_AUDIT) {
275 ret = efi_set_variable_int(u"PK", &efi_global_variable_guid,
276 EFI_VARIABLE_BOOTSERVICE_ACCESS |
277 EFI_VARIABLE_RUNTIME_ACCESS,
278 0, NULL, false);
279 if (ret != EFI_SUCCESS)
280 goto err;
281
282 ret = efi_set_secure_state(0, 1, 1, 0);
283 if (ret != EFI_SUCCESS)
284 goto err;
285 } else if (mode == EFI_MODE_USER) {
286 ret = efi_set_secure_state(1, 0, 0, 0);
287 if (ret != EFI_SUCCESS)
288 goto err;
289 } else if (mode == EFI_MODE_SETUP) {
290 ret = efi_set_secure_state(0, 1, 0, 0);
291 if (ret != EFI_SUCCESS)
292 goto err;
293 } else {
294 return EFI_INVALID_PARAMETER;
295 }
296
297 efi_secure_mode = mode;
298
299 return EFI_SUCCESS;
300
301 err:
302 /* TODO: What action should be taken here? */
303 printf("ERROR: Secure state transition failed\n");
304 return ret;
305 }
306
efi_init_secure_state(void)307 efi_status_t efi_init_secure_state(void)
308 {
309 enum efi_secure_mode mode;
310 u8 efi_vendor_keys = 0;
311 efi_uintn_t size;
312 efi_status_t ret;
313 u8 deployed_mode = 0;
314 u8 audit_mode = 0;
315 u8 setup_mode = 1;
316
317 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
318 size = sizeof(deployed_mode);
319 ret = efi_get_variable_int(u"DeployedMode", &efi_global_variable_guid,
320 NULL, &size, &deployed_mode, NULL);
321 size = sizeof(audit_mode);
322 ret = efi_get_variable_int(u"AuditMode", &efi_global_variable_guid,
323 NULL, &size, &audit_mode, NULL);
324 size = 0;
325 ret = efi_get_variable_int(u"PK", &efi_global_variable_guid,
326 NULL, &size, NULL, NULL);
327 if (ret == EFI_BUFFER_TOO_SMALL) {
328 setup_mode = 0;
329 audit_mode = 0;
330 } else {
331 setup_mode = 1;
332 deployed_mode = 0;
333 }
334 }
335 if (deployed_mode)
336 mode = EFI_MODE_DEPLOYED;
337 else if (audit_mode)
338 mode = EFI_MODE_AUDIT;
339 else if (setup_mode)
340 mode = EFI_MODE_SETUP;
341 else
342 mode = EFI_MODE_USER;
343
344 ret = efi_transfer_secure_state(mode);
345 if (ret != EFI_SUCCESS)
346 return ret;
347
348 /* As we do not provide vendor keys this variable is always 0. */
349 ret = efi_set_variable_int(u"VendorKeys",
350 &efi_global_variable_guid,
351 EFI_VARIABLE_BOOTSERVICE_ACCESS |
352 EFI_VARIABLE_RUNTIME_ACCESS |
353 EFI_VARIABLE_READ_ONLY,
354 sizeof(efi_vendor_keys),
355 &efi_vendor_keys, false);
356 return ret;
357 }
358
359 /**
360 * efi_secure_boot_enabled - return if secure boot is enabled or not
361 *
362 * Return: true if enabled, false if disabled
363 */
efi_secure_boot_enabled(void)364 bool efi_secure_boot_enabled(void)
365 {
366 return efi_secure_boot;
367 }
368
efi_auth_var_get_type(const u16 * name,const efi_guid_t * guid)369 enum efi_auth_var_type efi_auth_var_get_type(const u16 *name,
370 const efi_guid_t *guid)
371 {
372 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
373 if (!u16_strcmp(name, name_type[i].name) &&
374 !guidcmp(guid, name_type[i].guid))
375 return name_type[i].type;
376 }
377 return EFI_AUTH_VAR_NONE;
378 }
379
efi_auth_var_get_guid(const u16 * name)380 const efi_guid_t *efi_auth_var_get_guid(const u16 *name)
381 {
382 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
383 if (!u16_strcmp(name, name_type[i].name))
384 return name_type[i].guid;
385 }
386 return &efi_global_variable_guid;
387 }
388
389 /**
390 * efi_get_var() - read value of an EFI variable
391 *
392 * @name: variable name
393 * @start: vendor GUID
394 * @size: size of allocated buffer
395 *
396 * Return: buffer with variable data or NULL
397 */
efi_get_var(const u16 * name,const efi_guid_t * vendor,efi_uintn_t * size)398 void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
399 {
400 efi_status_t ret;
401 void *buf = NULL;
402
403 *size = 0;
404 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
405 if (ret == EFI_BUFFER_TOO_SMALL) {
406 buf = malloc(*size);
407 if (!buf)
408 return NULL;
409 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
410 }
411
412 if (ret != EFI_SUCCESS) {
413 free(buf);
414 *size = 0;
415 return NULL;
416 }
417
418 return buf;
419 }
420