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