4 #include <Library/BaseCryptLib.h>
5 #include <openssl/x509.h>
8 #include "PasswordCrypt.h"
12 #include "variables.h"
13 #include "simple_file.h"
14 #include "efiauthenticated.h"
16 #define PASSWORD_MAX 256
17 #define PASSWORD_MIN 1
18 #define SB_PASSWORD_LEN 16
20 #define NAME_LINE_MAX 70
23 #define SHIM_VENDOR L"Shim"
26 #define EFI_VARIABLE_APPEND_WRITE 0x00000040
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} };
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"
38 INTN (* callback
)(void *data
, void *data2
, void *data3
);
49 } __attribute__ ((packed
)) MokListNode
;
54 CHAR16 Password
[SB_PASSWORD_LEN
];
55 } __attribute__ ((packed
)) MokSBvar
;
60 CHAR16 Password
[SB_PASSWORD_LEN
];
61 } __attribute__ ((packed
)) MokDBvar
;
63 static EFI_STATUS
get_sha1sum (void *Data
, int DataSize
, UINT8
*hash
)
69 ctxsize
= Sha1GetContextSize();
70 ctx
= AllocatePool(ctxsize
);
73 console_notify(L
"Unable to allocate memory for hash context");
74 return EFI_OUT_OF_RESOURCES
;
78 console_notify(L
"Unable to initialise hash");
79 status
= EFI_OUT_OF_RESOURCES
;
83 if (!(Sha1Update(ctx
, Data
, DataSize
))) {
84 console_notify(L
"Unable to generate hash");
85 status
= EFI_OUT_OF_RESOURCES
;
89 if (!(Sha1Final(ctx
, hash
))) {
90 console_notify(L
"Unable to finalise hash");
91 status
= EFI_OUT_OF_RESOURCES
;
100 static BOOLEAN
is_sha2_hash (EFI_GUID Type
)
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
;
107 if (CompareGuid(&Type
, &Sha224
) == 0)
109 else if (CompareGuid(&Type
, &Sha256
) == 0)
111 else if (CompareGuid(&Type
, &Sha384
) == 0)
113 else if (CompareGuid(&Type
, &Sha512
) == 0)
119 static UINT32
sha_size (EFI_GUID Type
)
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
;
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
;
141 static BOOLEAN
is_valid_siglist (EFI_GUID Type
, UINT32 SigSize
)
143 EFI_GUID CertType
= X509_GUID
;
144 UINT32 hash_sig_size
;
146 if (CompareGuid (&Type
, &CertType
) == 0 && SigSize
!= 0)
149 if (!is_sha2_hash (Type
))
152 hash_sig_size
= sha_size (Type
) + sizeof(EFI_GUID
);
153 if (SigSize
!= hash_sig_size
)
159 static UINT32
count_keys(void *Data
, UINTN DataSize
)
161 EFI_SIGNATURE_LIST
*CertList
= Data
;
162 UINTN dbsize
= DataSize
;
164 void *end
= Data
+ DataSize
;
166 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
168 /* Use ptr arithmetics to ensure bounded access. Do not allow 0
169 * SignatureListSize that will cause endless loop.
171 if ((void *)(CertList
+ 1) > end
|| CertList
->SignatureListSize
== 0) {
172 console_notify(L
"Invalid MOK detected! Ignoring MOK List.");
176 if (CertList
->SignatureListSize
== 0 ||
177 CertList
->SignatureListSize
<= CertList
->SignatureSize
) {
178 console_errorbox(L
"Corrupted signature list");
182 if (!is_valid_siglist(CertList
->SignatureType
, CertList
->SignatureSize
)) {
183 console_errorbox(L
"Invalid signature list found");
188 dbsize
-= CertList
->SignatureListSize
;
189 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
190 CertList
->SignatureListSize
);
196 static MokListNode
*build_mok_list(UINT32 num
, void *Data
, UINTN DataSize
) {
198 EFI_SIGNATURE_LIST
*CertList
= Data
;
199 EFI_SIGNATURE_DATA
*Cert
;
200 EFI_GUID CertType
= X509_GUID
;
201 UINTN dbsize
= DataSize
;
203 void *end
= Data
+ DataSize
;
205 list
= AllocatePool(sizeof(MokListNode
) * num
);
208 console_notify(L
"Unable to allocate MOK list");
212 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
213 /* CertList out of bounds? */
214 if ((void *)(CertList
+ 1) > end
|| CertList
->SignatureListSize
== 0) {
219 /* Omit the signature check here since we already did it
222 Cert
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) CertList
) +
223 sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
225 /* Cert out of bounds? */
226 if ((void *)(Cert
+ 1) > end
|| CertList
->SignatureSize
<= sizeof(EFI_GUID
)) {
231 list
[count
].Type
= CertList
->SignatureType
;
232 if (CompareGuid (&CertList
->SignatureType
, &CertType
) == 0) {
233 list
[count
].MokSize
= CertList
->SignatureSize
-
235 list
[count
].Mok
= (void *)Cert
->SignatureData
;
237 list
[count
].MokSize
= CertList
->SignatureListSize
-
238 sizeof(EFI_SIGNATURE_LIST
);
239 list
[count
].Mok
= (void *)Cert
;
242 /* MOK out of bounds? */
243 if (list
[count
].MokSize
> (unsigned long)end
-
244 (unsigned long)list
[count
].Mok
) {
250 dbsize
-= CertList
->SignatureListSize
;
251 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
252 CertList
->SignatureListSize
);
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"},
272 static CHAR16
* get_x509_name (X509_NAME
*X509Name
)
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
;
280 rest
= NAME_LINE_MAX
;
282 for (i
= 0; nidname
[i
].name
!= NULL
; i
++) {
284 len
= X509_NAME_get_text_by_NID (X509Name
, nidname
[i
].nid
,
290 add
= len
+ (int)StrLen(nidname
[i
].name
) + 1;
292 add
= len
+ (int)StrLen(nidname
[i
].name
) + 3;
298 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
"%s=%a",
299 nidname
[i
].name
, str
);
301 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
", %s=%a",
302 nidname
[i
].name
, str
);
309 if (rest
>= 0 && rest
< NAME_LINE_MAX
)
310 return PoolPrint(L
"%s", name
);
315 static CHAR16
* get_x509_time (ASN1_TIME
*time
)
317 BIO
*bio
= BIO_new (BIO_s_mem());
321 ASN1_TIME_print (bio
, time
);
322 len
= BIO_read(bio
, str
, 29);
328 return PoolPrint(L
"%a", str
);
331 static void show_x509_info (X509
*X509Cert
, UINT8
*hash
)
333 ASN1_INTEGER
*serial
;
335 unsigned char hexbuf
[30];
338 CHAR16
*issuer
= NULL
;
339 CHAR16
*subject
= NULL
;
341 CHAR16
*until
= NULL
;
342 POOL_PRINT hash_string1
;
343 POOL_PRINT hash_string2
;
344 POOL_PRINT serial_string
;
349 ZeroMem(&hash_string1
, sizeof(hash_string1
));
350 ZeroMem(&hash_string2
, sizeof(hash_string2
));
351 ZeroMem(&serial_string
, sizeof(serial_string
));
353 serial
= X509_get_serialNumber(X509Cert
);
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
]);
363 if (serial_string
.str
)
366 X509Name
= X509_get_issuer_name(X509Cert
);
368 issuer
= get_x509_name(X509Name
);
373 X509Name
= X509_get_subject_name(X509Cert
);
375 subject
= get_x509_name(X509Name
);
380 time
= X509_get_notBefore(X509Cert
);
382 from
= get_x509_time(time
);
387 time
= X509_get_notAfter(X509Cert
);
389 until
= get_x509_time(time
);
395 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
396 for (i
=10; i
<20; i
++)
397 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
399 if (hash_string1
.str
)
402 if (hash_string2
.str
)
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
"");
416 text
[i
++] = StrDuplicate(L
"[Issuer]");
418 text
[i
++] = StrDuplicate(L
"");
421 text
[i
++] = StrDuplicate(L
"[Subject]");
423 text
[i
++] = StrDuplicate(L
"");
426 text
[i
++] = StrDuplicate(L
"[Valid Not Before]");
428 text
[i
++] = StrDuplicate(L
"");
431 text
[i
++] = StrDuplicate(L
"[Valid Not After]");
433 text
[i
++] = StrDuplicate(L
"");
435 if (hash_string1
.str
) {
436 text
[i
++] = StrDuplicate(L
"[Fingerprint]");
437 text
[i
++] = hash_string1
.str
;
439 if (hash_string2
.str
) {
440 text
[i
++] = hash_string2
.str
;
441 text
[i
++] = StrDuplicate(L
"");
445 console_print_box(text
, -1);
447 for (i
=0; text
[i
] != NULL
; i
++)
453 static void show_sha_digest (EFI_GUID Type
, UINT8
*hash
)
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
;
461 POOL_PRINT hash_string1
;
462 POOL_PRINT hash_string2
;
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";
485 ZeroMem(&hash_string1
, sizeof(hash_string1
));
486 ZeroMem(&hash_string2
, sizeof(hash_string2
));
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
]);
495 text
[2] = hash_string1
.str
;
496 text
[3] = hash_string2
.str
;
499 console_print_box(text
, -1);
501 if (hash_string1
.str
)
502 FreePool(hash_string1
.str
);
504 if (hash_string2
.str
)
505 FreePool(hash_string2
.str
);
508 static void show_efi_hash (EFI_GUID Type
, void *Mok
, UINTN MokSize
)
513 CHAR16
**menu_strings
;
517 sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
518 if ((MokSize
% sig_size
) != 0) {
519 console_errorbox(L
"Corrupted Hash List");
522 hash_num
= MokSize
/ sig_size
;
525 hash
= (UINT8
*)Mok
+ sizeof(EFI_GUID
);
526 show_sha_digest(Type
, hash
);
530 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (hash_num
+ 2));
532 console_errorbox(L
"Out of Resources");
535 for (i
=0; i
<hash_num
; i
++) {
536 menu_strings
[i
] = PoolPrint(L
"View hash %d", i
);
538 menu_strings
[i
] = StrDuplicate(L
"Back");
539 menu_strings
[i
+1] = NULL
;
541 while (key_num
< hash_num
) {
542 key_num
= console_select((CHAR16
*[]){ L
"[Hash List]", NULL
},
543 menu_strings
, key_num
);
545 if (key_num
< 0 || key_num
>= hash_num
)
548 hash
= (UINT8
*)Mok
+ sig_size
*key_num
+ sizeof(EFI_GUID
);
549 show_sha_digest(Type
, hash
);
552 for (i
=0; menu_strings
[i
] != NULL
; i
++)
553 FreePool(menu_strings
[i
]);
555 FreePool(menu_strings
);
558 static void show_mok_info (EFI_GUID Type
, void *Mok
, UINTN MokSize
)
560 EFI_STATUS efi_status
;
561 EFI_GUID CertType
= X509_GUID
;
563 if (!Mok
|| MokSize
== 0)
566 if (CompareGuid (&Type
, &CertType
) == 0) {
567 UINT8 hash
[SHA1_DIGEST_SIZE
];
569 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
571 if (efi_status
!= EFI_SUCCESS
) {
572 console_notify(L
"Failed to compute MOK fingerprint");
576 if (X509ConstructCertificate(Mok
, MokSize
,
577 (UINT8
**) &X509Cert
) && X509Cert
!= NULL
) {
578 show_x509_info(X509Cert
, hash
);
581 console_notify(L
"Not a valid X509 certificate");
584 } else if (is_sha2_hash(Type
)) {
585 show_efi_hash(Type
, Mok
, MokSize
);
589 static EFI_STATUS
list_keys (void *KeyList
, UINTN KeyListSize
, CHAR16
*title
)
592 MokListNode
*keys
= NULL
;
594 CHAR16
**menu_strings
;
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
;
603 MokNum
= count_keys(KeyList
, KeyListSize
);
605 console_errorbox(L
"Invalid key list");
608 keys
= build_mok_list(MokNum
, KeyList
, KeyListSize
);
610 console_errorbox(L
"Failed to construct key list");
614 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (MokNum
+ 2));
617 return EFI_OUT_OF_RESOURCES
;
619 for (i
=0; i
<MokNum
; i
++) {
620 menu_strings
[i
] = PoolPrint(L
"View key %d", i
);
622 menu_strings
[i
] = StrDuplicate(L
"Continue");
624 menu_strings
[i
+1] = NULL
;
626 while (key_num
< MokNum
) {
627 key_num
= console_select((CHAR16
*[]){ title
, NULL
},
628 menu_strings
, key_num
);
630 if (key_num
< 0 || key_num
>= MokNum
)
633 show_mok_info(keys
[key_num
].Type
, keys
[key_num
].Mok
,
634 keys
[key_num
].MokSize
);
637 for (i
=0; menu_strings
[i
] != NULL
; i
++)
638 FreePool(menu_strings
[i
]);
640 FreePool(menu_strings
);
647 static EFI_STATUS
get_line (UINT32
*length
, CHAR16
*line
, UINT32 line_max
, UINT8 show
)
651 unsigned int count
= 0;
654 status
= console_get_keystroke(&key
);
655 if (EFI_ERROR (status
)) {
656 console_error(L
"Failed to read the keystroke", status
);
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
) {
670 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
672 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
676 line
[--count
] = '\0';
681 Print(L
"%c", key
.UnicodeChar
);
684 line
[count
++] = key
.UnicodeChar
;
685 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
693 static EFI_STATUS
compute_pw_hash (void *Data
, UINTN DataSize
, UINT8
*password
,
694 UINT32 pw_length
, UINT8
*hash
)
697 unsigned int ctxsize
;
700 ctxsize
= Sha256GetContextSize();
701 ctx
= AllocatePool(ctxsize
);
704 console_notify(L
"Unable to allocate memory for hash context");
705 return EFI_OUT_OF_RESOURCES
;
708 if (!Sha256Init(ctx
)) {
709 console_notify(L
"Unable to initialise hash");
710 status
= EFI_OUT_OF_RESOURCES
;
714 if (Data
&& DataSize
) {
715 if (!(Sha256Update(ctx
, Data
, DataSize
))) {
716 console_notify(L
"Unable to generate hash");
717 status
= EFI_OUT_OF_RESOURCES
;
722 if (!(Sha256Update(ctx
, password
, pw_length
))) {
723 console_notify(L
"Unable to generate hash");
724 status
= EFI_OUT_OF_RESOURCES
;
728 if (!(Sha256Final(ctx
, hash
))) {
729 console_notify(L
"Unable to finalise hash");
730 status
= EFI_OUT_OF_RESOURCES
;
734 status
= EFI_SUCCESS
;
739 static void console_save_and_set_mode (SIMPLE_TEXT_OUTPUT_MODE
*SavedMode
)
742 Print(L
"Invalid parameter: SavedMode\n");
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
);
752 static void console_restore_mode (SIMPLE_TEXT_OUTPUT_MODE
*SavedMode
)
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
);
762 static UINT32
get_password (CHAR16
*prompt
, CHAR16
*password
, UINT32 max
)
764 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
771 prompt
= L
"Password:";
773 console_save_and_set_mode(&SavedMode
);
775 str
= PoolPrint(L
"%s ", prompt
);
777 console_errorbox(L
"Failed to allocate prompt");
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);
787 console_restore_mode(&SavedMode
);
794 static EFI_STATUS
match_password (PASSWORD_CRYPT
*pw_crypt
,
795 void *Data
, UINTN DataSize
,
796 UINT8
*auth
, CHAR16
*prompt
)
802 CHAR16 password
[PASSWORD_MAX
];
804 UINT8 fail_count
= 0;
808 auth_hash
= pw_crypt
->hash
;
809 auth_size
= get_hash_size (pw_crypt
->method
);
811 return EFI_INVALID_PARAMETER
;
814 auth_size
= SHA256_DIGEST_SIZE
;
816 return EFI_INVALID_PARAMETER
;
819 while (fail_count
< 3) {
820 pw_length
= get_password(prompt
, password
, PASSWORD_MAX
);
822 if (pw_length
< PASSWORD_MIN
|| pw_length
> PASSWORD_MAX
) {
823 console_errorbox(L
"Invalid password length");
829 * Compute password hash
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';
837 status
= password_crypt(pw_ascii
, pw_length
, pw_crypt
, hash
);
840 * For backward compatibility
842 status
= compute_pw_hash(Data
, DataSize
, (UINT8
*)password
,
843 pw_length
* sizeof(CHAR16
), hash
);
845 if (status
!= EFI_SUCCESS
) {
846 console_errorbox(L
"Unable to generate password hash");
851 if (CompareMem(auth_hash
, hash
, auth_size
) != 0) {
852 console_errorbox(L
"Password doesn't match");
861 return EFI_ACCESS_DENIED
;
866 static EFI_STATUS
store_keys (void *MokNew
, UINTN MokNewSize
, int authenticate
,
869 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
870 EFI_STATUS efi_status
;
873 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
874 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
878 db_name
= L
"MokListX";
879 auth_name
= L
"MokXAuth";
881 db_name
= L
"MokList";
882 auth_name
= L
"MokAuth";
886 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, auth_name
,
888 &attributes
, &auth_size
, auth
);
890 if (efi_status
!= EFI_SUCCESS
||
891 (auth_size
!= SHA256_DIGEST_SIZE
&&
892 auth_size
!= PASSWORD_CRYPT_SIZE
)) {
894 console_error(L
"Failed to get MokXAuth", efi_status
);
896 console_error(L
"Failed to get MokAuth", efi_status
);
900 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
901 efi_status
= match_password((PASSWORD_CRYPT
*)auth
,
902 NULL
, 0, NULL
, NULL
);
904 efi_status
= match_password(NULL
, MokNew
, MokNewSize
,
907 if (efi_status
!= EFI_SUCCESS
)
908 return EFI_ACCESS_DENIED
;
913 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, db_name
,
915 EFI_VARIABLE_NON_VOLATILE
916 | EFI_VARIABLE_BOOTSERVICE_ACCESS
,
920 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, db_name
,
922 EFI_VARIABLE_NON_VOLATILE
923 | EFI_VARIABLE_BOOTSERVICE_ACCESS
924 | EFI_VARIABLE_APPEND_WRITE
,
928 if (efi_status
!= EFI_SUCCESS
) {
929 console_error(L
"Failed to set variable", efi_status
);
936 static INTN
mok_enrollment_prompt (void *MokNew
, UINTN MokNewSize
, int auth
,
939 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
940 EFI_STATUS efi_status
;
944 title
= L
"[Enroll MOKX]";
946 title
= L
"[Enroll MOK]";
948 if (list_keys(MokNew
, MokNewSize
, title
) != EFI_SUCCESS
)
951 if (console_yes_no((CHAR16
*[]){L
"Enroll the key(s)?", NULL
}) == 0)
954 efi_status
= store_keys(MokNew
, MokNewSize
, auth
, MokX
);
956 if (efi_status
!= EFI_SUCCESS
) {
957 console_notify(L
"Failed to enroll keys\n");
963 LibDeleteVariable(L
"MokXNew", &shim_lock_guid
);
964 LibDeleteVariable(L
"MokXAuth", &shim_lock_guid
);
966 LibDeleteVariable(L
"MokNew", &shim_lock_guid
);
967 LibDeleteVariable(L
"MokAuth", &shim_lock_guid
);
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");
980 static INTN
mok_reset_prompt (BOOLEAN MokX
)
982 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
983 EFI_STATUS efi_status
;
986 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
989 prompt
= L
"Erase all stored keys in MokListX?";
991 prompt
= L
"Erase all stored keys in MokList?";
992 if (console_yes_no((CHAR16
*[]){prompt
, NULL
}) == 0)
995 efi_status
= store_keys(NULL
, 0, TRUE
, MokX
);
997 if (efi_status
!= EFI_SUCCESS
) {
998 console_notify(L
"Failed to erase keys\n");
1003 LibDeleteVariable(L
"MokXNew", &shim_lock_guid
);
1004 LibDeleteVariable(L
"MokXAuth", &shim_lock_guid
);
1006 LibDeleteVariable(L
"MokNew", &shim_lock_guid
);
1007 LibDeleteVariable(L
"MokAuth", &shim_lock_guid
);
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");
1017 static EFI_STATUS
write_back_mok_list (MokListNode
*list
, INTN key_num
,
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
;
1031 db_name
= L
"MokListX";
1033 db_name
= L
"MokList";
1035 for (i
= 0; i
< key_num
; i
++) {
1036 if (list
[i
].Mok
== NULL
)
1039 DataSize
+= sizeof(EFI_SIGNATURE_LIST
);
1040 if (CompareGuid(&(list
[i
].Type
), &CertType
) == 0)
1041 DataSize
+= sizeof(EFI_GUID
);
1042 DataSize
+= list
[i
].MokSize
;
1045 Data
= AllocatePool(DataSize
);
1046 if (Data
== NULL
&& DataSize
!= 0)
1047 return EFI_OUT_OF_RESOURCES
;
1051 for (i
= 0; i
< key_num
; i
++) {
1052 if (list
[i
].Mok
== NULL
)
1055 CertList
= (EFI_SIGNATURE_LIST
*)ptr
;
1056 CertData
= (EFI_SIGNATURE_DATA
*)(((uint8_t *)ptr
) +
1057 sizeof(EFI_SIGNATURE_LIST
));
1059 CertList
->SignatureType
= list
[i
].Type
;
1060 CertList
->SignatureHeaderSize
= 0;
1062 if (CompareGuid(&(list
[i
].Type
), &CertType
) == 0) {
1063 CertList
->SignatureListSize
= list
[i
].MokSize
+
1064 sizeof(EFI_SIGNATURE_LIST
) +
1066 CertList
->SignatureSize
= list
[i
].MokSize
+ sizeof(EFI_GUID
);
1068 CertData
->SignatureOwner
= shim_lock_guid
;
1069 CopyMem(CertData
->SignatureData
, list
[i
].Mok
, list
[i
].MokSize
);
1071 CertList
->SignatureListSize
= list
[i
].MokSize
+
1072 sizeof(EFI_SIGNATURE_LIST
);
1073 CertList
->SignatureSize
= sha_size(list
[i
].Type
) + sizeof(EFI_GUID
);
1075 CopyMem(CertData
, list
[i
].Mok
, list
[i
].MokSize
);
1077 ptr
= (uint8_t *)ptr
+ CertList
->SignatureListSize
;
1080 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, db_name
,
1082 EFI_VARIABLE_NON_VOLATILE
1083 | EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1088 if (efi_status
!= EFI_SUCCESS
) {
1089 console_error(L
"Failed to set variable", efi_status
);
1096 static void delete_cert (void *key
, UINT32 key_size
,
1097 MokListNode
*mok
, INTN mok_num
)
1099 EFI_GUID CertType
= X509_GUID
;
1102 for (i
= 0; i
< mok_num
; i
++) {
1103 if (CompareGuid(&(mok
[i
].Type
), &CertType
) != 0)
1106 if (mok
[i
].MokSize
== key_size
&&
1107 CompareMem(key
, mok
[i
].Mok
, key_size
) == 0) {
1108 /* Remove the key */
1115 static int match_hash (UINT8
*hash
, UINT32 hash_size
, int start
,
1116 void *hash_list
, UINT32 list_num
)
1121 ptr
= hash_list
+ sizeof(EFI_GUID
);
1122 for (i
= start
; i
< list_num
; i
++) {
1123 if (CompareMem(hash
, ptr
, hash_size
) == 0)
1125 ptr
+= hash_size
+ sizeof(EFI_GUID
);
1131 static void mem_move (void *dest
, void *src
, UINTN size
)
1138 for (i
= 0; i
< size
; i
++)
1142 static void delete_hash_in_list (EFI_GUID Type
, UINT8
*hash
, UINT32 hash_size
,
1143 MokListNode
*mok
, INTN mok_num
)
1151 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1153 for (i
= 0; i
< mok_num
; i
++) {
1154 if ((CompareGuid(&(mok
[i
].Type
), &Type
) != 0) ||
1155 (mok
[i
].MokSize
< sig_size
))
1158 list_num
= mok
[i
].MokSize
/ sig_size
;
1160 del_ind
= match_hash(hash
, hash_size
, 0, mok
[i
].Mok
,
1162 while (del_ind
>= 0) {
1163 /* Remove the hash */
1164 if (sig_size
== mok
[i
].MokSize
) {
1170 start
= mok
[i
].Mok
+ del_ind
* sig_size
;
1171 end
= start
+ sig_size
;
1172 remain
= mok
[i
].MokSize
- (del_ind
+ 1)*sig_size
;
1174 mem_move(start
, end
, remain
);
1175 mok
[i
].MokSize
-= sig_size
;
1178 del_ind
= match_hash(hash
, hash_size
, del_ind
,
1179 mok
[i
].Mok
, list_num
);
1184 static void delete_hash_list (EFI_GUID Type
, void *hash_list
, UINT32 list_size
,
1185 MokListNode
*mok
, INTN mok_num
)
1193 hash_size
= sha_size (Type
);
1194 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1195 if (list_size
< sig_size
)
1198 hash_num
= list_size
/ sig_size
;
1200 hash
= hash_list
+ sizeof(EFI_GUID
);
1202 for (i
= 0; i
< hash_num
; i
++) {
1203 delete_hash_in_list (Type
, hash
, hash_size
, mok
, mok_num
);
1208 static EFI_STATUS
delete_keys (void *MokDel
, UINTN MokDelSize
, BOOLEAN MokX
)
1210 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
1211 EFI_GUID CertType
= X509_GUID
;
1212 EFI_STATUS efi_status
;
1217 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
1218 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
1220 UINT8
*MokListData
= NULL
;
1221 UINTN MokListDataSize
= 0;
1222 MokListNode
*mok
, *del_key
;
1223 INTN mok_num
, del_num
;
1227 db_name
= L
"MokListX";
1228 auth_name
= L
"MokXDelAuth";
1230 db_name
= L
"MokList";
1231 auth_name
= L
"MokDelAuth";
1234 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, auth_name
,
1236 &attributes
, &auth_size
, auth
);
1238 if (efi_status
!= EFI_SUCCESS
||
1239 (auth_size
!= SHA256_DIGEST_SIZE
&& auth_size
!= PASSWORD_CRYPT_SIZE
)) {
1241 console_error(L
"Failed to get MokXDelAuth", efi_status
);
1243 console_error(L
"Failed to get MokDelAuth", efi_status
);
1247 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
1248 efi_status
= match_password((PASSWORD_CRYPT
*)auth
, NULL
, 0,
1251 efi_status
= match_password(NULL
, MokDel
, MokDelSize
, auth
, NULL
);
1253 if (efi_status
!= EFI_SUCCESS
)
1254 return EFI_ACCESS_DENIED
;
1256 efi_status
= get_variable_attr (db_name
, &MokListData
, &MokListDataSize
,
1257 shim_lock_guid
, &attributes
);
1258 if (efi_status
!= EFI_SUCCESS
) {
1260 console_errorbox(L
"Failed to retrieve MokListX");
1262 console_errorbox(L
"Failed to retrieve MokList");
1264 } else if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
1266 err_str1
= L
"MokListX is compromised!";
1267 err_str2
= L
"Erase all keys in MokListX!";
1269 err_str1
= L
"MokList is compromised!";
1270 err_str2
= L
"Erase all keys in MokList!";
1272 console_alertbox((CHAR16
*[]){err_str1
, err_str2
, NULL
});
1273 uefi_call_wrapper(RT
->SetVariable
, 5, db_name
,
1275 EFI_VARIABLE_NON_VOLATILE
|
1276 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1278 return EFI_ACCESS_DENIED
;
1282 if (!MokListData
|| MokListDataSize
== 0)
1285 /* Construct lists */
1286 mok_num
= count_keys(MokListData
, MokListDataSize
);
1289 err_str1
= L
"Failed to construct the key list of MokListX";
1290 err_str2
= L
"Reset MokListX!";
1292 err_str1
= L
"Failed to construct the key list of MokList";
1293 err_str2
= L
"Reset MokList!";
1295 console_alertbox((CHAR16
*[]){err_str1
, err_str2
, NULL
});
1296 uefi_call_wrapper(RT
->SetVariable
, 5, db_name
,
1298 EFI_VARIABLE_NON_VOLATILE
|
1299 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1301 efi_status
= EFI_ABORTED
;
1304 mok
= build_mok_list(mok_num
, MokListData
, MokListDataSize
);
1306 console_errorbox(L
"Failed to construct key list");
1307 efi_status
= EFI_ABORTED
;
1310 del_num
= count_keys(MokDel
, MokDelSize
);
1312 console_errorbox(L
"Invalid key delete list");
1313 efi_status
= EFI_ABORTED
;
1316 del_key
= build_mok_list(del_num
, MokDel
, MokDelSize
);
1318 console_errorbox(L
"Failed to construct key list");
1319 efi_status
= EFI_ABORTED
;
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
,
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
);
1334 efi_status
= write_back_mok_list(mok
, mok_num
, MokX
);
1338 FreePool(MokListData
);
1347 static INTN
mok_deletion_prompt (void *MokDel
, UINTN MokDelSize
, BOOLEAN MokX
)
1349 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
1350 EFI_STATUS efi_status
;
1354 title
= L
"[Delete MOKX]";
1356 title
= L
"[Delete MOK]";
1358 if (list_keys(MokDel
, MokDelSize
, title
) != EFI_SUCCESS
) {
1362 if (console_yes_no((CHAR16
*[]){L
"Delete the key(s)?", NULL
}) == 0)
1365 efi_status
= delete_keys(MokDel
, MokDelSize
, MokX
);
1367 if (efi_status
!= EFI_SUCCESS
) {
1368 console_notify(L
"Failed to delete keys");
1373 LibDeleteVariable(L
"MokXDel", &shim_lock_guid
);
1374 LibDeleteVariable(L
"MokXDelAuth", &shim_lock_guid
);
1376 LibDeleteVariable(L
"MokDel", &shim_lock_guid
);
1377 LibDeleteVariable(L
"MokDelAuth", &shim_lock_guid
);
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");
1387 static CHAR16
get_password_charater (CHAR16
*prompt
)
1389 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1397 prompt
= L
"Password charater: ";
1399 console_save_and_set_mode(&SavedMode
);
1401 message
[0] = prompt
;
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
))
1409 console_restore_mode(&SavedMode
);
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
;
1420 CHAR16 pass1
, pass2
, pass3
;
1422 UINT8 fail_count
= 0;
1424 UINT8 pos1
, pos2
, pos3
;
1427 if (MokSBSize
!= sizeof(MokSBvar
)) {
1428 console_notify(L
"Invalid MokSB variable contents");
1432 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
1434 message
[0] = L
"Change Secure Boot state";
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
);
1441 while (fail_count
< 3) {
1442 RandomBytes (&pos1
, sizeof(pos1
));
1443 pos1
= (pos1
% var
->PWLen
);
1446 RandomBytes (&pos2
, sizeof(pos2
));
1447 pos2
= (pos2
% var
->PWLen
);
1448 } while (pos2
== pos1
);
1451 RandomBytes (&pos3
, sizeof(pos3
));
1452 pos3
= (pos3
% var
->PWLen
) ;
1453 } while (pos3
== pos2
|| pos3
== pos1
);
1455 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1457 console_errorbox(L
"Failed to allocate buffer");
1460 pass1
= get_password_charater(str
);
1463 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1465 console_errorbox(L
"Failed to allocate buffer");
1468 pass2
= get_password_charater(str
);
1471 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1473 console_errorbox(L
"Failed to allocate buffer");
1476 pass3
= get_password_charater(str
);
1479 if (pass1
!= var
->Password
[pos1
] ||
1480 pass2
!= var
->Password
[pos2
] ||
1481 pass3
!= var
->Password
[pos3
]) {
1482 Print(L
"Invalid character\n");
1489 if (fail_count
>= 3) {
1490 console_notify(L
"Password limit reached");
1494 if (var
->MokSBState
== 0)
1495 ret
= console_yes_no((CHAR16
*[]){L
"Disable Secure Boot", NULL
});
1497 ret
= console_yes_no((CHAR16
*[]){L
"Enable Secure Boot", NULL
});
1500 LibDeleteVariable(L
"MokSB", &shim_lock_guid
);
1504 if (var
->MokSBState
== 0) {
1505 efi_status
= uefi_call_wrapper(RT
->SetVariable
,
1508 EFI_VARIABLE_NON_VOLATILE
|
1509 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1511 if (efi_status
!= EFI_SUCCESS
) {
1512 console_notify(L
"Failed to set Secure Boot state");
1516 efi_status
= uefi_call_wrapper(RT
->SetVariable
,
1519 EFI_VARIABLE_NON_VOLATILE
|
1520 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1522 if (efi_status
!= EFI_SUCCESS
) {
1523 console_notify(L
"Failed to delete Secure Boot state");
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");
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
;
1541 CHAR16 pass1
, pass2
, pass3
;
1543 UINT8 fail_count
= 0;
1545 UINT8 pos1
, pos2
, pos3
;
1548 if (MokDBSize
!= sizeof(MokDBvar
)) {
1549 console_notify(L
"Invalid MokDB variable contents");
1553 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
1555 message
[0] = L
"Change DB state";
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
);
1562 while (fail_count
< 3) {
1563 RandomBytes (&pos1
, sizeof(pos1
));
1564 pos1
= (pos1
% var
->PWLen
);
1567 RandomBytes (&pos2
, sizeof(pos2
));
1568 pos2
= (pos2
% var
->PWLen
);
1569 } while (pos2
== pos1
);
1572 RandomBytes (&pos3
, sizeof(pos3
));
1573 pos3
= (pos3
% var
->PWLen
) ;
1574 } while (pos3
== pos2
|| pos3
== pos1
);
1576 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1578 console_errorbox(L
"Failed to allocate buffer");
1581 pass1
= get_password_charater(str
);
1584 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1586 console_errorbox(L
"Failed to allocate buffer");
1589 pass2
= get_password_charater(str
);
1592 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1594 console_errorbox(L
"Failed to allocate buffer");
1597 pass3
= get_password_charater(str
);
1600 if (pass1
!= var
->Password
[pos1
] ||
1601 pass2
!= var
->Password
[pos2
] ||
1602 pass3
!= var
->Password
[pos3
]) {
1603 Print(L
"Invalid character\n");
1610 if (fail_count
>= 3) {
1611 console_notify(L
"Password limit reached");
1615 if (var
->MokDBState
== 0)
1616 ret
= console_yes_no((CHAR16
*[]){L
"Ignore DB certs/hashes", NULL
});
1618 ret
= console_yes_no((CHAR16
*[]){L
"Use DB certs/hashes", NULL
});
1621 LibDeleteVariable(L
"MokDB", &shim_lock_guid
);
1625 if (var
->MokDBState
== 0) {
1626 efi_status
= uefi_call_wrapper(RT
->SetVariable
,
1629 EFI_VARIABLE_NON_VOLATILE
|
1630 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1632 if (efi_status
!= EFI_SUCCESS
) {
1633 console_notify(L
"Failed to set DB state");
1637 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5,
1640 EFI_VARIABLE_NON_VOLATILE
|
1641 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1643 if (efi_status
!= EFI_SUCCESS
) {
1644 console_notify(L
"Failed to delete DB state");
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");
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
];
1662 if (MokPWSize
!= SHA256_DIGEST_SIZE
&& MokPWSize
!= PASSWORD_CRYPT_SIZE
) {
1663 console_notify(L
"Invalid MokPW variable contents");
1667 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
1669 SetMem(hash
, PASSWORD_CRYPT_SIZE
, 0);
1671 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1672 if (CompareMem(MokPW
, hash
, PASSWORD_CRYPT_SIZE
) == 0)
1675 if (CompareMem(MokPW
, hash
, SHA256_DIGEST_SIZE
) == 0)
1680 if (console_yes_no((CHAR16
*[]){L
"Clear MOK password?", NULL
}) == 0)
1683 uefi_call_wrapper(RT
->SetVariable
, 5, L
"MokPWStore",
1685 EFI_VARIABLE_NON_VOLATILE
1686 | EFI_VARIABLE_BOOTSERVICE_ACCESS
,
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,
1692 console_notify(L
"Failed to reboot");
1696 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1697 efi_status
= match_password((PASSWORD_CRYPT
*)MokPW
, NULL
, 0,
1698 NULL
, L
"Confirm MOK passphrase: ");
1700 efi_status
= match_password(NULL
, NULL
, 0, MokPW
,
1701 L
"Confirm MOK passphrase: ");
1704 if (efi_status
!= EFI_SUCCESS
) {
1705 console_notify(L
"Password limit reached");
1709 if (console_yes_no((CHAR16
*[]){L
"Set MOK password?", NULL
}) == 0)
1712 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5,
1715 EFI_VARIABLE_NON_VOLATILE
|
1716 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1718 if (efi_status
!= EFI_SUCCESS
) {
1719 console_notify(L
"Failed to set MOK password");
1723 LibDeleteVariable(L
"MokPW", &shim_lock_guid
);
1725 console_notify(L
"The system must now be rebooted");
1726 uefi_call_wrapper(RT
->ResetSystem
, 4, EfiResetWarm
, EFI_SUCCESS
, 0,
1728 console_notify(L
"Failed to reboot");
1732 static BOOLEAN
verify_certificate(UINT8
*cert
, UINTN size
)
1736 if (!cert
|| size
< 0)
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.
1746 if (cert
[0] != 0x30 || cert
[1] != 0x82) {
1747 console_notify(L
"Not a DER encoding X509 certificate");
1751 length
= (cert
[2]<<8 | cert
[3]);
1752 if (length
!= (size
- 4)) {
1753 console_notify(L
"Invalid X509 certificate: Inconsistent size");
1757 if (!(X509ConstructCertificate(cert
, size
, (UINT8
**) &X509Cert
)) ||
1759 console_notify(L
"Invalid X509 certificate");
1763 X509_free(X509Cert
);
1767 static EFI_STATUS
enroll_file (void *data
, UINTN datasize
, BOOLEAN hash
)
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
;
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
;
1783 status
= LibLocateProtocol(&shim_guid
, (VOID
**)&shim_lock
);
1785 if (status
!= EFI_SUCCESS
)
1788 mokbuffersize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
) +
1791 mokbuffer
= AllocatePool(mokbuffersize
);
1796 status
= shim_lock
->Context(data
, datasize
, &context
);
1798 if (status
!= EFI_SUCCESS
)
1801 status
= shim_lock
->Hash(data
, datasize
, &context
, sha256
,
1804 if (status
!= EFI_SUCCESS
)
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
);
1814 mokbuffersize
= datasize
+ sizeof(EFI_SIGNATURE_LIST
) +
1816 mokbuffer
= AllocatePool(mokbuffersize
);
1821 CertList
= mokbuffer
;
1822 CertList
->SignatureType
= X509_GUID
;
1823 CertList
->SignatureSize
= 16 + datasize
;
1825 memcpy(mokbuffer
+ sizeof(EFI_SIGNATURE_LIST
) + 16, data
,
1828 CertData
= (EFI_SIGNATURE_DATA
*)(((UINT8
*)mokbuffer
) +
1829 sizeof(EFI_SIGNATURE_LIST
));
1832 CertList
->SignatureListSize
= mokbuffersize
;
1833 CertList
->SignatureHeaderSize
= 0;
1834 CertData
->SignatureOwner
= shim_lock_guid
;
1837 if (!verify_certificate(CertData
->SignatureData
, datasize
))
1841 mok_enrollment_prompt(mokbuffer
, mokbuffersize
, FALSE
, FALSE
);
1844 FreePool(mokbuffer
);
1849 static void mok_hash_enroll(void)
1851 EFI_STATUS efi_status
;
1852 CHAR16
*file_name
= NULL
;
1853 EFI_HANDLE im
= NULL
;
1854 EFI_FILE
*file
= NULL
;
1858 simple_file_selector(&im
, (CHAR16
*[]){
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",
1865 }, L
"\\", L
"", &file_name
);
1870 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1872 if (efi_status
!= EFI_SUCCESS
) {
1873 console_error(L
"Unable to open file", efi_status
);
1877 simple_file_read_all(file
, &filesize
, &data
);
1878 simple_file_close(file
);
1881 console_error(L
"Unable to read file", efi_status
);
1885 efi_status
= enroll_file(data
, filesize
, TRUE
);
1887 if (efi_status
!= EFI_SUCCESS
)
1888 console_error(L
"Hash failed (did you select a valid EFI binary?)", efi_status
);
1893 static CHAR16
*der_suffix
[] = {
1900 static BOOLEAN
check_der_suffix (CHAR16
*file_name
)
1905 if (!file_name
|| StrLen(file_name
) <= 4)
1909 StrCat(suffix
, file_name
+ StrLen(file_name
) - 4);
1912 for (i
= 0; der_suffix
[i
] != NULL
; i
++) {
1913 if (StrCmp(suffix
, der_suffix
[i
]) == 0) {
1921 static void mok_key_enroll(void)
1923 EFI_STATUS efi_status
;
1924 CHAR16
*file_name
= NULL
;
1925 EFI_HANDLE im
= NULL
;
1926 EFI_FILE
*file
= NULL
;
1930 simple_file_selector(&im
, (CHAR16
*[]){
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",
1937 }, L
"\\", L
"", &file_name
);
1942 if (!check_der_suffix(file_name
)) {
1943 console_alertbox((CHAR16
*[]){
1944 L
"Unsupported Format",
1946 L
"Only DER encoded certificate (*.cer/der/crt) is supported",
1951 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1953 if (efi_status
!= EFI_SUCCESS
) {
1954 console_error(L
"Unable to open file", efi_status
);
1958 simple_file_read_all(file
, &filesize
, &data
);
1959 simple_file_close(file
);
1962 console_error(L
"Unable to read file", efi_status
);
1966 enroll_file(data
, filesize
, FALSE
);
1970 static BOOLEAN
verify_pw(BOOLEAN
*protected)
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
;
1982 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokPWStore",
1983 &shim_lock_guid
, &attributes
, &size
,
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
1991 if (efi_status
!= EFI_SUCCESS
||
1992 (size
!= SHA256_DIGEST_SIZE
&& size
!= PASSWORD_CRYPT_SIZE
))
1995 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)
1998 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
2000 /* Draw the background */
2001 console_save_and_set_mode(&SavedMode
);
2002 message
[0] = PoolPrint (L
"%s UEFI key management", SHIM_VENDOR
);
2004 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
2005 FreePool(message
[0]);
2006 console_restore_mode(&SavedMode
);
2008 if (size
== PASSWORD_CRYPT_SIZE
) {
2009 efi_status
= match_password((PASSWORD_CRYPT
*)pwhash
, NULL
, 0,
2010 NULL
, L
"Enter MOK password:");
2012 efi_status
= match_password(NULL
, NULL
, 0, pwhash
,
2013 L
"Enter MOK password:");
2015 if (efi_status
!= EFI_SUCCESS
) {
2016 console_notify(L
"Password limit reached");
2025 static int draw_countdown()
2027 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
2032 CHAR16
*message
= L
"Press any key to perform MOK management";
2033 int timeout
= 10, wait
= 10000000;
2035 console_save_and_set_mode (&SavedMode
);
2037 title
[0] = PoolPrint (L
"%s UEFI key management", SHIM_VENDOR
);
2040 console_print_box_at(title
, -1, 0, 0, -1, -1, 1, 1);
2042 uefi_call_wrapper(ST
->ConOut
->QueryMode
, 4, ST
->ConOut
,
2043 ST
->ConOut
->Mode
->Mode
, &cols
, &rows
);
2045 PrintAt((cols
- StrLen(message
))/2, rows
/2, message
);
2048 PrintAt(2, rows
- 3, L
"Booting in %d seconds ", timeout
);
2050 PrintAt(2, rows
- 3, L
"Booting in %d second ", timeout
);
2052 status
= WaitForSingleEvent(ST
->ConIn
->WaitForKey
, wait
);
2054 if (status
!= EFI_TIMEOUT
) {
2055 /* Clear the key in the queue */
2056 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2,
2068 console_restore_mode(&SavedMode
);
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
)
2097 CHAR16
**menu_strings
;
2098 mok_menu_item
*menu_item
;
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
;
2111 EFI_STATUS ret
= EFI_SUCCESS
;
2113 if (verify_pw(&protected) == FALSE
)
2114 return EFI_ACCESS_DENIED
;
2116 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokAuth",
2118 &attributes
, &auth_size
, auth
);
2120 if ((efi_status
== EFI_SUCCESS
) &&
2121 (auth_size
== SHA256_DIGEST_SIZE
|| auth_size
== PASSWORD_CRYPT_SIZE
))
2124 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokDelAuth",
2126 &attributes
, &auth_size
, auth
);
2128 if ((efi_status
== EFI_SUCCESS
) &&
2129 (auth_size
== SHA256_DIGEST_SIZE
|| auth_size
== PASSWORD_CRYPT_SIZE
))
2132 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokXAuth",
2134 &attributes
, &auth_size
, auth
);
2136 if ((efi_status
== EFI_SUCCESS
) &&
2137 (auth_size
== SHA256_DIGEST_SIZE
|| auth_size
== PASSWORD_CRYPT_SIZE
))
2140 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokXDelAuth",
2142 &attributes
, &auth_size
, auth
);
2144 if ((efi_status
== EFI_SUCCESS
) &&
2145 (auth_size
== SHA256_DIGEST_SIZE
|| auth_size
== PASSWORD_CRYPT_SIZE
))
2148 if (MokNew
|| MokAuth
)
2151 if (MokDel
|| MokDelAuth
)
2154 if (MokXNew
|| MokXAuth
)
2157 if (MokXDel
|| MokXDelAuth
)
2169 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (menucount
+ 1));
2172 return EFI_OUT_OF_RESOURCES
;
2174 menu_item
= AllocateZeroPool(sizeof(mok_menu_item
) * menucount
);
2177 FreePool(menu_strings
);
2178 return EFI_OUT_OF_RESOURCES
;
2181 menu_strings
[i
] = L
"Continue boot";
2182 menu_item
[i
] = MOK_CONTINUE_BOOT
;
2186 if (MokNew
|| MokAuth
) {
2188 menu_strings
[i
] = L
"Reset MOK";
2189 menu_item
[i
] = MOK_RESET_MOK
;
2191 menu_strings
[i
] = L
"Enroll MOK";
2192 menu_item
[i
] = MOK_ENROLL_MOK
;
2197 if (MokDel
|| MokDelAuth
) {
2198 menu_strings
[i
] = L
"Delete MOK";
2199 menu_item
[i
] = MOK_DELETE_MOK
;
2203 if (MokXNew
|| MokXAuth
) {
2205 menu_strings
[i
] = L
"Reset MOKX";
2206 menu_item
[i
] = MOK_RESET_MOKX
;
2208 menu_strings
[i
] = L
"Enroll MOKX";
2209 menu_item
[i
] = MOK_ENROLL_MOKX
;
2214 if (MokXDel
|| MokXDelAuth
) {
2215 menu_strings
[i
] = L
"Delete MOKX";
2216 menu_item
[i
] = MOK_DELETE_MOKX
;
2221 menu_strings
[i
] = L
"Change Secure Boot state";
2222 menu_item
[i
] = MOK_CHANGE_SB
;
2227 menu_strings
[i
] = L
"Set MOK password";
2228 menu_item
[i
] = MOK_SET_PW
;
2233 menu_strings
[i
] = L
"Change DB state";
2234 menu_item
[i
] = MOK_CHANGE_DB
;
2238 menu_strings
[i
] = L
"Enroll key from disk";
2239 menu_item
[i
] = MOK_KEY_ENROLL
;
2242 menu_strings
[i
] = L
"Enroll hash from disk";
2243 menu_item
[i
] = MOK_HASH_ENROLL
;
2246 menu_strings
[i
] = NULL
;
2248 if (protected == FALSE
&& draw_countdown() == 0)
2251 while (choice
>= 0) {
2252 choice
= console_select((CHAR16
*[]){ L
"Perform MOK management", NULL
},
2258 switch (menu_item
[choice
]) {
2259 case MOK_CONTINUE_BOOT
:
2262 mok_reset_prompt(FALSE
);
2264 case MOK_ENROLL_MOK
:
2265 mok_enrollment_prompt(MokNew
, MokNewSize
, TRUE
, FALSE
);
2267 case MOK_DELETE_MOK
:
2268 mok_deletion_prompt(MokDel
, MokDelSize
, FALSE
);
2270 case MOK_RESET_MOKX
:
2271 mok_reset_prompt(TRUE
);
2273 case MOK_ENROLL_MOKX
:
2274 mok_enrollment_prompt(MokXNew
, MokXNewSize
, TRUE
, TRUE
);
2276 case MOK_DELETE_MOKX
:
2277 mok_deletion_prompt(MokXDel
, MokXDelSize
, TRUE
);
2280 mok_sb_prompt(MokSB
, MokSBSize
);
2283 mok_pw_prompt(MokPW
, MokPWSize
);
2286 mok_db_prompt(MokDB
, MokDBSize
);
2288 case MOK_KEY_ENROLL
:
2291 case MOK_HASH_ENROLL
:
2300 FreePool(menu_strings
);
2303 FreePool(menu_item
);
2308 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
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
;
2318 void *MokXNew
= NULL
;
2319 void *MokXDel
= NULL
;
2322 status
= get_variable(L
"MokNew", (UINT8
**)&MokNew
, &MokNewSize
,
2324 if (status
== EFI_SUCCESS
) {
2325 if (LibDeleteVariable(L
"MokNew", &shim_lock_guid
) != EFI_SUCCESS
) {
2326 console_notify(L
"Failed to delete MokNew");
2328 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2329 console_error(L
"Could not retrieve MokNew", status
);
2332 status
= get_variable(L
"MokDel", (UINT8
**)&MokDel
, &MokDelSize
,
2334 if (status
== EFI_SUCCESS
) {
2335 if (LibDeleteVariable(L
"MokDel", &shim_lock_guid
) != EFI_SUCCESS
) {
2336 console_notify(L
"Failed to delete MokDel");
2338 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2339 console_error(L
"Could not retrieve MokDel", status
);
2342 status
= get_variable(L
"MokSB", (UINT8
**)&MokSB
, &MokSBSize
,
2344 if (status
== EFI_SUCCESS
) {
2345 if (LibDeleteVariable(L
"MokSB", &shim_lock_guid
) != EFI_SUCCESS
) {
2346 console_notify(L
"Failed to delete MokSB");
2348 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2349 console_error(L
"Could not retrieve MokSB", status
);
2352 status
= get_variable(L
"MokPW", (UINT8
**)&MokPW
, &MokPWSize
,
2354 if (status
== EFI_SUCCESS
) {
2355 if (LibDeleteVariable(L
"MokPW", &shim_lock_guid
) != EFI_SUCCESS
) {
2356 console_notify(L
"Failed to delete MokPW");
2358 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2359 console_error(L
"Could not retrieve MokPW", status
);
2362 status
= get_variable(L
"MokDB", (UINT8
**)&MokDB
, &MokDBSize
,
2364 if (status
== EFI_SUCCESS
) {
2365 if (LibDeleteVariable(L
"MokDB", &shim_lock_guid
) != EFI_SUCCESS
) {
2366 console_notify(L
"Failed to delete MokDB");
2368 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2369 console_error(L
"Could not retrieve MokDB", status
);
2372 status
= get_variable(L
"MokXNew", (UINT8
**)&MokXNew
, &MokXNewSize
,
2374 if (status
== EFI_SUCCESS
) {
2375 if (LibDeleteVariable(L
"MokXNew", &shim_lock_guid
) != EFI_SUCCESS
) {
2376 console_notify(L
"Failed to delete MokXNew");
2378 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2379 console_error(L
"Could not retrieve MokXNew", status
);
2382 status
= get_variable(L
"MokXDel", (UINT8
**)&MokXDel
, &MokXDelSize
,
2384 if (status
== EFI_SUCCESS
) {
2385 if (LibDeleteVariable(L
"MokXDel", &shim_lock_guid
) != EFI_SUCCESS
) {
2386 console_notify(L
"Failed to delete MokXDel");
2388 } else if (EFI_ERROR(status
) && status
!= EFI_NOT_FOUND
) {
2389 console_error(L
"Could not retrieve MokXDel", status
);
2392 enter_mok_menu(image_handle
, MokNew
, MokNewSize
, MokDel
, MokDelSize
,
2393 MokSB
, MokSBSize
, MokPW
, MokPWSize
, MokDB
, MokDBSize
,
2394 MokXNew
, MokXNewSize
, MokXDel
, MokXDelSize
);
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
);
2425 static EFI_STATUS
setup_rand (void)
2428 EFI_STATUS efi_status
;
2432 efi_status
= uefi_call_wrapper(RT
->GetTime
, 2, &time
, NULL
);
2434 if (efi_status
!= EFI_SUCCESS
)
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
);
2442 status
= RandomSeed((UINT8
*)&seed
, sizeof(seed
));
2450 EFI_STATUS
efi_main (EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
*systab
)
2452 EFI_STATUS efi_status
;
2454 InitializeLib(image_handle
, systab
);
2460 efi_status
= check_mok_request(image_handle
);