1
2
3
4
5
6
7
8
9#include <common.h>
10#include <efi_loader.h>
11#include <efi_variable.h>
12#include <stdlib.h>
13
14enum efi_secure_mode {
15 EFI_MODE_SETUP,
16 EFI_MODE_USER,
17 EFI_MODE_AUDIT,
18 EFI_MODE_DEPLOYED,
19};
20
21struct 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
27const efi_guid_t efi_guid_image_security_database =
28 EFI_IMAGE_SECURITY_DATABASE_GUID;
29
30static 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
41static bool efi_secure_boot;
42static enum efi_secure_mode efi_secure_mode;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59efi_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
72 if (attributes)
73 *attributes &= EFI_VARIABLE_MASK;
74
75 return EFI_EXIT(ret);
76}
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93efi_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
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
114
115
116
117
118
119
120
121
122
123
124efi_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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156efi_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 !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))
170 return EFI_EXIT(EFI_INVALID_PARAMETER);
171
172 if ((attributes & ~(u32)EFI_VARIABLE_MASK) ||
173 (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) ||
174 (attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) ||
175 (!IS_ENABLED(CONFIG_EFI_SECURE_BOOT) &&
176 (attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)))
177 return EFI_EXIT(EFI_UNSUPPORTED);
178
179 ret = efi_query_variable_info_int(attributes,
180 maximum_variable_storage_size,
181 remaining_variable_storage_size,
182 maximum_variable_size);
183
184 return EFI_EXIT(ret);
185}
186
187efi_status_t __efi_runtime EFIAPI
188efi_get_variable_runtime(u16 *variable_name, const efi_guid_t *guid,
189 u32 *attributes, efi_uintn_t *data_size, void *data)
190{
191 efi_status_t ret;
192
193 ret = efi_get_variable_mem(variable_name, guid, attributes, data_size, data, NULL);
194
195
196 if (attributes)
197 *attributes &= EFI_VARIABLE_MASK;
198
199 return ret;
200}
201
202efi_status_t __efi_runtime EFIAPI
203efi_get_next_variable_name_runtime(efi_uintn_t *variable_name_size,
204 u16 *variable_name, efi_guid_t *guid)
205{
206 return efi_get_next_variable_name_mem(variable_name_size, variable_name, guid);
207}
208
209
210
211
212
213
214
215
216
217
218
219
220static efi_status_t efi_set_secure_state(u8 secure_boot, u8 setup_mode,
221 u8 audit_mode, u8 deployed_mode)
222{
223 efi_status_t ret;
224 const u32 attributes_ro = EFI_VARIABLE_BOOTSERVICE_ACCESS |
225 EFI_VARIABLE_RUNTIME_ACCESS |
226 EFI_VARIABLE_READ_ONLY;
227 const u32 attributes_rw = EFI_VARIABLE_BOOTSERVICE_ACCESS |
228 EFI_VARIABLE_RUNTIME_ACCESS;
229
230 efi_secure_boot = secure_boot;
231
232 ret = efi_set_variable_int(u"SecureBoot", &efi_global_variable_guid,
233 attributes_ro, sizeof(secure_boot),
234 &secure_boot, false);
235 if (ret != EFI_SUCCESS)
236 goto err;
237
238 ret = efi_set_variable_int(u"SetupMode", &efi_global_variable_guid,
239 attributes_ro, sizeof(setup_mode),
240 &setup_mode, false);
241 if (ret != EFI_SUCCESS)
242 goto err;
243
244 ret = efi_set_variable_int(u"AuditMode", &efi_global_variable_guid,
245 audit_mode || setup_mode ?
246 attributes_ro : attributes_rw,
247 sizeof(audit_mode), &audit_mode, false);
248 if (ret != EFI_SUCCESS)
249 goto err;
250
251 ret = efi_set_variable_int(u"DeployedMode",
252 &efi_global_variable_guid,
253 audit_mode || deployed_mode || setup_mode ?
254 attributes_ro : attributes_rw,
255 sizeof(deployed_mode), &deployed_mode,
256 false);
257err:
258 return ret;
259}
260
261
262
263
264
265
266
267
268
269
270
271static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
272{
273 efi_status_t ret;
274
275 EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
276 mode);
277
278 if (mode == EFI_MODE_DEPLOYED) {
279 ret = efi_set_secure_state(1, 0, 0, 1);
280 if (ret != EFI_SUCCESS)
281 goto err;
282 } else if (mode == EFI_MODE_AUDIT) {
283 ret = efi_set_variable_int(u"PK", &efi_global_variable_guid,
284 EFI_VARIABLE_BOOTSERVICE_ACCESS |
285 EFI_VARIABLE_RUNTIME_ACCESS,
286 0, NULL, false);
287 if (ret != EFI_SUCCESS)
288 goto err;
289
290 ret = efi_set_secure_state(0, 1, 1, 0);
291 if (ret != EFI_SUCCESS)
292 goto err;
293 } else if (mode == EFI_MODE_USER) {
294 ret = efi_set_secure_state(1, 0, 0, 0);
295 if (ret != EFI_SUCCESS)
296 goto err;
297 } else if (mode == EFI_MODE_SETUP) {
298 ret = efi_set_secure_state(0, 1, 0, 0);
299 if (ret != EFI_SUCCESS)
300 goto err;
301 } else {
302 return EFI_INVALID_PARAMETER;
303 }
304
305 efi_secure_mode = mode;
306
307 return EFI_SUCCESS;
308
309err:
310
311 printf("ERROR: Secure state transition failed\n");
312 return ret;
313}
314
315efi_status_t efi_init_secure_state(void)
316{
317 enum efi_secure_mode mode;
318 u8 efi_vendor_keys = 0;
319 efi_uintn_t size;
320 efi_status_t ret;
321 u8 deployed_mode = 0;
322 u8 audit_mode = 0;
323 u8 setup_mode = 1;
324
325 if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) {
326 size = sizeof(deployed_mode);
327 ret = efi_get_variable_int(u"DeployedMode", &efi_global_variable_guid,
328 NULL, &size, &deployed_mode, NULL);
329 size = sizeof(audit_mode);
330 ret = efi_get_variable_int(u"AuditMode", &efi_global_variable_guid,
331 NULL, &size, &audit_mode, NULL);
332 size = 0;
333 ret = efi_get_variable_int(u"PK", &efi_global_variable_guid,
334 NULL, &size, NULL, NULL);
335 if (ret == EFI_BUFFER_TOO_SMALL) {
336 setup_mode = 0;
337 audit_mode = 0;
338 } else {
339 setup_mode = 1;
340 deployed_mode = 0;
341 }
342 }
343 if (deployed_mode)
344 mode = EFI_MODE_DEPLOYED;
345 else if (audit_mode)
346 mode = EFI_MODE_AUDIT;
347 else if (setup_mode)
348 mode = EFI_MODE_SETUP;
349 else
350 mode = EFI_MODE_USER;
351
352 ret = efi_transfer_secure_state(mode);
353 if (ret != EFI_SUCCESS)
354 return ret;
355
356
357 ret = efi_set_variable_int(u"VendorKeys",
358 &efi_global_variable_guid,
359 EFI_VARIABLE_BOOTSERVICE_ACCESS |
360 EFI_VARIABLE_RUNTIME_ACCESS |
361 EFI_VARIABLE_READ_ONLY,
362 sizeof(efi_vendor_keys),
363 &efi_vendor_keys, false);
364 return ret;
365}
366
367
368
369
370
371
372bool efi_secure_boot_enabled(void)
373{
374 return efi_secure_boot;
375}
376
377enum efi_auth_var_type efi_auth_var_get_type(const u16 *name,
378 const efi_guid_t *guid)
379{
380 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
381 if (!u16_strcmp(name, name_type[i].name) &&
382 !guidcmp(guid, name_type[i].guid))
383 return name_type[i].type;
384 }
385 return EFI_AUTH_VAR_NONE;
386}
387
388const efi_guid_t *efi_auth_var_get_guid(const u16 *name)
389{
390 for (size_t i = 0; i < ARRAY_SIZE(name_type); ++i) {
391 if (!u16_strcmp(name, name_type[i].name))
392 return name_type[i].guid;
393 }
394 return &efi_global_variable_guid;
395}
396
397
398
399
400
401
402
403
404
405
406void *efi_get_var(const u16 *name, const efi_guid_t *vendor, efi_uintn_t *size)
407{
408 efi_status_t ret;
409 void *buf = NULL;
410
411 *size = 0;
412 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
413 if (ret == EFI_BUFFER_TOO_SMALL) {
414 buf = malloc(*size);
415 if (!buf)
416 return NULL;
417 ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL);
418 }
419
420 if (ret != EFI_SUCCESS) {
421 free(buf);
422 *size = 0;
423 return NULL;
424 }
425
426 return buf;
427}
428