1
2
3
4
5
6
7
8
9#include <common.h>
10#include <efi_loader.h>
11#include <efi_variable.h>
12
13enum efi_secure_mode {
14 EFI_MODE_SETUP,
15 EFI_MODE_USER,
16 EFI_MODE_AUDIT,
17 EFI_MODE_DEPLOYED,
18};
19
20struct 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
26static 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
32
33
34
35};
36
37static bool efi_secure_boot;
38static enum efi_secure_mode efi_secure_mode;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55efi_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
68 if (attributes)
69 *attributes &= EFI_VARIABLE_MASK;
70
71 return EFI_EXIT(ret);
72}
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89efi_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
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
110
111
112
113
114
115
116
117
118
119
120efi_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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152efi_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
170efi_status_t __efi_runtime EFIAPI
171efi_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
179 if (attributes)
180 *attributes &= EFI_VARIABLE_MASK;
181
182 return ret;
183}
184
185efi_status_t __efi_runtime EFIAPI
186efi_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
194
195
196
197
198
199
200
201
202
203static 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);
240err:
241 return ret;
242}
243
244
245
246
247
248
249
250
251
252
253
254static 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
292err:
293
294 printf("ERROR: Secure state transition failed\n");
295 return ret;
296}
297
298efi_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
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
329
330
331
332bool efi_secure_boot_enabled(void)
333{
334 return efi_secure_boot;
335}
336
337enum 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