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