1 /*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 *
4 * uefi vars device - AuthVariableLib
5 */
6
7 #include "qemu/osdep.h"
8 #include "qemu/error-report.h"
9 #include "system/dma.h"
10
11 #include "hw/uefi/var-service.h"
12
13 static const uint16_t name_pk[] = u"PK";
14 static const uint16_t name_kek[] = u"KEK";
15 static const uint16_t name_db[] = u"db";
16 static const uint16_t name_dbx[] = u"dbx";
17 static const uint16_t name_setup_mode[] = u"SetupMode";
18 static const uint16_t name_sigs_support[] = u"SignatureSupport";
19 static const uint16_t name_sb[] = u"SecureBoot";
20 static const uint16_t name_sb_enable[] = u"SecureBootEnable";
21 static const uint16_t name_custom_mode[] = u"CustomMode";
22 static const uint16_t name_vk[] = u"VendorKeys";
23 static const uint16_t name_vk_nv[] = u"VendorKeysNv";
24
25 static const uint32_t sigdb_attrs =
26 EFI_VARIABLE_NON_VOLATILE |
27 EFI_VARIABLE_BOOTSERVICE_ACCESS |
28 EFI_VARIABLE_RUNTIME_ACCESS |
29 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
30
set_secure_boot(uefi_vars_state * uv,uint8_t sb)31 static void set_secure_boot(uefi_vars_state *uv, uint8_t sb)
32 {
33 uefi_vars_set_variable(uv, EfiGlobalVariable,
34 name_sb, sizeof(name_sb),
35 EFI_VARIABLE_BOOTSERVICE_ACCESS |
36 EFI_VARIABLE_RUNTIME_ACCESS,
37 &sb, sizeof(sb));
38 }
39
set_secure_boot_enable(uefi_vars_state * uv,uint8_t sbe)40 static void set_secure_boot_enable(uefi_vars_state *uv, uint8_t sbe)
41 {
42 uefi_vars_set_variable(uv, EfiSecureBootEnableDisable,
43 name_sb_enable, sizeof(name_sb_enable),
44 EFI_VARIABLE_NON_VOLATILE |
45 EFI_VARIABLE_BOOTSERVICE_ACCESS,
46 &sbe, sizeof(sbe));
47 }
48
set_setup_mode(uefi_vars_state * uv,uint8_t sm)49 static void set_setup_mode(uefi_vars_state *uv, uint8_t sm)
50 {
51 uefi_vars_set_variable(uv, EfiGlobalVariable,
52 name_setup_mode, sizeof(name_setup_mode),
53 EFI_VARIABLE_BOOTSERVICE_ACCESS |
54 EFI_VARIABLE_RUNTIME_ACCESS,
55 &sm, sizeof(sm));
56 }
57
set_custom_mode(uefi_vars_state * uv,uint8_t cm)58 static void set_custom_mode(uefi_vars_state *uv, uint8_t cm)
59 {
60 uefi_vars_set_variable(uv, EfiCustomModeEnable,
61 name_custom_mode, sizeof(name_custom_mode),
62 EFI_VARIABLE_NON_VOLATILE |
63 EFI_VARIABLE_BOOTSERVICE_ACCESS,
64 &cm, sizeof(cm));
65 }
66
set_signature_support(uefi_vars_state * uv)67 static void set_signature_support(uefi_vars_state *uv)
68 {
69 QemuUUID sigs_support[5];
70
71 sigs_support[0] = EfiCertSha256Guid;
72 sigs_support[1] = EfiCertSha384Guid;
73 sigs_support[2] = EfiCertSha512Guid;
74 sigs_support[3] = EfiCertRsa2048Guid;
75 sigs_support[4] = EfiCertX509Guid;
76
77 uefi_vars_set_variable(uv, EfiGlobalVariable,
78 name_sigs_support, sizeof(name_sigs_support),
79 EFI_VARIABLE_BOOTSERVICE_ACCESS |
80 EFI_VARIABLE_RUNTIME_ACCESS,
81 sigs_support, sizeof(sigs_support));
82 }
83
setup_mode_is_active(uefi_vars_state * uv)84 static bool setup_mode_is_active(uefi_vars_state *uv)
85 {
86 uefi_variable *var;
87 uint8_t *value;
88
89 var = uefi_vars_find_variable(uv, EfiGlobalVariable,
90 name_setup_mode, sizeof(name_setup_mode));
91 if (var) {
92 value = var->data;
93 if (value[0] == SETUP_MODE) {
94 return true;
95 }
96 }
97 return false;
98 }
99
custom_mode_is_active(uefi_vars_state * uv)100 static bool custom_mode_is_active(uefi_vars_state *uv)
101 {
102 uefi_variable *var;
103 uint8_t *value;
104
105 var = uefi_vars_find_variable(uv, EfiCustomModeEnable,
106 name_custom_mode, sizeof(name_custom_mode));
107 if (var) {
108 value = var->data;
109 if (value[0] == CUSTOM_SECURE_BOOT_MODE) {
110 return true;
111 }
112 }
113 return false;
114 }
115
uefi_vars_is_sb_pk(uefi_variable * var)116 bool uefi_vars_is_sb_pk(uefi_variable *var)
117 {
118 if (qemu_uuid_is_equal(&var->guid, &EfiGlobalVariable) &&
119 uefi_str_equal(var->name, var->name_size, name_pk, sizeof(name_pk))) {
120 return true;
121 }
122 return false;
123 }
124
uefi_vars_is_sb_kek(uefi_variable * var)125 static bool uefi_vars_is_sb_kek(uefi_variable *var)
126 {
127 if (qemu_uuid_is_equal(&var->guid, &EfiGlobalVariable) &&
128 uefi_str_equal(var->name, var->name_size, name_kek, sizeof(name_kek))) {
129 return true;
130 }
131 return false;
132 }
133
uefi_vars_is_sb_db(uefi_variable * var)134 static bool uefi_vars_is_sb_db(uefi_variable *var)
135 {
136 if (!qemu_uuid_is_equal(&var->guid, &EfiImageSecurityDatabase)) {
137 return false;
138 }
139 if (uefi_str_equal(var->name, var->name_size, name_db, sizeof(name_db))) {
140 return true;
141 }
142 if (uefi_str_equal(var->name, var->name_size, name_dbx, sizeof(name_dbx))) {
143 return true;
144 }
145 return false;
146 }
147
uefi_vars_is_sb_any(uefi_variable * var)148 bool uefi_vars_is_sb_any(uefi_variable *var)
149 {
150 if (uefi_vars_is_sb_pk(var) ||
151 uefi_vars_is_sb_kek(var) ||
152 uefi_vars_is_sb_db(var)) {
153 return true;
154 }
155 return false;
156 }
157
uefi_vars_find_siglist(uefi_vars_state * uv,uefi_variable * var)158 static uefi_variable *uefi_vars_find_siglist(uefi_vars_state *uv,
159 uefi_variable *var)
160 {
161 if (uefi_vars_is_sb_pk(var)) {
162 return uefi_vars_find_variable(uv, EfiGlobalVariable,
163 name_pk, sizeof(name_pk));
164 }
165 if (uefi_vars_is_sb_kek(var)) {
166 return uefi_vars_find_variable(uv, EfiGlobalVariable,
167 name_pk, sizeof(name_pk));
168 }
169 if (uefi_vars_is_sb_db(var)) {
170 return uefi_vars_find_variable(uv, EfiGlobalVariable,
171 name_kek, sizeof(name_kek));
172 }
173
174 return NULL;
175 }
176
uefi_vars_check_auth_2_sb(uefi_vars_state * uv,uefi_variable * var,mm_variable_access * va,void * data,uint64_t data_offset)177 static efi_status uefi_vars_check_auth_2_sb(uefi_vars_state *uv,
178 uefi_variable *var,
179 mm_variable_access *va,
180 void *data,
181 uint64_t data_offset)
182 {
183 variable_auth_2 *auth = data;
184 uefi_variable *siglist;
185
186 if (custom_mode_is_active(uv)) {
187 /* no authentication in custom mode */
188 return EFI_SUCCESS;
189 }
190
191 if (setup_mode_is_active(uv) && !uefi_vars_is_sb_pk(var)) {
192 /* no authentication in setup mode (except PK) */
193 return EFI_SUCCESS;
194 }
195
196 if (auth->hdr_length == 24) {
197 /* no signature (auth->cert_data is empty) */
198 return EFI_SECURITY_VIOLATION;
199 }
200
201 siglist = uefi_vars_find_siglist(uv, var);
202 if (!siglist && setup_mode_is_active(uv) && uefi_vars_is_sb_pk(var)) {
203 /* check PK is self-signed */
204 uefi_variable tmp = {
205 .guid = EfiGlobalVariable,
206 .name = (uint16_t *)name_pk,
207 .name_size = sizeof(name_pk),
208 .attributes = sigdb_attrs,
209 .data = data + data_offset,
210 .data_size = va->data_size - data_offset,
211 };
212 return uefi_vars_check_pkcs7_2(&tmp, NULL, NULL, va, data);
213 }
214
215 return uefi_vars_check_pkcs7_2(siglist, NULL, NULL, va, data);
216 }
217
uefi_vars_check_auth_2(uefi_vars_state * uv,uefi_variable * var,mm_variable_access * va,void * data)218 efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
219 mm_variable_access *va, void *data)
220 {
221 variable_auth_2 *auth = data;
222 uint64_t data_offset;
223 efi_status status;
224
225 if (va->data_size < sizeof(*auth)) {
226 return EFI_SECURITY_VIOLATION;
227 }
228 if (uadd64_overflow(sizeof(efi_time), auth->hdr_length, &data_offset)) {
229 return EFI_SECURITY_VIOLATION;
230 }
231 if (va->data_size < data_offset) {
232 return EFI_SECURITY_VIOLATION;
233 }
234
235 if (auth->hdr_revision != 0x0200 ||
236 auth->hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
237 !qemu_uuid_is_equal(&auth->guid_cert_type, &EfiCertTypePkcs7Guid)) {
238 return EFI_UNSUPPORTED;
239 }
240
241 if (uefi_vars_is_sb_any(var)) {
242 /* secure boot variables */
243 status = uefi_vars_check_auth_2_sb(uv, var, va, data, data_offset);
244 if (status != EFI_SUCCESS) {
245 return status;
246 }
247 } else {
248 /* other authenticated variables */
249 status = uefi_vars_check_pkcs7_2(NULL,
250 &var->digest, &var->digest_size,
251 va, data);
252 if (status != EFI_SUCCESS) {
253 return status;
254 }
255 }
256
257 /* checks passed, set variable data */
258 var->time = auth->timestamp;
259 if (va->data_size - data_offset > 0) {
260 var->data = g_malloc(va->data_size - data_offset);
261 memcpy(var->data, data + data_offset, va->data_size - data_offset);
262 var->data_size = va->data_size - data_offset;
263 }
264
265 return EFI_SUCCESS;
266 }
267
uefi_vars_check_secure_boot(uefi_vars_state * uv,uefi_variable * var)268 efi_status uefi_vars_check_secure_boot(uefi_vars_state *uv, uefi_variable *var)
269 {
270 uint8_t *value = var->data;
271
272 if (uefi_vars_is_sb_any(var)) {
273 if (var->attributes != sigdb_attrs) {
274 return EFI_INVALID_PARAMETER;
275 }
276 }
277
278 /* reject SecureBootEnable updates if force_secure_boot is set */
279 if (qemu_uuid_is_equal(&var->guid, &EfiSecureBootEnableDisable) &&
280 uefi_str_equal(var->name, var->name_size,
281 name_sb_enable, sizeof(name_sb_enable)) &&
282 uv->force_secure_boot &&
283 value[0] != SECURE_BOOT_ENABLE) {
284 return EFI_WRITE_PROTECTED;
285 }
286
287 /* reject CustomMode updates if disable_custom_mode is set */
288 if (qemu_uuid_is_equal(&var->guid, &EfiCustomModeEnable) &&
289 uefi_str_equal(var->name, var->name_size,
290 name_custom_mode, sizeof(name_custom_mode)) &&
291 uv->disable_custom_mode) {
292 return EFI_WRITE_PROTECTED;
293 }
294
295 return EFI_SUCCESS;
296 }
297
298 /* AuthVariableLibInitialize */
uefi_vars_auth_init(uefi_vars_state * uv)299 void uefi_vars_auth_init(uefi_vars_state *uv)
300 {
301 uefi_variable *pk_var, *sbe_var;
302 uint8_t platform_mode, sb, sbe, vk;
303
304 /* SetupMode */
305 pk_var = uefi_vars_find_variable(uv, EfiGlobalVariable,
306 name_pk, sizeof(name_pk));
307 if (!pk_var) {
308 platform_mode = SETUP_MODE;
309 } else {
310 platform_mode = USER_MODE;
311 }
312 set_setup_mode(uv, platform_mode);
313
314 /* SignatureSupport */
315 set_signature_support(uv);
316
317 /* SecureBootEnable */
318 sbe = SECURE_BOOT_DISABLE;
319 sbe_var = uefi_vars_find_variable(uv, EfiSecureBootEnableDisable,
320 name_sb_enable, sizeof(name_sb_enable));
321 if (sbe_var) {
322 if (platform_mode == USER_MODE) {
323 sbe = ((uint8_t *)sbe_var->data)[0];
324 }
325 } else if (platform_mode == USER_MODE) {
326 sbe = SECURE_BOOT_ENABLE;
327 set_secure_boot_enable(uv, sbe);
328 }
329
330 if (uv->force_secure_boot && sbe != SECURE_BOOT_ENABLE) {
331 sbe = SECURE_BOOT_ENABLE;
332 set_secure_boot_enable(uv, sbe);
333 }
334
335 /* SecureBoot */
336 if ((sbe == SECURE_BOOT_ENABLE) && (platform_mode == USER_MODE)) {
337 sb = SECURE_BOOT_MODE_ENABLE;
338 } else {
339 sb = SECURE_BOOT_MODE_DISABLE;
340 }
341 set_secure_boot(uv, sb);
342
343 /* CustomMode */
344 set_custom_mode(uv, STANDARD_SECURE_BOOT_MODE);
345
346 vk = 0;
347 uefi_vars_set_variable(uv, EfiGlobalVariable,
348 name_vk_nv, sizeof(name_vk_nv),
349 EFI_VARIABLE_NON_VOLATILE |
350 EFI_VARIABLE_BOOTSERVICE_ACCESS |
351 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
352 &vk, sizeof(vk));
353 uefi_vars_set_variable(uv, EfiGlobalVariable,
354 name_vk, sizeof(name_vk),
355 EFI_VARIABLE_BOOTSERVICE_ACCESS |
356 EFI_VARIABLE_RUNTIME_ACCESS,
357 &vk, sizeof(vk));
358
359 /* flush to disk */
360 uefi_vars_json_save(uv);
361 }
362