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