]> git.proxmox.com Git - efi-boot-shim.git/blob - MokManager.c
Try again with includes
[efi-boot-shim.git] / MokManager.c
1 // SPDX-License-Identifier: BSD-2-Clause-Patent
2 #include "shim.h"
3
4 #include <Library/BaseCryptLib.h>
5 #include <openssl/x509.h>
6 #include <openssl/x509v3.h>
7 #include <openssl/asn1.h>
8 #include <openssl/bn.h>
9
10 #define PASSWORD_MAX 256
11 #define PASSWORD_MIN 1
12 #define SB_PASSWORD_LEN 16
13
14 #define NAME_LINE_MAX 70
15
16 #ifndef SHIM_VENDOR
17 #define SHIM_VENDOR L"Shim"
18 #endif
19
20 #define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
21 #define HASH_STRING L"Select a file to trust:\n\n"
22
23 #define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID))
24
25 typedef struct {
26 UINT32 MokSize;
27 UINT8 *Mok;
28 EFI_GUID Type;
29 } __attribute__ ((packed)) MokListNode;
30
31 typedef struct {
32 UINT32 MokSBState;
33 UINT32 PWLen;
34 CHAR16 Password[SB_PASSWORD_LEN];
35 } __attribute__ ((packed)) MokSBvar;
36
37 typedef struct {
38 UINT32 MokDBState;
39 UINT32 PWLen;
40 CHAR16 Password[SB_PASSWORD_LEN];
41 } __attribute__ ((packed)) MokDBvar;
42
43 typedef struct {
44 UINT32 MokTMLState;
45 UINT32 PWLen;
46 CHAR16 Password[SB_PASSWORD_LEN];
47 } __attribute__ ((packed)) MokTMLvar;
48
49 typedef struct {
50 INT32 Timeout;
51 } __attribute__ ((packed)) MokTimeoutvar;
52
53 static EFI_STATUS get_sha1sum(void *Data, int DataSize, UINT8 * hash)
54 {
55 EFI_STATUS efi_status;
56 unsigned int ctxsize;
57 void *ctx = NULL;
58
59 ctxsize = Sha1GetContextSize();
60 ctx = AllocatePool(ctxsize);
61
62 if (!ctx) {
63 console_notify(L"Unable to allocate memory for hash context");
64 return EFI_OUT_OF_RESOURCES;
65 }
66
67 if (!Sha1Init(ctx)) {
68 console_notify(L"Unable to initialise hash");
69 efi_status = EFI_OUT_OF_RESOURCES;
70 goto done;
71 }
72
73 if (!(Sha1Update(ctx, Data, DataSize))) {
74 console_notify(L"Unable to generate hash");
75 efi_status = EFI_OUT_OF_RESOURCES;
76 goto done;
77 }
78
79 if (!(Sha1Final(ctx, hash))) {
80 console_notify(L"Unable to finalise hash");
81 efi_status = EFI_OUT_OF_RESOURCES;
82 goto done;
83 }
84
85 efi_status = EFI_SUCCESS;
86 done:
87 return efi_status;
88 }
89
90 static BOOLEAN is_sha2_hash(EFI_GUID Type)
91 {
92 if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0)
93 return TRUE;
94 else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0)
95 return TRUE;
96 else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0)
97 return TRUE;
98 else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0)
99 return TRUE;
100
101 return FALSE;
102 }
103
104 static UINT32 sha_size(EFI_GUID Type)
105 {
106 if (CompareGuid(&Type, &EFI_CERT_SHA1_GUID) == 0)
107 return SHA1_DIGEST_SIZE;
108 else if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0)
109 return SHA224_DIGEST_LENGTH;
110 else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0)
111 return SHA256_DIGEST_SIZE;
112 else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0)
113 return SHA384_DIGEST_LENGTH;
114 else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0)
115 return SHA512_DIGEST_LENGTH;
116
117 return 0;
118 }
119
120 static BOOLEAN is_valid_siglist(EFI_GUID Type, UINT32 SigSize)
121 {
122 UINT32 hash_sig_size;
123
124 if (CompareGuid (&Type, &X509_GUID) == 0 && SigSize != 0)
125 return TRUE;
126
127 if (!is_sha2_hash(Type))
128 return FALSE;
129
130 hash_sig_size = sha_size(Type) + sizeof(EFI_GUID);
131 if (SigSize != hash_sig_size)
132 return FALSE;
133
134 return TRUE;
135 }
136
137 static UINT32 count_keys(void *Data, UINTN DataSize)
138 {
139 EFI_SIGNATURE_LIST *CertList = Data;
140 UINTN dbsize = DataSize;
141 UINT32 MokNum = 0;
142 void *end = Data + DataSize;
143
144 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
145 /* Use ptr arithmetics to ensure bounded access. Do not allow 0
146 * SignatureListSize that will cause endless loop. */
147 if ((void *)(CertList + 1) > end
148 || CertList->SignatureListSize == 0) {
149 console_notify
150 (L"Invalid MOK detected! Ignoring MOK List.");
151 return 0;
152 }
153
154 if (CertList->SignatureListSize == 0 ||
155 CertList->SignatureListSize <= CertList->SignatureSize) {
156 console_errorbox(L"Corrupted signature list");
157 return 0;
158 }
159
160 if (!is_valid_siglist
161 (CertList->SignatureType, CertList->SignatureSize)) {
162 console_errorbox(L"Invalid signature list found");
163 return 0;
164 }
165
166 MokNum++;
167 dbsize -= CertList->SignatureListSize;
168 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
169 CertList->SignatureListSize);
170 }
171
172 return MokNum;
173 }
174
175 static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize)
176 {
177 MokListNode *list;
178 EFI_SIGNATURE_LIST *CertList = Data;
179 EFI_SIGNATURE_DATA *Cert;
180 UINTN dbsize = DataSize;
181 UINTN count = 0;
182 void *end = Data + DataSize;
183
184 list = AllocatePool(sizeof(MokListNode) * num);
185 if (!list) {
186 console_notify(L"Unable to allocate MOK list");
187 return NULL;
188 }
189
190 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
191 /* CertList out of bounds? */
192 if ((void *)(CertList + 1) > end
193 || CertList->SignatureListSize == 0) {
194 FreePool(list);
195 return NULL;
196 }
197
198 /* Omit the signature check here since we already did it
199 in count_keys() */
200
201 Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) +
202 sizeof(EFI_SIGNATURE_LIST) +
203 CertList->SignatureHeaderSize);
204 /* Cert out of bounds? */
205 if ((void *)(Cert + 1) > end
206 || CertList->SignatureSize <= sizeof(EFI_GUID)) {
207 FreePool(list);
208 return NULL;
209 }
210
211 list[count].Type = CertList->SignatureType;
212 if (CompareGuid (&CertList->SignatureType, &X509_GUID) == 0) {
213 list[count].MokSize = CertList->SignatureSize -
214 sizeof(EFI_GUID);
215 list[count].Mok = (void *)Cert->SignatureData;
216 } else {
217 list[count].MokSize = CertList->SignatureListSize -
218 sizeof(EFI_SIGNATURE_LIST);
219 list[count].Mok = (void *)Cert;
220 }
221
222 /* MOK out of bounds? */
223 if (list[count].MokSize > (unsigned long)end -
224 (unsigned long)list[count].Mok) {
225 FreePool(list);
226 return NULL;
227 }
228
229 count++;
230 dbsize -= CertList->SignatureListSize;
231 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
232 CertList->SignatureListSize);
233 }
234
235 return list;
236 }
237
238 typedef struct {
239 int nid;
240 CHAR16 *name;
241 } NidName;
242
243 static NidName nidname[] = {
244 {NID_commonName, L"CN"},
245 {NID_organizationName, L"O"},
246 {NID_countryName, L"C"},
247 {NID_stateOrProvinceName, L"ST"},
248 {NID_localityName, L"L"},
249 {-1, NULL}
250 };
251
252 static CHAR16 *get_x509_name(X509_NAME * X509Name)
253 {
254 CHAR16 name[NAME_LINE_MAX + 1];
255 CHAR16 part[NAME_LINE_MAX + 1];
256 char str[NAME_LINE_MAX];
257 int i, len, rest, first;
258
259 name[0] = '\0';
260 rest = NAME_LINE_MAX;
261 first = 1;
262 for (i = 0; nidname[i].name != NULL; i++) {
263 int add;
264 len = X509_NAME_get_text_by_NID(X509Name, nidname[i].nid,
265 str, NAME_LINE_MAX);
266 if (len <= 0)
267 continue;
268
269 if (first)
270 add = len + (int)StrLen(nidname[i].name) + 1;
271 else
272 add = len + (int)StrLen(nidname[i].name) + 3;
273
274 if (add > rest)
275 continue;
276
277 if (first) {
278 SPrint(part, NAME_LINE_MAX * sizeof(CHAR16), L"%s=%a",
279 nidname[i].name, str);
280 } else {
281 SPrint(part, NAME_LINE_MAX * sizeof(CHAR16), L", %s=%a",
282 nidname[i].name, str);
283 }
284 StrCat(name, part);
285 rest -= add;
286 first = 0;
287 }
288
289 if (rest >= 0 && rest < NAME_LINE_MAX)
290 return PoolPrint(L"%s", name);
291
292 return NULL;
293 }
294
295 static CHAR16 *get_x509_time(ASN1_TIME * time)
296 {
297 BIO *bio = BIO_new(BIO_s_mem());
298 char str[30];
299 int len;
300
301 ASN1_TIME_print(bio, time);
302 len = BIO_read(bio, str, 29);
303 if (len < 0)
304 len = 0;
305 str[len] = '\0';
306 BIO_free(bio);
307
308 return PoolPrint(L"%a", str);
309 }
310
311 static void show_x509_info(X509 * X509Cert, UINT8 * hash)
312 {
313 ASN1_INTEGER *serial;
314 BIGNUM *bnser;
315 unsigned char hexbuf[30];
316 X509_NAME *X509Name;
317 ASN1_TIME *time;
318 CHAR16 *issuer = NULL;
319 CHAR16 *subject = NULL;
320 CHAR16 *from = NULL;
321 CHAR16 *until = NULL;
322 EXTENDED_KEY_USAGE *extusage;
323 POOL_PRINT hash_string1;
324 POOL_PRINT hash_string2;
325 POOL_PRINT serial_string;
326 int fields = 0;
327 CHAR16 **text;
328 int i = 0;
329
330 ZeroMem(&hash_string1, sizeof(hash_string1));
331 ZeroMem(&hash_string2, sizeof(hash_string2));
332 ZeroMem(&serial_string, sizeof(serial_string));
333
334 serial = X509_get_serialNumber(X509Cert);
335 if (serial) {
336 int i, n;
337 bnser = ASN1_INTEGER_to_BN(serial, NULL);
338 n = BN_bn2bin(bnser, hexbuf);
339 for (i = 0; i < n; i++) {
340 CatPrint(&serial_string, L"%02x:", hexbuf[i]);
341 }
342 BN_free(bnser);
343 }
344
345 if (serial_string.str)
346 fields++;
347
348 X509Name = X509_get_issuer_name(X509Cert);
349 if (X509Name) {
350 issuer = get_x509_name(X509Name);
351 if (issuer)
352 fields++;
353 }
354
355 X509Name = X509_get_subject_name(X509Cert);
356 if (X509Name) {
357 subject = get_x509_name(X509Name);
358 if (subject)
359 fields++;
360 }
361
362 time = X509_get_notBefore(X509Cert);
363 if (time) {
364 from = get_x509_time(time);
365 if (from)
366 fields++;
367 }
368
369 time = X509_get_notAfter(X509Cert);
370 if (time) {
371 until = get_x509_time(time);
372 if (until)
373 fields++;
374 }
375
376 for (i = 0; i < 10; i++)
377 CatPrint(&hash_string1, L"%02x ", hash[i]);
378 for (i = 10; i < 20; i++)
379 CatPrint(&hash_string2, L"%02x ", hash[i]);
380
381 if (hash_string1.str)
382 fields++;
383
384 if (hash_string2.str)
385 fields++;
386
387 if (!fields)
388 return;
389
390 i = 0;
391
392 extusage = X509_get_ext_d2i(X509Cert, NID_ext_key_usage, NULL, NULL);
393 text = AllocateZeroPool(sizeof(CHAR16 *) *
394 (fields * 3 +
395 sk_ASN1_OBJECT_num(extusage) + 3));
396 if (extusage) {
397 int j = 0;
398
399 text[i++] = StrDuplicate(L"[Extended Key Usage]");
400
401 for (j = 0; j < sk_ASN1_OBJECT_num(extusage); j++) {
402 POOL_PRINT extkeyusage;
403 ASN1_OBJECT *obj = sk_ASN1_OBJECT_value(extusage, j);
404 int buflen = 80;
405 char buf[buflen];
406
407 ZeroMem(&extkeyusage, sizeof(extkeyusage));
408
409 OBJ_obj2txt(buf, buflen, obj, 0);
410 CatPrint(&extkeyusage, L"OID: %a", buf);
411 text[i++] = StrDuplicate(extkeyusage.str);
412 FreePool(extkeyusage.str);
413 }
414 text[i++] = StrDuplicate(L"");
415 EXTENDED_KEY_USAGE_free(extusage);
416 }
417
418 if (serial_string.str) {
419 text[i++] = StrDuplicate(L"[Serial Number]");
420 text[i++] = serial_string.str;
421 text[i++] = StrDuplicate(L"");
422 }
423 if (issuer) {
424 text[i++] = StrDuplicate(L"[Issuer]");
425 text[i++] = issuer;
426 text[i++] = StrDuplicate(L"");
427 }
428 if (subject) {
429 text[i++] = StrDuplicate(L"[Subject]");
430 text[i++] = subject;
431 text[i++] = StrDuplicate(L"");
432 }
433 if (from) {
434 text[i++] = StrDuplicate(L"[Valid Not Before]");
435 text[i++] = from;
436 text[i++] = StrDuplicate(L"");
437 }
438 if (until) {
439 text[i++] = StrDuplicate(L"[Valid Not After]");
440 text[i++] = until;
441 text[i++] = StrDuplicate(L"");
442 }
443 if (hash_string1.str) {
444 text[i++] = StrDuplicate(L"[Fingerprint]");
445 text[i++] = hash_string1.str;
446 }
447 if (hash_string2.str) {
448 text[i++] = hash_string2.str;
449 text[i++] = StrDuplicate(L"");
450 }
451 text[i] = NULL;
452
453 console_print_box(text, -1);
454
455 for (i = 0; text[i] != NULL; i++)
456 FreePool(text[i]);
457
458 FreePool(text);
459 }
460
461 static void show_sha_digest(EFI_GUID Type, UINT8 * hash)
462 {
463 CHAR16 *text[5];
464 POOL_PRINT hash_string1;
465 POOL_PRINT hash_string2;
466 int i;
467 int length;
468
469 if (CompareGuid(&Type, &EFI_CERT_SHA1_GUID) == 0) {
470 length = SHA1_DIGEST_SIZE;
471 text[0] = L"SHA1 hash";
472 } else if (CompareGuid(&Type, &EFI_CERT_SHA224_GUID) == 0) {
473 length = SHA224_DIGEST_LENGTH;
474 text[0] = L"SHA224 hash";
475 } else if (CompareGuid(&Type, &EFI_CERT_SHA256_GUID) == 0) {
476 length = SHA256_DIGEST_SIZE;
477 text[0] = L"SHA256 hash";
478 } else if (CompareGuid(&Type, &EFI_CERT_SHA384_GUID) == 0) {
479 length = SHA384_DIGEST_LENGTH;
480 text[0] = L"SHA384 hash";
481 } else if (CompareGuid(&Type, &EFI_CERT_SHA512_GUID) == 0) {
482 length = SHA512_DIGEST_LENGTH;
483 text[0] = L"SHA512 hash";
484 } else {
485 return;
486 }
487
488 ZeroMem(&hash_string1, sizeof(hash_string1));
489 ZeroMem(&hash_string2, sizeof(hash_string2));
490
491 text[1] = L"";
492
493 for (i = 0; i < length / 2; i++)
494 CatPrint(&hash_string1, L"%02x ", hash[i]);
495 for (i = length / 2; i < length; i++)
496 CatPrint(&hash_string2, L"%02x ", hash[i]);
497
498 text[2] = hash_string1.str;
499 text[3] = hash_string2.str;
500 text[4] = NULL;
501
502 console_print_box(text, -1);
503
504 if (hash_string1.str)
505 FreePool(hash_string1.str);
506
507 if (hash_string2.str)
508 FreePool(hash_string2.str);
509 }
510
511 static void show_efi_hash(EFI_GUID Type, void *Mok, UINTN MokSize)
512 {
513 UINTN sig_size;
514 UINTN hash_num;
515 UINT8 *hash;
516 CHAR16 **menu_strings;
517 CHAR16 *selection[] = { L"[Hash List]", NULL };
518 UINTN key_num = 0;
519 UINTN i;
520
521 sig_size = sha_size(Type) + sizeof(EFI_GUID);
522 if ((MokSize % sig_size) != 0) {
523 console_errorbox(L"Corrupted Hash List");
524 return;
525 }
526 hash_num = MokSize / sig_size;
527
528 if (hash_num == 1) {
529 hash = (UINT8 *) Mok + sizeof(EFI_GUID);
530 show_sha_digest(Type, hash);
531 return;
532 }
533
534 menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (hash_num + 2));
535 if (!menu_strings) {
536 console_errorbox(L"Out of Resources");
537 return;
538 }
539
540 for (i = 0; i < hash_num; i++) {
541 menu_strings[i] = PoolPrint(L"View hash %d", i);
542 }
543 menu_strings[i] = StrDuplicate(L"Back");
544 menu_strings[i + 1] = NULL;
545
546 while (key_num < hash_num) {
547 int rc;
548
549 key_num = rc = console_select(selection, menu_strings, key_num);
550 if (rc < 0 || key_num >= hash_num)
551 break;
552
553 hash = (UINT8 *) Mok + sig_size * key_num + sizeof(EFI_GUID);
554 show_sha_digest(Type, hash);
555 }
556
557 for (i = 0; menu_strings[i] != NULL; i++)
558 FreePool(menu_strings[i]);
559
560 FreePool(menu_strings);
561 }
562
563 static void show_mok_info(EFI_GUID Type, void *Mok, UINTN MokSize)
564 {
565 EFI_STATUS efi_status;
566
567 if (!Mok || MokSize == 0)
568 return;
569
570 if (CompareGuid (&Type, &X509_GUID) == 0) {
571 UINT8 hash[SHA1_DIGEST_SIZE];
572 X509 *X509Cert;
573
574 efi_status = get_sha1sum(Mok, MokSize, hash);
575 if (EFI_ERROR(efi_status)) {
576 console_notify(L"Failed to compute MOK fingerprint");
577 return;
578 }
579
580 if (X509ConstructCertificate(Mok, MokSize,
581 (UINT8 **) & X509Cert)
582 && X509Cert != NULL) {
583 show_x509_info(X509Cert, hash);
584 X509_free(X509Cert);
585 } else {
586 console_notify(L"Not a valid X509 certificate");
587 return;
588 }
589 } else if (is_sha2_hash(Type)) {
590 show_efi_hash(Type, Mok, MokSize);
591 }
592 }
593
594 static EFI_STATUS list_keys(void *KeyList, UINTN KeyListSize, CHAR16 * title)
595 {
596 UINTN MokNum = 0;
597 MokListNode *keys = NULL;
598 UINT32 key_num = 0;
599 CHAR16 **menu_strings;
600 CHAR16 *selection[] = { title, NULL };
601 unsigned int i;
602
603 if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) +
604 sizeof(EFI_SIGNATURE_DATA))) {
605 console_notify(L"No MOK keys found");
606 return EFI_NOT_FOUND;
607 }
608
609 MokNum = count_keys(KeyList, KeyListSize);
610 if (MokNum == 0) {
611 console_errorbox(L"Invalid key list");
612 return EFI_ABORTED;
613 }
614 keys = build_mok_list(MokNum, KeyList, KeyListSize);
615 if (!keys) {
616 console_errorbox(L"Failed to construct key list");
617 return EFI_ABORTED;
618 }
619
620 menu_strings = AllocateZeroPool(sizeof(CHAR16 *) * (MokNum + 2));
621 if (!menu_strings)
622 return EFI_OUT_OF_RESOURCES;
623
624 for (i = 0; i < MokNum; i++) {
625 menu_strings[i] = PoolPrint(L"View key %d", i);
626 }
627 menu_strings[i] = StrDuplicate(L"Continue");
628
629 menu_strings[i + 1] = NULL;
630
631 while (key_num < MokNum) {
632 int rc;
633 rc = key_num = console_select(selection, menu_strings, key_num);
634
635 if (rc < 0 || key_num >= MokNum)
636 break;
637
638 show_mok_info(keys[key_num].Type, keys[key_num].Mok,
639 keys[key_num].MokSize);
640 }
641
642 for (i = 0; menu_strings[i] != NULL; i++)
643 FreePool(menu_strings[i]);
644 FreePool(menu_strings);
645 FreePool(keys);
646
647 return EFI_SUCCESS;
648 }
649
650 static EFI_STATUS get_line(UINT32 * length, CHAR16 * line, UINT32 line_max,
651 UINT8 show)
652 {
653 EFI_INPUT_KEY key;
654 EFI_STATUS efi_status;
655 unsigned int count = 0;
656
657 do {
658 efi_status = console_get_keystroke(&key);
659 if (EFI_ERROR(efi_status)) {
660 console_error(L"Failed to read the keystroke",
661 efi_status);
662 *length = 0;
663 return efi_status;
664 }
665
666 if ((count >= line_max &&
667 key.UnicodeChar != CHAR_BACKSPACE) ||
668 key.UnicodeChar == CHAR_NULL ||
669 key.UnicodeChar == CHAR_TAB ||
670 key.UnicodeChar == CHAR_LINEFEED ||
671 key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
672 continue;
673 }
674
675 if (count == 0 && key.UnicodeChar == CHAR_BACKSPACE) {
676 continue;
677 } else if (key.UnicodeChar == CHAR_BACKSPACE) {
678 if (show) {
679 console_print(L"\b");
680 }
681 line[--count] = '\0';
682 continue;
683 }
684
685 if (show) {
686 console_print(L"%c", key.UnicodeChar);
687 }
688
689 line[count++] = key.UnicodeChar;
690 } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN);
691 console_print(L"\n");
692
693 *length = count;
694
695 return EFI_SUCCESS;
696 }
697
698 static EFI_STATUS compute_pw_hash(void *Data, UINTN DataSize, UINT8 * password,
699 UINT32 pw_length, UINT8 * hash)
700 {
701 EFI_STATUS efi_status;
702 unsigned int ctxsize;
703 void *ctx = NULL;
704
705 ctxsize = Sha256GetContextSize();
706 ctx = AllocatePool(ctxsize);
707 if (!ctx) {
708 console_notify(L"Unable to allocate memory for hash context");
709 return EFI_OUT_OF_RESOURCES;
710 }
711
712 if (!Sha256Init(ctx)) {
713 console_notify(L"Unable to initialise hash");
714 efi_status = EFI_OUT_OF_RESOURCES;
715 goto done;
716 }
717
718 if (Data && DataSize) {
719 if (!(Sha256Update(ctx, Data, DataSize))) {
720 console_notify(L"Unable to generate hash");
721 efi_status = EFI_OUT_OF_RESOURCES;
722 goto done;
723 }
724 }
725
726 if (!(Sha256Update(ctx, password, pw_length))) {
727 console_notify(L"Unable to generate hash");
728 efi_status = EFI_OUT_OF_RESOURCES;
729 goto done;
730 }
731
732 if (!(Sha256Final(ctx, hash))) {
733 console_notify(L"Unable to finalise hash");
734 efi_status = EFI_OUT_OF_RESOURCES;
735 goto done;
736 }
737
738 efi_status = EFI_SUCCESS;
739 done:
740 return efi_status;
741 }
742
743 static INTN reset_system()
744 {
745 RT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
746 console_notify(L"Failed to reboot\n");
747 return -1;
748 }
749
750 static UINT32 get_password(CHAR16 * prompt, CHAR16 * password, UINT32 max)
751 {
752 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
753 CHAR16 *str;
754 CHAR16 *message[2];
755 UINTN length;
756 UINT32 pw_length;
757
758 if (!prompt)
759 prompt = L"Password:";
760
761 console_save_and_set_mode(&SavedMode);
762
763 str = PoolPrint(L"%s ", prompt);
764 if (!str) {
765 console_errorbox(L"Failed to allocate prompt");
766 return 0;
767 }
768
769 message[0] = str;
770 message[1] = NULL;
771 length = StrLen(message[0]);
772 console_print_box_at(message, -1, -length - 4, -5, length + 4, 3, 0, 1);
773 get_line(&pw_length, password, max, 0);
774
775 console_restore_mode(&SavedMode);
776
777 FreePool(str);
778
779 return pw_length;
780 }
781
782 static EFI_STATUS match_password(PASSWORD_CRYPT * pw_crypt,
783 void *Data, UINTN DataSize,
784 UINT8 * auth, CHAR16 * prompt)
785 {
786 EFI_STATUS efi_status;
787 UINT8 hash[128];
788 UINT8 *auth_hash;
789 UINT32 auth_size;
790 CHAR16 password[PASSWORD_MAX];
791 UINT32 pw_length;
792 UINT8 fail_count = 0;
793 unsigned int i;
794
795 if (pw_crypt) {
796 auth_hash = pw_crypt->hash;
797 auth_size = get_hash_size(pw_crypt->method);
798 if (auth_size == 0)
799 return EFI_INVALID_PARAMETER;
800 } else if (auth) {
801 auth_hash = auth;
802 auth_size = SHA256_DIGEST_SIZE;
803 } else {
804 return EFI_INVALID_PARAMETER;
805 }
806
807 while (fail_count < 3) {
808 pw_length = get_password(prompt, password, PASSWORD_MAX);
809
810 if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) {
811 console_errorbox(L"Invalid password length");
812 fail_count++;
813 continue;
814 }
815
816 /*
817 * Compute password hash
818 */
819 if (pw_crypt) {
820 char pw_ascii[PASSWORD_MAX + 1];
821 for (i = 0; i < pw_length; i++)
822 pw_ascii[i] = (char)password[i];
823 pw_ascii[pw_length] = '\0';
824
825 efi_status = password_crypt(pw_ascii, pw_length,
826 pw_crypt, hash);
827 } else {
828 /*
829 * For backward compatibility
830 */
831 efi_status = compute_pw_hash(Data, DataSize,
832 (UINT8 *) password,
833 pw_length * sizeof(CHAR16),
834 hash);
835 }
836 if (EFI_ERROR(efi_status)) {
837 console_errorbox(L"Unable to generate password hash");
838 fail_count++;
839 continue;
840 }
841
842 if (CompareMem(auth_hash, hash, auth_size) != 0) {
843 console_errorbox(L"Password doesn't match");
844 fail_count++;
845 continue;
846 }
847
848 break;
849 }
850
851 if (fail_count >= 3)
852 return EFI_ACCESS_DENIED;
853
854 return EFI_SUCCESS;
855 }
856
857 static EFI_STATUS write_db(CHAR16 * db_name, void *MokNew, UINTN MokNewSize)
858 {
859 EFI_STATUS efi_status;
860 UINT32 attributes;
861 void *old_data = NULL;
862 void *new_data = NULL;
863 UINTN old_size;
864 UINTN new_size;
865
866 /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares.
867 * ref: https://github.com/rhboot/shim/issues/55
868 * https://github.com/rhboot/shim/issues/105 */
869
870 efi_status = get_variable_attr(db_name, (UINT8 **)&old_data, &old_size,
871 SHIM_LOCK_GUID, &attributes);
872 if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
873 return efi_status;
874 }
875
876 /* Check if the old db is compromised or not */
877 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
878 FreePool(old_data);
879 old_data = NULL;
880 old_size = 0;
881 }
882
883 new_size = old_size + MokNewSize;
884 new_data = AllocatePool(new_size);
885 if (new_data == NULL) {
886 efi_status = EFI_OUT_OF_RESOURCES;
887 goto out;
888 }
889
890 CopyMem(new_data, old_data, old_size);
891 CopyMem(new_data + old_size, MokNew, MokNewSize);
892
893 efi_status = RT->SetVariable(db_name, &SHIM_LOCK_GUID,
894 EFI_VARIABLE_NON_VOLATILE |
895 EFI_VARIABLE_BOOTSERVICE_ACCESS,
896 new_size, new_data);
897 out:
898 if (old_size > 0) {
899 FreePool(old_data);
900 }
901
902 if (new_data != NULL) {
903 FreePool(new_data);
904 }
905
906 return efi_status;
907 }
908
909 static EFI_STATUS store_keys(void *MokNew, UINTN MokNewSize, int authenticate,
910 BOOLEAN MokX)
911 {
912 EFI_STATUS efi_status;
913 CHAR16 *db_name;
914 CHAR16 *auth_name;
915 UINT8 auth[PASSWORD_CRYPT_SIZE];
916 UINTN auth_size = PASSWORD_CRYPT_SIZE;
917 UINT32 attributes;
918
919 if (MokX) {
920 db_name = L"MokListX";
921 auth_name = L"MokXAuth";
922 } else {
923 db_name = L"MokList";
924 auth_name = L"MokAuth";
925 }
926
927 if (authenticate) {
928 efi_status = RT->GetVariable(auth_name, &SHIM_LOCK_GUID,
929 &attributes, &auth_size, auth);
930 if (EFI_ERROR(efi_status) ||
931 (auth_size != SHA256_DIGEST_SIZE &&
932 auth_size != PASSWORD_CRYPT_SIZE)) {
933 if (MokX)
934 console_error(L"Failed to get MokXAuth",
935 efi_status);
936 else
937 console_error(L"Failed to get MokAuth",
938 efi_status);
939 return efi_status;
940 }
941
942 if (auth_size == PASSWORD_CRYPT_SIZE) {
943 efi_status = match_password((PASSWORD_CRYPT *) auth,
944 NULL, 0, NULL, NULL);
945 } else {
946 efi_status = match_password(NULL, MokNew, MokNewSize,
947 auth, NULL);
948 }
949 if (EFI_ERROR(efi_status))
950 return EFI_ACCESS_DENIED;
951 }
952
953 if (!MokNewSize) {
954 /* Delete MOK */
955 efi_status = RT->SetVariable(db_name, &SHIM_LOCK_GUID,
956 EFI_VARIABLE_NON_VOLATILE |
957 EFI_VARIABLE_BOOTSERVICE_ACCESS,
958 0, NULL);
959 } else {
960 /* Write new MOK */
961 efi_status = write_db(db_name, MokNew, MokNewSize);
962 }
963
964 if (EFI_ERROR(efi_status)) {
965 console_error(L"Failed to set variable", efi_status);
966 return efi_status;
967 }
968
969 return EFI_SUCCESS;
970 }
971
972 static EFI_STATUS mok_enrollment_prompt(void *MokNew, UINTN MokNewSize,
973 int auth, BOOLEAN MokX)
974 {
975 EFI_STATUS efi_status;
976 CHAR16 *enroll_p[] = { L"Enroll the key(s)?", NULL };
977 CHAR16 *title;
978
979 if (MokX)
980 title = L"[Enroll MOKX]";
981 else
982 title = L"[Enroll MOK]";
983
984 efi_status = list_keys(MokNew, MokNewSize, title);
985 if (EFI_ERROR(efi_status))
986 return efi_status;
987
988 if (console_yes_no(enroll_p) == 0)
989 return EFI_ABORTED;
990
991 efi_status = store_keys(MokNew, MokNewSize, auth, MokX);
992 if (EFI_ERROR(efi_status)) {
993 console_notify(L"Failed to enroll keys\n");
994 return efi_status;
995 }
996
997 if (auth) {
998 if (MokX) {
999 LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID);
1000 LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID);
1001 } else {
1002 LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID);
1003 LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID);
1004 }
1005 }
1006
1007 return EFI_SUCCESS;
1008 }
1009
1010 static EFI_STATUS mok_reset_prompt(BOOLEAN MokX)
1011 {
1012 EFI_STATUS efi_status;
1013 CHAR16 *prompt[] = { NULL, NULL };
1014
1015 clear_screen();
1016
1017 if (MokX)
1018 prompt[0] = L"Erase all stored keys in MokListX?";
1019 else
1020 prompt[0] = L"Erase all stored keys in MokList?";
1021
1022 if (console_yes_no(prompt) == 0)
1023 return EFI_ABORTED;
1024
1025 efi_status = store_keys(NULL, 0, TRUE, MokX);
1026 if (EFI_ERROR(efi_status)) {
1027 console_notify(L"Failed to erase keys\n");
1028 return efi_status;
1029 }
1030
1031 if (MokX) {
1032 LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID);
1033 LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID);
1034 LibDeleteVariable(L"MokListX", &SHIM_LOCK_GUID);
1035 } else {
1036 LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID);
1037 LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID);
1038 LibDeleteVariable(L"MokList", &SHIM_LOCK_GUID);
1039 }
1040
1041 return EFI_SUCCESS;
1042 }
1043
1044 static EFI_STATUS write_back_mok_list(MokListNode * list, INTN key_num,
1045 BOOLEAN MokX)
1046 {
1047 EFI_STATUS efi_status;
1048 EFI_SIGNATURE_LIST *CertList;
1049 EFI_SIGNATURE_DATA *CertData;
1050 EFI_GUID type;
1051 void *Data = NULL, *ptr;
1052 INTN DataSize = 0;
1053 int i;
1054 CHAR16 *db_name;
1055
1056 if (MokX)
1057 db_name = L"MokListX";
1058 else
1059 db_name = L"MokList";
1060
1061 dprint(L"Writing back %s (%d entries)\n", db_name, key_num);
1062 for (i = 0; i < key_num; i++) {
1063 if (list[i].Mok == NULL)
1064 continue;
1065
1066 DataSize += sizeof(EFI_SIGNATURE_LIST);
1067 type = list[i].Type; /* avoid -Werror=address-of-packed-member */
1068 if (CompareGuid(&type, &X509_GUID) == 0)
1069 DataSize += sizeof(EFI_GUID);
1070 DataSize += list[i].MokSize;
1071 }
1072 if (DataSize == 0) {
1073 dprint(L"DataSize = 0; deleting variable %s\n", db_name);
1074 efi_status = RT->SetVariable(db_name, &SHIM_LOCK_GUID,
1075 EFI_VARIABLE_NON_VOLATILE |
1076 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1077 DataSize, Data);
1078 dprint(L"efi_status:%llu\n", efi_status);
1079 return EFI_SUCCESS;
1080 }
1081
1082 Data = AllocatePool(DataSize);
1083 if (Data == NULL)
1084 return EFI_OUT_OF_RESOURCES;
1085
1086 ptr = Data;
1087
1088 for (i = 0; i < key_num; i++) {
1089 if (list[i].Mok == NULL)
1090 continue;
1091
1092 CertList = (EFI_SIGNATURE_LIST *) ptr;
1093 CertData = (EFI_SIGNATURE_DATA *) (((uint8_t *) ptr) +
1094 sizeof(EFI_SIGNATURE_LIST));
1095
1096 CertList->SignatureType = list[i].Type;
1097 CertList->SignatureHeaderSize = 0;
1098
1099 if (CompareGuid(&(CertList->SignatureType), &X509_GUID) == 0) {
1100 CertList->SignatureListSize = list[i].MokSize +
1101 sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
1102 CertList->SignatureSize =
1103 list[i].MokSize + sizeof(EFI_GUID);
1104
1105 CertData->SignatureOwner = SHIM_LOCK_GUID;
1106 CopyMem(CertData->SignatureData, list[i].Mok,
1107 list[i].MokSize);
1108 } else {
1109 CertList->SignatureListSize = list[i].MokSize +
1110 sizeof(EFI_SIGNATURE_LIST);
1111 CertList->SignatureSize =
1112 sha_size(list[i].Type) + sizeof(EFI_GUID);
1113
1114 CopyMem(CertData, list[i].Mok, list[i].MokSize);
1115 }
1116 ptr = (uint8_t *) ptr + CertList->SignatureListSize;
1117 }
1118
1119 efi_status = RT->SetVariable(db_name, &SHIM_LOCK_GUID,
1120 EFI_VARIABLE_NON_VOLATILE |
1121 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1122 DataSize, Data);
1123 if (Data)
1124 FreePool(Data);
1125
1126 if (EFI_ERROR(efi_status)) {
1127 console_error(L"Failed to set variable", efi_status);
1128 return efi_status;
1129 }
1130
1131 return EFI_SUCCESS;
1132 }
1133
1134 static void delete_cert(void *key, UINT32 key_size,
1135 MokListNode * mok, INTN mok_num)
1136 {
1137 EFI_GUID type;
1138 int i;
1139
1140 for (i = 0; i < mok_num; i++) {
1141 type = mok[i].Type; /* avoid -Werror=address-of-packed-member */
1142 if (CompareGuid(&type, &X509_GUID) != 0)
1143 continue;
1144
1145 if (mok[i].MokSize == key_size &&
1146 CompareMem(key, mok[i].Mok, key_size) == 0) {
1147 /* Remove the key */
1148 mok[i].Mok = NULL;
1149 mok[i].MokSize = 0;
1150 }
1151 }
1152 }
1153
1154 static int match_hash(UINT8 * hash, UINT32 hash_size, int start,
1155 void *hash_list, UINT32 list_num)
1156 {
1157 UINT8 *ptr;
1158 UINTN i;
1159
1160 ptr = hash_list + sizeof(EFI_GUID);
1161 for (i = start; i < list_num; i++) {
1162 if (CompareMem(hash, ptr, hash_size) == 0)
1163 return i;
1164 ptr += hash_size + sizeof(EFI_GUID);
1165 }
1166
1167 return -1;
1168 }
1169
1170 static void mem_move(void *dest, void *src, UINTN size)
1171 {
1172 UINT8 *d, *s;
1173 UINTN i;
1174
1175 d = (UINT8 *) dest;
1176 s = (UINT8 *) src;
1177 for (i = 0; i < size; i++)
1178 d[i] = s[i];
1179 }
1180
1181 static void delete_hash_in_list(EFI_GUID Type, UINT8 * hash, UINT32 hash_size,
1182 MokListNode * mok, INTN mok_num)
1183 {
1184 EFI_GUID type;
1185 UINT32 sig_size;
1186 UINT32 list_num;
1187 int i, del_ind;
1188 void *start, *end;
1189 UINT32 remain;
1190
1191 sig_size = hash_size + sizeof(EFI_GUID);
1192
1193 for (i = 0; i < mok_num; i++) {
1194 type = mok[i].Type; /* avoid -Werror=address-of-packed-member */
1195 if ((CompareGuid(&type, &Type) != 0) ||
1196 (mok[i].MokSize < sig_size))
1197 continue;
1198
1199 list_num = mok[i].MokSize / sig_size;
1200
1201 del_ind = match_hash(hash, hash_size, 0, mok[i].Mok, list_num);
1202 while (del_ind >= 0) {
1203 /* Remove the hash */
1204 if (sig_size == mok[i].MokSize) {
1205 mok[i].Mok = NULL;
1206 mok[i].MokSize = 0;
1207 break;
1208 }
1209
1210 start = mok[i].Mok + del_ind * sig_size;
1211 end = start + sig_size;
1212 remain = mok[i].MokSize - (del_ind + 1) * sig_size;
1213
1214 mem_move(start, end, remain);
1215 mok[i].MokSize -= sig_size;
1216 list_num--;
1217
1218 del_ind = match_hash(hash, hash_size, del_ind,
1219 mok[i].Mok, list_num);
1220 }
1221 }
1222 }
1223
1224 static void delete_hash_list(EFI_GUID Type, void *hash_list, UINT32 list_size,
1225 MokListNode * mok, INTN mok_num)
1226 {
1227 UINT32 hash_size;
1228 UINT32 hash_num;
1229 UINT32 sig_size;
1230 UINT8 *hash;
1231 UINT32 i;
1232
1233 hash_size = sha_size(Type);
1234 sig_size = hash_size + sizeof(EFI_GUID);
1235 if (list_size < sig_size)
1236 return;
1237
1238 hash_num = list_size / sig_size;
1239
1240 hash = hash_list + sizeof(EFI_GUID);
1241
1242 for (i = 0; i < hash_num; i++) {
1243 delete_hash_in_list(Type, hash, hash_size, mok, mok_num);
1244 hash += sig_size;
1245 }
1246 }
1247
1248 static EFI_STATUS delete_keys(void *MokDel, UINTN MokDelSize, BOOLEAN MokX)
1249 {
1250 EFI_STATUS efi_status;
1251 EFI_GUID type;
1252 CHAR16 *db_name;
1253 CHAR16 *auth_name;
1254 CHAR16 *err_strs[] = { NULL, NULL, NULL };
1255 UINT8 auth[PASSWORD_CRYPT_SIZE];
1256 UINTN auth_size = PASSWORD_CRYPT_SIZE;
1257 UINT32 attributes;
1258 UINT8 *MokListData = NULL;
1259 UINTN MokListDataSize = 0;
1260 MokListNode *mok = NULL, *del_key = NULL;
1261 INTN mok_num, del_num;
1262 int i;
1263
1264 if (MokX) {
1265 db_name = L"MokListX";
1266 auth_name = L"MokXDelAuth";
1267 } else {
1268 db_name = L"MokList";
1269 auth_name = L"MokDelAuth";
1270 }
1271
1272 efi_status = RT->GetVariable(auth_name, &SHIM_LOCK_GUID, &attributes,
1273 &auth_size, auth);
1274 if (EFI_ERROR(efi_status) ||
1275 (auth_size != SHA256_DIGEST_SIZE
1276 && auth_size != PASSWORD_CRYPT_SIZE)) {
1277 if (MokX)
1278 console_error(L"Failed to get MokXDelAuth", efi_status);
1279 else
1280 console_error(L"Failed to get MokDelAuth", efi_status);
1281 return efi_status;
1282 }
1283
1284 if (auth_size == PASSWORD_CRYPT_SIZE) {
1285 dprint(L"matching password with CRYPT");
1286 efi_status = match_password((PASSWORD_CRYPT *) auth, NULL, 0,
1287 NULL, NULL);
1288 dprint(L"match_password(0x%llx, NULL, 0, NULL, NULL) = %lu\n", auth, efi_status);
1289 } else {
1290 dprint(L"matching password as sha256sum");
1291 efi_status =
1292 match_password(NULL, MokDel, MokDelSize, auth, NULL);
1293 dprint(L"match_password(NULL, 0x%llx, %llu, 0x%llx, NULL) = %lu\n", MokDel, MokDelSize, auth, efi_status);
1294 }
1295 if (EFI_ERROR(efi_status))
1296 return EFI_ACCESS_DENIED;
1297
1298 efi_status = get_variable_attr(db_name, &MokListData, &MokListDataSize,
1299 SHIM_LOCK_GUID, &attributes);
1300 if (EFI_ERROR(efi_status)) {
1301 if (MokX)
1302 console_errorbox(L"Failed to retrieve MokListX");
1303 else
1304 console_errorbox(L"Failed to retrieve MokList");
1305 return EFI_ABORTED;
1306 } else if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
1307 if (MokX) {
1308 err_strs[0] = L"MokListX is compromised!";
1309 err_strs[1] = L"Erase all keys in MokListX!";
1310 } else {
1311 err_strs[0] = L"MokList is compromised!";
1312 err_strs[1] = L"Erase all keys in MokList!";
1313 }
1314 console_alertbox(err_strs);
1315 RT->SetVariable(db_name, &SHIM_LOCK_GUID,
1316 EFI_VARIABLE_NON_VOLATILE |
1317 EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL);
1318 efi_status = EFI_ACCESS_DENIED;
1319 goto error;
1320 }
1321
1322 /* Nothing to do */
1323 if (!MokListData || MokListDataSize == 0)
1324 return EFI_SUCCESS;
1325
1326 /* Construct lists */
1327 mok_num = count_keys(MokListData, MokListDataSize);
1328 if (mok_num == 0) {
1329 if (MokX) {
1330 err_strs[0] = L"Failed to construct the key list of MokListX";
1331 err_strs[1] = L"Reset MokListX!";
1332 } else {
1333 err_strs[0] = L"Failed to construct the key list of MokList";
1334 err_strs[1] = L"Reset MokList!";
1335 }
1336 console_alertbox(err_strs);
1337 RT->SetVariable(db_name, &SHIM_LOCK_GUID,
1338 EFI_VARIABLE_NON_VOLATILE |
1339 EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL);
1340 efi_status = EFI_ABORTED;
1341 goto error;
1342 }
1343 mok = build_mok_list(mok_num, MokListData, MokListDataSize);
1344 if (!mok) {
1345 console_errorbox(L"Failed to construct key list");
1346 efi_status = EFI_ABORTED;
1347 goto error;
1348 }
1349 del_num = count_keys(MokDel, MokDelSize);
1350 if (del_num == 0) {
1351 console_errorbox(L"Invalid key delete list");
1352 efi_status = EFI_ABORTED;
1353 goto error;
1354 }
1355 del_key = build_mok_list(del_num, MokDel, MokDelSize);
1356 if (!del_key) {
1357 console_errorbox(L"Failed to construct key list");
1358 efi_status = EFI_ABORTED;
1359 goto error;
1360 }
1361
1362 /* Search and destroy */
1363 dprint(L"deleting certs from %a\n", MokX ? "MokListX" : "MokList");
1364 for (i = 0; i < del_num; i++) {
1365 type = del_key[i].Type; /* avoid -Werror=address-of-packed-member */
1366 if (CompareGuid(&type, &X509_GUID) == 0) {
1367 dprint(L"deleting key %d (total %d):\n", i, mok_num);
1368 dhexdumpat(del_key[i].Mok, del_key[i].MokSize, 0);
1369 delete_cert(del_key[i].Mok, del_key[i].MokSize,
1370 mok, mok_num);
1371 } else if (is_sha2_hash(del_key[i].Type)) {
1372 dprint(L"deleting hash %d (total %d):\n", i, mok_num);
1373 dhexdumpat(del_key[i].Mok, del_key[i].MokSize, 0);
1374 delete_hash_list(del_key[i].Type, del_key[i].Mok,
1375 del_key[i].MokSize, mok, mok_num);
1376 }
1377 }
1378
1379 efi_status = write_back_mok_list(mok, mok_num, MokX);
1380
1381 error:
1382 if (MokListData)
1383 FreePool(MokListData);
1384 if (mok)
1385 FreePool(mok);
1386 if (del_key)
1387 FreePool(del_key);
1388
1389 return efi_status;
1390 }
1391
1392 static EFI_STATUS mok_deletion_prompt(void *MokDel, UINTN MokDelSize,
1393 BOOLEAN MokX)
1394 {
1395 EFI_STATUS efi_status;
1396 CHAR16 *delete_p[] = { L"Delete the key(s)?", NULL };
1397 CHAR16 *title;
1398
1399 if (MokX)
1400 title = L"[Delete MOKX]";
1401 else
1402 title = L"[Delete MOK]";
1403
1404 efi_status = list_keys(MokDel, MokDelSize, title);
1405 if (EFI_ERROR(efi_status))
1406 return efi_status;
1407
1408 if (console_yes_no(delete_p) == 0)
1409 return EFI_ABORTED;
1410
1411 efi_status = delete_keys(MokDel, MokDelSize, MokX);
1412 if (EFI_ERROR(efi_status)) {
1413 console_notify(L"Failed to delete keys");
1414 return efi_status;
1415 }
1416
1417 if (MokX) {
1418 LibDeleteVariable(L"MokXDel", &SHIM_LOCK_GUID);
1419 LibDeleteVariable(L"MokXDelAuth", &SHIM_LOCK_GUID);
1420 } else {
1421 LibDeleteVariable(L"MokDel", &SHIM_LOCK_GUID);
1422 LibDeleteVariable(L"MokDelAuth", &SHIM_LOCK_GUID);
1423 }
1424
1425 if (MokDel)
1426 FreePool(MokDel);
1427
1428 return EFI_SUCCESS;
1429 }
1430
1431 static CHAR16 get_password_charater(CHAR16 * prompt)
1432 {
1433 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
1434 EFI_STATUS efi_status;
1435 CHAR16 *message[2];
1436 CHAR16 character = 0;
1437 UINTN length;
1438 UINT32 pw_length;
1439
1440 if (!prompt)
1441 prompt = L"Password charater: ";
1442
1443 console_save_and_set_mode(&SavedMode);
1444
1445 message[0] = prompt;
1446 message[1] = NULL;
1447 length = StrLen(message[0]);
1448 console_print_box_at(message, -1, -length - 4, -5, length + 4, 3, 0, 1);
1449 efi_status = get_line(&pw_length, &character, 1, 0);
1450 if (EFI_ERROR(efi_status))
1451 character = 0;
1452
1453 console_restore_mode(&SavedMode);
1454
1455 return character;
1456 }
1457
1458 static EFI_STATUS mok_sb_prompt(void *MokSB, UINTN MokSBSize)
1459 {
1460 EFI_STATUS efi_status;
1461 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
1462 MokSBvar *var = MokSB;
1463 CHAR16 *message[4];
1464 CHAR16 pass1, pass2, pass3;
1465 CHAR16 *str;
1466 UINT8 fail_count = 0;
1467 UINT8 sbval = 1;
1468 UINT8 pos1, pos2, pos3;
1469 int ret;
1470 CHAR16 *disable_sb[] = { L"Disable Secure Boot", NULL };
1471 CHAR16 *enable_sb[] = { L"Enable Secure Boot", NULL };
1472
1473 if (MokSBSize != sizeof(MokSBvar)) {
1474 console_notify(L"Invalid MokSB variable contents");
1475 return EFI_INVALID_PARAMETER;
1476 }
1477
1478 clear_screen();
1479
1480 message[0] = L"Change Secure Boot state";
1481 message[1] = NULL;
1482
1483 console_save_and_set_mode(&SavedMode);
1484 console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1);
1485 console_restore_mode(&SavedMode);
1486
1487 while (fail_count < 3) {
1488 RandomBytes(&pos1, sizeof(pos1));
1489 pos1 = (pos1 % var->PWLen);
1490
1491 do {
1492 RandomBytes(&pos2, sizeof(pos2));
1493 pos2 = (pos2 % var->PWLen);
1494 } while (pos2 == pos1);
1495
1496 do {
1497 RandomBytes(&pos3, sizeof(pos3));
1498 pos3 = (pos3 % var->PWLen);
1499 } while (pos3 == pos2 || pos3 == pos1);
1500
1501 str = PoolPrint(L"Enter password character %d: ", pos1 + 1);
1502 if (!str) {
1503 console_errorbox(L"Failed to allocate buffer");
1504 return EFI_OUT_OF_RESOURCES;
1505 }
1506 pass1 = get_password_charater(str);
1507 FreePool(str);
1508
1509 str = PoolPrint(L"Enter password character %d: ", pos2 + 1);
1510 if (!str) {
1511 console_errorbox(L"Failed to allocate buffer");
1512 return EFI_OUT_OF_RESOURCES;
1513 }
1514 pass2 = get_password_charater(str);
1515 FreePool(str);
1516
1517 str = PoolPrint(L"Enter password character %d: ", pos3 + 1);
1518 if (!str) {
1519 console_errorbox(L"Failed to allocate buffer");
1520 return EFI_OUT_OF_RESOURCES;
1521 }
1522 pass3 = get_password_charater(str);
1523 FreePool(str);
1524
1525 if (pass1 != var->Password[pos1] ||
1526 pass2 != var->Password[pos2] ||
1527 pass3 != var->Password[pos3]) {
1528 console_print(L"Invalid character\n");
1529 fail_count++;
1530 } else {
1531 break;
1532 }
1533 }
1534
1535 if (fail_count >= 3) {
1536 console_notify(L"Password limit reached");
1537 return EFI_ACCESS_DENIED;
1538 }
1539
1540 if (var->MokSBState == 0)
1541 ret = console_yes_no(disable_sb);
1542 else
1543 ret = console_yes_no(enable_sb);
1544
1545 if (ret == 0) {
1546 LibDeleteVariable(L"MokSB", &SHIM_LOCK_GUID);
1547 return EFI_ABORTED;
1548 }
1549
1550 if (var->MokSBState == 0) {
1551 efi_status = RT->SetVariable(L"MokSBState", &SHIM_LOCK_GUID,
1552 EFI_VARIABLE_NON_VOLATILE |
1553 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1554 1, &sbval);
1555 if (EFI_ERROR(efi_status)) {
1556 console_notify(L"Failed to set Secure Boot state");
1557 return efi_status;
1558 }
1559 } else {
1560 efi_status = RT->SetVariable(L"MokSBState", &SHIM_LOCK_GUID,
1561 EFI_VARIABLE_NON_VOLATILE |
1562 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1563 0, NULL);
1564 if (EFI_ERROR(efi_status)) {
1565 console_notify(L"Failed to delete Secure Boot state");
1566 return efi_status;
1567 }
1568 }
1569
1570 return EFI_SUCCESS;
1571 }
1572
1573 static EFI_STATUS mok_db_prompt(void *MokDB, UINTN MokDBSize)
1574 {
1575 EFI_STATUS efi_status;
1576 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
1577 MokDBvar *var = MokDB;
1578 CHAR16 *message[4];
1579 CHAR16 pass1, pass2, pass3;
1580 CHAR16 *str;
1581 UINT8 fail_count = 0;
1582 UINT8 dbval = 1;
1583 UINT8 pos1, pos2, pos3;
1584 int ret;
1585 CHAR16 *ignore_db[] = { L"Ignore DB certs/hashes", NULL };
1586 CHAR16 *use_db[] = { L"Use DB certs/hashes", NULL };
1587
1588 if (MokDBSize != sizeof(MokDBvar)) {
1589 console_notify(L"Invalid MokDB variable contents");
1590 return EFI_INVALID_PARAMETER;
1591 }
1592
1593 clear_screen();
1594
1595 message[0] = L"Change DB state";
1596 message[1] = NULL;
1597
1598 console_save_and_set_mode(&SavedMode);
1599 console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1);
1600 console_restore_mode(&SavedMode);
1601
1602 while (fail_count < 3) {
1603 RandomBytes(&pos1, sizeof(pos1));
1604 pos1 = (pos1 % var->PWLen);
1605
1606 do {
1607 RandomBytes(&pos2, sizeof(pos2));
1608 pos2 = (pos2 % var->PWLen);
1609 } while (pos2 == pos1);
1610
1611 do {
1612 RandomBytes(&pos3, sizeof(pos3));
1613 pos3 = (pos3 % var->PWLen);
1614 } while (pos3 == pos2 || pos3 == pos1);
1615
1616 str = PoolPrint(L"Enter password character %d: ", pos1 + 1);
1617 if (!str) {
1618 console_errorbox(L"Failed to allocate buffer");
1619 return EFI_OUT_OF_RESOURCES;
1620 }
1621 pass1 = get_password_charater(str);
1622 FreePool(str);
1623
1624 str = PoolPrint(L"Enter password character %d: ", pos2 + 1);
1625 if (!str) {
1626 console_errorbox(L"Failed to allocate buffer");
1627 return EFI_OUT_OF_RESOURCES;
1628 }
1629 pass2 = get_password_charater(str);
1630 FreePool(str);
1631
1632 str = PoolPrint(L"Enter password character %d: ", pos3 + 1);
1633 if (!str) {
1634 console_errorbox(L"Failed to allocate buffer");
1635 return EFI_OUT_OF_RESOURCES;
1636 }
1637 pass3 = get_password_charater(str);
1638 FreePool(str);
1639
1640 if (pass1 != var->Password[pos1] ||
1641 pass2 != var->Password[pos2] ||
1642 pass3 != var->Password[pos3]) {
1643 console_print(L"Invalid character\n");
1644 fail_count++;
1645 } else {
1646 break;
1647 }
1648 }
1649
1650 if (fail_count >= 3) {
1651 console_notify(L"Password limit reached");
1652 return EFI_ACCESS_DENIED;
1653 }
1654
1655 if (var->MokDBState == 0)
1656 ret = console_yes_no(ignore_db);
1657 else
1658 ret = console_yes_no(use_db);
1659
1660 if (ret == 0) {
1661 LibDeleteVariable(L"MokDB", &SHIM_LOCK_GUID);
1662 return EFI_ABORTED;
1663 }
1664
1665 if (var->MokDBState == 0) {
1666 efi_status = RT->SetVariable(L"MokDBState", &SHIM_LOCK_GUID,
1667 EFI_VARIABLE_NON_VOLATILE |
1668 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1669 1, &dbval);
1670 if (EFI_ERROR(efi_status)) {
1671 console_notify(L"Failed to set DB state");
1672 return efi_status;
1673 }
1674 } else {
1675 efi_status = RT->SetVariable(L"MokDBState", &SHIM_LOCK_GUID,
1676 EFI_VARIABLE_NON_VOLATILE |
1677 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1678 0, NULL);
1679 if (EFI_ERROR(efi_status)) {
1680 console_notify(L"Failed to delete DB state");
1681 return efi_status;
1682 }
1683 }
1684
1685 return EFI_SUCCESS;
1686 }
1687
1688 static EFI_STATUS mok_tml_prompt(void *MokTML, UINTN MokTMLSize)
1689 {
1690 EFI_STATUS efi_status;
1691 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
1692 MokTMLvar *var = MokTML;
1693 CHAR16 *message[4];
1694 CHAR16 pass1, pass2, pass3;
1695 CHAR16 *str;
1696 UINT8 fail_count = 0;
1697 UINT8 dbval = 1;
1698 UINT8 pos1, pos2, pos3;
1699 int ret;
1700 CHAR16 *untrust_tml[] = { L"Do not trust the MOK list", NULL };
1701 CHAR16 *trust_tml[] = { L"Trust the MOK list", NULL };
1702
1703 if (MokTMLSize != sizeof(MokTMLvar)) {
1704 console_notify(L"Invalid MokTML variable contents");
1705 return EFI_INVALID_PARAMETER;
1706 }
1707
1708 clear_screen();
1709
1710 message[0] = L"Change Trusted MOK List Keyring state";
1711 message[1] = NULL;
1712
1713 console_save_and_set_mode(&SavedMode);
1714 console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1);
1715 console_restore_mode(&SavedMode);
1716
1717 while (fail_count < 3) {
1718 RandomBytes(&pos1, sizeof(pos1));
1719 pos1 = (pos1 % var->PWLen);
1720
1721 do {
1722 RandomBytes(&pos2, sizeof(pos2));
1723 pos2 = (pos2 % var->PWLen);
1724 } while (pos2 == pos1);
1725
1726 do {
1727 RandomBytes(&pos3, sizeof(pos3));
1728 pos3 = (pos3 % var->PWLen);
1729 } while (pos3 == pos2 || pos3 == pos1);
1730
1731 str = PoolPrint(L"Enter password character %d: ", pos1 + 1);
1732 if (!str) {
1733 console_errorbox(L"Failed to allocate buffer");
1734 return EFI_OUT_OF_RESOURCES;
1735 }
1736 pass1 = get_password_charater(str);
1737 FreePool(str);
1738
1739 str = PoolPrint(L"Enter password character %d: ", pos2 + 1);
1740 if (!str) {
1741 console_errorbox(L"Failed to allocate buffer");
1742 return EFI_OUT_OF_RESOURCES;
1743 }
1744 pass2 = get_password_charater(str);
1745 FreePool(str);
1746
1747 str = PoolPrint(L"Enter password character %d: ", pos3 + 1);
1748 if (!str) {
1749 console_errorbox(L"Failed to allocate buffer");
1750 return EFI_OUT_OF_RESOURCES;
1751 }
1752 pass3 = get_password_charater(str);
1753 FreePool(str);
1754
1755 if (pass1 != var->Password[pos1] ||
1756 pass2 != var->Password[pos2] ||
1757 pass3 != var->Password[pos3]) {
1758 console_print(L"Invalid character\n");
1759 fail_count++;
1760 } else {
1761 break;
1762 }
1763 }
1764
1765 if (fail_count >= 3) {
1766 console_notify(L"Password limit reached");
1767 return EFI_ACCESS_DENIED;
1768 }
1769
1770 if (var->MokTMLState == 0)
1771 ret = console_yes_no(trust_tml);
1772 else
1773 ret = console_yes_no(untrust_tml);
1774
1775 if (ret == 0) {
1776 LibDeleteVariable(L"MokListTrustedNew", &SHIM_LOCK_GUID);
1777 return EFI_ABORTED;
1778 }
1779
1780 if (var->MokTMLState == 0) {
1781 efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID,
1782 EFI_VARIABLE_NON_VOLATILE |
1783 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1784 1, &dbval);
1785 if (EFI_ERROR(efi_status)) {
1786 console_notify(L"Failed to set MokListTrusted state");
1787 return efi_status;
1788 }
1789 } else {
1790 efi_status = RT->SetVariable(L"MokListTrusted", &SHIM_LOCK_GUID,
1791 EFI_VARIABLE_NON_VOLATILE |
1792 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1793 0, NULL);
1794 if (EFI_ERROR(efi_status)) {
1795 console_notify(L"Failed to delete MokListTrusted state");
1796 return efi_status;
1797 }
1798 }
1799
1800 return EFI_SUCCESS;
1801 }
1802
1803 static EFI_STATUS mok_pw_prompt(void *MokPW, UINTN MokPWSize)
1804 {
1805 EFI_STATUS efi_status;
1806 UINT8 hash[PASSWORD_CRYPT_SIZE];
1807 UINT8 clear = 0;
1808 CHAR16 *clear_p[] = { L"Clear MOK password?", NULL };
1809 CHAR16 *set_p[] = { L"Set MOK password?", NULL };
1810
1811 if (MokPWSize != SHA256_DIGEST_SIZE && MokPWSize != PASSWORD_CRYPT_SIZE) {
1812 console_notify(L"Invalid MokPW variable contents");
1813 return EFI_INVALID_PARAMETER;
1814 }
1815
1816 clear_screen();
1817
1818 SetMem(hash, PASSWORD_CRYPT_SIZE, 0);
1819
1820 if (MokPWSize == PASSWORD_CRYPT_SIZE) {
1821 if (CompareMem(MokPW, hash, PASSWORD_CRYPT_SIZE) == 0)
1822 clear = 1;
1823 } else {
1824 if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0)
1825 clear = 1;
1826 }
1827
1828 if (clear) {
1829 if (console_yes_no(clear_p) == 0)
1830 return EFI_ABORTED;
1831
1832 RT->SetVariable(L"MokPWStore", &SHIM_LOCK_GUID,
1833 EFI_VARIABLE_NON_VOLATILE |
1834 EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL);
1835 goto mokpw_done;
1836 }
1837
1838 if (MokPWSize == PASSWORD_CRYPT_SIZE) {
1839 efi_status = match_password((PASSWORD_CRYPT *) MokPW, NULL, 0,
1840 NULL, L"Confirm MOK passphrase: ");
1841 } else {
1842 efi_status = match_password(NULL, NULL, 0, MokPW,
1843 L"Confirm MOK passphrase: ");
1844 }
1845
1846 if (EFI_ERROR(efi_status)) {
1847 console_notify(L"Password limit reached");
1848 return efi_status;
1849 }
1850
1851 if (console_yes_no(set_p) == 0)
1852 return EFI_ABORTED;
1853
1854 efi_status = RT->SetVariable(L"MokPWStore", &SHIM_LOCK_GUID,
1855 EFI_VARIABLE_NON_VOLATILE |
1856 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1857 MokPWSize, MokPW);
1858 if (EFI_ERROR(efi_status)) {
1859 console_notify(L"Failed to set MOK password");
1860 return efi_status;
1861 }
1862
1863 mokpw_done:
1864 LibDeleteVariable(L"MokPW", &SHIM_LOCK_GUID);
1865
1866 return EFI_SUCCESS;
1867 }
1868
1869 static BOOLEAN verify_certificate(UINT8 * cert, UINTN size)
1870 {
1871 X509 *X509Cert;
1872 UINTN length;
1873 if (!cert || size < 4)
1874 return FALSE;
1875
1876 /*
1877 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
1878 * the number of length bytes, and the number of value bytes.
1879 * The size of a x509 certificate is usually between 127 bytes
1880 * and 64KB. For convenience, assume the number of value bytes
1881 * is 2, i.e. the second byte is 0x82.
1882 */
1883 if (cert[0] != 0x30 || cert[1] != 0x82) {
1884 console_notify(L"Not a DER encoding X509 certificate");
1885 return FALSE;
1886 }
1887
1888 length = (cert[2] << 8 | cert[3]);
1889 if (length != (size - 4)) {
1890 console_notify(L"Invalid X509 certificate: Inconsistent size");
1891 return FALSE;
1892 }
1893
1894 if (!(X509ConstructCertificate(cert, size, (UINT8 **) & X509Cert)) ||
1895 X509Cert == NULL) {
1896 console_notify(L"Invalid X509 certificate");
1897 return FALSE;
1898 }
1899
1900 X509_free(X509Cert);
1901 return TRUE;
1902 }
1903
1904 static EFI_STATUS enroll_file(void *data, UINTN datasize, BOOLEAN hash)
1905 {
1906 EFI_STATUS efi_status = EFI_SUCCESS;
1907 EFI_SIGNATURE_LIST *CertList;
1908 EFI_SIGNATURE_DATA *CertData;
1909 UINTN mokbuffersize;
1910 void *mokbuffer = NULL;
1911
1912 if (hash) {
1913 UINT8 sha256[SHA256_DIGEST_SIZE];
1914 UINT8 sha1[SHA1_DIGEST_SIZE];
1915 SHIM_LOCK *shim_lock;
1916 PE_COFF_LOADER_IMAGE_CONTEXT context;
1917
1918 efi_status = LibLocateProtocol(&SHIM_LOCK_GUID,
1919 (VOID **) &shim_lock);
1920 if (EFI_ERROR(efi_status))
1921 goto out;
1922
1923 mokbuffersize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) +
1924 SHA256_DIGEST_SIZE;
1925
1926 mokbuffer = AllocatePool(mokbuffersize);
1927 if (!mokbuffer)
1928 goto out;
1929
1930 efi_status = shim_lock->Context(data, datasize, &context);
1931 if (EFI_ERROR(efi_status))
1932 goto out;
1933
1934 efi_status = shim_lock->Hash(data, datasize, &context, sha256,
1935 sha1);
1936 if (EFI_ERROR(efi_status))
1937 goto out;
1938
1939 CertList = mokbuffer;
1940 CertList->SignatureType = EFI_CERT_SHA256_GUID;
1941 CertList->SignatureSize = 16 + SHA256_DIGEST_SIZE;
1942 CertData = (EFI_SIGNATURE_DATA *) (((UINT8 *) mokbuffer) +
1943 sizeof(EFI_SIGNATURE_LIST));
1944 CopyMem(CertData->SignatureData, sha256, SHA256_DIGEST_SIZE);
1945 } else {
1946 mokbuffersize = datasize + sizeof(EFI_SIGNATURE_LIST) +
1947 sizeof(EFI_GUID);
1948 mokbuffer = AllocatePool(mokbuffersize);
1949
1950 if (!mokbuffer)
1951 goto out;
1952
1953 CertList = mokbuffer;
1954 CertList->SignatureType = X509_GUID;
1955 CertList->SignatureSize = 16 + datasize;
1956
1957 memcpy(mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16, data,
1958 datasize);
1959
1960 CertData = (EFI_SIGNATURE_DATA *) (((UINT8 *) mokbuffer) +
1961 sizeof(EFI_SIGNATURE_LIST));
1962 }
1963
1964 CertList->SignatureListSize = mokbuffersize;
1965 CertList->SignatureHeaderSize = 0;
1966 CertData->SignatureOwner = SHIM_LOCK_GUID;
1967
1968 if (!hash) {
1969 if (!verify_certificate(CertData->SignatureData, datasize))
1970 goto out;
1971 }
1972
1973 efi_status = mok_enrollment_prompt(mokbuffer, mokbuffersize,
1974 FALSE, FALSE);
1975 out:
1976 if (mokbuffer)
1977 FreePool(mokbuffer);
1978
1979 return efi_status;
1980 }
1981
1982 static EFI_STATUS mok_hash_enroll(void)
1983 {
1984 EFI_STATUS efi_status;
1985 CHAR16 *file_name = NULL;
1986 EFI_HANDLE im = NULL;
1987 EFI_FILE *file = NULL;
1988 UINTN filesize;
1989 void *data;
1990 CHAR16 *selections[] = {
1991 L"Select Binary",
1992 L"",
1993 L"The Selected Binary will have its hash Enrolled",
1994 L"This means it will subsequently Boot with no prompting",
1995 L"Remember to make sure it is a genuine binary before enrolling its hash",
1996 NULL
1997 };
1998
1999 simple_file_selector(&im, selections, L"\\", L"", &file_name);
2000
2001 if (!file_name)
2002 return EFI_INVALID_PARAMETER;
2003
2004 efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ);
2005 if (EFI_ERROR(efi_status)) {
2006 console_error(L"Unable to open file", efi_status);
2007 return efi_status;
2008 }
2009
2010 simple_file_read_all(file, &filesize, &data);
2011 file->Close(file);
2012 if (!filesize) {
2013 console_error(L"Unable to read file", efi_status);
2014 return EFI_BAD_BUFFER_SIZE;
2015 }
2016
2017 efi_status = enroll_file(data, filesize, TRUE);
2018 if (EFI_ERROR(efi_status))
2019 console_error(
2020 L"Hash failed (did you select a valid EFI binary?)",
2021 efi_status);
2022
2023 FreePool(data);
2024
2025 return efi_status;
2026 }
2027
2028 static CHAR16 *der_suffix[] = {
2029 L".cer",
2030 L".der",
2031 L".crt",
2032 NULL
2033 };
2034
2035 static BOOLEAN check_der_suffix(CHAR16 * file_name)
2036 {
2037 CHAR16 suffix[5];
2038 int i;
2039
2040 if (!file_name || StrLen(file_name) <= 4)
2041 return FALSE;
2042
2043 suffix[0] = '\0';
2044 StrnCat(suffix, file_name + StrLen(file_name) - 4, 4);
2045
2046 StrLwr(suffix);
2047 for (i = 0; der_suffix[i] != NULL; i++) {
2048 if (StrCmp(suffix, der_suffix[i]) == 0) {
2049 return TRUE;
2050 }
2051 }
2052
2053 return FALSE;
2054 }
2055
2056 static EFI_STATUS mok_key_enroll(void)
2057 {
2058 EFI_STATUS efi_status;
2059 CHAR16 *file_name = NULL;
2060 EFI_HANDLE im = NULL;
2061 EFI_FILE *file = NULL;
2062 UINTN filesize;
2063 void *data;
2064 CHAR16 *selections[] = {
2065 L"Select Key",
2066 L"",
2067 L"The selected key will be enrolled into the MOK database",
2068 L"This means any binaries signed with it will be run without prompting",
2069 L"Remember to make sure it is a genuine key before Enrolling it",
2070 NULL
2071 };
2072 CHAR16 *alert[] = {
2073 L"Unsupported Format",
2074 L"",
2075 L"Only DER encoded certificate (*.cer/der/crt) is supported",
2076 NULL
2077 };
2078
2079 simple_file_selector(&im, selections, L"\\", L"", &file_name);
2080
2081 if (!file_name)
2082 return EFI_INVALID_PARAMETER;
2083
2084 if (!check_der_suffix(file_name)) {
2085 console_alertbox(alert);
2086 return EFI_UNSUPPORTED;
2087 }
2088
2089 efi_status = simple_file_open(im, file_name, &file, EFI_FILE_MODE_READ);
2090 if (EFI_ERROR(efi_status)) {
2091 console_error(L"Unable to open file", efi_status);
2092 return efi_status;
2093 }
2094
2095 simple_file_read_all(file, &filesize, &data);
2096 file->Close(file);
2097 if (!filesize) {
2098 console_error(L"Unable to read file", efi_status);
2099 return EFI_BAD_BUFFER_SIZE;
2100 }
2101
2102 efi_status = enroll_file(data, filesize, FALSE);
2103 FreePool(data);
2104
2105 return efi_status;
2106 }
2107
2108 static BOOLEAN verify_pw(BOOLEAN * protected)
2109 {
2110 EFI_STATUS efi_status;
2111 SIMPLE_TEXT_OUTPUT_MODE SavedMode;
2112 UINT8 pwhash[PASSWORD_CRYPT_SIZE];
2113 UINTN size = PASSWORD_CRYPT_SIZE;
2114 UINT32 attributes;
2115 CHAR16 *message[2];
2116
2117 *protected = FALSE;
2118
2119 efi_status = RT->GetVariable(L"MokPWStore", &SHIM_LOCK_GUID, &attributes,
2120 &size, pwhash);
2121 /*
2122 * If anything can attack the password it could just set it to a
2123 * known value, so there's no safety advantage in failing to validate
2124 * purely because of a failure to read the variable
2125 */
2126 if (EFI_ERROR(efi_status) ||
2127 (size != SHA256_DIGEST_SIZE && size != PASSWORD_CRYPT_SIZE))
2128 return TRUE;
2129
2130 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS)
2131 return TRUE;
2132
2133 clear_screen();
2134
2135 /* Draw the background */
2136 console_save_and_set_mode(&SavedMode);
2137 message[0] = PoolPrint(L"%s UEFI key management", SHIM_VENDOR);
2138 message[1] = NULL;
2139 console_print_box_at(message, -1, 0, 0, -1, -1, 1, 1);
2140 FreePool(message[0]);
2141 console_restore_mode(&SavedMode);
2142
2143 if (size == PASSWORD_CRYPT_SIZE) {
2144 efi_status = match_password((PASSWORD_CRYPT *) pwhash, NULL, 0,
2145 NULL, L"Enter MOK password:");
2146 } else {
2147 efi_status = match_password(NULL, NULL, 0, pwhash,
2148 L"Enter MOK password:");
2149 }
2150 if (EFI_ERROR(efi_status)) {
2151 console_notify(L"Password limit reached");
2152 return FALSE;
2153 }
2154
2155 *protected = TRUE;
2156
2157 return TRUE;
2158 }
2159
2160 static int draw_countdown()
2161 {
2162 CHAR16 *message = L"Press any key to perform MOK management";
2163 CHAR16 *title;
2164 void *MokTimeout = NULL;
2165 MokTimeoutvar *var;
2166 UINTN MokTimeoutSize = 0;
2167 int timeout = 10;
2168 EFI_STATUS efi_status;
2169
2170 efi_status = get_variable(L"MokTimeout", (UINT8 **) &MokTimeout,
2171 &MokTimeoutSize, SHIM_LOCK_GUID);
2172 if (!EFI_ERROR(efi_status)) {
2173 var = MokTimeout;
2174 timeout = (int)var->Timeout;
2175 FreePool(MokTimeout);
2176 LibDeleteVariable(L"MokTimeout", &SHIM_LOCK_GUID);
2177 }
2178
2179 if (timeout < 0)
2180 return timeout;
2181
2182 title = PoolPrint(L"%s UEFI key management", SHIM_VENDOR);
2183 timeout = console_countdown(title, message, timeout);
2184
2185 FreePool(title);
2186 return timeout;
2187 }
2188
2189 typedef enum {
2190 MOK_BOOT,
2191 MOK_RESET_MOK,
2192 MOK_RESET_MOKX,
2193 MOK_ENROLL_MOK,
2194 MOK_ENROLL_MOKX,
2195 MOK_DELETE_MOK,
2196 MOK_DELETE_MOKX,
2197 MOK_CHANGE_SB,
2198 MOK_SET_PW,
2199 MOK_CHANGE_DB,
2200 MOK_KEY_ENROLL,
2201 MOK_HASH_ENROLL,
2202 MOK_CHANGE_TML
2203 } mok_menu_item;
2204
2205 static void free_menu(mok_menu_item * menu_item, CHAR16 ** menu_strings)
2206 {
2207 if (menu_strings)
2208 FreePool(menu_strings);
2209
2210 if (menu_item)
2211 FreePool(menu_item);
2212 }
2213
2214 static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle UNUSED,
2215 void *MokNew, UINTN MokNewSize,
2216 void *MokDel, UINTN MokDelSize,
2217 void *MokSB, UINTN MokSBSize,
2218 void *MokPW, UINTN MokPWSize,
2219 void *MokDB, UINTN MokDBSize,
2220 void *MokXNew, UINTN MokXNewSize,
2221 void *MokXDel, UINTN MokXDelSize,
2222 void *MokTML, UINTN MokTMLSize)
2223 {
2224 CHAR16 **menu_strings = NULL;
2225 mok_menu_item *menu_item = NULL;
2226 int choice = 0;
2227 int mok_changed = 0;
2228 EFI_STATUS efi_status;
2229 UINT8 auth[PASSWORD_CRYPT_SIZE];
2230 UINTN auth_size = PASSWORD_CRYPT_SIZE;
2231 UINT32 attributes;
2232 BOOLEAN protected;
2233 CHAR16 *mok_mgmt_p[] = { L"Perform MOK management", NULL };
2234 EFI_STATUS ret = EFI_SUCCESS;
2235
2236 if (verify_pw(&protected) == FALSE)
2237 return EFI_ACCESS_DENIED;
2238
2239 if (protected == FALSE && draw_countdown() == 0)
2240 goto out;
2241
2242 while (choice >= 0) {
2243 UINTN menucount = 3, i = 0;
2244 UINT32 MokAuth = 0;
2245 UINT32 MokDelAuth = 0;
2246 UINT32 MokXAuth = 0;
2247 UINT32 MokXDelAuth = 0;
2248
2249 efi_status = RT->GetVariable(L"MokAuth", &SHIM_LOCK_GUID,
2250 &attributes, &auth_size, auth);
2251 if (!EFI_ERROR(efi_status) &&
2252 (auth_size == SHA256_DIGEST_SIZE ||
2253 auth_size == PASSWORD_CRYPT_SIZE))
2254 MokAuth = 1;
2255
2256 efi_status = RT->GetVariable(L"MokDelAuth", &SHIM_LOCK_GUID,
2257 &attributes, &auth_size, auth);
2258 if (!EFI_ERROR(efi_status) &&
2259 (auth_size == SHA256_DIGEST_SIZE ||
2260 auth_size == PASSWORD_CRYPT_SIZE))
2261 MokDelAuth = 1;
2262
2263 efi_status = RT->GetVariable(L"MokXAuth", &SHIM_LOCK_GUID,
2264 &attributes, &auth_size, auth);
2265 if (!EFI_ERROR(efi_status) &&
2266 (auth_size == SHA256_DIGEST_SIZE ||
2267 auth_size == PASSWORD_CRYPT_SIZE))
2268 MokXAuth = 1;
2269
2270 efi_status = RT->GetVariable(L"MokXDelAuth", &SHIM_LOCK_GUID,
2271 &attributes, &auth_size, auth);
2272 if (!EFI_ERROR(efi_status) &&
2273 (auth_size == SHA256_DIGEST_SIZE ||
2274 auth_size == PASSWORD_CRYPT_SIZE))
2275 MokXDelAuth = 1;
2276
2277 if (MokNew || MokAuth)
2278 menucount++;
2279
2280 if (MokDel || MokDelAuth)
2281 menucount++;
2282
2283 if (MokXNew || MokXAuth)
2284 menucount++;
2285
2286 if (MokXDel || MokXDelAuth)
2287 menucount++;
2288
2289 if (MokSB)
2290 menucount++;
2291
2292 if (MokPW)
2293 menucount++;
2294
2295 if (MokDB)
2296 menucount++;
2297
2298 if (MokTML)
2299 menucount++;
2300
2301 menu_strings = AllocateZeroPool(sizeof(CHAR16 *) *
2302 (menucount + 1));
2303 if (!menu_strings)
2304 return EFI_OUT_OF_RESOURCES;
2305
2306 menu_item = AllocateZeroPool(sizeof(mok_menu_item) * menucount);
2307 if (!menu_item) {
2308 FreePool(menu_strings);
2309 return EFI_OUT_OF_RESOURCES;
2310 }
2311
2312 if (mok_changed)
2313 menu_strings[i] = L"Reboot";
2314 else
2315 menu_strings[i] = L"Continue boot";
2316 menu_item[i] = MOK_BOOT;
2317
2318 i++;
2319
2320 if (MokNew || MokAuth) {
2321 if (!MokNew) {
2322 menu_strings[i] = L"Reset MOK";
2323 menu_item[i] = MOK_RESET_MOK;
2324 } else {
2325 menu_strings[i] = L"Enroll MOK";
2326 menu_item[i] = MOK_ENROLL_MOK;
2327 }
2328 i++;
2329 }
2330
2331 if (MokDel || MokDelAuth) {
2332 menu_strings[i] = L"Delete MOK";
2333 menu_item[i] = MOK_DELETE_MOK;
2334 i++;
2335 }
2336
2337 if (MokXNew || MokXAuth) {
2338 if (!MokXNew) {
2339 menu_strings[i] = L"Reset MOKX";
2340 menu_item[i] = MOK_RESET_MOKX;
2341 } else {
2342 menu_strings[i] = L"Enroll MOKX";
2343 menu_item[i] = MOK_ENROLL_MOKX;
2344 }
2345 i++;
2346 }
2347
2348 if (MokXDel || MokXDelAuth) {
2349 menu_strings[i] = L"Delete MOKX";
2350 menu_item[i] = MOK_DELETE_MOKX;
2351 i++;
2352 }
2353
2354 if (MokSB) {
2355 menu_strings[i] = L"Change Secure Boot state";
2356 menu_item[i] = MOK_CHANGE_SB;
2357 i++;
2358 }
2359
2360 if (MokPW) {
2361 menu_strings[i] = L"Set MOK password";
2362 menu_item[i] = MOK_SET_PW;
2363 i++;
2364 }
2365
2366 if (MokDB) {
2367 menu_strings[i] = L"Change DB state";
2368 menu_item[i] = MOK_CHANGE_DB;
2369 i++;
2370 }
2371
2372 if (MokTML) {
2373 menu_strings[i] = L"Change MOK List Trusted State";
2374 menu_item[i] = MOK_CHANGE_TML;
2375 i++;
2376 }
2377
2378 menu_strings[i] = L"Enroll key from disk";
2379 menu_item[i] = MOK_KEY_ENROLL;
2380 i++;
2381
2382 menu_strings[i] = L"Enroll hash from disk";
2383 menu_item[i] = MOK_HASH_ENROLL;
2384 i++;
2385
2386 menu_strings[i] = NULL;
2387
2388 choice = console_select(mok_mgmt_p, menu_strings, 0);
2389 if (choice < 0)
2390 goto out;
2391
2392 switch (menu_item[choice]) {
2393 case MOK_BOOT:
2394 goto out;
2395 case MOK_RESET_MOK:
2396 efi_status = mok_reset_prompt(FALSE);
2397 break;
2398 case MOK_ENROLL_MOK:
2399 if (!MokNew) {
2400 console_print(L"MokManager: internal error: %s",
2401 L"MokNew was !NULL but is now NULL\n");
2402 ret = EFI_ABORTED;
2403 goto out;
2404 }
2405 efi_status = mok_enrollment_prompt(MokNew, MokNewSize,
2406 TRUE, FALSE);
2407 if (!EFI_ERROR(efi_status))
2408 MokNew = NULL;
2409 break;
2410 case MOK_DELETE_MOK:
2411 if (!MokDel) {
2412 console_print(L"MokManager: internal error: %s",
2413 L"MokDel was !NULL but is now NULL\n");
2414 ret = EFI_ABORTED;
2415 goto out;
2416 }
2417 efi_status = mok_deletion_prompt(MokDel, MokDelSize,
2418 FALSE);
2419 if (!EFI_ERROR(efi_status))
2420 MokDel = NULL;
2421 break;
2422 case MOK_RESET_MOKX:
2423 efi_status = mok_reset_prompt(TRUE);
2424 break;
2425 case MOK_ENROLL_MOKX:
2426 if (!MokXNew) {
2427 console_print(L"MokManager: internal error: %s",
2428 L"MokXNew was !NULL but is now NULL\n");
2429 ret = EFI_ABORTED;
2430 goto out;
2431 }
2432 efi_status = mok_enrollment_prompt(MokXNew, MokXNewSize,
2433 TRUE, TRUE);
2434 if (!EFI_ERROR(efi_status))
2435 MokXNew = NULL;
2436 break;
2437 case MOK_DELETE_MOKX:
2438 if (!MokXDel) {
2439 console_print(L"MokManager: internal error: %s",
2440 L"MokXDel was !NULL but is now NULL\n");
2441 ret = EFI_ABORTED;
2442 goto out;
2443 }
2444 efi_status = mok_deletion_prompt(MokXDel, MokXDelSize,
2445 TRUE);
2446 if (!EFI_ERROR(efi_status))
2447 MokXDel = NULL;
2448 break;
2449 case MOK_CHANGE_SB:
2450 if (!MokSB) {
2451 console_print(L"MokManager: internal error: %s",
2452 L"MokSB was !NULL but is now NULL\n");
2453 ret = EFI_ABORTED;
2454 goto out;
2455 }
2456 efi_status = mok_sb_prompt(MokSB, MokSBSize);
2457 if (!EFI_ERROR(efi_status))
2458 MokSB = NULL;
2459 break;
2460 case MOK_SET_PW:
2461 if (!MokPW) {
2462 console_print(L"MokManager: internal error: %s",
2463 L"MokPW was !NULL but is now NULL\n");
2464 ret = EFI_ABORTED;
2465 goto out;
2466 }
2467 efi_status = mok_pw_prompt(MokPW, MokPWSize);
2468 if (!EFI_ERROR(efi_status))
2469 MokPW = NULL;
2470 break;
2471 case MOK_CHANGE_DB:
2472 if (!MokDB) {
2473 console_print(L"MokManager: internal error: %s",
2474 L"MokDB was !NULL but is now NULL\n");
2475 ret = EFI_ABORTED;
2476 goto out;
2477 }
2478 efi_status = mok_db_prompt(MokDB, MokDBSize);
2479 if (!EFI_ERROR(efi_status))
2480 MokDB = NULL;
2481 break;
2482 case MOK_KEY_ENROLL:
2483 efi_status = mok_key_enroll();
2484 break;
2485 case MOK_HASH_ENROLL:
2486 efi_status = mok_hash_enroll();
2487 break;
2488 case MOK_CHANGE_TML:
2489 if (!MokTML) {
2490 console_print(L"MokManager: internal error: %s",
2491 L"MokListTrusted was ! NULL bs is now NULL\n");
2492 ret = EFI_ABORTED;
2493 goto out;
2494 }
2495 efi_status = mok_tml_prompt(MokTML, MokTMLSize);
2496 if (!EFI_ERROR(efi_status))
2497 MokTML = NULL;
2498 break;
2499 }
2500
2501 if (!EFI_ERROR(efi_status))
2502 mok_changed = 1;
2503
2504 free_menu(menu_item, menu_strings);
2505 menu_item = NULL;
2506 menu_strings = NULL;
2507 }
2508
2509 out:
2510 free_menu(menu_item, menu_strings);
2511
2512 if (mok_changed)
2513 return reset_system();
2514
2515 console_reset();
2516
2517 return ret;
2518 }
2519
2520 static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
2521 {
2522 UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0;
2523 UINTN MokDBSize = 0, MokXNewSize = 0, MokXDelSize = 0, MokTMLSize = 0;
2524 void *MokNew = NULL;
2525 void *MokDel = NULL;
2526 void *MokSB = NULL;
2527 void *MokPW = NULL;
2528 void *MokDB = NULL;
2529 void *MokXNew = NULL;
2530 void *MokXDel = NULL;
2531 void *MokTML = NULL;
2532 EFI_STATUS efi_status;
2533
2534 efi_status = get_variable(L"MokNew", (UINT8 **) & MokNew, &MokNewSize,
2535 SHIM_LOCK_GUID);
2536 if (!EFI_ERROR(efi_status)) {
2537 efi_status = LibDeleteVariable(L"MokNew", &SHIM_LOCK_GUID);
2538 if (EFI_ERROR(efi_status))
2539 console_notify(L"Failed to delete MokNew");
2540 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2541 console_error(L"Could not retrieve MokNew", efi_status);
2542 }
2543
2544 efi_status = get_variable(L"MokDel", (UINT8 **) & MokDel, &MokDelSize,
2545 SHIM_LOCK_GUID);
2546 if (!EFI_ERROR(efi_status)) {
2547 efi_status = LibDeleteVariable(L"MokDel", &SHIM_LOCK_GUID);
2548 if (EFI_ERROR(efi_status))
2549 console_notify(L"Failed to delete MokDel");
2550 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2551 console_error(L"Could not retrieve MokDel", efi_status);
2552 }
2553
2554 efi_status = get_variable(L"MokSB", (UINT8 **) & MokSB, &MokSBSize,
2555 SHIM_LOCK_GUID);
2556 if (!EFI_ERROR(efi_status)) {
2557 efi_status = LibDeleteVariable(L"MokSB", &SHIM_LOCK_GUID);
2558 if (EFI_ERROR(efi_status))
2559 console_notify(L"Failed to delete MokSB");
2560 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2561 console_error(L"Could not retrieve MokSB", efi_status);
2562 }
2563
2564 efi_status = get_variable(L"MokPW", (UINT8 **) & MokPW, &MokPWSize,
2565 SHIM_LOCK_GUID);
2566 if (!EFI_ERROR(efi_status)) {
2567 efi_status = LibDeleteVariable(L"MokPW", &SHIM_LOCK_GUID);
2568 if (EFI_ERROR(efi_status))
2569 console_notify(L"Failed to delete MokPW");
2570 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2571 console_error(L"Could not retrieve MokPW", efi_status);
2572 }
2573
2574 efi_status = get_variable(L"MokDB", (UINT8 **) & MokDB, &MokDBSize,
2575 SHIM_LOCK_GUID);
2576 if (!EFI_ERROR(efi_status)) {
2577 efi_status = LibDeleteVariable(L"MokDB", &SHIM_LOCK_GUID);
2578 if (EFI_ERROR(efi_status))
2579 console_notify(L"Failed to delete MokDB");
2580 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2581 console_error(L"Could not retrieve MokDB", efi_status);
2582 }
2583
2584 efi_status = get_variable(L"MokListTrustedNew", (UINT8 **) & MokTML,
2585 &MokTMLSize, SHIM_LOCK_GUID);
2586 if (!EFI_ERROR(efi_status)) {
2587 efi_status = LibDeleteVariable(L"MokListTrustedNew",
2588 &SHIM_LOCK_GUID);
2589 if (EFI_ERROR(efi_status))
2590 console_notify(L"Failed to delete MokListTrustedNew");
2591 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2592 console_error(L"Could not retrieve MokListTrustedNew",
2593 efi_status);
2594 }
2595
2596 efi_status = get_variable(L"MokXNew", (UINT8 **) & MokXNew,
2597 &MokXNewSize, SHIM_LOCK_GUID);
2598 if (!EFI_ERROR(efi_status)) {
2599 efi_status = LibDeleteVariable(L"MokXNew", &SHIM_LOCK_GUID);
2600 if (EFI_ERROR(efi_status))
2601 console_notify(L"Failed to delete MokXNew");
2602 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2603 console_error(L"Could not retrieve MokXNew", efi_status);
2604 }
2605
2606 efi_status = get_variable(L"MokXDel", (UINT8 **) & MokXDel,
2607 &MokXDelSize, SHIM_LOCK_GUID);
2608 if (!EFI_ERROR(efi_status)) {
2609 efi_status = LibDeleteVariable(L"MokXDel", &SHIM_LOCK_GUID);
2610 if (EFI_ERROR(efi_status))
2611 console_notify(L"Failed to delete MokXDel");
2612 } else if (EFI_ERROR(efi_status) && efi_status != EFI_NOT_FOUND) {
2613 console_error(L"Could not retrieve MokXDel", efi_status);
2614 }
2615
2616 enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize,
2617 MokSB, MokSBSize, MokPW, MokPWSize, MokDB, MokDBSize,
2618 MokXNew, MokXNewSize, MokXDel, MokXDelSize, MokTML, MokTMLSize);
2619
2620 if (MokNew)
2621 FreePool(MokNew);
2622
2623 if (MokDel)
2624 FreePool(MokDel);
2625
2626 if (MokSB)
2627 FreePool(MokSB);
2628
2629 if (MokPW)
2630 FreePool(MokPW);
2631
2632 if (MokDB)
2633 FreePool(MokDB);
2634
2635 if (MokXNew)
2636 FreePool(MokXNew);
2637
2638 if (MokXDel)
2639 FreePool(MokXDel);
2640
2641 if (MokTML)
2642 FreePool(MokTML);
2643
2644 LibDeleteVariable(L"MokAuth", &SHIM_LOCK_GUID);
2645 LibDeleteVariable(L"MokDelAuth", &SHIM_LOCK_GUID);
2646 LibDeleteVariable(L"MokXAuth", &SHIM_LOCK_GUID);
2647 LibDeleteVariable(L"MokXDelAuth", &SHIM_LOCK_GUID);
2648
2649 return EFI_SUCCESS;
2650 }
2651
2652 static EFI_STATUS setup_rand(void)
2653 {
2654 EFI_TIME time;
2655 EFI_STATUS efi_status;
2656 UINT64 seed;
2657 BOOLEAN status;
2658
2659 efi_status = RT->GetTime(&time, NULL);
2660 if (EFI_ERROR(efi_status))
2661 return efi_status;
2662
2663 seed = ((UINT64) time.Year << 48) | ((UINT64) time.Month << 40) |
2664 ((UINT64) time.Day << 32) | ((UINT64) time.Hour << 24) |
2665 ((UINT64) time.Minute << 16) | ((UINT64) time.Second << 8) |
2666 ((UINT64) time.Daylight);
2667
2668 status = RandomSeed((UINT8 *) & seed, sizeof(seed));
2669 if (!status)
2670 return EFI_ABORTED;
2671
2672 return EFI_SUCCESS;
2673 }
2674
2675 EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE * systab)
2676 {
2677 EFI_STATUS efi_status;
2678
2679 InitializeLib(image_handle, systab);
2680
2681 setup_verbosity();
2682 setup_rand();
2683
2684 console_mode_handle();
2685
2686 efi_status = check_mok_request(image_handle);
2687
2688 console_fini();
2689 return efi_status;
2690 }