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