blob: efaba869ef21d88221ad8b4f7ffe55e391f77c45 [file] [log] [blame]
Tom Rini70df9d62018-05-07 17:02:21 -04001// SPDX-License-Identifier: GPL-2.0+
Rob Clark15f3d742017-09-13 18:05:37 -04002/*
Heinrich Schuchardtc69addd2020-03-19 17:15:18 +00003 * UEFI runtime variable services
Rob Clark15f3d742017-09-13 18:05:37 -04004 *
Heinrich Schuchardtc69addd2020-03-19 17:15:18 +00005 * Copyright (c) 2017 Rob Clark
Rob Clark15f3d742017-09-13 18:05:37 -04006 */
7
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +02008#include <common.h>
Rob Clark15f3d742017-09-13 18:05:37 -04009#include <efi_loader.h>
Simon Glassed38aef2020-05-10 11:40:03 -060010#include <env.h>
Simon Glass9d1f6192019-08-02 09:44:25 -060011#include <env_internal.h>
Heinrich Schuchardt147d5d32019-10-26 23:53:48 +020012#include <hexdump.h>
13#include <malloc.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090014#include <rtc.h>
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +010015#include <search.h>
Simon Glass6f044982020-05-10 11:39:52 -060016#include <uuid.h>
AKASHI Takahiro6ec67672020-04-21 09:38:17 +090017#include <crypto/pkcs7_parser.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060018#include <linux/bitops.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090019#include <linux/compat.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070020#include <u-boot/crc.h>
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090021
AKASHI Takahiroc78dc192020-04-14 11:51:42 +090022enum efi_secure_mode {
23 EFI_MODE_SETUP,
24 EFI_MODE_USER,
25 EFI_MODE_AUDIT,
26 EFI_MODE_DEPLOYED,
27};
28
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +090029static bool efi_secure_boot;
Heinrich Schuchardte422dcc2020-06-24 12:14:49 +020030static enum efi_secure_mode efi_secure_mode;
AKASHI Takahiro94b139a2020-04-14 11:51:43 +090031static u8 efi_vendor_keys;
Rob Clark15f3d742017-09-13 18:05:37 -040032
33#define READ_ONLY BIT(31)
34
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +020035static efi_status_t efi_get_variable_common(u16 *variable_name,
36 const efi_guid_t *vendor,
37 u32 *attributes,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +020038 efi_uintn_t *data_size, void *data,
39 u64 *timep);
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +020040
41static efi_status_t efi_set_variable_common(u16 *variable_name,
42 const efi_guid_t *vendor,
43 u32 attributes,
44 efi_uintn_t data_size,
45 const void *data,
46 bool ro_check);
47
Rob Clark15f3d742017-09-13 18:05:37 -040048/*
49 * Mapping between EFI variables and u-boot variables:
50 *
51 * efi_$guid_$varname = {attributes}(type)value
52 *
53 * For example:
54 *
55 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=
56 * "{ro,boot,run}(blob)0000000000000000"
57 * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=
58 * "(blob)00010000"
59 *
60 * The attributes are a comma separated list of these possible
61 * attributes:
62 *
63 * + ro - read-only
64 * + boot - boot-services access
65 * + run - runtime access
66 *
67 * NOTE: with current implementation, no variables are available after
68 * ExitBootServices, and all are persisted (if possible).
69 *
70 * If not specified, the attributes default to "{boot}".
71 *
72 * The required type is one of:
73 *
74 * + utf8 - raw utf8 string
75 * + blob - arbitrary length hex string
76 *
77 * Maybe a utf16 type would be useful to for a string value to be auto
78 * converted to utf16?
79 */
80
Heinrich Schuchardt44389cb2018-09-23 04:08:09 +020081#define PREFIX_LEN (strlen("efi_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_"))
Rob Clark15f3d742017-09-13 18:05:37 -040082
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +010083/**
84 * efi_to_native() - convert the UEFI variable name and vendor GUID to U-Boot
85 * variable name
86 *
87 * The U-Boot variable name is a concatenation of prefix 'efi', the hexstring
88 * encoded vendor GUID, and the UTF-8 encoded UEFI variable name separated by
89 * underscores, e.g. 'efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder'.
90 *
91 * @native: pointer to pointer to U-Boot variable name
92 * @variable_name: UEFI variable name
93 * @vendor: vendor GUID
94 * Return: status code
95 */
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +020096static efi_status_t efi_to_native(char **native, const u16 *variable_name,
Heinrich Schuchardte06ae192018-12-30 20:53:51 +010097 const efi_guid_t *vendor)
Rob Clark15f3d742017-09-13 18:05:37 -040098{
99 size_t len;
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200100 char *pos;
Rob Clark15f3d742017-09-13 18:05:37 -0400101
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200102 len = PREFIX_LEN + utf16_utf8_strlen(variable_name) + 1;
103 *native = malloc(len);
104 if (!*native)
105 return EFI_OUT_OF_RESOURCES;
Rob Clark15f3d742017-09-13 18:05:37 -0400106
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200107 pos = *native;
108 pos += sprintf(pos, "efi_%pUl_", vendor);
109 utf16_utf8_strcpy(&pos, variable_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400110
111 return EFI_SUCCESS;
112}
113
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100114/**
115 * prefix() - skip over prefix
116 *
117 * Skip over a prefix string.
118 *
119 * @str: string with prefix
120 * @prefix: prefix string
121 * Return: string without prefix, or NULL if prefix not found
122 */
Rob Clark15f3d742017-09-13 18:05:37 -0400123static const char *prefix(const char *str, const char *prefix)
124{
125 size_t n = strlen(prefix);
126 if (!strncmp(prefix, str, n))
127 return str + n;
128 return NULL;
129}
130
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100131/**
132 * parse_attr() - decode attributes part of variable value
133 *
134 * Convert the string encoded attributes of a UEFI variable to a bit mask.
135 * TODO: Several attributes are not supported.
136 *
137 * @str: value of U-Boot variable
138 * @attrp: pointer to UEFI attributes
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900139 * @timep: pointer to time attribute
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100140 * Return: pointer to remainder of U-Boot variable value
141 */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900142static const char *parse_attr(const char *str, u32 *attrp, u64 *timep)
Rob Clark15f3d742017-09-13 18:05:37 -0400143{
144 u32 attr = 0;
145 char sep = '{';
146
147 if (*str != '{') {
148 *attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;
149 return str;
150 }
151
152 while (*str == sep) {
153 const char *s;
154
155 str++;
156
157 if ((s = prefix(str, "ro"))) {
158 attr |= READ_ONLY;
AKASHI Takahiro7f334332019-06-04 15:52:06 +0900159 } else if ((s = prefix(str, "nv"))) {
160 attr |= EFI_VARIABLE_NON_VOLATILE;
Rob Clark15f3d742017-09-13 18:05:37 -0400161 } else if ((s = prefix(str, "boot"))) {
162 attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
163 } else if ((s = prefix(str, "run"))) {
164 attr |= EFI_VARIABLE_RUNTIME_ACCESS;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900165 } else if ((s = prefix(str, "time="))) {
166 attr |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
167 hex2bin((u8 *)timep, s, sizeof(*timep));
168 s += sizeof(*timep) * 2;
169 } else if (*str == '}') {
170 break;
Rob Clark15f3d742017-09-13 18:05:37 -0400171 } else {
172 printf("invalid attribute: %s\n", str);
173 break;
174 }
175
176 str = s;
177 sep = ',';
178 }
179
180 str++;
181
182 *attrp = attr;
183
184 return str;
185}
186
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900187/**
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900188 * efi_set_secure_state - modify secure boot state variables
Heinrich Schuchardtbae548c2020-06-24 12:38:00 +0200189 * @secure_boot: value of SecureBoot
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900190 * @setup_mode: value of SetupMode
191 * @audit_mode: value of AuditMode
192 * @deployed_mode: value of DeployedMode
193 *
Heinrich Schuchardtbae548c2020-06-24 12:38:00 +0200194 * Modify secure boot status related variables as indicated.
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900195 *
196 * Return: status code
197 */
Heinrich Schuchardtbae548c2020-06-24 12:38:00 +0200198static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
199 u8 audit_mode, u8 deployed_mode)
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900200{
201 u32 attributes;
202 efi_status_t ret;
203
204 attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS |
205 EFI_VARIABLE_RUNTIME_ACCESS |
206 READ_ONLY;
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200207 ret = efi_set_variable_common(L"SecureBoot", &efi_global_variable_guid,
Heinrich Schuchardtbae548c2020-06-24 12:38:00 +0200208 attributes, sizeof(secure_boot),
209 &secure_boot, false);
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900210 if (ret != EFI_SUCCESS)
211 goto err;
212
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200213 ret = efi_set_variable_common(L"SetupMode", &efi_global_variable_guid,
214 attributes, sizeof(setup_mode),
215 &setup_mode, false);
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900216 if (ret != EFI_SUCCESS)
217 goto err;
218
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200219 ret = efi_set_variable_common(L"AuditMode", &efi_global_variable_guid,
220 attributes, sizeof(audit_mode),
221 &audit_mode, false);
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900222 if (ret != EFI_SUCCESS)
223 goto err;
224
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200225 ret = efi_set_variable_common(L"DeployedMode",
226 &efi_global_variable_guid, attributes,
227 sizeof(deployed_mode), &deployed_mode,
228 false);
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900229err:
230 return ret;
231}
232
233/**
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900234 * efi_transfer_secure_state - handle a secure boot state transition
235 * @mode: new state
236 *
237 * Depending on @mode, secure boot related variables are updated.
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200238 * Those variables are *read-only* for users, efi_set_variable_common()
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900239 * is called here.
240 *
Heinrich Schuchardte2c43da2020-05-03 16:29:00 +0200241 * Return: status code
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900242 */
243static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
244{
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900245 efi_status_t ret;
246
AKASHI Takahiro37123732020-06-09 14:09:34 +0900247 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
248 mode);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900249
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900250 if (mode == EFI_MODE_DEPLOYED) {
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900251 ret = efi_set_secure_state(1, 0, 0, 1);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900252 if (ret != EFI_SUCCESS)
253 goto err;
254
255 efi_secure_boot = true;
256 } else if (mode == EFI_MODE_AUDIT) {
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200257 ret = efi_set_variable_common(L"PK", &efi_global_variable_guid,
258 EFI_VARIABLE_BOOTSERVICE_ACCESS |
259 EFI_VARIABLE_RUNTIME_ACCESS,
260 0, NULL, false);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900261 if (ret != EFI_SUCCESS)
262 goto err;
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900263
264 ret = efi_set_secure_state(0, 1, 1, 0);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900265 if (ret != EFI_SUCCESS)
266 goto err;
267
268 efi_secure_boot = true;
269 } else if (mode == EFI_MODE_USER) {
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900270 ret = efi_set_secure_state(1, 0, 0, 0);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900271 if (ret != EFI_SUCCESS)
272 goto err;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900273
274 efi_secure_boot = true;
275 } else if (mode == EFI_MODE_SETUP) {
AKASHI Takahirodae117a2020-04-21 09:39:20 +0900276 ret = efi_set_secure_state(0, 1, 0, 0);
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900277 if (ret != EFI_SUCCESS)
278 goto err;
279 } else {
280 return EFI_INVALID_PARAMETER;
281 }
282
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900283 efi_secure_mode = mode;
284
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900285 return EFI_SUCCESS;
286
287err:
288 /* TODO: What action should be taken here? */
289 printf("ERROR: Secure state transition failed\n");
290 return ret;
291}
292
293/**
294 * efi_init_secure_state - initialize secure boot state
295 *
Heinrich Schuchardte2c43da2020-05-03 16:29:00 +0200296 * Return: status code
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900297 */
298static efi_status_t efi_init_secure_state(void)
299{
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900300 enum efi_secure_mode mode;
301 efi_uintn_t size;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900302 efi_status_t ret;
303
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900304 /*
305 * TODO:
306 * Since there is currently no "platform-specific" installation
307 * method of Platform Key, we can't say if VendorKeys is 0 or 1
308 * precisely.
309 */
310
311 size = 0;
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +0200312 ret = efi_get_variable_common(L"PK", &efi_global_variable_guid,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +0200313 NULL, &size, NULL, NULL);
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900314 if (ret == EFI_BUFFER_TOO_SMALL) {
315 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
316 mode = EFI_MODE_USER;
317 else
318 mode = EFI_MODE_SETUP;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900319
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900320 efi_vendor_keys = 0;
321 } else if (ret == EFI_NOT_FOUND) {
322 mode = EFI_MODE_SETUP;
323 efi_vendor_keys = 1;
324 } else {
325 goto err;
326 }
327
328 ret = efi_transfer_secure_state(mode);
329 if (ret == EFI_SUCCESS)
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200330 ret = efi_set_variable_common(L"VendorKeys",
331 &efi_global_variable_guid,
332 EFI_VARIABLE_BOOTSERVICE_ACCESS |
333 EFI_VARIABLE_RUNTIME_ACCESS |
334 READ_ONLY,
335 sizeof(efi_vendor_keys),
336 &efi_vendor_keys, false);
AKASHI Takahiro94b139a2020-04-14 11:51:43 +0900337
338err:
AKASHI Takahiroc78dc192020-04-14 11:51:42 +0900339 return ret;
340}
341
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100342/**
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900343 * efi_secure_boot_enabled - return if secure boot is enabled or not
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100344 *
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900345 * Return: true if enabled, false if disabled
346 */
347bool efi_secure_boot_enabled(void)
348{
349 return efi_secure_boot;
350}
351
352#ifdef CONFIG_EFI_SECURE_BOOT
353static u8 pkcs7_hdr[] = {
354 /* SEQUENCE */
355 0x30, 0x82, 0x05, 0xc7,
356 /* OID: pkcs7-signedData */
357 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
358 /* Context Structured? */
359 0xa0, 0x82, 0x05, 0xb8,
360};
361
362/**
363 * efi_variable_parse_signature - parse a signature in variable
364 * @buf: Pointer to variable's value
365 * @buflen: Length of @buf
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100366 *
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900367 * Parse a signature embedded in variable's value and instantiate
368 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
369 * pkcs7's signedData, some header needed be prepended for correctly
370 * parsing authentication data, particularly for variable's.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100371 *
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900372 * Return: Pointer to pkcs7_message structure on success, NULL on error
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100373 */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900374static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
375 size_t buflen)
376{
377 u8 *ebuf;
378 size_t ebuflen, len;
379 struct pkcs7_message *msg;
380
381 /*
382 * This is the best assumption to check if the binary is
383 * already in a form of pkcs7's signedData.
384 */
385 if (buflen > sizeof(pkcs7_hdr) &&
386 !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
387 msg = pkcs7_parse_message(buf, buflen);
388 goto out;
389 }
390
391 /*
392 * Otherwise, we should add a dummy prefix sequence for pkcs7
393 * message parser to be able to process.
394 * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
395 * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
396 * TODO:
397 * The header should be composed in a more refined manner.
398 */
AKASHI Takahiro37123732020-06-09 14:09:34 +0900399 EFI_PRINT("Makeshift prefix added to authentication data\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900400 ebuflen = sizeof(pkcs7_hdr) + buflen;
401 if (ebuflen <= 0x7f) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900402 EFI_PRINT("Data is too short\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900403 return NULL;
404 }
405
406 ebuf = malloc(ebuflen);
407 if (!ebuf) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900408 EFI_PRINT("Out of memory\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900409 return NULL;
410 }
411
412 memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
413 memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
414 len = ebuflen - 4;
415 ebuf[2] = (len >> 8) & 0xff;
416 ebuf[3] = len & 0xff;
417 len = ebuflen - 0x13;
418 ebuf[0x11] = (len >> 8) & 0xff;
419 ebuf[0x12] = len & 0xff;
420
421 msg = pkcs7_parse_message(ebuf, ebuflen);
422
423 free(ebuf);
424
425out:
426 if (IS_ERR(msg))
427 return NULL;
428
429 return msg;
430}
431
432/**
433 * efi_variable_authenticate - authenticate a variable
434 * @variable: Variable name in u16
435 * @vendor: Guid of variable
436 * @data_size: Size of @data
437 * @data: Pointer to variable's value
438 * @given_attr: Attributes to be given at SetVariable()
439 * @env_attr: Attributes that an existing variable holds
440 * @time: signed time that an existing variable holds
441 *
442 * Called by efi_set_variable() to verify that the input is correct.
443 * Will replace the given data pointer with another that points to
444 * the actual data to store in the internal memory.
445 * On success, @data and @data_size will be replaced with variable's
446 * actual data, excluding authentication data, and its size, and variable's
447 * attributes and signed time will also be returned in @env_attr and @time,
448 * respectively.
449 *
Heinrich Schuchardte2c43da2020-05-03 16:29:00 +0200450 * Return: status code
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900451 */
452static efi_status_t efi_variable_authenticate(u16 *variable,
453 const efi_guid_t *vendor,
454 efi_uintn_t *data_size,
455 const void **data, u32 given_attr,
456 u32 *env_attr, u64 *time)
457{
458 const struct efi_variable_authentication_2 *auth;
459 struct efi_signature_store *truststore, *truststore2;
460 struct pkcs7_message *var_sig;
461 struct efi_image_regions *regs;
462 struct efi_time timestamp;
463 struct rtc_time tm;
464 u64 new_time;
465 efi_status_t ret;
466
467 var_sig = NULL;
468 truststore = NULL;
469 truststore2 = NULL;
470 regs = NULL;
471 ret = EFI_SECURITY_VIOLATION;
472
473 if (*data_size < sizeof(struct efi_variable_authentication_2))
474 goto err;
475
476 /* authentication data */
477 auth = *data;
478 if (*data_size < (sizeof(auth->time_stamp)
479 + auth->auth_info.hdr.dwLength))
480 goto err;
481
482 if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7))
483 goto err;
484
Heinrich Schuchardt7a76a3f2020-07-01 12:44:00 +0200485 memcpy(&timestamp, &auth->time_stamp, sizeof(timestamp));
486 if (timestamp.pad1 || timestamp.nanosecond || timestamp.timezone ||
487 timestamp.daylight || timestamp.pad2)
488 goto err;
489
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900490 *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;
491 *data_size -= (sizeof(auth->time_stamp)
492 + auth->auth_info.hdr.dwLength);
493
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900494 memset(&tm, 0, sizeof(tm));
495 tm.tm_year = timestamp.year;
496 tm.tm_mon = timestamp.month;
497 tm.tm_mday = timestamp.day;
498 tm.tm_hour = timestamp.hour;
499 tm.tm_min = timestamp.minute;
500 tm.tm_sec = timestamp.second;
501 new_time = rtc_mktime(&tm);
502
503 if (!efi_secure_boot_enabled()) {
504 /* finished checking */
505 *time = new_time;
506 return EFI_SUCCESS;
507 }
508
509 if (new_time <= *time)
510 goto err;
511
512 /* data to be digested */
513 regs = calloc(sizeof(*regs) + sizeof(struct image_region) * 5, 1);
514 if (!regs)
515 goto err;
516 regs->max = 5;
517 efi_image_region_add(regs, (uint8_t *)variable,
518 (uint8_t *)variable
519 + u16_strlen(variable) * sizeof(u16), 1);
520 efi_image_region_add(regs, (uint8_t *)vendor,
521 (uint8_t *)vendor + sizeof(*vendor), 1);
522 efi_image_region_add(regs, (uint8_t *)&given_attr,
523 (uint8_t *)&given_attr + sizeof(given_attr), 1);
524 efi_image_region_add(regs, (uint8_t *)&timestamp,
525 (uint8_t *)&timestamp + sizeof(timestamp), 1);
526 efi_image_region_add(regs, (uint8_t *)*data,
527 (uint8_t *)*data + *data_size, 1);
528
529 /* variable's signature list */
530 if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info))
531 goto err;
532 var_sig = efi_variable_parse_signature(auth->auth_info.cert_data,
533 auth->auth_info.hdr.dwLength
534 - sizeof(auth->auth_info));
Patrick Wildtcd8a55b2020-05-07 02:13:18 +0200535 if (!var_sig) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900536 EFI_PRINT("Parsing variable's signature failed\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900537 goto err;
538 }
539
540 /* signature database used for authentication */
541 if (u16_strcmp(variable, L"PK") == 0 ||
542 u16_strcmp(variable, L"KEK") == 0) {
543 /* with PK */
544 truststore = efi_sigstore_parse_sigdb(L"PK");
545 if (!truststore)
546 goto err;
547 } else if (u16_strcmp(variable, L"db") == 0 ||
548 u16_strcmp(variable, L"dbx") == 0) {
549 /* with PK and KEK */
550 truststore = efi_sigstore_parse_sigdb(L"KEK");
551 truststore2 = efi_sigstore_parse_sigdb(L"PK");
552
553 if (!truststore) {
554 if (!truststore2)
555 goto err;
556
557 truststore = truststore2;
558 truststore2 = NULL;
559 }
560 } else {
561 /* TODO: support private authenticated variables */
562 goto err;
563 }
564
565 /* verify signature */
566 if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900567 EFI_PRINT("Verified\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900568 } else {
569 if (truststore2 &&
570 efi_signature_verify_with_sigdb(regs, var_sig,
571 truststore2, NULL)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900572 EFI_PRINT("Verified\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900573 } else {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900574 EFI_PRINT("Verifying variable's signature failed\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900575 goto err;
576 }
577 }
578
579 /* finished checking */
Heinrich Schuchardt5106dc72020-06-30 12:02:14 +0200580 *time = new_time;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900581 ret = EFI_SUCCESS;
582
583err:
584 efi_sigstore_free(truststore);
585 efi_sigstore_free(truststore2);
586 pkcs7_free_message(var_sig);
587 free(regs);
588
589 return ret;
590}
591#else
592static efi_status_t efi_variable_authenticate(u16 *variable,
593 const efi_guid_t *vendor,
594 efi_uintn_t *data_size,
595 const void **data, u32 given_attr,
596 u32 *env_attr, u64 *time)
597{
598 return EFI_SUCCESS;
599}
600#endif /* CONFIG_EFI_SECURE_BOOT */
601
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +0200602static efi_status_t efi_get_variable_common(u16 *variable_name,
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900603 const efi_guid_t *vendor,
604 u32 *attributes,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +0200605 efi_uintn_t *data_size, void *data,
606 u64 *timep)
Rob Clark15f3d742017-09-13 18:05:37 -0400607{
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200608 char *native_name;
Rob Clark15f3d742017-09-13 18:05:37 -0400609 efi_status_t ret;
610 unsigned long in_size;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900611 const char *val = NULL, *s;
612 u64 time = 0;
Rob Clark15f3d742017-09-13 18:05:37 -0400613 u32 attr;
614
Rob Clark15f3d742017-09-13 18:05:37 -0400615 if (!variable_name || !vendor || !data_size)
Heinrich Schuchardt563e5522020-06-29 11:49:58 +0200616 return EFI_INVALID_PARAMETER;
Rob Clark15f3d742017-09-13 18:05:37 -0400617
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200618 ret = efi_to_native(&native_name, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400619 if (ret)
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900620 return ret;
Rob Clark15f3d742017-09-13 18:05:37 -0400621
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200622 EFI_PRINT("get '%s'\n", native_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400623
624 val = env_get(native_name);
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200625 free(native_name);
Rob Clark15f3d742017-09-13 18:05:37 -0400626 if (!val)
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900627 return EFI_NOT_FOUND;
Rob Clark15f3d742017-09-13 18:05:37 -0400628
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900629 val = parse_attr(val, &attr, &time);
Rob Clark15f3d742017-09-13 18:05:37 -0400630
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +0200631 if (timep)
632 *timep = time;
633
Rob Clark15f3d742017-09-13 18:05:37 -0400634 in_size = *data_size;
635
636 if ((s = prefix(val, "(blob)"))) {
Heinrich Schuchardt2d8aedc2019-01-18 12:31:54 +0100637 size_t len = strlen(s);
Rob Clark15f3d742017-09-13 18:05:37 -0400638
Ivan Gorinovd3ea6b72018-05-11 13:18:25 -0700639 /* number of hexadecimal digits must be even */
640 if (len & 1)
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900641 return EFI_DEVICE_ERROR;
Ivan Gorinovd3ea6b72018-05-11 13:18:25 -0700642
Rob Clark15f3d742017-09-13 18:05:37 -0400643 /* two characters per byte: */
Ivan Gorinovd3ea6b72018-05-11 13:18:25 -0700644 len /= 2;
Rob Clark15f3d742017-09-13 18:05:37 -0400645 *data_size = len;
646
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200647 if (in_size < len) {
648 ret = EFI_BUFFER_TOO_SMALL;
649 goto out;
650 }
Rob Clark15f3d742017-09-13 18:05:37 -0400651
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900652 if (!data) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900653 EFI_PRINT("Variable with no data shouldn't exist.\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900654 return EFI_INVALID_PARAMETER;
655 }
Rob Clark15f3d742017-09-13 18:05:37 -0400656
Heinrich Schuchardt2d8aedc2019-01-18 12:31:54 +0100657 if (hex2bin(data, s, len))
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900658 return EFI_DEVICE_ERROR;
Rob Clark15f3d742017-09-13 18:05:37 -0400659
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200660 EFI_PRINT("got value: \"%s\"\n", s);
Rob Clark15f3d742017-09-13 18:05:37 -0400661 } else if ((s = prefix(val, "(utf8)"))) {
662 unsigned len = strlen(s) + 1;
663
664 *data_size = len;
665
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200666 if (in_size < len) {
667 ret = EFI_BUFFER_TOO_SMALL;
668 goto out;
669 }
Rob Clark15f3d742017-09-13 18:05:37 -0400670
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900671 if (!data) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900672 EFI_PRINT("Variable with no data shouldn't exist.\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900673 return EFI_INVALID_PARAMETER;
674 }
Rob Clark15f3d742017-09-13 18:05:37 -0400675
676 memcpy(data, s, len);
677 ((char *)data)[len] = '\0';
678
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200679 EFI_PRINT("got value: \"%s\"\n", (char *)data);
Rob Clark15f3d742017-09-13 18:05:37 -0400680 } else {
Heinrich Schuchardt55111c32019-04-04 21:36:44 +0200681 EFI_PRINT("invalid value: '%s'\n", val);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900682 return EFI_DEVICE_ERROR;
Rob Clark15f3d742017-09-13 18:05:37 -0400683 }
684
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200685out:
Rob Clark15f3d742017-09-13 18:05:37 -0400686 if (attributes)
687 *attributes = attr & EFI_VARIABLE_MASK;
688
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900689 return ret;
690}
691
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900692/**
693 * efi_efi_get_variable() - retrieve value of a UEFI variable
694 *
695 * This function implements the GetVariable runtime service.
696 *
697 * See the Unified Extensible Firmware Interface (UEFI) specification for
698 * details.
699 *
700 * @variable_name: name of the variable
701 * @vendor: vendor GUID
702 * @attributes: attributes of the variable
703 * @data_size: size of the buffer to which the variable value is copied
704 * @data: buffer to which the variable value is copied
705 * Return: status code
706 */
707efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
708 const efi_guid_t *vendor, u32 *attributes,
709 efi_uintn_t *data_size, void *data)
710{
711 efi_status_t ret;
712
713 EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
714 data_size, data);
715
Heinrich Schuchardt87ab0b22020-04-18 12:31:17 +0200716 ret = efi_get_variable_common(variable_name, vendor, attributes,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +0200717 data_size, data, NULL);
Heinrich Schuchardt05f728f2019-05-15 19:32:43 +0200718 return EFI_EXIT(ret);
Rob Clark15f3d742017-09-13 18:05:37 -0400719}
720
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100721static char *efi_variables_list;
722static char *efi_cur_variable;
723
724/**
725 * parse_uboot_variable() - parse a u-boot variable and get uefi-related
726 * information
727 * @variable: whole data of u-boot variable (ie. name=value)
728 * @variable_name_size: size of variable_name buffer in byte
729 * @variable_name: name of uefi variable in u16, null-terminated
730 * @vendor: vendor's guid
731 * @attributes: attributes
732 *
733 * A uefi variable is encoded into a u-boot variable as described above.
734 * This function parses such a u-boot variable and retrieve uefi-related
735 * information into respective parameters. In return, variable_name_size
736 * is the size of variable name including NULL.
737 *
738 * Return: EFI_SUCCESS if parsing is OK, EFI_NOT_FOUND when
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200739 * the entire variable list has been returned,
740 * otherwise non-zero status code
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100741 */
742static efi_status_t parse_uboot_variable(char *variable,
743 efi_uintn_t *variable_name_size,
744 u16 *variable_name,
745 const efi_guid_t *vendor,
746 u32 *attributes)
747{
748 char *guid, *name, *end, c;
Heinrich Schuchardt31d9b3a2020-03-20 19:04:34 +0100749 size_t name_len;
750 efi_uintn_t old_variable_name_size;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900751 u64 time;
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100752 u16 *p;
753
754 guid = strchr(variable, '_');
755 if (!guid)
756 return EFI_INVALID_PARAMETER;
757 guid++;
758 name = strchr(guid, '_');
759 if (!name)
760 return EFI_INVALID_PARAMETER;
761 name++;
762 end = strchr(name, '=');
763 if (!end)
764 return EFI_INVALID_PARAMETER;
765
766 name_len = end - name;
Heinrich Schuchardt31d9b3a2020-03-20 19:04:34 +0100767 old_variable_name_size = *variable_name_size;
768 *variable_name_size = sizeof(u16) * (name_len + 1);
769 if (old_variable_name_size < *variable_name_size)
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100770 return EFI_BUFFER_TOO_SMALL;
Heinrich Schuchardt31d9b3a2020-03-20 19:04:34 +0100771
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100772 end++; /* point to value */
773
774 /* variable name */
775 p = variable_name;
776 utf8_utf16_strncpy(&p, name, name_len);
777 variable_name[name_len] = 0;
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100778
779 /* guid */
780 c = *(name - 1);
781 *(name - 1) = '\0'; /* guid need be null-terminated here */
AKASHI Takahiro4854f782020-05-08 14:51:21 +0900782 if (uuid_str_to_bin(guid, (unsigned char *)vendor,
783 UUID_STR_FORMAT_GUID))
784 /* The only error would be EINVAL. */
785 return EFI_INVALID_PARAMETER;
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100786 *(name - 1) = c;
787
788 /* attributes */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900789 parse_attr(end, attributes, &time);
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100790
791 return EFI_SUCCESS;
792}
793
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100794/**
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100795 * efi_get_next_variable_name() - enumerate the current variable names
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200796 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100797 * @variable_name_size: size of variable_name buffer in byte
798 * @variable_name: name of uefi variable's name in u16
799 * @vendor: vendor's guid
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100800 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100801 * This function implements the GetNextVariableName service.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100802 *
803 * See the Unified Extensible Firmware Interface (UEFI) specification for
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +0200804 * details.
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100805 *
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100806 * Return: status code
Heinrich Schuchardt0ffda472019-01-18 19:52:05 +0100807 */
Heinrich Schuchardtd6a6baa2018-05-17 07:57:05 +0200808efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
809 u16 *variable_name,
Heinrich Schuchardt82cd6c42020-03-22 18:28:20 +0100810 efi_guid_t *vendor)
Rob Clark15f3d742017-09-13 18:05:37 -0400811{
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100812 char *native_name, *variable;
813 ssize_t name_len, list_len;
814 char regex[256];
815 char * const regexlist[] = {regex};
816 u32 attributes;
817 int i;
818 efi_status_t ret;
819
Rob Clark238f88c2017-09-13 18:05:41 -0400820 EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400821
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100822 if (!variable_name_size || !variable_name || !vendor)
Heinrich Schuchardt793a6252019-03-19 18:36:21 +0100823 return EFI_EXIT(EFI_INVALID_PARAMETER);
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100824
825 if (variable_name[0]) {
826 /* check null-terminated string */
827 for (i = 0; i < *variable_name_size; i++)
828 if (!variable_name[i])
829 break;
830 if (i >= *variable_name_size)
831 return EFI_EXIT(EFI_INVALID_PARAMETER);
832
833 /* search for the last-returned variable */
834 ret = efi_to_native(&native_name, variable_name, vendor);
835 if (ret)
836 return EFI_EXIT(ret);
837
838 name_len = strlen(native_name);
839 for (variable = efi_variables_list; variable && *variable;) {
840 if (!strncmp(variable, native_name, name_len) &&
841 variable[name_len] == '=')
842 break;
843
844 variable = strchr(variable, '\n');
845 if (variable)
846 variable++;
847 }
848
849 free(native_name);
850 if (!(variable && *variable))
851 return EFI_EXIT(EFI_INVALID_PARAMETER);
852
853 /* next variable */
854 variable = strchr(variable, '\n');
855 if (variable)
856 variable++;
857 if (!(variable && *variable))
858 return EFI_EXIT(EFI_NOT_FOUND);
859 } else {
860 /*
861 *new search: free a list used in the previous search
862 */
863 free(efi_variables_list);
864 efi_variables_list = NULL;
865 efi_cur_variable = NULL;
866
867 snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_.*");
868 list_len = hexport_r(&env_htab, '\n',
869 H_MATCH_REGEX | H_MATCH_KEY,
870 &efi_variables_list, 0, 1, regexlist);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900871
Heinrich Schuchardtfd738482019-01-22 20:10:46 +0100872 if (list_len <= 1)
AKASHI Takahiroad3f36c2019-01-21 12:43:13 +0100873 return EFI_EXIT(EFI_NOT_FOUND);
874
875 variable = efi_variables_list;
876 }
877
878 ret = parse_uboot_variable(variable, variable_name_size, variable_name,
879 vendor, &attributes);
880
881 return EFI_EXIT(ret);
Rob Clark15f3d742017-09-13 18:05:37 -0400882}
883
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200884static efi_status_t efi_set_variable_common(u16 *variable_name,
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900885 const efi_guid_t *vendor,
886 u32 attributes,
887 efi_uintn_t data_size,
888 const void *data,
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +0200889 bool ro_check)
Rob Clark15f3d742017-09-13 18:05:37 -0400890{
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900891 char *native_name = NULL, *old_data = NULL, *val = NULL, *s;
892 efi_uintn_t old_size;
893 bool append, delete;
894 u64 time = 0;
Rob Clark15f3d742017-09-13 18:05:37 -0400895 u32 attr;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900896 efi_status_t ret = EFI_SUCCESS;
Rob Clark15f3d742017-09-13 18:05:37 -0400897
Heinrich Schuchardtadba3962019-06-12 23:28:42 +0200898 if (!variable_name || !*variable_name || !vendor ||
899 ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900900 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200901 ret = EFI_INVALID_PARAMETER;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900902 goto err;
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200903 }
Rob Clark15f3d742017-09-13 18:05:37 -0400904
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +0200905 ret = efi_to_native(&native_name, variable_name, vendor);
Rob Clark15f3d742017-09-13 18:05:37 -0400906 if (ret)
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900907 goto err;
Rob Clark15f3d742017-09-13 18:05:37 -0400908
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900909 /* check if a variable exists */
910 old_size = 0;
911 attr = 0;
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +0200912 ret = efi_get_variable_common(variable_name, vendor, &attr,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +0200913 &old_size, NULL, &time);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900914 append = !!(attributes & EFI_VARIABLE_APPEND_WRITE);
915 attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE;
916 delete = !append && (!data_size || !attributes);
917
918 /* check attributes */
919 if (old_size) {
920 if (ro_check && (attr & READ_ONLY)) {
921 ret = EFI_WRITE_PROTECTED;
922 goto err;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900923 }
924
925 /* attributes won't be changed */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900926 if (!delete &&
927 ((ro_check && attr != attributes) ||
928 (!ro_check && ((attr & ~(u32)READ_ONLY)
929 != (attributes & ~(u32)READ_ONLY))))) {
AKASHI Takahiro186b5a42019-05-24 15:59:03 +0900930 ret = EFI_INVALID_PARAMETER;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900931 goto err;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900932 }
933 } else {
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900934 if (delete || append) {
Heinrich Schuchardt8021bbe2019-09-26 21:40:18 +0200935 /*
936 * Trying to delete or to update a non-existent
937 * variable.
938 */
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900939 ret = EFI_NOT_FOUND;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900940 goto err;
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900941 }
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900942 }
AKASHI Takahiroe5023b72019-09-06 15:09:52 +0900943
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900944 if (((!u16_strcmp(variable_name, L"PK") ||
945 !u16_strcmp(variable_name, L"KEK")) &&
946 !guidcmp(vendor, &efi_global_variable_guid)) ||
947 ((!u16_strcmp(variable_name, L"db") ||
948 !u16_strcmp(variable_name, L"dbx")) &&
949 !guidcmp(vendor, &efi_guid_image_security_database))) {
950 /* authentication is mandatory */
951 if (!(attributes &
952 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900953 EFI_PRINT("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
954 variable_name);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900955 ret = EFI_INVALID_PARAMETER;
956 goto err;
957 }
958 }
959
960 /* authenticate a variable */
961 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
962 if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) {
963 ret = EFI_INVALID_PARAMETER;
964 goto err;
965 }
966 if (attributes &
967 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
968 ret = efi_variable_authenticate(variable_name, vendor,
969 &data_size, &data,
970 attributes, &attr,
971 &time);
972 if (ret != EFI_SUCCESS)
973 goto err;
974
975 /* last chance to check for delete */
976 if (!data_size)
977 delete = true;
978 }
979 } else {
980 if (attributes &
981 (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
982 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
AKASHI Takahiro37123732020-06-09 14:09:34 +0900983 EFI_PRINT("Secure boot is not configured\n");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +0900984 ret = EFI_INVALID_PARAMETER;
985 goto err;
986 }
987 }
988
989 /* delete a variable */
990 if (delete) {
991 /* !old_size case has been handled before */
992 val = NULL;
993 ret = EFI_SUCCESS;
994 goto out;
995 }
996
997 if (append) {
998 old_data = malloc(old_size);
999 if (!old_data) {
Heinrich Schuchardtebbda7b2020-05-06 01:37:25 +02001000 ret = EFI_OUT_OF_RESOURCES;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001001 goto err;
1002 }
Heinrich Schuchardtda0a7912020-05-06 01:51:04 +02001003 ret = efi_get_variable_common(variable_name, vendor,
Heinrich Schuchardt2db39ef2020-07-01 15:32:47 +02001004 &attr, &old_size, old_data, NULL);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001005 if (ret != EFI_SUCCESS)
1006 goto err;
1007 } else {
AKASHI Takahiroe5023b72019-09-06 15:09:52 +09001008 old_size = 0;
Rob Clark15f3d742017-09-13 18:05:37 -04001009 }
1010
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001011 val = malloc(2 * old_size + 2 * data_size
1012 + strlen("{ro,run,boot,nv,time=0123456701234567}(blob)")
1013 + 1);
Heinrich Schuchardtbd095f52018-10-02 05:30:05 +02001014 if (!val) {
1015 ret = EFI_OUT_OF_RESOURCES;
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001016 goto err;
Heinrich Schuchardtbd095f52018-10-02 05:30:05 +02001017 }
Rob Clark15f3d742017-09-13 18:05:37 -04001018
1019 s = val;
1020
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001021 /*
1022 * store attributes
1023 */
1024 attributes &= (READ_ONLY |
1025 EFI_VARIABLE_NON_VOLATILE |
AKASHI Takahiro7f334332019-06-04 15:52:06 +09001026 EFI_VARIABLE_BOOTSERVICE_ACCESS |
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001027 EFI_VARIABLE_RUNTIME_ACCESS |
1028 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS);
Rob Clark15f3d742017-09-13 18:05:37 -04001029 s += sprintf(s, "{");
1030 while (attributes) {
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001031 attr = 1 << (ffs(attributes) - 1);
Rob Clark15f3d742017-09-13 18:05:37 -04001032
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001033 if (attr == READ_ONLY) {
1034 s += sprintf(s, "ro");
1035 } else if (attr == EFI_VARIABLE_NON_VOLATILE) {
AKASHI Takahiro7f334332019-06-04 15:52:06 +09001036 s += sprintf(s, "nv");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001037 } else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) {
Rob Clark15f3d742017-09-13 18:05:37 -04001038 s += sprintf(s, "boot");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001039 } else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) {
Rob Clark15f3d742017-09-13 18:05:37 -04001040 s += sprintf(s, "run");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001041 } else if (attr ==
1042 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
1043 s += sprintf(s, "time=");
1044 s = bin2hex(s, (u8 *)&time, sizeof(time));
1045 }
Rob Clark15f3d742017-09-13 18:05:37 -04001046
1047 attributes &= ~attr;
1048 if (attributes)
1049 s += sprintf(s, ",");
1050 }
1051 s += sprintf(s, "}");
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001052 s += sprintf(s, "(blob)");
AKASHI Takahiroe5023b72019-09-06 15:09:52 +09001053
Rob Clark15f3d742017-09-13 18:05:37 -04001054 /* store payload: */
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001055 if (append)
1056 s = bin2hex(s, old_data, old_size);
Heinrich Schuchardt807899d2019-01-18 18:54:26 +01001057 s = bin2hex(s, data, data_size);
Rob Clark15f3d742017-09-13 18:05:37 -04001058 *s = '\0';
1059
Heinrich Schuchardt55111c32019-04-04 21:36:44 +02001060 EFI_PRINT("setting: %s=%s\n", native_name, val);
Rob Clark15f3d742017-09-13 18:05:37 -04001061
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001062out:
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001063 if (env_set(native_name, val)) {
Rob Clark15f3d742017-09-13 18:05:37 -04001064 ret = EFI_DEVICE_ERROR;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001065 } else {
AKASHI Takahiro94b139a2020-04-14 11:51:43 +09001066 bool vendor_keys_modified = false;
1067
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001068 if ((u16_strcmp(variable_name, L"PK") == 0 &&
1069 guidcmp(vendor, &efi_global_variable_guid) == 0)) {
1070 ret = efi_transfer_secure_state(
1071 (delete ? EFI_MODE_SETUP :
1072 EFI_MODE_USER));
1073 if (ret != EFI_SUCCESS)
1074 goto err;
AKASHI Takahiro94b139a2020-04-14 11:51:43 +09001075
1076 if (efi_secure_mode != EFI_MODE_SETUP)
1077 vendor_keys_modified = true;
1078 } else if ((u16_strcmp(variable_name, L"KEK") == 0 &&
1079 guidcmp(vendor, &efi_global_variable_guid) == 0)) {
1080 if (efi_secure_mode != EFI_MODE_SETUP)
1081 vendor_keys_modified = true;
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001082 }
AKASHI Takahiro94b139a2020-04-14 11:51:43 +09001083
1084 /* update VendorKeys */
1085 if (vendor_keys_modified & efi_vendor_keys) {
1086 efi_vendor_keys = 0;
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +02001087 ret = efi_set_variable_common(
AKASHI Takahiro94b139a2020-04-14 11:51:43 +09001088 L"VendorKeys",
1089 &efi_global_variable_guid,
1090 EFI_VARIABLE_BOOTSERVICE_ACCESS
1091 | EFI_VARIABLE_RUNTIME_ACCESS
1092 | READ_ONLY,
1093 sizeof(efi_vendor_keys),
1094 &efi_vendor_keys,
1095 false);
1096 } else {
1097 ret = EFI_SUCCESS;
1098 }
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001099 }
Rob Clark15f3d742017-09-13 18:05:37 -04001100
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001101err:
Heinrich Schuchardtaf1a9202018-08-31 21:31:31 +02001102 free(native_name);
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001103 free(old_data);
Rob Clark15f3d742017-09-13 18:05:37 -04001104 free(val);
1105
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001106 return ret;
1107}
1108
AKASHI Takahirob0f49ee2020-04-14 11:51:41 +09001109/**
1110 * efi_set_variable() - set value of a UEFI variable
1111 *
1112 * This function implements the SetVariable runtime service.
1113 *
1114 * See the Unified Extensible Firmware Interface (UEFI) specification for
1115 * details.
1116 *
1117 * @variable_name: name of the variable
1118 * @vendor: vendor GUID
1119 * @attributes: attributes of the variable
1120 * @data_size: size of the buffer with the variable value
1121 * @data: buffer with the variable value
1122 * Return: status code
1123 */
1124efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
1125 const efi_guid_t *vendor, u32 attributes,
1126 efi_uintn_t data_size, const void *data)
1127{
1128 EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
1129 data_size, data);
1130
1131 /* READ_ONLY bit is not part of API */
1132 attributes &= ~(u32)READ_ONLY;
1133
Heinrich Schuchardt37ab7362020-05-03 10:02:20 +02001134 return EFI_EXIT(efi_set_variable_common(variable_name, vendor,
1135 attributes, data_size, data,
1136 true));
Rob Clark15f3d742017-09-13 18:05:37 -04001137}
Heinrich Schuchardt9b19dae2019-06-20 12:13:05 +02001138
1139/**
1140 * efi_query_variable_info() - get information about EFI variables
1141 *
1142 * This function implements the QueryVariableInfo() runtime service.
1143 *
1144 * See the Unified Extensible Firmware Interface (UEFI) specification for
1145 * details.
1146 *
1147 * @attributes: bitmask to select variables to be
1148 * queried
1149 * @maximum_variable_storage_size: maximum size of storage area for the
1150 * selected variable types
1151 * @remaining_variable_storage_size: remaining size of storage are for the
1152 * selected variable types
1153 * @maximum_variable_size: maximum size of a variable of the
1154 * selected type
1155 * Returns: status code
1156 */
1157efi_status_t __efi_runtime EFIAPI efi_query_variable_info(
1158 u32 attributes,
1159 u64 *maximum_variable_storage_size,
1160 u64 *remaining_variable_storage_size,
1161 u64 *maximum_variable_size)
1162{
1163 return EFI_UNSUPPORTED;
1164}
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +02001165
1166/**
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +02001167 * efi_get_variable_runtime() - runtime implementation of GetVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +02001168 *
1169 * @variable_name: name of the variable
1170 * @vendor: vendor GUID
1171 * @attributes: attributes of the variable
1172 * @data_size: size of the buffer to which the variable value is copied
1173 * @data: buffer to which the variable value is copied
1174 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +02001175 */
1176static efi_status_t __efi_runtime EFIAPI
1177efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1178 u32 *attributes, efi_uintn_t *data_size, void *data)
1179{
1180 return EFI_UNSUPPORTED;
1181}
1182
1183/**
1184 * efi_get_next_variable_name_runtime() - runtime implementation of
1185 * GetNextVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +02001186 *
1187 * @variable_name_size: size of variable_name buffer in byte
1188 * @variable_name: name of uefi variable's name in u16
1189 * @vendor: vendor's guid
1190 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +02001191 */
1192static efi_status_t __efi_runtime EFIAPI
1193efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
Heinrich Schuchardt82cd6c42020-03-22 18:28:20 +01001194 u16 *variable_name, efi_guid_t *vendor)
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +02001195{
1196 return EFI_UNSUPPORTED;
1197}
1198
1199/**
1200 * efi_set_variable_runtime() - runtime implementation of SetVariable()
Heinrich Schuchardtee1f0e42019-07-14 12:11:16 +02001201 *
1202 * @variable_name: name of the variable
1203 * @vendor: vendor GUID
1204 * @attributes: attributes of the variable
1205 * @data_size: size of the buffer with the variable value
1206 * @data: buffer with the variable value
1207 * Return: status code
Heinrich Schuchardt2ac62582019-06-20 15:25:48 +02001208 */
1209static efi_status_t __efi_runtime EFIAPI
1210efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
1211 u32 attributes, efi_uintn_t data_size,
1212 const void *data)
1213{
1214 return EFI_UNSUPPORTED;
1215}
1216
1217/**
1218 * efi_variables_boot_exit_notify() - notify ExitBootServices() is called
1219 */
1220void efi_variables_boot_exit_notify(void)
1221{
1222 efi_runtime_services.get_variable = efi_get_variable_runtime;
1223 efi_runtime_services.get_next_variable_name =
1224 efi_get_next_variable_name_runtime;
1225 efi_runtime_services.set_variable = efi_set_variable_runtime;
1226 efi_update_table_header_crc32(&efi_runtime_services.hdr);
1227}
1228
1229/**
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +02001230 * efi_init_variables() - initialize variable services
1231 *
1232 * Return: status code
1233 */
1234efi_status_t efi_init_variables(void)
1235{
AKASHI Takahiroc78dc192020-04-14 11:51:42 +09001236 efi_status_t ret;
1237
1238 ret = efi_init_secure_state();
1239
1240 return ret;
Heinrich Schuchardtcf3b1182019-06-20 13:52:16 +02001241}