xref: /qemu/hw/uefi/var-service-auth.c (revision d64db833d6e3cbe9ea5f36342480f920f3675cea)
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 = 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 
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 
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 */
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