efi_loader: update attribute check for QueryVariableInfo()
[platform/kernel/u-boot.git] / lib / efi_loader / efi_var_common.c
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  */
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  */
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  */
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  */
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
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
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  */
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  */
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
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  */
364 bool efi_secure_boot_enabled(void)
365 {
366         return efi_secure_boot;
367 }
368
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
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  */
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 }