master
c 374 lines 11.8 KB
Raw
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
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
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
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
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
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
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
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
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
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
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
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
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
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;
184 uefi_variable *siglist;
185
186 memcpy(&auth, data, sizeof(auth));
187 if (custom_mode_is_active(uv)) {
188 /* no authentication in custom mode */
189 return EFI_SUCCESS;
190 }
191
192 if (setup_mode_is_active(uv) && !uefi_vars_is_sb_pk(var)) {
193 /* no authentication in setup mode (except PK) */
194 return EFI_SUCCESS;
195 }
196
197 if (auth.hdr_length == (sizeof(auth) - sizeof(auth.timestamp))) {
198 /* no signature (auth->cert_data is empty) */
199 return EFI_SECURITY_VIOLATION;
200 }
201
202 siglist = uefi_vars_find_siglist(uv, var);
203 if (!siglist && setup_mode_is_active(uv) && uefi_vars_is_sb_pk(var)) {
204 /* check PK is self-signed */
205 uefi_variable tmp = {
206 .guid = EfiGlobalVariable,
207 .name = (uint16_t *)name_pk,
208 .name_size = sizeof(name_pk),
209 .attributes = sigdb_attrs,
210 .data = data + data_offset,
211 .data_size = va->data_size - data_offset,
212 };
213 return uefi_vars_check_pkcs7_2(&tmp, NULL, NULL, va, data);
214 }
215
216 return uefi_vars_check_pkcs7_2(siglist, NULL, NULL, va, data);
217 }
218
219 efi_status uefi_vars_check_auth_2(uefi_vars_state *uv, uefi_variable *var,
220 mm_variable_access *va, void *data)
221 {
222 variable_auth_2 auth;
223 uint64_t data_offset;
224 efi_status status;
225
226 if (va->data_size < sizeof(auth)) {
227 return EFI_SECURITY_VIOLATION;
228 }
229 memcpy(&auth, data, sizeof(auth));
230
231 if (auth.hdr_length < (sizeof(auth) - sizeof(auth.timestamp))) {
232 return EFI_SECURITY_VIOLATION;
233 }
234 if (uadd64_overflow(sizeof(efi_time), auth.hdr_length, &data_offset)) {
235 return EFI_SECURITY_VIOLATION;
236 }
237 if (va->data_size < data_offset) {
238 return EFI_SECURITY_VIOLATION;
239 }
240
241 if (auth.hdr_revision != 0x0200 ||
242 auth.hdr_cert_type != WIN_CERT_TYPE_EFI_GUID ||
243 !qemu_uuid_is_equal(&auth.guid_cert_type, &EfiCertTypePkcs7Guid)) {
244 return EFI_UNSUPPORTED;
245 }
246
247 if (uefi_vars_is_sb_any(var)) {
248 /* secure boot variables */
249 status = uefi_vars_check_auth_2_sb(uv, var, va, data, data_offset);
250 if (status != EFI_SUCCESS) {
251 return status;
252 }
253 } else {
254 /* other authenticated variables */
255 status = uefi_vars_check_pkcs7_2(NULL,
256 &var->digest, &var->digest_size,
257 va, data);
258 if (status != EFI_SUCCESS) {
259 return status;
260 }
261 }
262
263 /* checks passed, set variable data */
264 var->time = auth.timestamp;
265 if (va->data_size - data_offset > 0) {
266 var->data = g_malloc(va->data_size - data_offset);
267 memcpy(var->data, data + data_offset, va->data_size - data_offset);
268 var->data_size = va->data_size - data_offset;
269 }
270
271 return EFI_SUCCESS;
272 }
273
274 efi_status uefi_vars_check_secure_boot(uefi_vars_state *uv, uefi_variable *var)
275 {
276 uint8_t *value = var->data;
277
278 if (uefi_vars_is_sb_any(var)) {
279 if (var->attributes != sigdb_attrs) {
280 return EFI_INVALID_PARAMETER;
281 }
282 }
283
284 /* reject SecureBootEnable updates if force_secure_boot is set */
285 if (qemu_uuid_is_equal(&var->guid, &EfiSecureBootEnableDisable) &&
286 uefi_str_equal(var->name, var->name_size,
287 name_sb_enable, sizeof(name_sb_enable)) &&
288 uv->force_secure_boot &&
289 value[0] != SECURE_BOOT_ENABLE) {
290 return EFI_WRITE_PROTECTED;
291 }
292
293 /* reject CustomMode updates if disable_custom_mode is set */
294 if (qemu_uuid_is_equal(&var->guid, &EfiCustomModeEnable) &&
295 uefi_str_equal(var->name, var->name_size,
296 name_custom_mode, sizeof(name_custom_mode)) &&
297 uv->disable_custom_mode) {
298 return EFI_WRITE_PROTECTED;
299 }
300
301 /* reject SetupMode updates */
302 if (qemu_uuid_is_equal(&var->guid, &EfiGlobalVariable) &&
303 uefi_str_equal(var->name, var->name_size,
304 name_setup_mode, sizeof(name_setup_mode))) {
305 return EFI_WRITE_PROTECTED;
306 }
307
308 return EFI_SUCCESS;
309 }
310
311 /* AuthVariableLibInitialize */
312 void uefi_vars_auth_init(uefi_vars_state *uv)
313 {
314 uefi_variable *pk_var, *sbe_var;
315 uint8_t platform_mode, sb, sbe, vk;
316
317 /* SetupMode */
318 pk_var = uefi_vars_find_variable(uv, EfiGlobalVariable,
319 name_pk, sizeof(name_pk));
320 if (!pk_var) {
321 platform_mode = SETUP_MODE;
322 } else {
323 platform_mode = USER_MODE;
324 }
325 set_setup_mode(uv, platform_mode);
326
327 /* SignatureSupport */
328 set_signature_support(uv);
329
330 /* SecureBootEnable */
331 sbe = SECURE_BOOT_DISABLE;
332 sbe_var = uefi_vars_find_variable(uv, EfiSecureBootEnableDisable,
333 name_sb_enable, sizeof(name_sb_enable));
334 if (sbe_var) {
335 if (platform_mode == USER_MODE) {
336 sbe = ((uint8_t *)sbe_var->data)[0];
337 }
338 } else if (platform_mode == USER_MODE) {
339 sbe = SECURE_BOOT_ENABLE;
340 set_secure_boot_enable(uv, sbe);
341 }
342
343 if (uv->force_secure_boot && sbe != SECURE_BOOT_ENABLE) {
344 sbe = SECURE_BOOT_ENABLE;
345 set_secure_boot_enable(uv, sbe);
346 }
347
348 /* SecureBoot */
349 if ((sbe == SECURE_BOOT_ENABLE) && (platform_mode == USER_MODE)) {
350 sb = SECURE_BOOT_MODE_ENABLE;
351 } else {
352 sb = SECURE_BOOT_MODE_DISABLE;
353 }
354 set_secure_boot(uv, sb);
355
356 /* CustomMode */
357 set_custom_mode(uv, STANDARD_SECURE_BOOT_MODE);
358
359 vk = 0;
360 uefi_vars_set_variable(uv, EfiGlobalVariable,
361 name_vk_nv, sizeof(name_vk_nv),
362 EFI_VARIABLE_NON_VOLATILE |
363 EFI_VARIABLE_BOOTSERVICE_ACCESS |
364 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS,
365 &vk, sizeof(vk));
366 uefi_vars_set_variable(uv, EfiGlobalVariable,
367 name_vk, sizeof(name_vk),
368 EFI_VARIABLE_BOOTSERVICE_ACCESS |
369 EFI_VARIABLE_RUNTIME_ACCESS,
370 &vk, sizeof(vk));
371
372 /* flush to disk */
373 uefi_vars_json_save(uv);
374 }