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 
13 enum efi_secure_mode {
14 	EFI_MODE_SETUP,
15 	EFI_MODE_USER,
16 	EFI_MODE_AUDIT,
17 	EFI_MODE_DEPLOYED,
18 };
19 
20 struct efi_auth_var_name_type {
21 	const u16 *name;
22 	const efi_guid_t *guid;
23 	const enum efi_auth_var_type type;
24 };
25 
26 static const struct efi_auth_var_name_type name_type[] = {
27 	{u"PK", &efi_global_variable_guid, EFI_AUTH_VAR_PK},
28 	{u"KEK", &efi_global_variable_guid, EFI_AUTH_VAR_KEK},
29 	{u"db",  &efi_guid_image_security_database, EFI_AUTH_VAR_DB},
30 	{u"dbx",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBX},
31 	/* not used yet
32 	{u"dbt",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBT},
33 	{u"dbr",  &efi_guid_image_security_database, EFI_AUTH_VAR_DBR},
34 	*/
35 };
36 
37 static bool efi_secure_boot;
38 static enum efi_secure_mode efi_secure_mode;
39 
40 /**
41  * efi_efi_get_variable() - retrieve value of a UEFI variable
42  *
43  * This function implements the GetVariable runtime service.
44  *
45  * See the Unified Extensible Firmware Interface (UEFI) specification for
46  * details.
47  *
48  * @variable_name:	name of the variable
49  * @vendor:		vendor GUID
50  * @attributes:		attributes of the variable
51  * @data_size:		size of the buffer to which the variable value is copied
52  * @data:		buffer to which the variable value is copied
53  * Return:		status code
54  */
efi_get_variable(u16 * variable_name,const efi_guid_t * vendor,u32 * attributes,efi_uintn_t * data_size,void * data)55 efi_status_t EFIAPI efi_get_variable(u16 *variable_name,
56 				     const efi_guid_t *vendor, u32 *attributes,
57 				     efi_uintn_t *data_size, void *data)
58 {
59 	efi_status_t ret;
60 
61 	EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes,
62 		  data_size, data);
63 
64 	ret = efi_get_variable_int(variable_name, vendor, attributes,
65 				   data_size, data, NULL);
66 
67 	/* Remove EFI_VARIABLE_READ_ONLY flag */
68 	if (attributes)
69 		*attributes &= EFI_VARIABLE_MASK;
70 
71 	return EFI_EXIT(ret);
72 }
73 
74 /**
75  * efi_set_variable() - set value of a UEFI variable
76  *
77  * This function implements the SetVariable runtime service.
78  *
79  * See the Unified Extensible Firmware Interface (UEFI) specification for
80  * details.
81  *
82  * @variable_name:	name of the variable
83  * @vendor:		vendor GUID
84  * @attributes:		attributes of the variable
85  * @data_size:		size of the buffer with the variable value
86  * @data:		buffer with the variable value
87  * Return:		status code
88  */
efi_set_variable(u16 * variable_name,const efi_guid_t * vendor,u32 attributes,efi_uintn_t data_size,const void * data)89 efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
90 				     const efi_guid_t *vendor, u32 attributes,
91 				     efi_uintn_t data_size, const void *data)
92 {
93 	efi_status_t ret;
94 
95 	EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
96 		  data_size, data);
97 
98 	/* Make sure that the EFI_VARIABLE_READ_ONLY flag is not set */
99 	if (attributes & ~(u32)EFI_VARIABLE_MASK)
100 		ret = EFI_INVALID_PARAMETER;
101 	else
102 		ret = efi_set_variable_int(variable_name, vendor, attributes,
103 					   data_size, data, true);
104 
105 	return EFI_EXIT(ret);
106 }
107 
108 /**
109  * efi_get_next_variable_name() - enumerate the current variable names
110  *
111  * @variable_name_size:	size of variable_name buffer in byte
112  * @variable_name:	name of uefi variable's name in u16
113  * @vendor:		vendor's guid
114  *
115  * See the Unified Extensible Firmware Interface (UEFI) specification for
116  * details.
117  *
118  * Return: status code
119  */
efi_get_next_variable_name(efi_uintn_t * variable_name_size,u16 * variable_name,efi_guid_t * vendor)120 efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
121 					       u16 *variable_name,
122 					       efi_guid_t *vendor)
123 {
124 	efi_status_t ret;
125 
126 	EFI_ENTRY("%p \"%ls\" %pUl", variable_name_size, variable_name, vendor);
127 
128 	ret = efi_get_next_variable_name_int(variable_name_size, variable_name,
129 					     vendor);
130 
131 	return EFI_EXIT(ret);
132 }
133 
134 /**
135  * efi_query_variable_info() - get information about EFI variables
136  *
137  * This function implements the QueryVariableInfo() runtime service.
138  *
139  * See the Unified Extensible Firmware Interface (UEFI) specification for
140  * details.
141  *
142  * @attributes:				bitmask to select variables to be
143  *					queried
144  * @maximum_variable_storage_size:	maximum size of storage area for the
145  *					selected variable types
146  * @remaining_variable_storage_size:	remaining size of storage are for the
147  *					selected variable types
148  * @maximum_variable_size:		maximum size of a variable of the
149  *					selected type
150  * Returns:				status code
151  */
efi_query_variable_info(u32 attributes,u64 * maximum_variable_storage_size,u64 * remaining_variable_storage_size,u64 * maximum_variable_size)152 efi_status_t EFIAPI efi_query_variable_info(
153 			u32 attributes, u64 *maximum_variable_storage_size,
154 			u64 *remaining_variable_storage_size,
155 			u64 *maximum_variable_size)
156 {
157 	efi_status_t ret;
158 
159 	EFI_ENTRY("%x %p %p %p", attributes, maximum_variable_storage_size,
160 		  remaining_variable_storage_size, maximum_variable_size);
161 
162 	ret = efi_query_variable_info_int(attributes,
163 					  maximum_variable_storage_size,
164 					  remaining_variable_storage_size,
165 					  maximum_variable_size);
166 
167 	return EFI_EXIT(ret);
168 }
169 
170 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)171 efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
172 			 u32 *attributes, efi_uintn_t *data_size, void *data)
173 {
174 	efi_status_t ret;
175 
176 	ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
177 
178 	/* Remove EFI_VARIABLE_READ_ONLY flag */
179 	if (attributes)
180 		*attributes &= EFI_VARIABLE_MASK;
181 
182 	return ret;
183 }
184 
185 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)186 efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
187 				   u16 *variable_name, efi_guid_t *guid)
188 {
189 	return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
190 }
191 
192 /**
193  * efi_set_secure_state - modify secure boot state variables
194  * @secure_boot:	value of SecureBoot
195  * @setup_mode:		value of SetupMode
196  * @audit_mode:		value of AuditMode
197  * @deployed_mode:	value of DeployedMode
198  *
199  * Modify secure boot status related variables as indicated.
200  *
201  * Return:		status code
202  */
efi_set_secure_state(u8 secure_boot,u8 setup_mode,u8 audit_mode,u8 deployed_mode)203 static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
204 					 u8 audit_mode, u8 deployed_mode)
205 {
206 	efi_status_t ret;
207 	const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
208 				  EFI_VARIABLE_RUNTIME_ACCESS |
209 				  EFI_VARIABLE_READ_ONLY;
210 	const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
211 				  EFI_VARIABLE_RUNTIME_ACCESS;
212 
213 	efi_secure_boot = secure_boot;
214 
215 	ret = efi_set_variable_int(L"SecureBoot", &efi_global_variable_guid,
216 				   attributes_ro, sizeof(secure_boot),
217 				   &secure_boot, false);
218 	if (ret != EFI_SUCCESS)
219 		goto err;
220 
221 	ret = efi_set_variable_int(L"SetupMode", &efi_global_variable_guid,
222 				   attributes_ro, sizeof(setup_mode),
223 				   &setup_mode, false);
224 	if (ret != EFI_SUCCESS)
225 		goto err;
226 
227 	ret = efi_set_variable_int(L"AuditMode", &efi_global_variable_guid,
228 				   audit_mode || setup_mode ?
229 				   attributes_ro : attributes_rw,
230 				   sizeof(audit_mode), &audit_mode, false);
231 	if (ret != EFI_SUCCESS)
232 		goto err;
233 
234 	ret = efi_set_variable_int(L"DeployedMode",
235 				   &efi_global_variable_guid,
236 				   audit_mode || deployed_mode || setup_mode ?
237 				   attributes_ro : attributes_rw,
238 				   sizeof(deployed_mode), &deployed_mode,
239 				   false);
240 err:
241 	return ret;
242 }
243 
244 /**
245  * efi_transfer_secure_state - handle a secure boot state transition
246  * @mode:	new state
247  *
248  * Depending on @mode, secure boot related variables are updated.
249  * Those variables are *read-only* for users, efi_set_variable_int()
250  * is called here.
251  *
252  * Return:	status code
253  */
efi_transfer_secure_state(enum efi_secure_mode mode)254 static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
255 {
256 	efi_status_t ret;
257 
258 	EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
259 		  mode);
260 
261 	if (mode == EFI_MODE_DEPLOYED) {
262 		ret = efi_set_secure_state(1, 0, 0, 1);
263 		if (ret != EFI_SUCCESS)
264 			goto err;
265 	} else if (mode == EFI_MODE_AUDIT) {
266 		ret = efi_set_variable_int(L"PK", &efi_global_variable_guid,
267 					   EFI_VARIABLE_BOOTSERVICE_ACCESS |
268 					   EFI_VARIABLE_RUNTIME_ACCESS,
269 					   0, NULL, false);
270 		if (ret != EFI_SUCCESS)
271 			goto err;
272 
273 		ret = efi_set_secure_state(0, 1, 1, 0);
274 		if (ret != EFI_SUCCESS)
275 			goto err;
276 	} else if (mode == EFI_MODE_USER) {
277 		ret = efi_set_secure_state(1, 0, 0, 0);
278 		if (ret != EFI_SUCCESS)
279 			goto err;
280 	} else if (mode == EFI_MODE_SETUP) {
281 		ret = efi_set_secure_state(0, 1, 0, 0);
282 		if (ret != EFI_SUCCESS)
283 			goto err;
284 	} else {
285 		return EFI_INVALID_PARAMETER;
286 	}
287 
288 	efi_secure_mode = mode;
289 
290 	return EFI_SUCCESS;
291 
292 err:
293 	/* TODO: What action should be taken here? */
294 	printf("ERROR: Secure state transition failed\n");
295 	return ret;
296 }
297 
efi_init_secure_state(void)298 efi_status_t efi_init_secure_state(void)
299 {
300 	enum efi_secure_mode mode = EFI_MODE_SETUP;
301 	u8 efi_vendor_keys = 0;
302 	efi_uintn_t size = 0;
303 	efi_status_t ret;
304 
305 	ret = efi_get_variable_int(L"PK", &efi_global_variable_guid,
306 				   NULL, &size, NULL, NULL);
307 	if (ret == EFI_BUFFER_TOO_SMALL) {
308 		if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT))
309 			mode = EFI_MODE_USER;
310 	}
311 
312 	ret = efi_transfer_secure_state(mode);
313 	if (ret != EFI_SUCCESS)
314 		return ret;
315 
316 	/* As we do not provide vendor keys this variable is always 0. */
317 	ret = efi_set_variable_int(L"VendorKeys",
318 				   &efi_global_variable_guid,
319 				   EFI_VARIABLE_BOOTSERVICE_ACCESS |
320 				   EFI_VARIABLE_RUNTIME_ACCESS |
321 				   EFI_VARIABLE_READ_ONLY,
322 				   sizeof(efi_vendor_keys),
323 				   &efi_vendor_keys, false);
324 	return ret;
325 }
326 
327 /**
328  * efi_secure_boot_enabled - return if secure boot is enabled or not
329  *
330  * Return:	true if enabled, false if disabled
331  */
efi_secure_boot_enabled(void)332 bool efi_secure_boot_enabled(void)
333 {
334 	return efi_secure_boot;
335 }
336 
efi_auth_var_get_type(u16 * name,const efi_guid_t * guid)337 enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid)
338 {
339 	for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
340 		if (!u16_strcmp(name, name_type[i].name) &&
341 		    !guidcmp(guid, name_type[i].guid))
342 			return name_type[i].type;
343 	}
344 	return EFI_AUTH_VAR_NONE;
345 }
346