]> git.proxmox.com Git - efi-boot-shim.git/blame - MokManager.c
Make sure the menu shows when the callback fails
[efi-boot-shim.git] / MokManager.c
CommitLineData
333bd977
GCPL
1#include <efi.h>
2#include <efilib.h>
3#include <Library/BaseCryptLib.h>
4#include <openssl/x509.h>
5#include "shim.h"
0a6565c5
MG
6#include "signature.h"
7#include "PeImage.h"
333bd977 8
aa8e9067
GCPL
9#define PASSWORD_MAX 16
10#define PASSWORD_MIN 8
9272bc5b 11#define SB_PASSWORD_LEN 8
ff857b4b 12
e204505d
MG
13#ifndef SHIM_VENDOR
14#define SHIM_VENDOR L"Shim"
15#endif
16
0a6565c5
MG
17#define EFI_VARIABLE_APPEND_WRITE 0x00000040
18
1bc1cd96
MG
19#define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
20#define HASH_STRING L"Select a file to trust:\n\n"
21
d991c4a1
MG
22struct menu_item {
23 CHAR16 *text;
0a6565c5 24 INTN (* callback)(void *data, void *data2, void *data3);
d991c4a1
MG
25 void *data;
26 void *data2;
0a6565c5 27 void *data3;
d991c4a1
MG
28 UINTN colour;
29};
30
333bd977
GCPL
31typedef struct {
32 UINT32 MokSize;
33 UINT8 *Mok;
92a136d8 34 EFI_GUID Type;
cb22de62 35} __attribute__ ((packed)) MokListNode;
333bd977 36
9272bc5b
MG
37typedef struct {
38 UINT32 MokSBState;
79a5aa03
MG
39 UINT32 PWLen;
40 CHAR16 Password[PASSWORD_MAX];
9272bc5b
MG
41} __attribute__ ((packed)) MokSBvar;
42
92a136d8
GCPL
43static EFI_STATUS get_variable (CHAR16 *name, EFI_GUID guid, UINT32 *attributes,
44 UINTN *size, void **buffer)
45{
46 EFI_STATUS efi_status;
47 char allocate = !(*size);
48
49 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
50 attributes, size, buffer);
51
52 if (efi_status != EFI_BUFFER_TOO_SMALL || !allocate) {
53 return efi_status;
54 }
55
56 *buffer = AllocatePool(*size);
57
58 if (!*buffer) {
59 Print(L"Unable to allocate variable buffer\n");
60 return EFI_OUT_OF_RESOURCES;
61 }
62
63 efi_status = uefi_call_wrapper(RT->GetVariable, 5, name, &guid,
64 attributes, size, *buffer);
65
66 return efi_status;
67}
68
333bd977
GCPL
69static EFI_INPUT_KEY get_keystroke (void)
70{
71 EFI_INPUT_KEY key;
72 UINTN EventIndex;
73
74 uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey,
75 &EventIndex);
76 uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &key);
77
78 return key;
79}
80
5e43e91f 81static EFI_STATUS get_sha1sum (void *Data, int DataSize, UINT8 *hash)
333bd977
GCPL
82{
83 EFI_STATUS status;
84 unsigned int ctxsize;
85 void *ctx = NULL;
86
5e43e91f 87 ctxsize = Sha1GetContextSize();
333bd977
GCPL
88 ctx = AllocatePool(ctxsize);
89
90 if (!ctx) {
91 Print(L"Unable to allocate memory for hash context\n");
92 return EFI_OUT_OF_RESOURCES;
93 }
94
5e43e91f 95 if (!Sha1Init(ctx)) {
333bd977
GCPL
96 Print(L"Unable to initialise hash\n");
97 status = EFI_OUT_OF_RESOURCES;
98 goto done;
99 }
100
5e43e91f 101 if (!(Sha1Update(ctx, Data, DataSize))) {
333bd977
GCPL
102 Print(L"Unable to generate hash\n");
103 status = EFI_OUT_OF_RESOURCES;
104 goto done;
105 }
106
5e43e91f 107 if (!(Sha1Final(ctx, hash))) {
333bd977
GCPL
108 Print(L"Unable to finalise hash\n");
109 status = EFI_OUT_OF_RESOURCES;
110 goto done;
111 }
112
113 status = EFI_SUCCESS;
114done:
115 return status;
116}
117
92a136d8
GCPL
118static UINT32 count_keys(void *Data, UINTN DataSize)
119{
120 EFI_SIGNATURE_LIST *CertList = Data;
121 EFI_GUID CertType = EfiCertX509Guid;
122 EFI_GUID HashType = EfiHashSha256Guid;
123 UINTN dbsize = DataSize;
124 UINT32 MokNum = 0;
125
126 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
127 if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
128 (CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
129 Print(L"Doesn't look like a key or hash\n");
130 dbsize -= CertList->SignatureListSize;
131 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
132 CertList->SignatureListSize);
133 continue;
134 }
135
136 if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
137 (CertList->SignatureSize != 48)) {
138 Print(L"Doesn't look like a valid hash\n");
139 dbsize -= CertList->SignatureListSize;
140 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
141 CertList->SignatureListSize);
142 continue;
143 }
144
145 MokNum++;
146 dbsize -= CertList->SignatureListSize;
147 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
148 CertList->SignatureListSize);
149 }
150
151 return MokNum;
152}
153
333bd977
GCPL
154static MokListNode *build_mok_list(UINT32 num, void *Data, UINTN DataSize) {
155 MokListNode *list;
0a6565c5
MG
156 EFI_SIGNATURE_LIST *CertList = Data;
157 EFI_SIGNATURE_DATA *Cert;
158 EFI_GUID CertType = EfiCertX509Guid;
159 EFI_GUID HashType = EfiHashSha256Guid;
160 UINTN dbsize = DataSize;
161 UINTN count = 0;
6919a3f7 162
333bd977
GCPL
163 list = AllocatePool(sizeof(MokListNode) * num);
164
165 if (!list) {
166 Print(L"Unable to allocate MOK list\n");
167 return NULL;
168 }
169
0a6565c5
MG
170 while ((dbsize > 0) && (dbsize >= CertList->SignatureListSize)) {
171 if ((CompareGuid (&CertList->SignatureType, &CertType) != 0) &&
172 (CompareGuid (&CertList->SignatureType, &HashType) != 0)) {
173 dbsize -= CertList->SignatureListSize;
174 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
3a593361 175 CertList->SignatureListSize);
0a6565c5
MG
176 continue;
177 }
c326e2df 178
0a6565c5
MG
179 if ((CompareGuid (&CertList->SignatureType, &HashType) == 0) &&
180 (CertList->SignatureSize != 48)) {
181 dbsize -= CertList->SignatureListSize;
182 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *) CertList +
3a593361 183 CertList->SignatureListSize);
0a6565c5 184 continue;
333bd977
GCPL
185 }
186
0a6565c5
MG
187 Cert = (EFI_SIGNATURE_DATA *) (((UINT8 *) CertList) +
188 sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
189
a05c7c57 190 list[count].MokSize = CertList->SignatureSize - sizeof(EFI_GUID);
0a6565c5 191 list[count].Mok = (void *)Cert->SignatureData;
92a136d8 192 list[count].Type = CertList->SignatureType;
0a6565c5
MG
193
194 count++;
195 dbsize -= CertList->SignatureListSize;
196 CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList +
3a593361 197 CertList->SignatureListSize);
333bd977
GCPL
198 }
199
200 return list;
201}
202
ea8ee444 203static void print_x509_name (X509_NAME *X509Name, CHAR16 *name)
333bd977
GCPL
204{
205 char *str;
206
207 str = X509_NAME_oneline(X509Name, NULL, 0);
208 if (str) {
ea8ee444 209 Print(L" %s:\n %a\n", name, str);
333bd977
GCPL
210 OPENSSL_free(str);
211 }
212}
213
214static const char *mon[12]= {
215"Jan","Feb","Mar","Apr","May","Jun",
216"Jul","Aug","Sep","Oct","Nov","Dec"
217};
218
ea8ee444
GCPL
219static void print_x509_GENERALIZEDTIME_time (ASN1_TIME *time, CHAR16 *time_string)
220{
333bd977
GCPL
221 char *v;
222 int gmt = 0;
223 int i;
224 int y = 0,M = 0,d = 0,h = 0,m = 0,s = 0;
225 char *f = NULL;
226 int f_len = 0;
227
228 i=time->length;
229 v=(char *)time->data;
230
231 if (i < 12)
232 goto error;
233
234 if (v[i-1] == 'Z')
235 gmt=1;
236
237 for (i=0; i<12; i++) {
238 if ((v[i] > '9') || (v[i] < '0'))
239 goto error;
240 }
241
242 y = (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
243 M = (v[4]-'0')*10+(v[5]-'0');
244
245 if ((M > 12) || (M < 1))
246 goto error;
247
248 d = (v[6]-'0')*10+(v[7]-'0');
249 h = (v[8]-'0')*10+(v[9]-'0');
250 m = (v[10]-'0')*10+(v[11]-'0');
251
252 if (time->length >= 14 &&
253 (v[12] >= '0') && (v[12] <= '9') &&
254 (v[13] >= '0') && (v[13] <= '9')) {
255 s = (v[12]-'0')*10+(v[13]-'0');
256 /* Check for fractions of seconds. */
257 if (time->length >= 15 && v[14] == '.') {
258 int l = time->length;
259 f = &v[14]; /* The decimal point. */
260 f_len = 1;
ea8ee444
GCPL
261 while (14 + f_len < l && f[f_len] >= '0' &&
262 f[f_len] <= '9')
333bd977
GCPL
263 ++f_len;
264 }
265 }
266
ea8ee444
GCPL
267 SPrint(time_string, 0, L"%a %2d %02d:%02d:%02d%.*a %d%a",
268 mon[M-1], d, h, m, s, f_len, f, y, (gmt)?" GMT":"");
333bd977
GCPL
269error:
270 return;
271}
272
ea8ee444 273static void print_x509_UTCTIME_time (ASN1_TIME *time, CHAR16 *time_string)
333bd977
GCPL
274{
275 char *v;
276 int gmt=0;
277 int i;
278 int y = 0,M = 0,d = 0,h = 0,m = 0,s = 0;
279
280 i=time->length;
281 v=(char *)time->data;
282
283 if (i < 10)
284 goto error;
285
286 if (v[i-1] == 'Z')
287 gmt=1;
288
289 for (i=0; i<10; i++)
290 if ((v[i] > '9') || (v[i] < '0'))
291 goto error;
292
293 y = (v[0]-'0')*10+(v[1]-'0');
294
295 if (y < 50)
296 y+=100;
297
298 M = (v[2]-'0')*10+(v[3]-'0');
299
300 if ((M > 12) || (M < 1))
301 goto error;
302
303 d = (v[4]-'0')*10+(v[5]-'0');
304 h = (v[6]-'0')*10+(v[7]-'0');
305 m = (v[8]-'0')*10+(v[9]-'0');
306
307 if (time->length >=12 &&
308 (v[10] >= '0') && (v[10] <= '9') &&
309 (v[11] >= '0') && (v[11] <= '9'))
310 s = (v[10]-'0')*10+(v[11]-'0');
311
ea8ee444
GCPL
312 SPrint(time_string, 0, L"%a %2d %02d:%02d:%02d %d%a",
313 mon[M-1], d, h, m, s, y+1900, (gmt)?" GMT":"");
333bd977
GCPL
314error:
315 return;
316}
317
ea8ee444 318static void print_x509_time (ASN1_TIME *time, CHAR16 *name)
333bd977 319{
ea8ee444
GCPL
320 CHAR16 time_string[30];
321
f78ff3bf 322 if (time->type == V_ASN1_UTCTIME) {
ea8ee444 323 print_x509_UTCTIME_time(time, time_string);
f78ff3bf 324 } else if (time->type == V_ASN1_GENERALIZEDTIME) {
ea8ee444 325 print_x509_GENERALIZEDTIME_time(time, time_string);
f78ff3bf
GCPL
326 } else {
327 time_string[0] = '\0';
328 }
ea8ee444
GCPL
329
330 Print(L" %s:\n %s\n", name, time_string);
333bd977
GCPL
331}
332
333static void show_x509_info (X509 *X509Cert)
334{
ea8ee444
GCPL
335 ASN1_INTEGER *serial;
336 BIGNUM *bnser;
337 unsigned char hexbuf[30];
333bd977
GCPL
338 X509_NAME *X509Name;
339 ASN1_TIME *time;
340
ea8ee444
GCPL
341 serial = X509_get_serialNumber(X509Cert);
342 if (serial) {
343 int i, n;
344 bnser = ASN1_INTEGER_to_BN(serial, NULL);
345 n = BN_bn2bin(bnser, hexbuf);
346 Print(L" Serial Number:\n ");
347 for (i = 0; i < n-1; i++) {
348 Print(L"%02x:", hexbuf[i]);
349 }
350 Print(L"%02x\n", hexbuf[n-1]);
351 }
352
333bd977
GCPL
353 X509Name = X509_get_issuer_name(X509Cert);
354 if (X509Name) {
ea8ee444 355 print_x509_name(X509Name, L"Issuer");
333bd977
GCPL
356 }
357
358 X509Name = X509_get_subject_name(X509Cert);
359 if (X509Name) {
ea8ee444 360 print_x509_name(X509Name, L"Subject");
333bd977
GCPL
361 }
362
363 time = X509_get_notBefore(X509Cert);
364 if (time) {
ea8ee444 365 print_x509_time(time, L"Validity from");
333bd977
GCPL
366 }
367
368 time = X509_get_notAfter(X509Cert);
369 if (time) {
ea8ee444 370 print_x509_time(time, L"Validity till");
333bd977
GCPL
371 }
372}
373
374static void show_mok_info (void *Mok, UINTN MokSize)
375{
376 EFI_STATUS efi_status;
5e43e91f 377 UINT8 hash[SHA1_DIGEST_SIZE];
333bd977
GCPL
378 unsigned int i;
379 X509 *X509Cert;
380
381 if (!Mok || MokSize == 0)
382 return;
383
a05c7c57 384 if (MokSize != SHA256_DIGEST_SIZE) {
16c512f9
MG
385 if (X509ConstructCertificate(Mok, MokSize,
386 (UINT8 **) &X509Cert) && X509Cert != NULL) {
0a6565c5
MG
387 show_x509_info(X509Cert);
388 X509_free(X509Cert);
389 } else {
390 Print(L" Not a valid X509 certificate: %x\n\n",
391 ((UINT32 *)Mok)[0]);
392 return;
393 }
16c512f9
MG
394
395 efi_status = get_sha1sum(Mok, MokSize, hash);
396
397 if (efi_status != EFI_SUCCESS) {
398 Print(L"Failed to compute MOK fingerprint\n");
399 return;
400 }
401
402 Print(L" Fingerprint (SHA1):\n ");
403 for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
404 Print(L" %02x", hash[i]);
405 if (i % 10 == 9)
406 Print(L"\n ");
407 }
ea8ee444 408 } else {
0a6565c5
MG
409 Print(L"SHA256 hash:\n ");
410 for (i = 0; i < SHA256_DIGEST_SIZE; i++) {
411 Print(L" %02x", ((UINT8 *)Mok)[i]);
412 if (i % 10 == 9)
413 Print(L"\n ");
414 }
415 Print(L"\n");
ea8ee444 416 }
333bd977 417
ea8ee444 418 Print(L"\n");
333bd977
GCPL
419}
420
f775849e
GCPL
421static INTN get_number ()
422{
423 EFI_INPUT_KEY input_key;
424 CHAR16 input[10];
425 int count = 0;
426
427 do {
428 input_key = get_keystroke();
429
430 if ((input_key.UnicodeChar < '0' ||
431 input_key.UnicodeChar > '9' ||
432 count >= 10) &&
433 input_key.UnicodeChar != CHAR_BACKSPACE) {
434 continue;
435 }
436
437 if (count == 0 && input_key.UnicodeChar == CHAR_BACKSPACE)
438 continue;
439
440 Print(L"%c", input_key.UnicodeChar);
441
442 if (input_key.UnicodeChar == CHAR_BACKSPACE) {
443 input[--count] = '\0';
444 continue;
445 }
446
447 input[count++] = input_key.UnicodeChar;
448 } while (input_key.UnicodeChar != CHAR_CARRIAGE_RETURN);
449
450 if (count == 0)
451 return -1;
452
453 input[count] = '\0';
454
455 return (INTN)Atoi(input);
456}
457
92a136d8 458static UINT8 list_keys (void *KeyList, UINTN KeyListSize, CHAR16 *title)
333bd977 459{
0a6565c5 460 UINT32 MokNum = 0;
c326e2df 461 MokListNode *keys = NULL;
f775849e
GCPL
462 INTN key_num = 0;
463 UINT8 initial = 1;
0a6565c5 464
92a136d8
GCPL
465 if (KeyListSize < (sizeof(EFI_SIGNATURE_LIST) +
466 sizeof(EFI_SIGNATURE_DATA))) {
0a6565c5
MG
467 Print(L"No keys\n");
468 Pause();
6306b495 469 return 0;
333bd977 470 }
333bd977 471
92a136d8
GCPL
472 MokNum = count_keys(KeyList, KeyListSize);
473 keys = build_mok_list(MokNum, KeyList, KeyListSize);
c326e2df
GCPL
474
475 if (!keys) {
92a136d8 476 Print(L"Failed to construct key list\n");
6306b495 477 return 0;
333bd977
GCPL
478 }
479
f775849e
GCPL
480 do {
481 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
92a136d8
GCPL
482 if (title)
483 Print(L"%s\n", title);
f775849e
GCPL
484 Print(L"Input the key number to show the details of the key or\n"
485 L"type \'0\' to continue\n\n");
92a136d8 486 Print(L"%d key(s) in the key list\n\n", MokNum);
f775849e
GCPL
487
488 if (key_num > MokNum) {
67f1e0b2 489 Print(L"[Key %d]\n", key_num);
f775849e 490 Print(L"No such key\n\n");
577029ad 491 } else if (initial != 1 && key_num > 0){
f775849e
GCPL
492 Print(L"[Key %d]\n", key_num);
493 show_mok_info(keys[key_num-1].Mok, keys[key_num-1].MokSize);
494 }
495
496 Print(L"Key Number: ");
497
498 key_num = get_number();
499
500 Print(L"\n\n");
501
502 if (key_num == -1)
503 continue;
504
505 initial = 0;
506 } while (key_num != 0);
333bd977 507
6306b495 508 FreePool(keys);
c326e2df 509
6306b495 510 return 1;
333bd977
GCPL
511}
512
3ece2b33 513static UINT8 get_line (UINT32 *length, CHAR16 *line, UINT32 line_max, UINT8 show)
333bd977
GCPL
514{
515 EFI_INPUT_KEY key;
3ece2b33
GCPL
516 int count = 0;
517
518 do {
519 key = get_keystroke();
520
521 if ((count >= line_max &&
522 key.UnicodeChar != CHAR_BACKSPACE) ||
523 key.UnicodeChar == CHAR_NULL ||
524 key.UnicodeChar == CHAR_TAB ||
525 key.UnicodeChar == CHAR_LINEFEED ||
526 key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
527 continue;
528 }
529
530 if (count == 0 && key.UnicodeChar == CHAR_BACKSPACE) {
531 continue;
532 } else if (key.UnicodeChar == CHAR_BACKSPACE) {
533 if (show) {
534 Print(L"\b");
535 }
536 line[--count] = '\0';
537 continue;
538 }
539
540 if (show) {
541 Print(L"%c", key.UnicodeChar);
542 }
543
544 line[count++] = key.UnicodeChar;
545 } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN);
546 Print(L"\n");
547
548 *length = count;
549
550 return 1;
551}
552
215e462b
GCPL
553static EFI_STATUS compute_pw_hash (void *MokNew, UINTN MokNewSize, CHAR16 *password,
554 UINT32 pw_length, UINT8 *hash)
555{
556 EFI_STATUS status;
557 unsigned int ctxsize;
558 void *ctx = NULL;
559
560 ctxsize = Sha256GetContextSize();
561 ctx = AllocatePool(ctxsize);
562
563 if (!ctx) {
564 Print(L"Unable to allocate memory for hash context\n");
565 return EFI_OUT_OF_RESOURCES;
566 }
567
568 if (!Sha256Init(ctx)) {
569 Print(L"Unable to initialise hash\n");
570 status = EFI_OUT_OF_RESOURCES;
571 goto done;
572 }
573
0a6565c5
MG
574 if (MokNew && MokNewSize) {
575 if (!(Sha256Update(ctx, MokNew, MokNewSize))) {
576 Print(L"Unable to generate hash\n");
577 status = EFI_OUT_OF_RESOURCES;
578 goto done;
579 }
215e462b
GCPL
580 }
581
582 if (!(Sha256Update(ctx, password, pw_length * sizeof(CHAR16)))) {
583 Print(L"Unable to generate hash\n");
584 status = EFI_OUT_OF_RESOURCES;
585 goto done;
586 }
587
588 if (!(Sha256Final(ctx, hash))) {
589 Print(L"Unable to finalise hash\n");
590 status = EFI_OUT_OF_RESOURCES;
591 goto done;
592 }
593
594 status = EFI_SUCCESS;
595done:
596 return status;
597}
598
262d6714
GCPL
599static EFI_STATUS match_password (void *Data, UINTN DataSize,
600 UINT8 auth[SHA256_DIGEST_SIZE],
601 CHAR16 *prompt)
602{
603 EFI_STATUS efi_status;
604 UINT8 hash[SHA256_DIGEST_SIZE];
605 CHAR16 password[PASSWORD_MAX];
606 UINT32 pw_length;
607 UINT8 fail_count = 0;
608
609 while (fail_count < 3) {
610 if (prompt) {
611 Print(L"%s", prompt);
612 } else {
613 Print(L"Password: ");
614 }
615 get_line(&pw_length, password, PASSWORD_MAX, 0);
616
617 if (pw_length < PASSWORD_MIN || pw_length > PASSWORD_MAX) {
618 Print(L"Invalid password length\n");
619 fail_count++;
620 continue;
621 }
622
623 efi_status = compute_pw_hash(Data, DataSize, password,
624 pw_length, hash);
625
626 if (efi_status != EFI_SUCCESS) {
627 Print(L"Unable to generate password hash\n");
628 fail_count++;
629 continue;
630 }
631
632 if (CompareMem(auth, hash, SHA256_DIGEST_SIZE) != 0) {
633 Print(L"Password doesn't match\n");
634 fail_count++;
635 continue;
636 }
637
638 break;
639 }
640
641 if (fail_count >= 3)
642 return EFI_ACCESS_DENIED;
643
644 return EFI_SUCCESS;
645}
646
1e9de96f 647static EFI_STATUS store_keys (void *MokNew, UINTN MokNewSize, int authenticate)
333bd977
GCPL
648{
649 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
650 EFI_STATUS efi_status;
215e462b
GCPL
651 UINT8 auth[SHA256_DIGEST_SIZE];
652 UINTN auth_size;
653 UINT32 attributes;
215e462b 654
1e9de96f
MG
655 if (authenticate) {
656 auth_size = SHA256_DIGEST_SIZE;
657 efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
658 &shim_lock_guid,
659 &attributes, &auth_size, auth);
215e462b
GCPL
660
661
1e9de96f
MG
662 if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) {
663 Print(L"Failed to get MokAuth %d\n", efi_status);
664 return efi_status;
665 }
215e462b 666
262d6714
GCPL
667 efi_status = match_password(MokNew, MokNewSize, auth, NULL);
668 if (efi_status != EFI_SUCCESS)
1e9de96f
MG
669 return EFI_ACCESS_DENIED;
670 }
333bd977 671
0a6565c5
MG
672 if (!MokNewSize) {
673 /* Delete MOK */
674 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
675 &shim_lock_guid,
676 EFI_VARIABLE_NON_VOLATILE
868d5b90 677 | EFI_VARIABLE_BOOTSERVICE_ACCESS,
0a6565c5
MG
678 0, NULL);
679 } else {
680 /* Write new MOK */
681 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
682 &shim_lock_guid,
683 EFI_VARIABLE_NON_VOLATILE
684 | EFI_VARIABLE_BOOTSERVICE_ACCESS
685 | EFI_VARIABLE_APPEND_WRITE,
686 MokNewSize, MokNew);
687 }
688
333bd977
GCPL
689 if (efi_status != EFI_SUCCESS) {
690 Print(L"Failed to set variable %d\n", efi_status);
5d328c6c 691 return efi_status;
333bd977
GCPL
692 }
693
5d328c6c 694 return EFI_SUCCESS;
333bd977
GCPL
695}
696
1e9de96f 697static UINTN mok_enrollment_prompt (void *MokNew, UINTN MokNewSize, int auth) {
a64ab2ec 698 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
d991c4a1
MG
699 CHAR16 line[1];
700 UINT32 length;
333bd977 701 EFI_STATUS efi_status;
333bd977 702
d991c4a1 703 do {
92a136d8 704 if (!list_keys(MokNew, MokNewSize, L"[Enroll MOK]")) {
d991c4a1
MG
705 return 0;
706 }
333bd977 707
d991c4a1 708 Print(L"Enroll the key(s)? (y/n): ");
333bd977 709
d991c4a1 710 get_line (&length, line, 1, 1);
333bd977 711
d991c4a1 712 if (line[0] == 'Y' || line[0] == 'y') {
1e9de96f 713 efi_status = store_keys(MokNew, MokNewSize, auth);
333bd977 714
d991c4a1
MG
715 if (efi_status != EFI_SUCCESS) {
716 Print(L"Failed to enroll keys\n");
717 return -1;
718 }
a64ab2ec
GCPL
719
720 if (auth) {
721 LibDeleteVariable(L"MokNew", &shim_lock_guid);
722 LibDeleteVariable(L"MokAuth", &shim_lock_guid);
723
724 Print(L"\nPress a key to reboot system\n");
725 Pause();
726 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
727 EFI_SUCCESS, 0, NULL);
728 Print(L"Failed to reboot\n");
729 return -1;
730 }
731
d991c4a1
MG
732 return 0;
733 }
734 } while (line[0] != 'N' && line[0] != 'n');
735 return -1;
736}
737
0a6565c5 738static INTN mok_enrollment_prompt_callback (void *MokNew, void *data2,
6e05b32d
MG
739 void *data3)
740{
741 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
1e9de96f
MG
742 return mok_enrollment_prompt(MokNew, (UINTN)data2, TRUE);
743}
744
92a136d8
GCPL
745static INTN mok_reset_prompt (void *MokNew, void *data2, void *data3)
746{
a64ab2ec 747 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
d991c4a1
MG
748 CHAR16 line[1];
749 UINT32 length;
750 EFI_STATUS efi_status;
751
4895ca39 752 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
d991c4a1
MG
753 Print(L"Erase all stored keys? (y/N): ");
754
755 get_line (&length, line, 1, 1);
756
757 if (line[0] == 'Y' || line[0] == 'y') {
0a6565c5 758 efi_status = store_keys(NULL, 0, TRUE);
333bd977 759
5d328c6c
GCPL
760 if (efi_status != EFI_SUCCESS) {
761 Print(L"Failed to erase keys\n");
d991c4a1 762 return -1;
5d328c6c 763 }
a64ab2ec
GCPL
764
765 LibDeleteVariable(L"MokNew", &shim_lock_guid);
766 LibDeleteVariable(L"MokAuth", &shim_lock_guid);
767
768 Print(L"\nPress a key to reboot system\n");
769 Pause();
770 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
771 EFI_SUCCESS, 0, NULL);
772 Print(L"Failed to reboot\n");
773 return -1;
d991c4a1 774 }
5d328c6c 775
d991c4a1
MG
776 return 0;
777}
333bd977 778
92a136d8
GCPL
779static EFI_STATUS write_back_mok_list (MokListNode *list, INTN key_num)
780{
781 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
782 EFI_STATUS efi_status;
783 EFI_SIGNATURE_LIST *CertList;
784 EFI_SIGNATURE_DATA *CertData;
785 void *Data = NULL, *ptr;
786 INTN DataSize = 0;
787 int i;
788
789 for (i = 0; i < key_num; i++) {
790 if (list[i].Mok == NULL)
791 continue;
792
793 DataSize += sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID);
794 DataSize += list[i].MokSize;
795 }
796
797 Data = AllocatePool(DataSize);
798 if (Data == NULL && DataSize != 0)
799 return EFI_OUT_OF_RESOURCES;
800
801 ptr = Data;
802
803 for (i = 0; i < key_num; i++) {
804 if (list[i].Mok == NULL)
805 continue;
806
807 CertList = (EFI_SIGNATURE_LIST *)ptr;
808 CertData = (EFI_SIGNATURE_DATA *)(((uint8_t *)ptr) +
809 sizeof(EFI_SIGNATURE_LIST));
810
811 CertList->SignatureType = list[i].Type;
812 CertList->SignatureListSize = list[i].MokSize +
813 sizeof(EFI_SIGNATURE_LIST) +
814 sizeof(EFI_SIGNATURE_DATA) - 1;
815 CertList->SignatureHeaderSize = 0;
816 CertList->SignatureSize = list[i].MokSize + sizeof(EFI_GUID);
817
818 CertData->SignatureOwner = shim_lock_guid;
819 CopyMem(CertData->SignatureData, list[i].Mok, list[i].MokSize);
820
821 ptr = (uint8_t *)ptr + sizeof(EFI_SIGNATURE_LIST) +
822 sizeof(EFI_GUID) + list[i].MokSize;
823 }
824
825 efi_status = uefi_call_wrapper(RT->SetVariable, 5, L"MokList",
826 &shim_lock_guid,
827 EFI_VARIABLE_NON_VOLATILE
828 | EFI_VARIABLE_BOOTSERVICE_ACCESS,
829 DataSize, Data);
830 if (Data)
831 FreePool(Data);
832
833 if (efi_status != EFI_SUCCESS) {
834 Print(L"Failed to set variable %d\n", efi_status);
835 return efi_status;
836 }
837
838 return EFI_SUCCESS;
839}
840
841static EFI_STATUS delete_keys (void *MokDel, UINTN MokDelSize)
842{
843 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
844 EFI_STATUS efi_status;
845 UINT8 auth[SHA256_DIGEST_SIZE];
846 UINTN auth_size = SHA256_DIGEST_SIZE;
847 UINT32 attributes;
848 void *MokListData = NULL;
849 UINTN MokListDataSize = 0;
850 MokListNode *mok, *del_key;
851 INTN mok_num, del_num;
852 int i, j;
853
854 efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth",
855 &shim_lock_guid,
856 &attributes, &auth_size, auth);
857
858 if (efi_status != EFI_SUCCESS || auth_size != SHA256_DIGEST_SIZE) {
859 Print(L"Failed to get MokDelAuth %d\n", efi_status);
860 return efi_status;
861 }
862
863 efi_status = match_password(MokDel, MokDelSize, auth, NULL);
864 if (efi_status != EFI_SUCCESS)
865 return EFI_ACCESS_DENIED;
866
867 efi_status = get_variable(L"MokList", shim_lock_guid, &attributes,
868 &MokListDataSize, &MokListData);
869
870 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS) {
871 Print(L"MokList is compromised!\nErase all keys in MokList!\n");
872 if (LibDeleteVariable(L"MokList", &shim_lock_guid) != EFI_SUCCESS) {
873 Print(L"Failed to erase MokList\n");
874 }
875 return EFI_ACCESS_DENIED;
876 }
877
878 /* Nothing to do */
879 if (!MokListData || MokListDataSize == 0)
880 return EFI_SUCCESS;
881
882 /* Construct lists */
883 mok_num = count_keys(MokListData, MokListDataSize);
884 mok = build_mok_list(mok_num, MokListData, MokListDataSize);
885 del_num = count_keys(MokDel, MokDelSize);
886 del_key = build_mok_list(del_num, MokDel, MokDelSize);
887
888 /* Search and destroy */
889 for (i = 0; i < del_num; i++) {
890 UINT32 key_size = del_key[i].MokSize;
891 void *key = del_key[i].Mok;
892 for (j = 0; j < mok_num; j++) {
893 if (mok[j].MokSize == key_size &&
894 CompareMem(key, mok[j].Mok, key_size) == 0) {
895 /* Remove the key */
896 mok[j].Mok = NULL;
897 mok[j].MokSize = 0;
898 }
899 }
900 }
901
902 efi_status = write_back_mok_list(mok, mok_num);
903
904 if (MokListData)
905 FreePool(MokListData);
906 if (mok)
907 FreePool(mok);
908 if (del_key)
909 FreePool(del_key);
910
911 return efi_status;
912}
913
914static INTN mok_deletion_prompt (void *MokDel, void *data2, void *data3)
915{
916 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
917 UINTN MokDelSize = (UINTN)data2;
918 CHAR16 line[1];
919 UINT32 length;
920 EFI_STATUS efi_status;
921
922 do {
923 if (!list_keys(MokDel, MokDelSize, L"[Delete MOK]")) {
924 return 0;
925 }
926
927 Print(L"Delete the key(s)? (y/n): ");
928
929 get_line (&length, line, 1, 1);
930
931 if (line[0] == 'Y' || line[0] == 'y') {
932 efi_status = delete_keys(MokDel, MokDelSize);
933
934 if (efi_status != EFI_SUCCESS) {
935 Print(L"Failed to delete keys\n");
936 return -1;
937 }
938
939 LibDeleteVariable(L"MokDel", &shim_lock_guid);
940 LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
941
942 Print(L"\nPress a key to reboot system\n");
943 Pause();
944 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
945 EFI_SUCCESS, 0, NULL);
946 Print(L"Failed to reboot\n");
947 return -1;
948 }
949 } while (line[0] != 'N' && line[0] != 'n');
950 return -1;
951}
952
9272bc5b
MG
953static INTN mok_sb_prompt (void *MokSB, void *data2, void *data3) {
954 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
955 EFI_STATUS efi_status;
956 UINTN MokSBSize = (UINTN)data2;
957 MokSBvar *var = MokSB;
8a169068
MG
958 CHAR16 pass1, pass2, pass3;
959 UINT8 fail_count = 0;
9272bc5b
MG
960 UINT32 length;
961 CHAR16 line[1];
962 UINT8 sbval = 1;
8a169068 963 UINT8 pos1, pos2, pos3;
9272bc5b 964
9272bc5b
MG
965 if (MokSBSize != sizeof(MokSBvar)) {
966 Print(L"Invalid MokSB variable contents\n");
967 return -1;
968 }
969
34f0c4ab
MG
970 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
971
8a169068
MG
972 while (fail_count < 3) {
973 RandomBytes (&pos1, sizeof(pos1));
974 pos1 = (pos1 % var->PWLen);
975
976 do {
977 RandomBytes (&pos2, sizeof(pos2));
978 pos2 = (pos2 % var->PWLen);
979 } while (pos2 == pos1);
980
981 do {
982 RandomBytes (&pos3, sizeof(pos3));
983 pos3 = (pos3 % var->PWLen) ;
984 } while (pos3 == pos2 || pos3 == pos1);
985
986 Print(L"Enter password character %d: ", pos1 + 1);
987 get_line(&length, &pass1, 1, 0);
9272bc5b 988
8a169068
MG
989 Print(L"Enter password character %d: ", pos2 + 1);
990 get_line(&length, &pass2, 1, 0);
9272bc5b 991
8a169068
MG
992 Print(L"Enter password character %d: ", pos3 + 1);
993 get_line(&length, &pass3, 1, 0);
9272bc5b 994
8a169068
MG
995 if (pass1 != var->Password[pos1] ||
996 pass2 != var->Password[pos2] ||
997 pass3 != var->Password[pos3]) {
79a5aa03 998 Print(L"Invalid character\n");
9272bc5b 999 fail_count++;
79a5aa03 1000 } else {
79a5aa03 1001 break;
8a169068 1002 }
9272bc5b
MG
1003 }
1004
1005 if (fail_count >= 3) {
1006 Print(L"Password limit reached\n");
1007 return -1;
1008 }
1009
1010 if (var->MokSBState == 0) {
1011 Print(L"Disable Secure Boot? (y/n): ");
1012 } else {
1013 Print(L"Enable Secure Boot? (y/n): ");
1014 }
1015
1016 do {
1017 get_line (&length, line, 1, 1);
1018
1019 if (line[0] == 'Y' || line[0] == 'y') {
1020 if (var->MokSBState == 0) {
1021 efi_status = uefi_call_wrapper(RT->SetVariable,
1022 5, L"MokSBState",
1023 &shim_lock_guid,
1024 EFI_VARIABLE_NON_VOLATILE |
1025 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1026 1, &sbval);
1027 if (efi_status != EFI_SUCCESS) {
1028 Print(L"Failed to set Secure Boot state\n");
1029 return -1;
1030 }
1031 } else {
1032 LibDeleteVariable(L"MokSBState",
1033 &shim_lock_guid);
1034 }
1035
d77f421b
MG
1036 LibDeleteVariable(L"MokSB", &shim_lock_guid);
1037
9272bc5b
MG
1038 Print(L"Press a key to reboot system\n");
1039 Pause();
1040 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
1041 EFI_SUCCESS, 0, NULL);
1042 Print(L"Failed to reboot\n");
1043 return -1;
1044 }
1045 } while (line[0] != 'N' && line[0] != 'n');
1046
1047 return -1;
1048}
1049
801d1b93
MG
1050
1051static INTN mok_pw_prompt (void *MokPW, void *data2, void *data3) {
1052 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1053 EFI_STATUS efi_status;
1054 UINTN MokPWSize = (UINTN)data2;
801d1b93 1055 UINT8 hash[SHA256_DIGEST_SIZE];
801d1b93
MG
1056 UINT32 length;
1057 CHAR16 line[1];
1058
1059 if (MokPWSize != SHA256_DIGEST_SIZE) {
1060 Print(L"Invalid MokPW variable contents\n");
1061 return -1;
1062 }
1063
34f0c4ab
MG
1064 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
1065
d77f421b
MG
1066 SetMem(hash, SHA256_DIGEST_SIZE, 0);
1067
1068 if (CompareMem(MokPW, hash, SHA256_DIGEST_SIZE) == 0) {
1069 Print(L"Clear MOK password? (y/n): ");
1070
1071 do {
1072 get_line (&length, line, 1, 1);
1073
1074 if (line[0] == 'Y' || line[0] == 'y') {
1075 LibDeleteVariable(L"MokPWStore", &shim_lock_guid);
1076 LibDeleteVariable(L"MokPW", &shim_lock_guid);
1077 }
1078 } while (line[0] != 'N' && line[0] != 'n');
1079
1080 return 0;
1081 }
1082
262d6714
GCPL
1083 efi_status = match_password(NULL, 0, MokPW, L"Confirm MOK passphrase: ");
1084 if (efi_status != EFI_SUCCESS) {
801d1b93
MG
1085 Print(L"Password limit reached\n");
1086 return -1;
1087 }
1088
1089 Print(L"Set MOK password? (y/n): ");
1090
1091 do {
1092 get_line (&length, line, 1, 1);
1093
1094 if (line[0] == 'Y' || line[0] == 'y') {
1095 efi_status = uefi_call_wrapper(RT->SetVariable, 5,
1096 L"MokPWStore",
1097 &shim_lock_guid,
1098 EFI_VARIABLE_NON_VOLATILE |
1099 EFI_VARIABLE_BOOTSERVICE_ACCESS,
1100 MokPWSize, MokPW);
1101 if (efi_status != EFI_SUCCESS) {
1102 Print(L"Failed to set MOK password\n");
1103 return -1;
1104 }
1105
d77f421b
MG
1106 LibDeleteVariable(L"MokPW", &shim_lock_guid);
1107
801d1b93
MG
1108 Print(L"Press a key to reboot system\n");
1109 Pause();
1110 uefi_call_wrapper(RT->ResetSystem, 4, EfiResetWarm,
1111 EFI_SUCCESS, 0, NULL);
1112 Print(L"Failed to reboot\n");
1113 return -1;
1114 }
1115 } while (line[0] != 'N' && line[0] != 'n');
1116
1117 return 0;
1118}
1119
1bc1cd96
MG
1120static UINTN draw_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
1121 UINTN count) {
d991c4a1 1122 UINTN i;
5d328c6c 1123
d991c4a1
MG
1124 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
1125
e204505d
MG
1126 uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
1127 EFI_WHITE | EFI_BACKGROUND_BLACK);
1128
1129 Print(L"%s UEFI key management\n\n", SHIM_VENDOR);
1130
1bc1cd96
MG
1131 if (header)
1132 Print(L"%s", header);
1133
d991c4a1
MG
1134 for (i = 0; i < count; i++) {
1135 uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
1136 items[i].colour | EFI_BACKGROUND_BLACK);
1137 Print(L" %s\n", items[i].text);
1138 }
1139
1140 uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 0);
1141 uefi_call_wrapper(ST->ConOut->EnableCursor, 2, ST->ConOut, TRUE);
e204505d 1142
1bc1cd96 1143 return 2 + lines;
d991c4a1
MG
1144}
1145
c9d2ff8c
MG
1146static void free_menu (struct menu_item *items, UINTN count) {
1147 UINTN i;
1148
1149 for (i=0; i<count; i++) {
1150 if (items[i].text)
1151 FreePool(items[i].text);
1152 }
1153
1154 FreePool(items);
1155}
1156
37635f54
MG
1157static void update_time (UINTN position, UINTN timeout)
1158{
1159 uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
1160 position);
1161
1162 uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
1163 EFI_BLACK | EFI_BACKGROUND_BLACK);
1164
1165 Print(L" ", timeout);
1166
1167 uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0,
1168 position);
1169
1170 uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut,
1171 EFI_WHITE | EFI_BACKGROUND_BLACK);
1172
1173 if (timeout > 1)
1174 Print(L"Booting in %d seconds\n", timeout);
1175 else if (timeout)
1176 Print(L"Booting in %d second\n", timeout);
1177}
1178
1bc1cd96
MG
1179static void run_menu (CHAR16 *header, UINTN lines, struct menu_item *items,
1180 UINTN count, UINTN timeout) {
e204505d 1181 UINTN index, pos = 0, wait = 0, offset;
d991c4a1 1182 EFI_INPUT_KEY key;
202b5c3e 1183 EFI_STATUS status;
d08ea536 1184 INTN ret;
d991c4a1 1185
202b5c3e
MG
1186 if (timeout)
1187 wait = 10000000;
d991c4a1 1188
37635f54 1189 offset = draw_menu (header, lines, items, count);
202b5c3e 1190
37635f54
MG
1191 while (1) {
1192 update_time(count + offset + 1, timeout);
202b5c3e 1193
d991c4a1 1194 uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut,
e204505d 1195 0, pos + offset);
202b5c3e
MG
1196 status = WaitForSingleEvent(ST->ConIn->WaitForKey, wait);
1197
1198 if (status == EFI_TIMEOUT) {
1199 timeout--;
1200 if (!timeout) {
1201 free_menu(items, count);
1202 return;
1203 }
1204 continue;
1205 }
1206
1207 wait = 0;
1208 timeout = 0;
1209
d991c4a1
MG
1210 uefi_call_wrapper(BS->WaitForEvent, 3, 1,
1211 &ST->ConIn->WaitForKey, &index);
1212 uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn,
1213 &key);
1214
1215 switch(key.ScanCode) {
1216 case SCAN_UP:
1217 if (pos == 0)
1218 continue;
1219 pos--;
1220 continue;
1221 break;
1222 case SCAN_DOWN:
1223 if (pos == (count - 1))
1224 continue;
1225 pos++;
1226 continue;
1227 break;
5d328c6c 1228 }
d991c4a1
MG
1229
1230 switch(key.UnicodeChar) {
1231 case CHAR_LINEFEED:
1232 case CHAR_CARRIAGE_RETURN:
c9d2ff8c
MG
1233 if (items[pos].callback == NULL) {
1234 free_menu(items, count);
d991c4a1 1235 return;
c9d2ff8c 1236 }
d991c4a1 1237
d08ea536
MG
1238 ret = items[pos].callback(items[pos].data,
1239 items[pos].data2,
1240 items[pos].data3);
1241 if (ret < 0) {
1242 Print(L"Press a key to continue\n");
1243 Pause();
4a88de58
GCPL
1244 /* Clear the key in the queue */
1245 uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2,
1246 ST->ConIn, &key);
d08ea536 1247 }
1bc1cd96 1248 draw_menu (header, lines, items, count);
d991c4a1
MG
1249 pos = 0;
1250 break;
1251 }
1252 }
1253}
1254
0a6565c5
MG
1255static UINTN verify_certificate(void *cert, UINTN size)
1256{
1257 X509 *X509Cert;
1258 if (!cert || size == 0)
1259 return FALSE;
1260
1261 if (!(X509ConstructCertificate(cert, size, (UINT8 **) &X509Cert)) ||
1262 X509Cert == NULL) {
1263 Print(L"Invalid X509 certificate\n");
1264 Pause();
1265 return FALSE;
1266 }
1267
1268 X509_free(X509Cert);
1269 return TRUE;
1270}
1271
1272static INTN file_callback (void *data, void *data2, void *data3) {
d991c4a1 1273 EFI_FILE_INFO *buffer = NULL;
0a6565c5 1274 UINTN buffersize = 0, mokbuffersize;
d991c4a1
MG
1275 EFI_STATUS status;
1276 EFI_FILE *file;
1277 CHAR16 *filename = data;
1278 EFI_FILE *parent = data2;
0a6565c5 1279 BOOLEAN hash = !!data3;
d991c4a1 1280 EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
0a6565c5
MG
1281 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1282 EFI_SIGNATURE_LIST *CertList;
1283 EFI_SIGNATURE_DATA *CertData;
1284 void *mokbuffer = NULL;
d991c4a1
MG
1285
1286 status = uefi_call_wrapper(parent->Open, 5, parent, &file, filename,
1287 EFI_FILE_MODE_READ, 0);
1288
1289 if (status != EFI_SUCCESS)
1290 return 1;
1291
1292 status = uefi_call_wrapper(file->GetInfo, 4, file, &file_info_guid,
1293 &buffersize, buffer);
1294
1295 if (status == EFI_BUFFER_TOO_SMALL) {
1296 buffer = AllocatePool(buffersize);
1297 status = uefi_call_wrapper(file->GetInfo, 4, file,
1298 &file_info_guid, &buffersize,
1299 buffer);
5d328c6c 1300 }
d991c4a1
MG
1301
1302 if (!buffer)
1303 return 0;
1304
0a6565c5 1305 buffersize = buffer->FileSize;
d991c4a1 1306
0a6565c5
MG
1307 if (hash) {
1308 void *binary;
1309 UINT8 sha256[SHA256_DIGEST_SIZE];
1310 UINT8 sha1[SHA1_DIGEST_SIZE];
1311 SHIM_LOCK *shim_lock;
1312 EFI_GUID shim_guid = SHIM_LOCK_GUID;
1313 PE_COFF_LOADER_IMAGE_CONTEXT context;
1314
1315 status = LibLocateProtocol(&shim_guid, (VOID **)&shim_lock);
1316
1317 if (status != EFI_SUCCESS)
1318 goto out;
1319
1320 mokbuffersize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_GUID) +
1321 SHA256_DIGEST_SIZE;
1322
1323 mokbuffer = AllocatePool(mokbuffersize);
d1c2586c
MG
1324
1325 if (!mokbuffer)
1326 goto out;
1327
0a6565c5
MG
1328 binary = AllocatePool(buffersize);
1329
1330 status = uefi_call_wrapper(file->Read, 3, file, &buffersize,
1331 binary);
1332
1333 if (status != EFI_SUCCESS)
1334 goto out;
1335
1336 status = shim_lock->Context(binary, buffersize, &context);
1337
1338 if (status != EFI_SUCCESS)
1339 goto out;
1340
1341 status = shim_lock->Hash(binary, buffersize, &context, sha256,
1342 sha1);
1343
1344 if (status != EFI_SUCCESS)
1345 goto out;
1346
1347 CertList = mokbuffer;
1348 CertList->SignatureType = EfiHashSha256Guid;
1349 CertList->SignatureSize = 16 + SHA256_DIGEST_SIZE;
1350 CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) +
1351 sizeof(EFI_SIGNATURE_LIST));
1352 CopyMem(CertData->SignatureData, sha256, SHA256_DIGEST_SIZE);
d1c2586c 1353 } else {
0a6565c5
MG
1354 mokbuffersize = buffersize + sizeof(EFI_SIGNATURE_LIST) +
1355 sizeof(EFI_GUID);
1356 mokbuffer = AllocatePool(mokbuffersize);
d1c2586c
MG
1357
1358 if (!mokbuffer)
1359 goto out;
d991c4a1 1360
0a6565c5
MG
1361 CertList = mokbuffer;
1362 CertList->SignatureType = EfiCertX509Guid;
1363 CertList->SignatureSize = 16 + buffersize;
1364 status = uefi_call_wrapper(file->Read, 3, file, &buffersize,
1365 mokbuffer + sizeof(EFI_SIGNATURE_LIST) + 16);
1366
1367 if (status != EFI_SUCCESS)
1368 goto out;
1369 CertData = (EFI_SIGNATURE_DATA *)(((UINT8 *)mokbuffer) +
1370 sizeof(EFI_SIGNATURE_LIST));
1371 }
d991c4a1 1372
0a6565c5
MG
1373 CertList->SignatureListSize = mokbuffersize;
1374 CertList->SignatureHeaderSize = 0;
1375 CertData->SignatureOwner = shim_lock_guid;
d991c4a1 1376
0a6565c5
MG
1377 if (!hash) {
1378 if (!verify_certificate(CertData->SignatureData, buffersize))
1379 goto out;
1380 }
d991c4a1 1381
0a6565c5 1382 mok_enrollment_prompt(mokbuffer, mokbuffersize, FALSE);
d991c4a1
MG
1383out:
1384 if (buffer)
1385 FreePool(buffer);
1386
1387 if (mokbuffer)
1388 FreePool(mokbuffer);
1389
1390 return 0;
1391}
1392
0a6565c5 1393static INTN directory_callback (void *data, void *data2, void *data3) {
d991c4a1
MG
1394 EFI_FILE_INFO *buffer = NULL;
1395 UINTN buffersize = 0;
1396 EFI_STATUS status;
1397 UINTN dircount = 0, i = 0;
1398 struct menu_item *dircontent;
1399 EFI_FILE *dir;
1400 CHAR16 *filename = data;
1401 EFI_FILE *root = data2;
1bc1cd96 1402 BOOLEAN hash = !!data3;
d991c4a1
MG
1403
1404 status = uefi_call_wrapper(root->Open, 5, root, &dir, filename,
1405 EFI_FILE_MODE_READ, 0);
1406
1407 if (status != EFI_SUCCESS)
1408 return 1;
1409
1410 while (1) {
1411 status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize,
1412 buffer);
1413
1414 if (status == EFI_BUFFER_TOO_SMALL) {
1415 buffer = AllocatePool(buffersize);
1416 status = uefi_call_wrapper(dir->Read, 3, dir,
1417 &buffersize, buffer);
1418 }
1419
1420 if (status != EFI_SUCCESS)
1421 return 1;
1422
1423 if (!buffersize)
1424 break;
1425
1426 if ((StrCmp(buffer->FileName, L".") == 0) ||
1427 (StrCmp(buffer->FileName, L"..") == 0))
1428 continue;
1429
1430 dircount++;
1431
1432 FreePool(buffer);
1433 buffersize = 0;
1434 }
1435
1436 dircount++;
1437
1438 dircontent = AllocatePool(sizeof(struct menu_item) * dircount);
1439
1440 dircontent[0].text = StrDuplicate(L"..");
1441 dircontent[0].callback = NULL;
1442 dircontent[0].colour = EFI_YELLOW;
1443 i++;
1444
1445 uefi_call_wrapper(dir->SetPosition, 2, dir, 0);
1446
1447 while (1) {
1448 status = uefi_call_wrapper(dir->Read, 3, dir, &buffersize,
1449 buffer);
1450
1451 if (status == EFI_BUFFER_TOO_SMALL) {
1452 buffer = AllocatePool(buffersize);
1453 status = uefi_call_wrapper(dir->Read, 3, dir,
1454 &buffersize, buffer);
1455 }
1456
1457 if (status != EFI_SUCCESS)
1458 return 1;
1459
1460 if (!buffersize)
1461 break;
1462
1463 if ((StrCmp(buffer->FileName, L".") == 0) ||
1464 (StrCmp(buffer->FileName, L"..") == 0))
1465 continue;
1466
1467 if (buffer->Attribute & EFI_FILE_DIRECTORY) {
1468 dircontent[i].text = StrDuplicate(buffer->FileName);
1469 dircontent[i].callback = directory_callback;
1470 dircontent[i].data = dircontent[i].text;
1471 dircontent[i].data2 = dir;
0a6565c5 1472 dircontent[i].data3 = data3;
d991c4a1
MG
1473 dircontent[i].colour = EFI_YELLOW;
1474 } else {
1475 dircontent[i].text = StrDuplicate(buffer->FileName);
1476 dircontent[i].callback = file_callback;
1477 dircontent[i].data = dircontent[i].text;
1478 dircontent[i].data2 = dir;
0a6565c5 1479 dircontent[i].data3 = data3;
d991c4a1
MG
1480 dircontent[i].colour = EFI_WHITE;
1481 }
1482
1483 i++;
1484 FreePool(buffer);
1485 buffersize = 0;
1486 buffer = NULL;
1487 }
1488
1bc1cd96
MG
1489 if (hash)
1490 run_menu(HASH_STRING, 2, dircontent, dircount, 0);
1491 else
1492 run_menu(CERT_STRING, 2, dircontent, dircount, 0);
d991c4a1
MG
1493
1494 return 0;
1495}
1496
0a6565c5 1497static INTN filesystem_callback (void *data, void *data2, void *data3) {
d991c4a1
MG
1498 EFI_FILE_INFO *buffer = NULL;
1499 UINTN buffersize = 0;
1500 EFI_STATUS status;
1501 UINTN dircount = 0, i = 0;
1502 struct menu_item *dircontent;
1503 EFI_FILE *root = data;
1bc1cd96 1504 BOOLEAN hash = !!data3;
d991c4a1
MG
1505
1506 uefi_call_wrapper(root->SetPosition, 2, root, 0);
1507
1508 while (1) {
1509 status = uefi_call_wrapper(root->Read, 3, root, &buffersize,
1510 buffer);
1511
1512 if (status == EFI_BUFFER_TOO_SMALL) {
1513 buffer = AllocatePool(buffersize);
1514 status = uefi_call_wrapper(root->Read, 3, root,
1515 &buffersize, buffer);
1516 }
1517
1518 if (status != EFI_SUCCESS)
1519 return 1;
1520
1521 if (!buffersize)
1522 break;
1523
1524 if ((StrCmp(buffer->FileName, L".") == 0) ||
1525 (StrCmp(buffer->FileName, L"..") == 0))
1526 continue;
1527
1528 dircount++;
1529
1530 FreePool(buffer);
1531 buffersize = 0;
1532 }
1533
c9696a1c 1534 dircount++;
d991c4a1
MG
1535
1536 dircontent = AllocatePool(sizeof(struct menu_item) * dircount);
1537
1538 dircontent[0].text = StrDuplicate(L"Return to filesystem list");
1539 dircontent[0].callback = NULL;
1540 dircontent[0].colour = EFI_YELLOW;
1541 i++;
1542
1543 uefi_call_wrapper(root->SetPosition, 2, root, 0);
1544
1545 while (1) {
1546 status = uefi_call_wrapper(root->Read, 3, root, &buffersize,
1547 buffer);
1548
1549 if (status == EFI_BUFFER_TOO_SMALL) {
1550 buffer = AllocatePool(buffersize);
1551 status = uefi_call_wrapper(root->Read, 3, root,
1552 &buffersize, buffer);
1553 }
1554
1555 if (status != EFI_SUCCESS)
1556 return 1;
1557
1558 if (!buffersize)
1559 break;
1560
1561 if ((StrCmp(buffer->FileName, L".") == 0) ||
1562 (StrCmp(buffer->FileName, L"..") == 0))
1563 continue;
1564
1565 if (buffer->Attribute & EFI_FILE_DIRECTORY) {
1566 dircontent[i].text = StrDuplicate(buffer->FileName);
1567 dircontent[i].callback = directory_callback;
1568 dircontent[i].data = dircontent[i].text;
1569 dircontent[i].data2 = root;
0a6565c5 1570 dircontent[i].data3 = data3;
d991c4a1
MG
1571 dircontent[i].colour = EFI_YELLOW;
1572 } else {
1573 dircontent[i].text = StrDuplicate(buffer->FileName);
1574 dircontent[i].callback = file_callback;
1575 dircontent[i].data = dircontent[i].text;
1576 dircontent[i].data2 = root;
0a6565c5 1577 dircontent[i].data3 = data3;
d991c4a1
MG
1578 dircontent[i].colour = EFI_WHITE;
1579 }
1580
1581 i++;
1582 FreePool(buffer);
1583 buffer = NULL;
1584 buffersize = 0;
1585 }
1586
1bc1cd96
MG
1587 if (hash)
1588 run_menu(HASH_STRING, 2, dircontent, dircount, 0);
1589 else
1590 run_menu(CERT_STRING, 2, dircontent, dircount, 0);
d991c4a1
MG
1591
1592 return 0;
1593}
1594
0a6565c5 1595static INTN find_fs (void *data, void *data2, void *data3) {
d991c4a1
MG
1596 EFI_GUID fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
1597 UINTN count, i;
e65370d7 1598 UINTN OldSize, NewSize;
ed711b02 1599 EFI_HANDLE *filesystem_handles = NULL;
d991c4a1 1600 struct menu_item *filesystems;
1bc1cd96 1601 BOOLEAN hash = !!data3;
d991c4a1
MG
1602
1603 uefi_call_wrapper(BS->LocateHandleBuffer, 5, ByProtocol, &fs_guid,
1604 NULL, &count, &filesystem_handles);
1605
1606 if (!count || !filesystem_handles) {
1607 Print(L"No filesystems?\n");
1608 return 1;
1609 }
1610
1611 count++;
1612
1613 filesystems = AllocatePool(sizeof(struct menu_item) * count);
1614
1615 filesystems[0].text = StrDuplicate(L"Exit");
1616 filesystems[0].callback = NULL;
1617 filesystems[0].colour = EFI_YELLOW;
1618
1619 for (i=1; i<count; i++) {
ed711b02 1620 EFI_HANDLE fs = filesystem_handles[i-1];
d991c4a1
MG
1621 EFI_FILE_IO_INTERFACE *fs_interface;
1622 EFI_DEVICE_PATH *path;
1623 EFI_FILE *root;
1624 EFI_STATUS status;
1625 CHAR16 *VolumeLabel = NULL;
1626 EFI_FILE_SYSTEM_INFO *buffer = NULL;
1627 UINTN buffersize = 0;
1628 EFI_GUID file_info_guid = EFI_FILE_INFO_ID;
1629
1630 status = uefi_call_wrapper(BS->HandleProtocol, 3, fs, &fs_guid,
ed711b02 1631 (void **)&fs_interface);
d991c4a1
MG
1632
1633 if (status != EFI_SUCCESS || !fs_interface)
1634 continue;
1635
1636 path = DevicePathFromHandle(fs);
1637
1638 status = uefi_call_wrapper(fs_interface->OpenVolume, 2,
1639 fs_interface, &root);
1640
1641 if (status != EFI_SUCCESS || !root)
1642 continue;
1643
1644 status = uefi_call_wrapper(root->GetInfo, 4, root,
1645 &file_info_guid, &buffersize,
1646 buffer);
1647
1648 if (status == EFI_BUFFER_TOO_SMALL) {
1649 buffer = AllocatePool(buffersize);
1650 status = uefi_call_wrapper(root->GetInfo, 4, root,
1651 &file_info_guid,
1652 &buffersize, buffer);
1653 }
1654
1655 if (status == EFI_SUCCESS)
1656 VolumeLabel = buffer->VolumeLabel;
1657
1658 if (path)
1659 filesystems[i].text = DevicePathToStr(path);
1660 else
1661 filesystems[i].text = StrDuplicate(L"Unknown device\n");
e65370d7
GCPL
1662 if (VolumeLabel) {
1663 OldSize = (StrLen(filesystems[i].text) + 1) * sizeof(CHAR16);
1664 NewSize = OldSize + StrLen(VolumeLabel) * sizeof(CHAR16);
1665 filesystems[i].text = ReallocatePool(filesystems[i].text,
1666 OldSize, NewSize);
d991c4a1 1667 StrCat(filesystems[i].text, VolumeLabel);
e65370d7 1668 }
d991c4a1
MG
1669
1670 if (buffersize)
1671 FreePool(buffer);
1672
1673 filesystems[i].data = root;
1674 filesystems[i].data2 = NULL;
0a6565c5 1675 filesystems[i].data3 = data3;
d991c4a1
MG
1676 filesystems[i].callback = filesystem_callback;
1677 filesystems[i].colour = EFI_YELLOW;
1678 }
1679
1680 uefi_call_wrapper(BS->FreePool, 1, filesystem_handles);
1681
1bc1cd96
MG
1682 if (hash)
1683 run_menu(HASH_STRING, 2, filesystems, count, 0);
1684 else
1685 run_menu(CERT_STRING, 2, filesystems, count, 0);
d991c4a1
MG
1686
1687 return 0;
1688}
1689
801d1b93
MG
1690static BOOLEAN verify_pw(void)
1691{
1692 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1693 EFI_STATUS efi_status;
801d1b93
MG
1694 UINT8 pwhash[SHA256_DIGEST_SIZE];
1695 UINTN size = SHA256_DIGEST_SIZE;
801d1b93
MG
1696 UINT32 attributes;
1697
1698 efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokPWStore",
1699 &shim_lock_guid, &attributes, &size,
1700 pwhash);
1701
1702 /*
1703 * If anything can attack the password it could just set it to a
1704 * known value, so there's no safety advantage in failing to validate
1705 * purely because of a failure to read the variable
1706 */
1707 if (efi_status != EFI_SUCCESS)
1708 return TRUE;
1709
1710 if (attributes & EFI_VARIABLE_RUNTIME_ACCESS)
1711 return TRUE;
1712
34f0c4ab
MG
1713 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
1714
262d6714
GCPL
1715 efi_status = match_password(NULL, 0, pwhash, L"Enter MOK password: ");
1716 if (efi_status != EFI_SUCCESS) {
1717 Print(L"Password limit reached\n");
1718 return FALSE;
801d1b93
MG
1719 }
1720
262d6714 1721 return TRUE;
801d1b93
MG
1722}
1723
92a136d8
GCPL
1724static EFI_STATUS enter_mok_menu(EFI_HANDLE image_handle,
1725 void *MokNew, UINTN MokNewSize,
1726 void *MokDel, UINTN MokDelSize,
1727 void *MokSB, UINTN MokSBSize,
1728 void *MokPW, UINTN MokPWSize)
d991c4a1 1729{
24eace99 1730 struct menu_item *menu_item;
0a6565c5 1731 UINT32 MokAuth = 0;
92a136d8 1732 UINT32 MokDelAuth = 0;
9272bc5b 1733 UINTN menucount = 3, i = 0;
0a6565c5
MG
1734 EFI_STATUS efi_status;
1735 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
1736 UINT8 auth[SHA256_DIGEST_SIZE];
1737 UINTN auth_size = SHA256_DIGEST_SIZE;
1738 UINT32 attributes;
24eace99 1739
801d1b93
MG
1740 if (verify_pw() == FALSE)
1741 return EFI_ACCESS_DENIED;
1742
0a6565c5
MG
1743 efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokAuth",
1744 &shim_lock_guid,
1745 &attributes, &auth_size, auth);
1746
1747 if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_SIZE))
1748 MokAuth = 1;
1749
92a136d8
GCPL
1750 efi_status = uefi_call_wrapper(RT->GetVariable, 5, L"MokDelAuth",
1751 &shim_lock_guid,
1752 &attributes, &auth_size, auth);
1753
1754 if ((efi_status == EFI_SUCCESS) && (auth_size == SHA256_DIGEST_SIZE))
1755 MokDelAuth = 1;
1756
0a6565c5 1757 if (MokNew || MokAuth)
9272bc5b
MG
1758 menucount++;
1759
92a136d8
GCPL
1760 if (MokDel || MokDelAuth)
1761 menucount++;
1762
9272bc5b
MG
1763 if (MokSB)
1764 menucount++;
1765
801d1b93
MG
1766 if (MokPW)
1767 menucount++;
1768
9272bc5b 1769 menu_item = AllocateZeroPool(sizeof(struct menu_item) * menucount);
24eace99
MG
1770
1771 if (!menu_item)
1772 return EFI_OUT_OF_RESOURCES;
d991c4a1 1773
9272bc5b
MG
1774 menu_item[i].text = StrDuplicate(L"Continue boot");
1775 menu_item[i].colour = EFI_WHITE;
1776 menu_item[i].callback = NULL;
d991c4a1 1777
9272bc5b 1778 i++;
24eace99 1779
0a6565c5
MG
1780 if (MokNew || MokAuth) {
1781 if (!MokNew) {
92a136d8 1782 menu_item[i].text = StrDuplicate(L"Reset MOK");
9272bc5b 1783 menu_item[i].colour = EFI_WHITE;
92a136d8 1784 menu_item[i].callback = mok_reset_prompt;
24eace99 1785 } else {
9272bc5b
MG
1786 menu_item[i].text = StrDuplicate(L"Enroll MOK");
1787 menu_item[i].colour = EFI_WHITE;
1788 menu_item[i].data = MokNew;
1789 menu_item[i].data2 = (void *)MokNewSize;
1790 menu_item[i].callback = mok_enrollment_prompt_callback;
24eace99 1791 }
9272bc5b
MG
1792 i++;
1793 }
1794
92a136d8
GCPL
1795 if (MokDel || MokDelAuth) {
1796 menu_item[i].text = StrDuplicate(L"Delete MOK");
1797 menu_item[i].colour = EFI_WHITE;
1798 menu_item[i].data = MokDel;
1799 menu_item[i].data2 = (void *)MokDelSize;
1800 menu_item[i].callback = mok_deletion_prompt;
1801 i++;
1802 }
1803
9272bc5b
MG
1804 if (MokSB) {
1805 menu_item[i].text = StrDuplicate(L"Change Secure Boot state");
1806 menu_item[i].colour = EFI_WHITE;
1807 menu_item[i].callback = mok_sb_prompt;
1808 menu_item[i].data = MokSB;
1809 menu_item[i].data2 = (void *)MokSBSize;
1810 i++;
d991c4a1
MG
1811 }
1812
801d1b93
MG
1813 if (MokPW) {
1814 menu_item[i].text = StrDuplicate(L"Set MOK password");
1815 menu_item[i].colour = EFI_WHITE;
1816 menu_item[i].callback = mok_pw_prompt;
1817 menu_item[i].data = MokPW;
1818 menu_item[i].data2 = (void *)MokPWSize;
1819 i++;
1820 }
1821
9272bc5b
MG
1822 menu_item[i].text = StrDuplicate(L"Enroll key from disk");
1823 menu_item[i].colour = EFI_WHITE;
1824 menu_item[i].callback = find_fs;
1825 menu_item[i].data3 = (void *)FALSE;
0a6565c5 1826
9272bc5b 1827 i++;
0a6565c5 1828
9272bc5b
MG
1829 menu_item[i].text = StrDuplicate(L"Enroll hash from disk");
1830 menu_item[i].colour = EFI_WHITE;
1831 menu_item[i].callback = find_fs;
1832 menu_item[i].data3 = (void *)TRUE;
d991c4a1 1833
9272bc5b 1834 i++;
a68a0c7b 1835
1bc1cd96 1836 run_menu(NULL, 0, menu_item, menucount, 10);
d991c4a1 1837
5f292f8f
MG
1838 uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
1839
d991c4a1
MG
1840 return 0;
1841}
1842
1843static EFI_STATUS check_mok_request(EFI_HANDLE image_handle)
1844{
1845 EFI_GUID shim_lock_guid = SHIM_LOCK_GUID;
92a136d8 1846 UINTN MokNewSize = 0, MokDelSize = 0, MokSBSize = 0, MokPWSize = 0;
d991c4a1 1847 void *MokNew = NULL;
92a136d8 1848 void *MokDel = NULL;
9272bc5b 1849 void *MokSB = NULL;
801d1b93 1850 void *MokPW = NULL;
d991c4a1
MG
1851
1852 MokNew = LibGetVariableAndSize(L"MokNew", &shim_lock_guid, &MokNewSize);
1853
92a136d8
GCPL
1854 MokDel = LibGetVariableAndSize(L"MokDel", &shim_lock_guid, &MokDelSize);
1855
801d1b93
MG
1856 MokSB = LibGetVariableAndSize(L"MokSB", &shim_lock_guid, &MokSBSize);
1857
1858 MokPW = LibGetVariableAndSize(L"MokPW", &shim_lock_guid, &MokPWSize);
9272bc5b 1859
92a136d8
GCPL
1860 enter_mok_menu(image_handle, MokNew, MokNewSize, MokDel, MokDelSize,
1861 MokSB, MokSBSize, MokPW, MokPWSize);
d991c4a1 1862
c326e2df 1863 if (MokNew) {
f3104a73 1864 if (LibDeleteVariable(L"MokNew", &shim_lock_guid) != EFI_SUCCESS) {
333bd977
GCPL
1865 Print(L"Failed to delete MokNew\n");
1866 }
c326e2df 1867 FreePool (MokNew);
333bd977 1868 }
9272bc5b 1869
92a136d8
GCPL
1870 if (MokDel) {
1871 if (LibDeleteVariable(L"MokDel", &shim_lock_guid) != EFI_SUCCESS) {
1872 Print(L"Failed to delete MokDel\n");
1873 }
1874 FreePool (MokDel);
1875 }
1876
9272bc5b
MG
1877 if (MokSB) {
1878 if (LibDeleteVariable(L"MokSB", &shim_lock_guid) != EFI_SUCCESS) {
1879 Print(L"Failed to delete MokSB\n");
1880 }
1881 FreePool (MokNew);
1882 }
801d1b93
MG
1883
1884 if (MokPW) {
1885 if (LibDeleteVariable(L"MokPW", &shim_lock_guid) != EFI_SUCCESS) {
1886 Print(L"Failed to delete MokPW\n");
1887 }
1888 FreePool (MokNew);
1889 }
1890
f3104a73 1891 LibDeleteVariable(L"MokAuth", &shim_lock_guid);
92a136d8 1892 LibDeleteVariable(L"MokDelAuth", &shim_lock_guid);
333bd977 1893
333bd977
GCPL
1894 return EFI_SUCCESS;
1895}
1896
79a5aa03
MG
1897static EFI_STATUS setup_rand (void)
1898{
1899 EFI_TIME time;
1900 EFI_STATUS efi_status;
1901 UINT64 seed;
1902 BOOLEAN status;
1903
1904 efi_status = uefi_call_wrapper(RT->GetTime, 2, &time, NULL);
1905
1906 if (efi_status != EFI_SUCCESS)
1907 return efi_status;
1908
1909 seed = ((UINT64)time.Year << 48) | ((UINT64)time.Month << 40) |
1910 ((UINT64)time.Day << 32) | ((UINT64)time.Hour << 24) |
1911 ((UINT64)time.Minute << 16) | ((UINT64)time.Second << 8) |
1912 ((UINT64)time.Daylight);
1913
1914 status = RandomSeed((UINT8 *)&seed, sizeof(seed));
1915
1916 if (!status)
1917 return EFI_ABORTED;
1918
1919 return EFI_SUCCESS;
1920}
1921
333bd977
GCPL
1922EFI_STATUS efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
1923{
1924 EFI_STATUS efi_status;
1925
1926 InitializeLib(image_handle, systab);
1927
79a5aa03
MG
1928 setup_rand();
1929
333bd977
GCPL
1930 efi_status = check_mok_request(image_handle);
1931
1932 return efi_status;
1933}