]> git.proxmox.com Git - efi-boot-shim.git/blob - mok.c
Add changelog for 15.4-2 with new patches
[efi-boot-shim.git] / mok.c
1 // SPDX-License-Identifier: BSD-2-Clause-Patent
2 /*
3 * mok.c - MoK variable processing
4 * Copyright 2017 Peter Jones <pjones@redhat.com>
5 */
6
7 #include "shim.h"
8
9 /*
10 * Check if a variable exists
11 */
12 static BOOLEAN check_var(CHAR16 *varname)
13 {
14 EFI_STATUS efi_status;
15 UINTN size = sizeof(UINT32);
16 UINT32 MokVar;
17 UINT32 attributes;
18
19 efi_status = gRT->GetVariable(varname, &SHIM_LOCK_GUID, &attributes,
20 &size, (void *)&MokVar);
21 if (!EFI_ERROR(efi_status) || efi_status == EFI_BUFFER_TOO_SMALL)
22 return TRUE;
23
24 return FALSE;
25 }
26
27 #define SetVariable(name, guid, attrs, varsz, var) \
28 ({ \
29 EFI_STATUS efi_status_; \
30 efi_status_ = gRT->SetVariable(name, guid, attrs, varsz, var); \
31 dprint_(L"%a:%d:%a() SetVariable(\"%s\", ... varsz=0x%llx) = %r\n", \
32 __FILE__, __LINE__ - 5, __func__, name, varsz, \
33 efi_status_); \
34 efi_status_; \
35 })
36
37 /*
38 * If the OS has set any of these variables we need to drop into MOK and
39 * handle them appropriately
40 */
41 static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
42 {
43 EFI_STATUS efi_status;
44
45 if (check_var(L"MokNew") || check_var(L"MokSB") ||
46 check_var(L"MokPW") || check_var(L"MokAuth") ||
47 check_var(L"MokDel") || check_var(L"MokDB") ||
48 check_var(L"MokXNew") || check_var(L"MokXDel") ||
49 check_var(L"MokXAuth")) {
50 efi_status = start_image(image_handle, MOK_MANAGER);
51
52 if (EFI_ERROR(efi_status)) {
53 perror(L"Failed to start MokManager: %r\n", efi_status);
54 return efi_status;
55 }
56 }
57
58 return EFI_SUCCESS;
59 }
60
61 typedef enum {
62 VENDOR_ADDEND_DB,
63 VENDOR_ADDEND_X509,
64 VENDOR_ADDEND_NONE,
65 } vendor_addend_category_t;
66
67 struct mok_state_variable;
68 typedef vendor_addend_category_t (vendor_addend_categorizer_t)(struct mok_state_variable *);
69
70 /*
71 * MoK variables that need to have their storage validated.
72 *
73 * The order here is important, since this is where we measure for the
74 * tpm as well.
75 */
76 struct mok_state_variable {
77 CHAR16 *name; /* UCS-2 BS|NV variable name */
78 char *name8; /* UTF-8 BS|NV variable name */
79 CHAR16 *rtname; /* UCS-2 RT variable name */
80 char *rtname8; /* UTF-8 RT variable name */
81 EFI_GUID *guid; /* variable GUID */
82
83 /*
84 * these are used during processing, they shouldn't be filled out
85 * in the static table below.
86 */
87 UINT8 *data;
88 UINTN data_size;
89
90 /*
91 * addend are added to the input variable, as part of the runtime
92 * variable, so that they're visible to the kernel. These are
93 * where we put vendor_cert / vendor_db / vendor_dbx
94 *
95 * These are indirect pointers just to make initialization saner...
96 */
97 vendor_addend_categorizer_t *categorize_addend; /* determines format */
98 /*
99 * we call categorize_addend() and it determines what kind of thing
100 * this is. That is, if this shim was built with VENDOR_CERT, for
101 * the DB entry it'll return VENDOR_ADDEND_X509; if you used
102 * VENDOR_DB instead, it'll return VENDOR_ADDEND_DB. If you used
103 * neither, it'll do VENDOR_ADDEND_NONE.
104 *
105 * The existing categorizers are for db and dbx; they differ
106 * because we don't currently support a CERT for dbx.
107 */
108 UINT8 **addend;
109 UINT32 *addend_size;
110
111 /*
112 * build_cert is our build-time cert. Like addend, this is added
113 * to the input variable, as part of the runtime variable, so that
114 * they're visible to the kernel. This is the ephemeral cert used
115 * for signing MokManager.efi and fallback.efi.
116 *
117 * These are indirect pointers just to make initialization saner...
118 */
119 UINT8 **build_cert;
120 UINT32 *build_cert_size;
121
122 UINT32 yes_attr; /* var attrs that must be set */
123 UINT32 no_attr; /* var attrs that must not be set */
124 UINT32 flags; /* flags on what and how to mirror */
125 /*
126 * MOK_MIRROR_KEYDB mirror this as a key database
127 * MOK_MIRROR_DELETE_FIRST delete any existing variable first
128 * MOK_VARIABLE_MEASURE extend PCR 7 and log the hash change
129 * MOK_VARIABLE_LOG measure into whatever .pcr says and log
130 */
131 UINTN pcr; /* PCR to measure and hash to */
132
133 /*
134 * if this is a state value, a pointer to our internal state to be
135 * mirrored.
136 */
137 UINT8 *state;
138 };
139
140 static vendor_addend_category_t
141 categorize_authorized(struct mok_state_variable *v)
142 {
143 if (!(v->addend && v->addend_size &&
144 *v->addend && *v->addend_size)) {
145 return VENDOR_ADDEND_NONE;
146 }
147
148 return vendor_authorized_category;
149 }
150
151 static vendor_addend_category_t
152 categorize_deauthorized(struct mok_state_variable *v)
153 {
154 if (!(v->addend && v->addend_size &&
155 *v->addend && *v->addend_size)) {
156 return VENDOR_ADDEND_NONE;
157 }
158
159 return VENDOR_ADDEND_DB;
160 }
161
162 #define MOK_MIRROR_KEYDB 0x01
163 #define MOK_MIRROR_DELETE_FIRST 0x02
164 #define MOK_VARIABLE_MEASURE 0x04
165 #define MOK_VARIABLE_LOG 0x08
166
167 struct mok_state_variable mok_state_variables[] = {
168 {.name = L"MokList",
169 .name8 = "MokList",
170 .rtname = L"MokListRT",
171 .rtname8 = "MokListRT",
172 .guid = &SHIM_LOCK_GUID,
173 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
174 EFI_VARIABLE_NON_VOLATILE,
175 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
176 .categorize_addend = categorize_authorized,
177 .addend = &vendor_authorized,
178 .addend_size = &vendor_authorized_size,
179 #if defined(ENABLE_SHIM_CERT)
180 .build_cert = &build_cert,
181 .build_cert_size = &build_cert_size,
182 #endif /* defined(ENABLE_SHIM_CERT) */
183 .flags = MOK_MIRROR_KEYDB |
184 MOK_MIRROR_DELETE_FIRST |
185 MOK_VARIABLE_LOG,
186 .pcr = 14,
187 },
188 {.name = L"MokListX",
189 .name8 = "MokListX",
190 .rtname = L"MokListXRT",
191 .rtname8 = "MokListXRT",
192 .guid = &SHIM_LOCK_GUID,
193 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
194 EFI_VARIABLE_NON_VOLATILE,
195 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
196 .categorize_addend = categorize_deauthorized,
197 .addend = &vendor_deauthorized,
198 .addend_size = &vendor_deauthorized_size,
199 .flags = MOK_MIRROR_KEYDB |
200 MOK_MIRROR_DELETE_FIRST |
201 MOK_VARIABLE_LOG,
202 .pcr = 14,
203 },
204 {.name = L"MokSBState",
205 .name8 = "MokSBState",
206 .rtname = L"MokSBStateRT",
207 .rtname8 = "MokSBStateRT",
208 .guid = &SHIM_LOCK_GUID,
209 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
210 EFI_VARIABLE_NON_VOLATILE,
211 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
212 .flags = MOK_MIRROR_DELETE_FIRST |
213 MOK_VARIABLE_MEASURE |
214 MOK_VARIABLE_LOG,
215 .pcr = 14,
216 .state = &user_insecure_mode,
217 },
218 {.name = L"MokDBState",
219 .name8 = "MokDBState",
220 .rtname = L"MokIgnoreDB",
221 .rtname8 = "MokIgnoreDB",
222 .guid = &SHIM_LOCK_GUID,
223 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
224 EFI_VARIABLE_NON_VOLATILE,
225 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
226 .state = &ignore_db,
227 },
228 {.name = SBAT_VAR_NAME,
229 .name8 = SBAT_VAR_NAME8,
230 .rtname = SBAT_RT_VAR_NAME,
231 .rtname8 = SBAT_RT_VAR_NAME8,
232 .guid = &SHIM_LOCK_GUID,
233 .yes_attr = EFI_VARIABLE_BOOTSERVICE_ACCESS |
234 EFI_VARIABLE_NON_VOLATILE,
235 /*
236 * we're enforcing that SBAT can't have an RT flag here because
237 * there's no way to tell whether it's an authenticated variable.
238 */
239 #if !defined(ENABLE_SHIM_DEVEL)
240 .no_attr = EFI_VARIABLE_RUNTIME_ACCESS,
241 #else
242 .no_attr = 0,
243 #endif
244 .flags = MOK_MIRROR_DELETE_FIRST |
245 MOK_VARIABLE_MEASURE,
246 .pcr = 7,
247 },
248 { NULL, }
249 };
250
251 #define should_mirror_addend(v) (((v)->categorize_addend) && ((v)->categorize_addend(v) != VENDOR_ADDEND_NONE))
252
253 static inline BOOLEAN NONNULL(1)
254 should_mirror_build_cert(struct mok_state_variable *v)
255 {
256 return (v->build_cert && v->build_cert_size &&
257 *v->build_cert && *v->build_cert_size) ? TRUE : FALSE;
258 }
259
260 static const uint8_t null_sha256[32] = { 0, };
261
262 typedef UINTN SIZE_T;
263
264 static EFI_STATUS
265 get_max_var_sz(UINT32 attrs, SIZE_T *max_var_szp)
266 {
267 EFI_STATUS efi_status;
268 uint64_t max_storage_sz = 0;
269 uint64_t remaining_sz = 0;
270 uint64_t max_var_sz = 0;
271
272 *max_var_szp = 0;
273 efi_status = gRT->QueryVariableInfo(attrs, &max_storage_sz,
274 &remaining_sz, &max_var_sz);
275 if (EFI_ERROR(efi_status)) {
276 perror(L"Could not get variable storage info: %r\n", efi_status);
277 return efi_status;
278 }
279
280 /*
281 * I just don't trust implementations to not be showing static data
282 * for max_var_sz
283 */
284 *max_var_szp = (max_var_sz < remaining_sz) ? max_var_sz : remaining_sz;
285 dprint("max_var_sz:%lx remaining_sz:%lx max_storage_sz:%lx\n",
286 max_var_sz, remaining_sz, max_storage_sz);
287 return efi_status;
288 }
289
290 /*
291 * If any entries fit in < maxsz, and nothing goes wrong, create a variable
292 * of the given name and guid with as many esd entries as possible in it,
293 * and updates *esdp with what would be the next entry (even if makes *esdp
294 * > esl+esl->SignatureListSize), and returns whatever SetVariable()
295 * returns
296 *
297 * If no entries fit (i.e. sizeof(esl) + esl->SignatureSize > maxsz),
298 * returns EFI_BUFFER_TOO_SMALL;
299 */
300 static EFI_STATUS
301 mirror_one_esl(CHAR16 *name, EFI_GUID *guid, UINT32 attrs,
302 EFI_SIGNATURE_LIST *esl, EFI_SIGNATURE_DATA *esd,
303 SIZE_T howmany)
304 {
305 EFI_STATUS efi_status;
306 SIZE_T varsz = 0;
307 UINT8 *var;
308
309 /*
310 * We always assume esl->SignatureHeaderSize is 0 (and so far,
311 * that's true as per UEFI 2.8)
312 */
313 dprint(L"Trying to add %lx signatures to \"%s\" of size %lx\n",
314 howmany, name, esl->SignatureSize);
315
316 /*
317 * Because of the semantics of variable_create_esl(), the first
318 * owner guid from the data is not part of esdsz, or the data.
319 *
320 * Compensate here.
321 */
322 efi_status = variable_create_esl(esd, howmany,
323 &esl->SignatureType,
324 esl->SignatureSize,
325 &var, &varsz);
326 if (EFI_ERROR(efi_status) || !var || !varsz) {
327 LogError(L"Couldn't allocate %lu bytes for mok variable \"%s\": %r\n",
328 varsz, var, efi_status);
329 return efi_status;
330 }
331
332 dprint(L"new esl:\n");
333 dhexdumpat(var, varsz, 0);
334
335 efi_status = SetVariable(name, guid, attrs, varsz, var);
336 FreePool(var);
337 if (EFI_ERROR(efi_status)) {
338 LogError(L"Couldn't create mok variable \"%s\": %r\n",
339 varsz, var, efi_status);
340 return efi_status;
341 }
342
343 return efi_status;
344 }
345
346 static EFI_STATUS
347 mirror_mok_db(CHAR16 *name, CHAR8 *name8, EFI_GUID *guid, UINT32 attrs,
348 UINT8 *FullData, SIZE_T FullDataSize, BOOLEAN only_first)
349 {
350 EFI_STATUS efi_status = EFI_SUCCESS;
351 SIZE_T max_var_sz;
352
353 efi_status = get_max_var_sz(attrs, &max_var_sz);
354 if (EFI_ERROR(efi_status)) {
355 LogError(L"Could not get maximum variable size: %r",
356 efi_status);
357 return efi_status;
358 }
359
360 if (FullDataSize <= max_var_sz) {
361 if (only_first)
362 efi_status = SetVariable(name, guid, attrs,
363 FullDataSize, FullData);
364
365 return efi_status;
366 }
367
368 CHAR16 *namen;
369 CHAR8 *namen8;
370 UINTN namelen, namesz;
371
372 namelen = StrLen(name);
373 namesz = namelen * 2;
374 if (only_first) {
375 namen = name;
376 namen8 = name8;
377 } else {
378 namelen += 18;
379 namesz += 34;
380 namen = AllocateZeroPool(namesz);
381 if (!namen) {
382 LogError(L"Could not allocate %lu bytes", namesz);
383 return EFI_OUT_OF_RESOURCES;
384 }
385 namen8 = AllocateZeroPool(namelen);
386 if (!namen8) {
387 FreePool(namen);
388 LogError(L"Could not allocate %lu bytes", namelen);
389 return EFI_OUT_OF_RESOURCES;
390 }
391 }
392
393 UINTN pos, i;
394 const SIZE_T minsz = sizeof(EFI_SIGNATURE_LIST)
395 + sizeof(EFI_SIGNATURE_DATA)
396 + SHA1_DIGEST_SIZE;
397 BOOLEAN did_one = FALSE;
398
399 /*
400 * Create any entries that can fit.
401 */
402 if (!only_first) {
403 dprint(L"full data for \"%s\":\n", name);
404 dhexdumpat(FullData, FullDataSize, 0);
405 }
406 EFI_SIGNATURE_LIST *esl = NULL;
407 UINTN esl_end_pos = 0;
408 for (i = 0, pos = 0; FullDataSize - pos >= minsz && FullData; ) {
409 EFI_SIGNATURE_DATA *esd = NULL;
410
411 dprint(L"pos:0x%llx FullDataSize:0x%llx\n", pos, FullDataSize);
412 if (esl == NULL || pos >= esl_end_pos) {
413 UINT8 *nesl = FullData + pos;
414 dprint(L"esl:0x%llx->0x%llx\n", esl, nesl);
415 esl = (EFI_SIGNATURE_LIST *)nesl;
416 esl_end_pos = pos + esl->SignatureListSize;
417 dprint(L"pos:0x%llx->0x%llx\n", pos, pos + sizeof(*esl));
418 pos += sizeof(*esl);
419 }
420 esd = (EFI_SIGNATURE_DATA *)(FullData + pos);
421 if (pos >= FullDataSize)
422 break;
423 if (esl->SignatureListSize == 0 || esl->SignatureSize == 0)
424 break;
425
426 dprint(L"esl[%lu] 0x%llx = {sls=0x%lx, ss=0x%lx} esd:0x%llx\n",
427 i, esl, esl->SignatureListSize, esl->SignatureSize, esd);
428
429 if (!only_first) {
430 SPrint(namen, namelen, L"%s%lu", name, i);
431 namen[namelen-1] = 0;
432 /* uggggh */
433 UINTN j;
434 for (j = 0; j < namelen; j++)
435 namen8[j] = (CHAR8)(namen[j] & 0xff);
436 namen8[namelen - 1] = 0;
437 }
438
439 /*
440 * In case max_var_sz is computed dynamically, refresh the
441 * value here.
442 */
443 efi_status = get_max_var_sz(attrs, &max_var_sz);
444 if (EFI_ERROR(efi_status)) {
445 LogError(L"Could not get maximum variable size: %r",
446 efi_status);
447 if (!only_first) {
448 FreePool(namen);
449 FreePool(namen8);
450 }
451 return efi_status;
452 }
453
454 /* The name counts towards the size of the variable */
455 max_var_sz -= (StrLen(namen) + 1) * 2;
456 dprint(L"max_var_sz - name: %lx\n", max_var_sz);
457
458 SIZE_T howmany;
459 howmany = MIN((max_var_sz - sizeof(*esl)) / esl->SignatureSize,
460 (esl_end_pos - pos) / esl->SignatureSize);
461 if (howmany == 0) {
462 /* No signatures from this ESL can be mirrored in to a
463 * single variable, so skip it.
464 */
465 dprint(L"skipping esl, pos:0x%llx->0x%llx\n", pos, esl_end_pos);
466 pos = esl_end_pos;
467 continue;
468 }
469
470 UINTN adj = howmany * esl->SignatureSize;
471
472 if (!only_first && i == 0) {
473 dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj);
474 pos += adj;
475 i++;
476 continue;
477
478 }
479
480 efi_status = mirror_one_esl(namen, guid, attrs,
481 esl, esd, howmany);
482 dprint(L"esd:0x%llx adj:0x%llx\n", esd, adj);
483 if (EFI_ERROR(efi_status)) {
484 LogError(L"Could not mirror mok variable \"%s\": %r\n",
485 namen, efi_status);
486 break;
487 }
488
489 dprint(L"pos:0x%llx->0x%llx\n", pos, pos + adj);
490 pos += adj;
491 did_one = TRUE;
492 if (only_first)
493 break;
494 i++;
495 }
496
497 if (EFI_ERROR(efi_status)) {
498 perror(L"Failed to set %s: %r\n", name, efi_status);
499 } else if (only_first && !did_one) {
500 /*
501 * In this case we're going to try to create a
502 * dummy variable so that there's one there. It
503 * may or may not work, because on some firmware
504 * builds when the SetVariable call above fails it
505 * does actually set the variable(!), so aside from
506 * not using the allocation if it doesn't work, we
507 * don't care about failures here.
508 */
509 UINT8 *var;
510 UINTN varsz;
511
512 efi_status = variable_create_esl_with_one_signature(
513 null_sha256, sizeof(null_sha256),
514 &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
515 &var, &varsz);
516 /*
517 * from here we don't really care if it works or
518 * doesn't.
519 */
520 if (!EFI_ERROR(efi_status) && var && varsz) {
521 efi_status = SetVariable(name, guid,
522 EFI_VARIABLE_BOOTSERVICE_ACCESS
523 | EFI_VARIABLE_RUNTIME_ACCESS,
524 varsz, var);
525 FreePool(var);
526 }
527 }
528 return efi_status;
529 }
530
531
532 static EFI_STATUS NONNULL(1)
533 mirror_one_mok_variable(struct mok_state_variable *v,
534 BOOLEAN only_first)
535 {
536 EFI_STATUS efi_status = EFI_SUCCESS;
537 uint8_t *FullData = NULL;
538 size_t FullDataSize = 0;
539 vendor_addend_category_t addend_category = VENDOR_ADDEND_NONE;
540 uint8_t *p = NULL;
541 uint32_t attrs = EFI_VARIABLE_BOOTSERVICE_ACCESS |
542 EFI_VARIABLE_RUNTIME_ACCESS;
543 BOOLEAN measure = v->flags & MOK_VARIABLE_MEASURE;
544 BOOLEAN log = v->flags & MOK_VARIABLE_LOG;
545 size_t build_cert_esl_sz = 0, addend_esl_sz = 0;
546 bool reuse = FALSE;
547
548 if (v->categorize_addend)
549 addend_category = v->categorize_addend(v);
550
551 /*
552 * if it is, there's more data
553 */
554 if (v->flags & MOK_MIRROR_KEYDB) {
555
556 /*
557 * We're mirroring (into) an efi security database, aka an
558 * array of EFI_SIGNATURE_LIST. Its layout goes like:
559 *
560 * existing_variable_data
561 * existing_variable_data_size
562 * if flags & MOK_MIRROR_KEYDB
563 * if build_cert
564 * build_cert_esl
565 * build_cert_header (always sz=0)
566 * build_cert_esd[0] { owner, data }
567 * if addend==vendor_db
568 * for n=[1..N]
569 * vendor_db_esl_n
570 * vendor_db_header_n (always sz=0)
571 * vendor_db_esd_n[m] {{ owner, data }, ... }
572 * elif addend==vendor_cert
573 * vendor_cert_esl
574 * vendor_cert_header (always sz=0)
575 * vendor_cert_esd[1] { owner, data }
576 *
577 * first we determine the size of the variable, then alloc
578 * and add the data.
579 */
580
581 /*
582 * *first* vendor_db or vendor_cert
583 */
584 switch (addend_category) {
585 case VENDOR_ADDEND_DB:
586 /*
587 * if it's an ESL already, we use it wholesale
588 */
589 FullDataSize += *v->addend_size;
590 dprint(L"FullDataSize:%lu FullData:0x%llx\n",
591 FullDataSize, FullData);
592 break;
593 case VENDOR_ADDEND_X509:
594 efi_status = fill_esl_with_one_signature(*v->addend,
595 *v->addend_size,
596 &EFI_CERT_TYPE_X509_GUID,
597 &SHIM_LOCK_GUID,
598 NULL,
599 &addend_esl_sz);
600 if (efi_status != EFI_BUFFER_TOO_SMALL) {
601 perror(L"Could not add built-in cert to %s: %r\n",
602 v->name, efi_status);
603 return efi_status;
604 }
605 FullDataSize += addend_esl_sz;
606 dprint(L"FullDataSize:%lu FullData:0x%llx\n",
607 FullDataSize, FullData);
608 break;
609 default:
610 case VENDOR_ADDEND_NONE:
611 dprint(L"FullDataSize:%lu FullData:0x%llx\n",
612 FullDataSize, FullData);
613 break;
614 }
615
616 /*
617 * then the build cert if it's there
618 */
619 if (should_mirror_build_cert(v)) {
620 efi_status = fill_esl_with_one_signature(*v->build_cert,
621 *v->build_cert_size,
622 &EFI_CERT_TYPE_X509_GUID,
623 &SHIM_LOCK_GUID,
624 NULL, &build_cert_esl_sz);
625 if (efi_status != EFI_BUFFER_TOO_SMALL) {
626 perror(L"Could not add built-in cert to %s: %r\n",
627 v->name, efi_status);
628 return efi_status;
629 }
630 FullDataSize += build_cert_esl_sz;
631 dprint(L"FullDataSize:0x%lx FullData:0x%llx\n",
632 FullDataSize, FullData);
633 }
634
635 }
636
637 /*
638 * we're always mirroring the original data, whether this is an efi
639 * security database or not
640 */
641 dprint(L"v->name:\"%s\" v->rtname:\"%s\"\n", v->name, v->rtname);
642 dprint(L"v->data_size:%lu v->data:0x%llx\n", v->data_size, v->data);
643 dprint(L"FullDataSize:%lu FullData:0x%llx\n", FullDataSize, FullData);
644 if (v->data_size) {
645 FullDataSize += v->data_size;
646 dprint(L"FullDataSize:%lu FullData:0x%llx\n",
647 FullDataSize, FullData);
648 }
649 if (v->data_size == FullDataSize)
650 reuse = TRUE;
651
652 /*
653 * Now we have the full size
654 */
655 if (FullDataSize) {
656 /*
657 * allocate the buffer, or use the old one if it's just the
658 * existing data.
659 */
660 if (FullDataSize == v->data_size) {
661 FullData = v->data;
662 FullDataSize = v->data_size;
663 p = FullData + FullDataSize;
664 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
665 FullDataSize, FullData, p, p-(uintptr_t)FullData);
666 v->data = NULL;
667 v->data_size = 0;
668 } else {
669 dprint(L"FullDataSize:%lu FullData:0x%llx allocating FullData\n",
670 FullDataSize, FullData);
671 /*
672 * make sure we've got some zeroes at the end, just
673 * in case.
674 */
675 UINTN new, allocsz;
676
677 allocsz = FullDataSize + sizeof(EFI_SIGNATURE_LIST);
678 new = ALIGN_VALUE(allocsz, 4096);
679 allocsz = new == allocsz ? new + 4096 : new;
680 FullData = AllocateZeroPool(allocsz);
681 if (!FullData) {
682 perror(L"Failed to allocate %lu bytes for %s\n",
683 FullDataSize, v->name);
684 return EFI_OUT_OF_RESOURCES;
685 }
686 p = FullData;
687 }
688 }
689 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
690 FullDataSize, FullData, p, p-(uintptr_t)FullData);
691
692 /*
693 * Now fill it.
694 */
695 if (v->flags & MOK_MIRROR_KEYDB) {
696 /*
697 * first vendor_cert or vendor_db
698 */
699 switch (addend_category) {
700 case VENDOR_ADDEND_DB:
701 CopyMem(p, *v->addend, *v->addend_size);
702 p += *v->addend_size;
703 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
704 FullDataSize, FullData, p, p-(uintptr_t)FullData);
705 break;
706 case VENDOR_ADDEND_X509:
707 efi_status = fill_esl_with_one_signature(*v->addend,
708 *v->addend_size,
709 &EFI_CERT_TYPE_X509_GUID,
710 &SHIM_LOCK_GUID,
711 p, &addend_esl_sz);
712 if (EFI_ERROR(efi_status)) {
713 perror(L"Could not add built-in cert to %s: %r\n",
714 v->name, efi_status);
715 return efi_status;
716 }
717 p += addend_esl_sz;
718 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
719 FullDataSize, FullData, p, p-(uintptr_t)FullData);
720 break;
721 default:
722 case VENDOR_ADDEND_NONE:
723 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
724 FullDataSize, FullData, p, p-(uintptr_t)FullData);
725 break;
726 }
727
728 /*
729 * then is the build cert
730 */
731 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
732 FullDataSize, FullData, p, p-(uintptr_t)FullData);
733 if (should_mirror_build_cert(v)) {
734 efi_status = fill_esl_with_one_signature(*v->build_cert,
735 *v->build_cert_size,
736 &EFI_CERT_TYPE_X509_GUID,
737 &SHIM_LOCK_GUID,
738 p, &build_cert_esl_sz);
739 if (EFI_ERROR(efi_status)) {
740 perror(L"Could not add built-in cert to %s: %r\n",
741 v->name, efi_status);
742 return efi_status;
743 }
744 p += build_cert_esl_sz;
745 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
746 FullDataSize, FullData, p, p-(uintptr_t)FullData);
747 }
748 }
749
750 /*
751 * last bit is existing data, unless it's the only thing,
752 * in which case it's already there.
753 */
754 if (!reuse) {
755 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
756 FullDataSize, FullData, p, p-(uintptr_t)FullData);
757 if (v->data && v->data_size) {
758 CopyMem(p, v->data, v->data_size);
759 p += v->data_size;
760 }
761 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
762 FullDataSize, FullData, p, p-(uintptr_t)FullData);
763 }
764
765 /*
766 * We always want to create our key databases, so in this case we
767 * need a dummy entry
768 */
769 if ((v->flags & MOK_MIRROR_KEYDB) && FullDataSize == 0) {
770 efi_status = variable_create_esl_with_one_signature(
771 null_sha256, sizeof(null_sha256),
772 &EFI_CERT_SHA256_GUID, &SHIM_LOCK_GUID,
773 &FullData, &FullDataSize);
774 if (EFI_ERROR(efi_status)) {
775 perror(L"Failed to allocate %lu bytes for %s\n",
776 FullDataSize, v->name);
777 return efi_status;
778 }
779 p = FullData + FullDataSize;
780 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
781 FullDataSize, FullData, p, p-(uintptr_t)FullData);
782 }
783
784 dprint(L"FullDataSize:%lu FullData:0x%llx p:0x%llx pos:%lld\n",
785 FullDataSize, FullData, p, p-(uintptr_t)FullData);
786 if (FullDataSize && v->flags & MOK_MIRROR_KEYDB) {
787 dprint(L"calling mirror_mok_db(\"%s\", datasz=%lu)\n",
788 v->rtname, FullDataSize);
789 efi_status = mirror_mok_db(v->rtname, (CHAR8 *)v->rtname8, v->guid,
790 attrs, FullData, FullDataSize,
791 only_first);
792 dprint(L"mirror_mok_db(\"%s\", datasz=%lu) returned %r\n",
793 v->rtname, FullDataSize, efi_status);
794 } else if (FullDataSize && only_first) {
795 efi_status = SetVariable(v->rtname, v->guid, attrs,
796 FullDataSize, FullData);
797 }
798 if (FullDataSize && only_first) {
799 if (measure) {
800 /*
801 * Measure this into PCR 7 in the Microsoft format
802 */
803 efi_status = tpm_measure_variable(v->name, *v->guid,
804 FullDataSize, FullData);
805 if (EFI_ERROR(efi_status)) {
806 dprint(L"tpm_measure_variable(\"%s\",%lu,0x%llx)->%r\n",
807 v->name, FullDataSize, FullData, efi_status);
808 return efi_status;
809 }
810 }
811
812 if (log) {
813 /*
814 * Log this variable into whichever PCR the table
815 * says.
816 */
817 EFI_PHYSICAL_ADDRESS datap =
818 (EFI_PHYSICAL_ADDRESS)(UINTN)FullData,
819 efi_status = tpm_log_event(datap, FullDataSize,
820 v->pcr, (CHAR8 *)v->name8);
821 if (EFI_ERROR(efi_status)) {
822 dprint(L"tpm_log_event(0x%llx, %lu, %lu, \"%s\")->%r\n",
823 FullData, FullDataSize, v->pcr, v->name,
824 efi_status);
825 return efi_status;
826 }
827 }
828
829 }
830 if (v->data && v->data_size && v->data != FullData) {
831 FreePool(v->data);
832 v->data = NULL;
833 v->data_size = 0;
834 }
835 v->data = FullData;
836 v->data_size = FullDataSize;
837 dprint(L"returning %r\n", efi_status);
838 return efi_status;
839 }
840
841 /*
842 * Mirror a variable if it has an rtname, and preserve any
843 * EFI_SECURITY_VIOLATION status at the same time.
844 */
845 static EFI_STATUS NONNULL(1)
846 maybe_mirror_one_mok_variable(struct mok_state_variable *v,
847 EFI_STATUS ret, BOOLEAN only_first)
848 {
849 EFI_STATUS efi_status;
850 BOOLEAN present = FALSE;
851
852 if (v->rtname) {
853 if (!only_first && (v->flags & MOK_MIRROR_DELETE_FIRST)) {
854 dprint(L"deleting \"%s\"\n", v->rtname);
855 efi_status = LibDeleteVariable(v->rtname, v->guid);
856 dprint(L"LibDeleteVariable(\"%s\",...) => %r\n", v->rtname, efi_status);
857 }
858
859 efi_status = mirror_one_mok_variable(v, only_first);
860 if (EFI_ERROR(efi_status)) {
861 if (ret != EFI_SECURITY_VIOLATION)
862 ret = efi_status;
863 perror(L"Could not create %s: %r\n", v->rtname,
864 efi_status);
865 }
866 }
867
868 present = (v->data && v->data_size) ? TRUE : FALSE;
869 if (!present)
870 return ret;
871
872 if (v->data_size == sizeof(UINT8) && v->state) {
873 *v->state = v->data[0];
874 }
875
876 return ret;
877 }
878
879 struct mok_variable_config_entry {
880 CHAR8 name[256];
881 UINT64 data_size;
882 UINT8 data[];
883 };
884
885 EFI_STATUS import_one_mok_state(struct mok_state_variable *v,
886 BOOLEAN only_first)
887 {
888 EFI_STATUS ret = EFI_SUCCESS;
889 EFI_STATUS efi_status;
890
891 user_insecure_mode = 0;
892 ignore_db = 0;
893
894 UINT32 attrs = 0;
895 BOOLEAN delete = FALSE;
896
897 dprint(L"importing mok state for \"%s\"\n", v->name);
898
899 efi_status = get_variable_attr(v->name,
900 &v->data, &v->data_size,
901 *v->guid, &attrs);
902 if (efi_status == EFI_NOT_FOUND) {
903 v->data = NULL;
904 v->data_size = 0;
905 } else if (EFI_ERROR(efi_status)) {
906 perror(L"Could not verify %s: %r\n", v->name,
907 efi_status);
908 delete = TRUE;
909 } else {
910 if (!(attrs & v->yes_attr)) {
911 perror(L"Variable %s is missing attributes:\n",
912 v->name);
913 perror(L" 0x%08x should have 0x%08x set.\n",
914 attrs, v->yes_attr);
915 delete = TRUE;
916 }
917 if (attrs & v->no_attr) {
918 perror(L"Variable %s has incorrect attribute:\n",
919 v->name);
920 perror(L" 0x%08x should not have 0x%08x set.\n",
921 attrs, v->no_attr);
922 delete = TRUE;
923 }
924 }
925 if (delete == TRUE) {
926 perror(L"Deleting bad variable %s\n", v->name);
927 efi_status = LibDeleteVariable(v->name, v->guid);
928 if (EFI_ERROR(efi_status)) {
929 perror(L"Failed to erase %s\n", v->name);
930 ret = EFI_SECURITY_VIOLATION;
931 }
932 FreePool(v->data);
933 v->data = NULL;
934 v->data_size = 0;
935 }
936
937 dprint(L"maybe mirroring \"%s\". original data:\n", v->name);
938 dhexdumpat(v->data, v->data_size, 0);
939
940 ret = maybe_mirror_one_mok_variable(v, ret, only_first);
941 dprint(L"returning %r\n", ret);
942 return ret;
943 }
944
945 /*
946 * Verify our non-volatile MoK state. This checks the variables above
947 * accessable and have valid attributes. If they don't, it removes
948 * them. If any of them can't be removed, our ability to do this is
949 * comprimized, so return EFI_SECURITY_VIOLATION.
950 *
951 * Any variable that isn't deleted and has ->measure == TRUE is then
952 * measured into the tpm.
953 *
954 * Any variable with a ->rtname element is then mirrored to a
955 * runtime-accessable version. The new ones won't be marked NV, so the OS
956 * can't modify them.
957 */
958 EFI_STATUS import_mok_state(EFI_HANDLE image_handle)
959 {
960 UINTN i;
961 EFI_STATUS ret = EFI_SUCCESS;
962 EFI_STATUS efi_status;
963
964 user_insecure_mode = 0;
965 ignore_db = 0;
966
967 UINT64 config_sz = 0;
968 UINT8 *config_table = NULL;
969 size_t npages = 0;
970 struct mok_variable_config_entry config_template;
971
972 dprint(L"importing minimal mok state variables\n");
973 for (i = 0; mok_state_variables[i].name != NULL; i++) {
974 struct mok_state_variable *v = &mok_state_variables[i];
975
976 efi_status = import_one_mok_state(v, TRUE);
977 if (EFI_ERROR(efi_status)) {
978 dprint(L"import_one_mok_state(ih, \"%s\", TRUE): %r\n",
979 v->rtname);
980 /*
981 * don't clobber EFI_SECURITY_VIOLATION from some
982 * other variable in the list.
983 */
984 if (ret != EFI_SECURITY_VIOLATION)
985 ret = efi_status;
986 }
987
988 if (v->data && v->data_size) {
989 config_sz += v->data_size;
990 config_sz += sizeof(config_template);
991 }
992 }
993
994 /*
995 * Alright, so we're going to copy these to a config table. The
996 * table is a packed array of N+1 struct mok_variable_config_entry
997 * items, with the last item having all zero's in name and
998 * data_size.
999 */
1000 if (config_sz) {
1001 config_sz += sizeof(config_template);
1002 npages = ALIGN_VALUE(config_sz, PAGE_SIZE) >> EFI_PAGE_SHIFT;
1003 config_table = NULL;
1004 efi_status = gBS->AllocatePages(AllocateAnyPages,
1005 EfiRuntimeServicesData,
1006 npages,
1007 (EFI_PHYSICAL_ADDRESS *)&config_table);
1008 if (EFI_ERROR(efi_status) || !config_table) {
1009 console_print(L"Allocating %lu pages for mok config table failed: %r\n",
1010 npages, efi_status);
1011 config_table = NULL;
1012 } else {
1013 ZeroMem(config_table, npages << EFI_PAGE_SHIFT);
1014 }
1015 }
1016
1017 UINT8 *p = (UINT8 *)config_table;
1018 for (i = 0; p && mok_state_variables[i].name != NULL; i++) {
1019 struct mok_state_variable *v = &mok_state_variables[i];
1020
1021 ZeroMem(&config_template, sizeof(config_template));
1022 strncpy(config_template.name, (CHAR8 *)v->rtname8, 255);
1023 config_template.name[255] = '\0';
1024
1025 config_template.data_size = v->data_size;
1026
1027 CopyMem(p, &config_template, sizeof(config_template));
1028 p += sizeof(config_template);
1029 CopyMem(p, v->data, v->data_size);
1030 p += v->data_size;
1031 }
1032 if (p) {
1033 ZeroMem(&config_template, sizeof(config_template));
1034 CopyMem(p, &config_template, sizeof(config_template));
1035
1036 efi_status = gBS->InstallConfigurationTable(&MOK_VARIABLE_STORE,
1037 config_table);
1038 if (EFI_ERROR(efi_status)) {
1039 console_print(L"Couldn't install MoK configuration table\n");
1040 }
1041 }
1042
1043 /*
1044 * This is really just to make it easy for userland.
1045 */
1046 dprint(L"importing full mok state variables\n");
1047 for (i = 0; mok_state_variables[i].name != NULL; i++) {
1048 struct mok_state_variable *v = &mok_state_variables[i];
1049
1050 import_one_mok_state(v, FALSE);
1051 }
1052
1053 /*
1054 * Enter MokManager if necessary. Any actual *changes* here will
1055 * cause MokManager to demand a machine reboot, so this is safe to
1056 * have after the entire loop.
1057 */
1058 dprint(L"checking mok request\n");
1059 efi_status = check_mok_request(image_handle);
1060 dprint(L"mok returned %r\n", efi_status);
1061 if (EFI_ERROR(efi_status)) {
1062 /*
1063 * don't clobber EFI_SECURITY_VIOLATION
1064 */
1065 if (ret != EFI_SECURITY_VIOLATION)
1066 ret = efi_status;
1067 return ret;
1068 }
1069
1070 dprint(L"returning %r\n", ret);
1071 return ret;
1072 }
1073
1074 // vim:fenc=utf-8:tw=75:noet