4 #include <Library/BaseCryptLib.h>
5 #include <openssl/x509.h>
6 #include <openssl/x509v3.h>
7 #include <openssl/asn1.h>
8 #include <openssl/bn.h>
12 #define PASSWORD_MAX 256
13 #define PASSWORD_MIN 1
14 #define SB_PASSWORD_LEN 16
16 #define NAME_LINE_MAX 70
19 #define SHIM_VENDOR L"Shim"
22 #define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
23 #define HASH_STRING L"Select a file to trust:\n\n"
29 } __attribute__ ((packed
)) MokListNode
;
34 CHAR16 Password
[SB_PASSWORD_LEN
];
35 } __attribute__ ((packed
)) MokSBvar
;
40 CHAR16 Password
[SB_PASSWORD_LEN
];
41 } __attribute__ ((packed
)) MokDBvar
;
45 } __attribute__ ((packed
)) MokTimeoutvar
;
47 static EFI_STATUS
get_sha1sum(void *Data
, int DataSize
, UINT8
* hash
)
49 EFI_STATUS efi_status
;
53 ctxsize
= Sha1GetContextSize();
54 ctx
= AllocatePool(ctxsize
);
57 console_notify(L
"Unable to allocate memory for hash context");
58 return EFI_OUT_OF_RESOURCES
;
62 console_notify(L
"Unable to initialise hash");
63 efi_status
= EFI_OUT_OF_RESOURCES
;
67 if (!(Sha1Update(ctx
, Data
, DataSize
))) {
68 console_notify(L
"Unable to generate hash");
69 efi_status
= EFI_OUT_OF_RESOURCES
;
73 if (!(Sha1Final(ctx
, hash
))) {
74 console_notify(L
"Unable to finalise hash");
75 efi_status
= EFI_OUT_OF_RESOURCES
;
79 efi_status
= EFI_SUCCESS
;
84 static BOOLEAN
is_sha2_hash(EFI_GUID Type
)
86 if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0)
88 else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0)
90 else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0)
92 else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0)
98 static UINT32
sha_size(EFI_GUID Type
)
100 if (CompareGuid(&Type
, &EFI_CERT_SHA1_GUID
) == 0)
101 return SHA1_DIGEST_SIZE
;
102 else if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0)
103 return SHA224_DIGEST_LENGTH
;
104 else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0)
105 return SHA256_DIGEST_SIZE
;
106 else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0)
107 return SHA384_DIGEST_LENGTH
;
108 else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0)
109 return SHA512_DIGEST_LENGTH
;
114 static BOOLEAN
is_valid_siglist(EFI_GUID Type
, UINT32 SigSize
)
116 UINT32 hash_sig_size
;
118 if (CompareGuid (&Type
, &X509_GUID
) == 0 && SigSize
!= 0)
121 if (!is_sha2_hash(Type
))
124 hash_sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
125 if (SigSize
!= hash_sig_size
)
131 static UINT32
count_keys(void *Data
, UINTN DataSize
)
133 EFI_SIGNATURE_LIST
*CertList
= Data
;
134 UINTN dbsize
= DataSize
;
136 void *end
= Data
+ DataSize
;
138 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
139 /* Use ptr arithmetics to ensure bounded access. Do not allow 0
140 * SignatureListSize that will cause endless loop. */
141 if ((void *)(CertList
+ 1) > end
142 || CertList
->SignatureListSize
== 0) {
144 (L
"Invalid MOK detected! Ignoring MOK List.");
148 if (CertList
->SignatureListSize
== 0 ||
149 CertList
->SignatureListSize
<= CertList
->SignatureSize
) {
150 console_errorbox(L
"Corrupted signature list");
154 if (!is_valid_siglist
155 (CertList
->SignatureType
, CertList
->SignatureSize
)) {
156 console_errorbox(L
"Invalid signature list found");
161 dbsize
-= CertList
->SignatureListSize
;
162 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
163 CertList
->SignatureListSize
);
169 static MokListNode
*build_mok_list(UINT32 num
, void *Data
, UINTN DataSize
)
172 EFI_SIGNATURE_LIST
*CertList
= Data
;
173 EFI_SIGNATURE_DATA
*Cert
;
174 UINTN dbsize
= DataSize
;
176 void *end
= Data
+ DataSize
;
178 list
= AllocatePool(sizeof(MokListNode
) * num
);
180 console_notify(L
"Unable to allocate MOK list");
184 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
185 /* CertList out of bounds? */
186 if ((void *)(CertList
+ 1) > end
187 || CertList
->SignatureListSize
== 0) {
192 /* Omit the signature check here since we already did it
195 Cert
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) CertList
) +
196 sizeof(EFI_SIGNATURE_LIST
) +
197 CertList
->SignatureHeaderSize
);
198 /* Cert out of bounds? */
199 if ((void *)(Cert
+ 1) > end
200 || CertList
->SignatureSize
<= sizeof(EFI_GUID
)) {
205 list
[count
].Type
= CertList
->SignatureType
;
206 if (CompareGuid (&CertList
->SignatureType
, &X509_GUID
) == 0) {
207 list
[count
].MokSize
= CertList
->SignatureSize
-
209 list
[count
].Mok
= (void *)Cert
->SignatureData
;
211 list
[count
].MokSize
= CertList
->SignatureListSize
-
212 sizeof(EFI_SIGNATURE_LIST
);
213 list
[count
].Mok
= (void *)Cert
;
216 /* MOK out of bounds? */
217 if (list
[count
].MokSize
> (unsigned long)end
-
218 (unsigned long)list
[count
].Mok
) {
224 dbsize
-= CertList
->SignatureListSize
;
225 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
226 CertList
->SignatureListSize
);
237 static NidName nidname
[] = {
238 {NID_commonName
, L
"CN"},
239 {NID_organizationName
, L
"O"},
240 {NID_countryName
, L
"C"},
241 {NID_stateOrProvinceName
, L
"ST"},
242 {NID_localityName
, L
"L"},
246 static CHAR16
*get_x509_name(X509_NAME
* X509Name
)
248 CHAR16 name
[NAME_LINE_MAX
+ 1];
249 CHAR16 part
[NAME_LINE_MAX
+ 1];
250 char str
[NAME_LINE_MAX
];
251 int i
, len
, rest
, first
;
254 rest
= NAME_LINE_MAX
;
256 for (i
= 0; nidname
[i
].name
!= NULL
; i
++) {
258 len
= X509_NAME_get_text_by_NID(X509Name
, nidname
[i
].nid
,
264 add
= len
+ (int)StrLen(nidname
[i
].name
) + 1;
266 add
= len
+ (int)StrLen(nidname
[i
].name
) + 3;
272 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
"%s=%a",
273 nidname
[i
].name
, str
);
275 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
", %s=%a",
276 nidname
[i
].name
, str
);
283 if (rest
>= 0 && rest
< NAME_LINE_MAX
)
284 return PoolPrint(L
"%s", name
);
289 static CHAR16
*get_x509_time(ASN1_TIME
* time
)
291 BIO
*bio
= BIO_new(BIO_s_mem());
295 ASN1_TIME_print(bio
, time
);
296 len
= BIO_read(bio
, str
, 29);
302 return PoolPrint(L
"%a", str
);
305 static void show_x509_info(X509
* X509Cert
, UINT8
* hash
)
307 ASN1_INTEGER
*serial
;
309 unsigned char hexbuf
[30];
312 CHAR16
*issuer
= NULL
;
313 CHAR16
*subject
= NULL
;
315 CHAR16
*until
= NULL
;
316 EXTENDED_KEY_USAGE
*extusage
;
317 POOL_PRINT hash_string1
;
318 POOL_PRINT hash_string2
;
319 POOL_PRINT serial_string
;
324 ZeroMem(&hash_string1
, sizeof(hash_string1
));
325 ZeroMem(&hash_string2
, sizeof(hash_string2
));
326 ZeroMem(&serial_string
, sizeof(serial_string
));
328 serial
= X509_get_serialNumber(X509Cert
);
331 bnser
= ASN1_INTEGER_to_BN(serial
, NULL
);
332 n
= BN_bn2bin(bnser
, hexbuf
);
333 for (i
= 0; i
< n
; i
++) {
334 CatPrint(&serial_string
, L
"%02x:", hexbuf
[i
]);
338 if (serial_string
.str
)
341 X509Name
= X509_get_issuer_name(X509Cert
);
343 issuer
= get_x509_name(X509Name
);
348 X509Name
= X509_get_subject_name(X509Cert
);
350 subject
= get_x509_name(X509Name
);
355 time
= X509_getm_notBefore(X509Cert
);
357 from
= get_x509_time(time
);
362 time
= X509_getm_notAfter(X509Cert
);
364 until
= get_x509_time(time
);
369 for (i
= 0; i
< 10; i
++)
370 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
371 for (i
= 10; i
< 20; i
++)
372 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
374 if (hash_string1
.str
)
377 if (hash_string2
.str
)
385 extusage
= X509_get_ext_d2i(X509Cert
, NID_ext_key_usage
, NULL
, NULL
);
386 text
= AllocateZeroPool(sizeof(CHAR16
*) *
388 sk_ASN1_OBJECT_num(extusage
) + 3));
392 text
[i
++] = StrDuplicate(L
"[Extended Key Usage]");
394 for (j
= 0; j
< sk_ASN1_OBJECT_num(extusage
); j
++) {
395 POOL_PRINT extkeyusage
;
396 ASN1_OBJECT
*obj
= sk_ASN1_OBJECT_value(extusage
, j
);
400 ZeroMem(&extkeyusage
, sizeof(extkeyusage
));
402 OBJ_obj2txt(buf
, buflen
, obj
, 0);
403 CatPrint(&extkeyusage
, L
"OID: %a", buf
);
404 text
[i
++] = StrDuplicate(extkeyusage
.str
);
405 FreePool(extkeyusage
.str
);
407 text
[i
++] = StrDuplicate(L
"");
408 EXTENDED_KEY_USAGE_free(extusage
);
411 if (serial_string
.str
) {
412 text
[i
++] = StrDuplicate(L
"[Serial Number]");
413 text
[i
++] = serial_string
.str
;
414 text
[i
++] = StrDuplicate(L
"");
417 text
[i
++] = StrDuplicate(L
"[Issuer]");
419 text
[i
++] = StrDuplicate(L
"");
422 text
[i
++] = StrDuplicate(L
"[Subject]");
424 text
[i
++] = StrDuplicate(L
"");
427 text
[i
++] = StrDuplicate(L
"[Valid Not Before]");
429 text
[i
++] = StrDuplicate(L
"");
432 text
[i
++] = StrDuplicate(L
"[Valid Not After]");
434 text
[i
++] = StrDuplicate(L
"");
436 if (hash_string1
.str
) {
437 text
[i
++] = StrDuplicate(L
"[Fingerprint]");
438 text
[i
++] = hash_string1
.str
;
440 if (hash_string2
.str
) {
441 text
[i
++] = hash_string2
.str
;
442 text
[i
++] = StrDuplicate(L
"");
446 console_print_box(text
, -1);
448 for (i
= 0; text
[i
] != NULL
; i
++)
454 static void show_sha_digest(EFI_GUID Type
, UINT8
* hash
)
457 POOL_PRINT hash_string1
;
458 POOL_PRINT hash_string2
;
462 if (CompareGuid(&Type
, &EFI_CERT_SHA1_GUID
) == 0) {
463 length
= SHA1_DIGEST_SIZE
;
464 text
[0] = L
"SHA1 hash";
465 } else if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0) {
466 length
= SHA224_DIGEST_LENGTH
;
467 text
[0] = L
"SHA224 hash";
468 } else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0) {
469 length
= SHA256_DIGEST_SIZE
;
470 text
[0] = L
"SHA256 hash";
471 } else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0) {
472 length
= SHA384_DIGEST_LENGTH
;
473 text
[0] = L
"SHA384 hash";
474 } else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0) {
475 length
= SHA512_DIGEST_LENGTH
;
476 text
[0] = L
"SHA512 hash";
481 ZeroMem(&hash_string1
, sizeof(hash_string1
));
482 ZeroMem(&hash_string2
, sizeof(hash_string2
));
486 for (i
= 0; i
< length
/ 2; i
++)
487 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
488 for (i
= length
/ 2; i
< length
; i
++)
489 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
491 text
[2] = hash_string1
.str
;
492 text
[3] = hash_string2
.str
;
495 console_print_box(text
, -1);
497 if (hash_string1
.str
)
498 FreePool(hash_string1
.str
);
500 if (hash_string2
.str
)
501 FreePool(hash_string2
.str
);
504 static void show_efi_hash(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
509 CHAR16
**menu_strings
;
510 CHAR16
*selection
[] = { L
"[Hash List]", NULL
};
514 sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
515 if ((MokSize
% sig_size
) != 0) {
516 console_errorbox(L
"Corrupted Hash List");
519 hash_num
= MokSize
/ sig_size
;
522 hash
= (UINT8
*) Mok
+ sizeof(EFI_GUID
);
523 show_sha_digest(Type
, hash
);
527 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (hash_num
+ 2));
529 console_errorbox(L
"Out of Resources");
533 for (i
= 0; i
< hash_num
; i
++) {
534 menu_strings
[i
] = PoolPrint(L
"View hash %d", i
);
536 menu_strings
[i
] = StrDuplicate(L
"Back");
537 menu_strings
[i
+ 1] = NULL
;
539 while (key_num
< hash_num
) {
542 key_num
= rc
= console_select(selection
, menu_strings
, key_num
);
543 if (rc
< 0 || key_num
>= hash_num
)
546 hash
= (UINT8
*) Mok
+ sig_size
* key_num
+ sizeof(EFI_GUID
);
547 show_sha_digest(Type
, hash
);
550 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
551 FreePool(menu_strings
[i
]);
553 FreePool(menu_strings
);
556 static void show_mok_info(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
558 EFI_STATUS efi_status
;
560 if (!Mok
|| MokSize
== 0)
563 if (CompareGuid (&Type
, &X509_GUID
) == 0) {
564 UINT8 hash
[SHA1_DIGEST_SIZE
];
567 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
568 if (EFI_ERROR(efi_status
)) {
569 console_notify(L
"Failed to compute MOK fingerprint");
573 if (X509ConstructCertificate(Mok
, MokSize
,
574 (UINT8
**) & X509Cert
)
575 && X509Cert
!= NULL
) {
576 show_x509_info(X509Cert
, hash
);
579 console_notify(L
"Not a valid X509 certificate");
582 } else if (is_sha2_hash(Type
)) {
583 show_efi_hash(Type
, Mok
, MokSize
);
587 static EFI_STATUS
list_keys(void *KeyList
, UINTN KeyListSize
, CHAR16
* title
)
590 MokListNode
*keys
= NULL
;
592 CHAR16
**menu_strings
;
593 CHAR16
*selection
[] = { title
, NULL
};
596 if (KeyListSize
< (sizeof(EFI_SIGNATURE_LIST
) +
597 sizeof(EFI_SIGNATURE_DATA
))) {
598 console_notify(L
"No MOK keys found");
599 return EFI_NOT_FOUND
;
602 MokNum
= count_keys(KeyList
, KeyListSize
);
604 console_errorbox(L
"Invalid key list");
607 keys
= build_mok_list(MokNum
, KeyList
, KeyListSize
);
609 console_errorbox(L
"Failed to construct key list");
613 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (MokNum
+ 2));
615 return EFI_OUT_OF_RESOURCES
;
617 for (i
= 0; i
< MokNum
; i
++) {
618 menu_strings
[i
] = PoolPrint(L
"View key %d", i
);
620 menu_strings
[i
] = StrDuplicate(L
"Continue");
622 menu_strings
[i
+ 1] = NULL
;
624 while (key_num
< MokNum
) {
626 rc
= key_num
= console_select(selection
, menu_strings
, key_num
);
628 if (rc
< 0 || key_num
>= MokNum
)
631 show_mok_info(keys
[key_num
].Type
, keys
[key_num
].Mok
,
632 keys
[key_num
].MokSize
);
635 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
636 FreePool(menu_strings
[i
]);
637 FreePool(menu_strings
);
643 static EFI_STATUS
get_line(UINT32
* length
, CHAR16
* line
, UINT32 line_max
,
647 EFI_STATUS efi_status
;
648 unsigned int count
= 0;
651 efi_status
= console_get_keystroke(&key
);
652 if (EFI_ERROR(efi_status
)) {
653 console_error(L
"Failed to read the keystroke",
659 if ((count
>= line_max
&&
660 key
.UnicodeChar
!= CHAR_BACKSPACE
) ||
661 key
.UnicodeChar
== CHAR_NULL
||
662 key
.UnicodeChar
== CHAR_TAB
||
663 key
.UnicodeChar
== CHAR_LINEFEED
||
664 key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
668 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
670 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
672 console_print(L
"\b");
674 line
[--count
] = '\0';
679 console_print(L
"%c", key
.UnicodeChar
);
682 line
[count
++] = key
.UnicodeChar
;
683 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
684 console_print(L
"\n");
691 static EFI_STATUS
compute_pw_hash(void *Data
, UINTN DataSize
, UINT8
* password
,
692 UINT32 pw_length
, UINT8
* hash
)
694 EFI_STATUS efi_status
;
695 unsigned int ctxsize
;
698 ctxsize
= Sha256GetContextSize();
699 ctx
= AllocatePool(ctxsize
);
701 console_notify(L
"Unable to allocate memory for hash context");
702 return EFI_OUT_OF_RESOURCES
;
705 if (!Sha256Init(ctx
)) {
706 console_notify(L
"Unable to initialise hash");
707 efi_status
= EFI_OUT_OF_RESOURCES
;
711 if (Data
&& DataSize
) {
712 if (!(Sha256Update(ctx
, Data
, DataSize
))) {
713 console_notify(L
"Unable to generate hash");
714 efi_status
= EFI_OUT_OF_RESOURCES
;
719 if (!(Sha256Update(ctx
, password
, pw_length
))) {
720 console_notify(L
"Unable to generate hash");
721 efi_status
= EFI_OUT_OF_RESOURCES
;
725 if (!(Sha256Final(ctx
, hash
))) {
726 console_notify(L
"Unable to finalise hash");
727 efi_status
= EFI_OUT_OF_RESOURCES
;
731 efi_status
= EFI_SUCCESS
;
736 static void console_save_and_set_mode(SIMPLE_TEXT_OUTPUT_MODE
* SavedMode
)
738 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
741 console_print(L
"Invalid parameter: SavedMode\n");
745 CopyMem(SavedMode
, co
->Mode
, sizeof(SIMPLE_TEXT_OUTPUT_MODE
));
746 co
->EnableCursor(co
, FALSE
);
747 co
->SetAttribute(co
, EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
);
750 static void console_restore_mode(SIMPLE_TEXT_OUTPUT_MODE
* SavedMode
)
752 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
754 co
->EnableCursor(co
, SavedMode
->CursorVisible
);
755 co
->SetCursorPosition(co
, SavedMode
->CursorColumn
,
756 SavedMode
->CursorRow
);
757 co
->SetAttribute(co
, SavedMode
->Attribute
);
760 static INTN
reset_system()
762 gRT
->ResetSystem(EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
763 console_notify(L
"Failed to reboot\n");
767 static UINT32
get_password(CHAR16
* prompt
, CHAR16
* password
, UINT32 max
)
769 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
776 prompt
= L
"Password:";
778 console_save_and_set_mode(&SavedMode
);
780 str
= PoolPrint(L
"%s ", prompt
);
782 console_errorbox(L
"Failed to allocate prompt");
788 length
= StrLen(message
[0]);
789 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
790 get_line(&pw_length
, password
, max
, 0);
792 console_restore_mode(&SavedMode
);
799 static EFI_STATUS
match_password(PASSWORD_CRYPT
* pw_crypt
,
800 void *Data
, UINTN DataSize
,
801 UINT8
* auth
, CHAR16
* prompt
)
803 EFI_STATUS efi_status
;
807 CHAR16 password
[PASSWORD_MAX
];
809 UINT8 fail_count
= 0;
813 auth_hash
= pw_crypt
->hash
;
814 auth_size
= get_hash_size(pw_crypt
->method
);
816 return EFI_INVALID_PARAMETER
;
819 auth_size
= SHA256_DIGEST_SIZE
;
821 return EFI_INVALID_PARAMETER
;
824 while (fail_count
< 3) {
825 pw_length
= get_password(prompt
, password
, PASSWORD_MAX
);
827 if (pw_length
< PASSWORD_MIN
|| pw_length
> PASSWORD_MAX
) {
828 console_errorbox(L
"Invalid password length");
834 * Compute password hash
837 char pw_ascii
[PASSWORD_MAX
+ 1];
838 for (i
= 0; i
< pw_length
; i
++)
839 pw_ascii
[i
] = (char)password
[i
];
840 pw_ascii
[pw_length
] = '\0';
842 efi_status
= password_crypt(pw_ascii
, pw_length
,
846 * For backward compatibility
848 efi_status
= compute_pw_hash(Data
, DataSize
,
850 pw_length
* sizeof(CHAR16
),
853 if (EFI_ERROR(efi_status
)) {
854 console_errorbox(L
"Unable to generate password hash");
859 if (CompareMem(auth_hash
, hash
, auth_size
) != 0) {
860 console_errorbox(L
"Password doesn't match");
869 return EFI_ACCESS_DENIED
;
874 static EFI_STATUS
write_db(CHAR16
* db_name
, void *MokNew
, UINTN MokNewSize
)
876 EFI_STATUS efi_status
;
878 void *old_data
= NULL
;
879 void *new_data
= NULL
;
883 /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares.
884 * ref: https://github.com/rhboot/shim/issues/55
885 * https://github.com/rhboot/shim/issues/105 */
887 efi_status
= get_variable_attr(db_name
, (UINT8
**)&old_data
, &old_size
,
888 SHIM_LOCK_GUID
, &attributes
);
889 if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
893 /* Check if the old db is compromised or not */
894 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
900 new_size
= old_size
+ MokNewSize
;
901 new_data
= AllocatePool(new_size
);
902 if (new_data
== NULL
) {
903 efi_status
= EFI_OUT_OF_RESOURCES
;
907 CopyMem(new_data
, old_data
, old_size
);
908 CopyMem(new_data
+ old_size
, MokNew
, MokNewSize
);
910 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
911 EFI_VARIABLE_NON_VOLATILE
|
912 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
919 if (new_data
!= NULL
) {
926 static EFI_STATUS
store_keys(void *MokNew
, UINTN MokNewSize
, int authenticate
,
929 EFI_STATUS efi_status
;
932 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
933 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
937 db_name
= L
"MokListX";
938 auth_name
= L
"MokXAuth";
940 db_name
= L
"MokList";
941 auth_name
= L
"MokAuth";
945 efi_status
= gRT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
,
946 &attributes
, &auth_size
, auth
);
947 if (EFI_ERROR(efi_status
) ||
948 (auth_size
!= SHA256_DIGEST_SIZE
&&
949 auth_size
!= PASSWORD_CRYPT_SIZE
)) {
951 console_error(L
"Failed to get MokXAuth",
954 console_error(L
"Failed to get MokAuth",
959 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
960 efi_status
= match_password((PASSWORD_CRYPT
*) auth
,
961 NULL
, 0, NULL
, NULL
);
963 efi_status
= match_password(NULL
, MokNew
, MokNewSize
,
966 if (EFI_ERROR(efi_status
))
967 return EFI_ACCESS_DENIED
;
972 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
973 EFI_VARIABLE_NON_VOLATILE
|
974 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
978 efi_status
= write_db(db_name
, MokNew
, MokNewSize
);
981 if (EFI_ERROR(efi_status
)) {
982 console_error(L
"Failed to set variable", efi_status
);
989 static EFI_STATUS
mok_enrollment_prompt(void *MokNew
, UINTN MokNewSize
,
990 int auth
, BOOLEAN MokX
)
992 EFI_STATUS efi_status
;
993 CHAR16
*enroll_p
[] = { L
"Enroll the key(s)?", NULL
};
997 title
= L
"[Enroll MOKX]";
999 title
= L
"[Enroll MOK]";
1001 efi_status
= list_keys(MokNew
, MokNewSize
, title
);
1002 if (EFI_ERROR(efi_status
))
1005 if (console_yes_no(enroll_p
) == 0)
1008 efi_status
= store_keys(MokNew
, MokNewSize
, auth
, MokX
);
1009 if (EFI_ERROR(efi_status
)) {
1010 console_notify(L
"Failed to enroll keys\n");
1016 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
1017 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1019 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1020 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1027 static EFI_STATUS
mok_reset_prompt(BOOLEAN MokX
)
1029 EFI_STATUS efi_status
;
1030 CHAR16
*prompt
[] = { NULL
, NULL
};
1032 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1035 prompt
[0] = L
"Erase all stored keys in MokListX?";
1037 prompt
[0] = L
"Erase all stored keys in MokList?";
1039 if (console_yes_no(prompt
) == 0)
1042 efi_status
= store_keys(NULL
, 0, TRUE
, MokX
);
1043 if (EFI_ERROR(efi_status
)) {
1044 console_notify(L
"Failed to erase keys\n");
1049 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
1050 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1052 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1053 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1059 static EFI_STATUS
write_back_mok_list(MokListNode
* list
, INTN key_num
,
1062 EFI_STATUS efi_status
;
1063 EFI_SIGNATURE_LIST
*CertList
;
1064 EFI_SIGNATURE_DATA
*CertData
;
1065 void *Data
= NULL
, *ptr
;
1071 db_name
= L
"MokListX";
1073 db_name
= L
"MokList";
1075 for (i
= 0; i
< key_num
; i
++) {
1076 if (list
[i
].Mok
== NULL
)
1079 DataSize
+= sizeof(EFI_SIGNATURE_LIST
);
1080 if (CompareGuid(&(list
[i
].Type
), &X509_GUID
) == 0)
1081 DataSize
+= sizeof(EFI_GUID
);
1082 DataSize
+= list
[i
].MokSize
;
1085 Data
= AllocatePool(DataSize
);
1086 if (Data
== NULL
&& DataSize
!= 0)
1087 return EFI_OUT_OF_RESOURCES
;
1091 for (i
= 0; i
< key_num
; i
++) {
1092 if (list
[i
].Mok
== NULL
)
1095 CertList
= (EFI_SIGNATURE_LIST
*) ptr
;
1096 CertData
= (EFI_SIGNATURE_DATA
*) (((uint8_t *) ptr
) +
1097 sizeof(EFI_SIGNATURE_LIST
));
1099 CertList
->SignatureType
= list
[i
].Type
;
1100 CertList
->SignatureHeaderSize
= 0;
1102 if (CompareGuid(&(list
[i
].Type
), &X509_GUID
) == 0) {
1103 CertList
->SignatureListSize
= list
[i
].MokSize
+
1104 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
);
1105 CertList
->SignatureSize
=
1106 list
[i
].MokSize
+ sizeof(EFI_GUID
);
1108 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1109 CopyMem(CertData
->SignatureData
, list
[i
].Mok
,
1112 CertList
->SignatureListSize
= list
[i
].MokSize
+
1113 sizeof(EFI_SIGNATURE_LIST
);
1114 CertList
->SignatureSize
=
1115 sha_size(list
[i
].Type
) + sizeof(EFI_GUID
);
1117 CopyMem(CertData
, list
[i
].Mok
, list
[i
].MokSize
);
1119 ptr
= (uint8_t *) ptr
+ CertList
->SignatureListSize
;
1122 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1123 EFI_VARIABLE_NON_VOLATILE
|
1124 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1129 if (EFI_ERROR(efi_status
)) {
1130 console_error(L
"Failed to set variable", efi_status
);
1137 static void delete_cert(void *key
, UINT32 key_size
,
1138 MokListNode
* mok
, INTN mok_num
)
1142 for (i
= 0; i
< mok_num
; i
++) {
1143 if (CompareGuid(&(mok
[i
].Type
), &X509_GUID
) != 0)
1146 if (mok
[i
].MokSize
== key_size
&&
1147 CompareMem(key
, mok
[i
].Mok
, key_size
) == 0) {
1148 /* Remove the key */
1155 static int match_hash(UINT8
* hash
, UINT32 hash_size
, int start
,
1156 void *hash_list
, UINT32 list_num
)
1161 ptr
= hash_list
+ sizeof(EFI_GUID
);
1162 for (i
= start
; i
< list_num
; i
++) {
1163 if (CompareMem(hash
, ptr
, hash_size
) == 0)
1165 ptr
+= hash_size
+ sizeof(EFI_GUID
);
1171 static void mem_move(void *dest
, void *src
, UINTN size
)
1178 for (i
= 0; i
< size
; i
++)
1182 static void delete_hash_in_list(EFI_GUID Type
, UINT8
* hash
, UINT32 hash_size
,
1183 MokListNode
* mok
, INTN mok_num
)
1191 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1193 for (i
= 0; i
< mok_num
; i
++) {
1194 if ((CompareGuid(&(mok
[i
].Type
), &Type
) != 0) ||
1195 (mok
[i
].MokSize
< sig_size
))
1198 list_num
= mok
[i
].MokSize
/ sig_size
;
1200 del_ind
= match_hash(hash
, hash_size
, 0, mok
[i
].Mok
, list_num
);
1201 while (del_ind
>= 0) {
1202 /* Remove the hash */
1203 if (sig_size
== mok
[i
].MokSize
) {
1209 start
= mok
[i
].Mok
+ del_ind
* sig_size
;
1210 end
= start
+ sig_size
;
1211 remain
= mok
[i
].MokSize
- (del_ind
+ 1) * sig_size
;
1213 mem_move(start
, end
, remain
);
1214 mok
[i
].MokSize
-= sig_size
;
1217 del_ind
= match_hash(hash
, hash_size
, del_ind
,
1218 mok
[i
].Mok
, list_num
);
1223 static void delete_hash_list(EFI_GUID Type
, void *hash_list
, UINT32 list_size
,
1224 MokListNode
* mok
, INTN mok_num
)
1232 hash_size
= sha_size(Type
);
1233 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1234 if (list_size
< sig_size
)
1237 hash_num
= list_size
/ sig_size
;
1239 hash
= hash_list
+ sizeof(EFI_GUID
);
1241 for (i
= 0; i
< hash_num
; i
++) {
1242 delete_hash_in_list(Type
, hash
, hash_size
, mok
, mok_num
);
1247 static EFI_STATUS
delete_keys(void *MokDel
, UINTN MokDelSize
, BOOLEAN MokX
)
1249 EFI_STATUS efi_status
;
1252 CHAR16
*err_strs
[] = { NULL
, NULL
, NULL
};
1253 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
1254 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
1256 UINT8
*MokListData
= NULL
;
1257 UINTN MokListDataSize
= 0;
1258 MokListNode
*mok
= NULL
, *del_key
= NULL
;
1259 INTN mok_num
, del_num
;
1263 db_name
= L
"MokListX";
1264 auth_name
= L
"MokXDelAuth";
1266 db_name
= L
"MokList";
1267 auth_name
= L
"MokDelAuth";
1270 efi_status
= gRT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
, &attributes
,
1272 if (EFI_ERROR(efi_status
) ||
1273 (auth_size
!= SHA256_DIGEST_SIZE
1274 && auth_size
!= PASSWORD_CRYPT_SIZE
)) {
1276 console_error(L
"Failed to get MokXDelAuth", efi_status
);
1278 console_error(L
"Failed to get MokDelAuth", efi_status
);
1282 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
1283 efi_status
= match_password((PASSWORD_CRYPT
*) auth
, NULL
, 0,
1287 match_password(NULL
, MokDel
, MokDelSize
, auth
, NULL
);
1289 if (EFI_ERROR(efi_status
))
1290 return EFI_ACCESS_DENIED
;
1292 efi_status
= get_variable_attr(db_name
, &MokListData
, &MokListDataSize
,
1293 SHIM_LOCK_GUID
, &attributes
);
1294 if (EFI_ERROR(efi_status
)) {
1296 console_errorbox(L
"Failed to retrieve MokListX");
1298 console_errorbox(L
"Failed to retrieve MokList");
1300 } else if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
1302 err_strs
[0] = L
"MokListX is compromised!";
1303 err_strs
[1] = L
"Erase all keys in MokListX!";
1305 err_strs
[0] = L
"MokList is compromised!";
1306 err_strs
[1] = L
"Erase all keys in MokList!";
1308 console_alertbox(err_strs
);
1309 gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1310 EFI_VARIABLE_NON_VOLATILE
|
1311 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1312 efi_status
= EFI_ACCESS_DENIED
;
1317 if (!MokListData
|| MokListDataSize
== 0)
1320 /* Construct lists */
1321 mok_num
= count_keys(MokListData
, MokListDataSize
);
1324 err_strs
[0] = L
"Failed to construct the key list of MokListX";
1325 err_strs
[1] = L
"Reset MokListX!";
1327 err_strs
[0] = L
"Failed to construct the key list of MokList";
1328 err_strs
[1] = L
"Reset MokList!";
1330 console_alertbox(err_strs
);
1331 gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1332 EFI_VARIABLE_NON_VOLATILE
|
1333 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1334 efi_status
= EFI_ABORTED
;
1337 mok
= build_mok_list(mok_num
, MokListData
, MokListDataSize
);
1339 console_errorbox(L
"Failed to construct key list");
1340 efi_status
= EFI_ABORTED
;
1343 del_num
= count_keys(MokDel
, MokDelSize
);
1345 console_errorbox(L
"Invalid key delete list");
1346 efi_status
= EFI_ABORTED
;
1349 del_key
= build_mok_list(del_num
, MokDel
, MokDelSize
);
1351 console_errorbox(L
"Failed to construct key list");
1352 efi_status
= EFI_ABORTED
;
1356 /* Search and destroy */
1357 for (i
= 0; i
< del_num
; i
++) {
1358 if (CompareGuid(&(del_key
[i
].Type
), &X509_GUID
) == 0) {
1359 delete_cert(del_key
[i
].Mok
, del_key
[i
].MokSize
,
1361 } else if (is_sha2_hash(del_key
[i
].Type
)) {
1362 delete_hash_list(del_key
[i
].Type
, del_key
[i
].Mok
,
1363 del_key
[i
].MokSize
, mok
, mok_num
);
1367 efi_status
= write_back_mok_list(mok
, mok_num
, MokX
);
1371 FreePool(MokListData
);
1380 static EFI_STATUS
mok_deletion_prompt(void *MokDel
, UINTN MokDelSize
,
1383 EFI_STATUS efi_status
;
1384 CHAR16
*delete_p
[] = { L
"Delete the key(s)?", NULL
};
1388 title
= L
"[Delete MOKX]";
1390 title
= L
"[Delete MOK]";
1392 efi_status
= list_keys(MokDel
, MokDelSize
, title
);
1393 if (EFI_ERROR(efi_status
))
1396 if (console_yes_no(delete_p
) == 0)
1399 efi_status
= delete_keys(MokDel
, MokDelSize
, MokX
);
1400 if (EFI_ERROR(efi_status
)) {
1401 console_notify(L
"Failed to delete keys");
1406 LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
1407 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
1409 LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
1410 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
1419 static CHAR16
get_password_charater(CHAR16
* prompt
)
1421 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1422 EFI_STATUS efi_status
;
1429 prompt
= L
"Password charater: ";
1431 console_save_and_set_mode(&SavedMode
);
1433 message
[0] = prompt
;
1435 length
= StrLen(message
[0]);
1436 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
1437 efi_status
= get_line(&pw_length
, &character
, 1, 0);
1438 if (EFI_ERROR(efi_status
))
1441 console_restore_mode(&SavedMode
);
1446 static EFI_STATUS
mok_sb_prompt(void *MokSB
, UINTN MokSBSize
)
1448 EFI_STATUS efi_status
;
1449 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1450 MokSBvar
*var
= MokSB
;
1452 CHAR16 pass1
, pass2
, pass3
;
1454 UINT8 fail_count
= 0;
1456 UINT8 pos1
, pos2
, pos3
;
1458 CHAR16
*disable_sb
[] = { L
"Disable Secure Boot", NULL
};
1459 CHAR16
*enable_sb
[] = { L
"Enable Secure Boot", NULL
};
1461 if (MokSBSize
!= sizeof(MokSBvar
)) {
1462 console_notify(L
"Invalid MokSB variable contents");
1463 return EFI_INVALID_PARAMETER
;
1466 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1468 message
[0] = L
"Change Secure Boot state";
1471 console_save_and_set_mode(&SavedMode
);
1472 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1473 console_restore_mode(&SavedMode
);
1475 while (fail_count
< 3) {
1476 RandomBytes(&pos1
, sizeof(pos1
));
1477 pos1
= (pos1
% var
->PWLen
);
1480 RandomBytes(&pos2
, sizeof(pos2
));
1481 pos2
= (pos2
% var
->PWLen
);
1482 } while (pos2
== pos1
);
1485 RandomBytes(&pos3
, sizeof(pos3
));
1486 pos3
= (pos3
% var
->PWLen
);
1487 } while (pos3
== pos2
|| pos3
== pos1
);
1489 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1491 console_errorbox(L
"Failed to allocate buffer");
1492 return EFI_OUT_OF_RESOURCES
;
1494 pass1
= get_password_charater(str
);
1497 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1499 console_errorbox(L
"Failed to allocate buffer");
1500 return EFI_OUT_OF_RESOURCES
;
1502 pass2
= get_password_charater(str
);
1505 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1507 console_errorbox(L
"Failed to allocate buffer");
1508 return EFI_OUT_OF_RESOURCES
;
1510 pass3
= get_password_charater(str
);
1513 if (pass1
!= var
->Password
[pos1
] ||
1514 pass2
!= var
->Password
[pos2
] ||
1515 pass3
!= var
->Password
[pos3
]) {
1516 console_print(L
"Invalid character\n");
1523 if (fail_count
>= 3) {
1524 console_notify(L
"Password limit reached");
1525 return EFI_ACCESS_DENIED
;
1528 if (var
->MokSBState
== 0)
1529 ret
= console_yes_no(disable_sb
);
1531 ret
= console_yes_no(enable_sb
);
1534 LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
1538 if (var
->MokSBState
== 0) {
1539 efi_status
= gRT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1540 EFI_VARIABLE_NON_VOLATILE
|
1541 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1543 if (EFI_ERROR(efi_status
)) {
1544 console_notify(L
"Failed to set Secure Boot state");
1548 efi_status
= gRT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1549 EFI_VARIABLE_NON_VOLATILE
|
1550 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1552 if (EFI_ERROR(efi_status
)) {
1553 console_notify(L
"Failed to delete Secure Boot state");
1561 static EFI_STATUS
mok_db_prompt(void *MokDB
, UINTN MokDBSize
)
1563 EFI_STATUS efi_status
;
1564 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1565 MokDBvar
*var
= MokDB
;
1567 CHAR16 pass1
, pass2
, pass3
;
1569 UINT8 fail_count
= 0;
1571 UINT8 pos1
, pos2
, pos3
;
1573 CHAR16
*ignore_db
[] = { L
"Ignore DB certs/hashes", NULL
};
1574 CHAR16
*use_db
[] = { L
"Use DB certs/hashes", NULL
};
1576 if (MokDBSize
!= sizeof(MokDBvar
)) {
1577 console_notify(L
"Invalid MokDB variable contents");
1578 return EFI_INVALID_PARAMETER
;
1581 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1583 message
[0] = L
"Change DB state";
1586 console_save_and_set_mode(&SavedMode
);
1587 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1588 console_restore_mode(&SavedMode
);
1590 while (fail_count
< 3) {
1591 RandomBytes(&pos1
, sizeof(pos1
));
1592 pos1
= (pos1
% var
->PWLen
);
1595 RandomBytes(&pos2
, sizeof(pos2
));
1596 pos2
= (pos2
% var
->PWLen
);
1597 } while (pos2
== pos1
);
1600 RandomBytes(&pos3
, sizeof(pos3
));
1601 pos3
= (pos3
% var
->PWLen
);
1602 } while (pos3
== pos2
|| pos3
== pos1
);
1604 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1606 console_errorbox(L
"Failed to allocate buffer");
1607 return EFI_OUT_OF_RESOURCES
;
1609 pass1
= get_password_charater(str
);
1612 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1614 console_errorbox(L
"Failed to allocate buffer");
1615 return EFI_OUT_OF_RESOURCES
;
1617 pass2
= get_password_charater(str
);
1620 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1622 console_errorbox(L
"Failed to allocate buffer");
1623 return EFI_OUT_OF_RESOURCES
;
1625 pass3
= get_password_charater(str
);
1628 if (pass1
!= var
->Password
[pos1
] ||
1629 pass2
!= var
->Password
[pos2
] ||
1630 pass3
!= var
->Password
[pos3
]) {
1631 console_print(L
"Invalid character\n");
1638 if (fail_count
>= 3) {
1639 console_notify(L
"Password limit reached");
1640 return EFI_ACCESS_DENIED
;
1643 if (var
->MokDBState
== 0)
1644 ret
= console_yes_no(ignore_db
);
1646 ret
= console_yes_no(use_db
);
1649 LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
1653 if (var
->MokDBState
== 0) {
1654 efi_status
= gRT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1655 EFI_VARIABLE_NON_VOLATILE
|
1656 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1658 if (EFI_ERROR(efi_status
)) {
1659 console_notify(L
"Failed to set DB state");
1663 efi_status
= gRT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1664 EFI_VARIABLE_NON_VOLATILE
|
1665 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1667 if (EFI_ERROR(efi_status
)) {
1668 console_notify(L
"Failed to delete DB state");
1676 static EFI_STATUS
mok_pw_prompt(void *MokPW
, UINTN MokPWSize
)
1678 EFI_STATUS efi_status
;
1679 UINT8 hash
[PASSWORD_CRYPT_SIZE
];
1681 CHAR16
*clear_p
[] = { L
"Clear MOK password?", NULL
};
1682 CHAR16
*set_p
[] = { L
"Set MOK password?", NULL
};
1684 if (MokPWSize
!= SHA256_DIGEST_SIZE
&& MokPWSize
!= PASSWORD_CRYPT_SIZE
) {
1685 console_notify(L
"Invalid MokPW variable contents");
1686 return EFI_INVALID_PARAMETER
;
1689 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1691 SetMem(hash
, PASSWORD_CRYPT_SIZE
, 0);
1693 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1694 if (CompareMem(MokPW
, hash
, PASSWORD_CRYPT_SIZE
) == 0)
1697 if (CompareMem(MokPW
, hash
, SHA256_DIGEST_SIZE
) == 0)
1702 if (console_yes_no(clear_p
) == 0)
1705 gRT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1706 EFI_VARIABLE_NON_VOLATILE
|
1707 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1711 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1712 efi_status
= match_password((PASSWORD_CRYPT
*) MokPW
, NULL
, 0,
1713 NULL
, L
"Confirm MOK passphrase: ");
1715 efi_status
= match_password(NULL
, NULL
, 0, MokPW
,
1716 L
"Confirm MOK passphrase: ");
1719 if (EFI_ERROR(efi_status
)) {
1720 console_notify(L
"Password limit reached");
1724 if (console_yes_no(set_p
) == 0)
1727 efi_status
= gRT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1728 EFI_VARIABLE_NON_VOLATILE
|
1729 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1731 if (EFI_ERROR(efi_status
)) {
1732 console_notify(L
"Failed to set MOK password");
1737 LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
1742 static BOOLEAN
verify_certificate(UINT8
* cert
, UINTN size
)
1746 if (!cert
|| size
< 4)
1750 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
1751 * the number of length bytes, and the number of value bytes.
1752 * The size of a x509 certificate is usually between 127 bytes
1753 * and 64KB. For convenience, assume the number of value bytes
1754 * is 2, i.e. the second byte is 0x82.
1756 if (cert
[0] != 0x30 || cert
[1] != 0x82) {
1757 console_notify(L
"Not a DER encoding X509 certificate");
1761 length
= (cert
[2] << 8 | cert
[3]);
1762 if (length
!= (size
- 4)) {
1763 console_notify(L
"Invalid X509 certificate: Inconsistent size");
1767 if (!(X509ConstructCertificate(cert
, size
, (UINT8
**) & X509Cert
)) ||
1769 console_notify(L
"Invalid X509 certificate");
1773 X509_free(X509Cert
);
1777 static EFI_STATUS
enroll_file(void *data
, UINTN datasize
, BOOLEAN hash
)
1779 EFI_STATUS efi_status
= EFI_SUCCESS
;
1780 EFI_SIGNATURE_LIST
*CertList
;
1781 EFI_SIGNATURE_DATA
*CertData
;
1782 UINTN mokbuffersize
;
1783 void *mokbuffer
= NULL
;
1786 UINT8 sha256
[SHA256_DIGEST_SIZE
];
1787 UINT8 sha1
[SHA1_DIGEST_SIZE
];
1788 SHIM_LOCK
*shim_lock
;
1789 PE_COFF_LOADER_IMAGE_CONTEXT context
;
1791 efi_status
= LibLocateProtocol(&SHIM_LOCK_GUID
,
1792 (VOID
**) &shim_lock
);
1793 if (EFI_ERROR(efi_status
))
1796 mokbuffersize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
) +
1799 mokbuffer
= AllocatePool(mokbuffersize
);
1803 efi_status
= shim_lock
->Context(data
, datasize
, &context
);
1804 if (EFI_ERROR(efi_status
))
1807 efi_status
= shim_lock
->Hash(data
, datasize
, &context
, sha256
,
1809 if (EFI_ERROR(efi_status
))
1812 CertList
= mokbuffer
;
1813 CertList
->SignatureType
= EFI_CERT_SHA256_GUID
;
1814 CertList
->SignatureSize
= 16 + SHA256_DIGEST_SIZE
;
1815 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1816 sizeof(EFI_SIGNATURE_LIST
));
1817 CopyMem(CertData
->SignatureData
, sha256
, SHA256_DIGEST_SIZE
);
1819 mokbuffersize
= datasize
+ sizeof(EFI_SIGNATURE_LIST
) +
1821 mokbuffer
= AllocatePool(mokbuffersize
);
1826 CertList
= mokbuffer
;
1827 CertList
->SignatureType
= X509_GUID
;
1828 CertList
->SignatureSize
= 16 + datasize
;
1830 memcpy(mokbuffer
+ sizeof(EFI_SIGNATURE_LIST
) + 16, data
,
1833 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1834 sizeof(EFI_SIGNATURE_LIST
));
1837 CertList
->SignatureListSize
= mokbuffersize
;
1838 CertList
->SignatureHeaderSize
= 0;
1839 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1842 if (!verify_certificate(CertData
->SignatureData
, datasize
))
1846 efi_status
= mok_enrollment_prompt(mokbuffer
, mokbuffersize
,
1850 FreePool(mokbuffer
);
1855 static EFI_STATUS
mok_hash_enroll(void)
1857 EFI_STATUS efi_status
;
1858 CHAR16
*file_name
= NULL
;
1859 EFI_HANDLE im
= NULL
;
1860 EFI_FILE
*file
= NULL
;
1863 CHAR16
*selections
[] = {
1866 L
"The Selected Binary will have its hash Enrolled",
1867 L
"This means it will subsequently Boot with no prompting",
1868 L
"Remember to make sure it is a genuine binary before enrolling its hash",
1872 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
1875 return EFI_INVALID_PARAMETER
;
1877 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1878 if (EFI_ERROR(efi_status
)) {
1879 console_error(L
"Unable to open file", efi_status
);
1883 simple_file_read_all(file
, &filesize
, &data
);
1886 console_error(L
"Unable to read file", efi_status
);
1887 return EFI_BAD_BUFFER_SIZE
;
1890 efi_status
= enroll_file(data
, filesize
, TRUE
);
1891 if (EFI_ERROR(efi_status
))
1893 L
"Hash failed (did you select a valid EFI binary?)",
1901 static CHAR16
*der_suffix
[] = {
1908 static BOOLEAN
check_der_suffix(CHAR16
* file_name
)
1913 if (!file_name
|| StrLen(file_name
) <= 4)
1917 StrnCat(suffix
, file_name
+ StrLen(file_name
) - 4, 4);
1920 for (i
= 0; der_suffix
[i
] != NULL
; i
++) {
1921 if (StrCmp(suffix
, der_suffix
[i
]) == 0) {
1929 static EFI_STATUS
mok_key_enroll(void)
1931 EFI_STATUS efi_status
;
1932 CHAR16
*file_name
= NULL
;
1933 EFI_HANDLE im
= NULL
;
1934 EFI_FILE
*file
= NULL
;
1937 CHAR16
*selections
[] = {
1940 L
"The selected key will be enrolled into the MOK database",
1941 L
"This means any binaries signed with it will be run without prompting",
1942 L
"Remember to make sure it is a genuine key before Enrolling it",
1946 L
"Unsupported Format",
1948 L
"Only DER encoded certificate (*.cer/der/crt) is supported",
1952 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
1955 return EFI_INVALID_PARAMETER
;
1957 if (!check_der_suffix(file_name
)) {
1958 console_alertbox(alert
);
1959 return EFI_UNSUPPORTED
;
1962 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1963 if (EFI_ERROR(efi_status
)) {
1964 console_error(L
"Unable to open file", efi_status
);
1968 simple_file_read_all(file
, &filesize
, &data
);
1971 console_error(L
"Unable to read file", efi_status
);
1972 return EFI_BAD_BUFFER_SIZE
;
1975 efi_status
= enroll_file(data
, filesize
, FALSE
);
1981 static BOOLEAN
verify_pw(BOOLEAN
* protected)
1983 EFI_STATUS efi_status
;
1984 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1985 UINT8 pwhash
[PASSWORD_CRYPT_SIZE
];
1986 UINTN size
= PASSWORD_CRYPT_SIZE
;
1992 efi_status
= gRT
->GetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
, &attributes
,
1995 * If anything can attack the password it could just set it to a
1996 * known value, so there's no safety advantage in failing to validate
1997 * purely because of a failure to read the variable
1999 if (EFI_ERROR(efi_status
) ||
2000 (size
!= SHA256_DIGEST_SIZE
&& size
!= PASSWORD_CRYPT_SIZE
))
2003 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)
2006 ST
->ConOut
->ClearScreen(ST
->ConOut
);
2008 /* Draw the background */
2009 console_save_and_set_mode(&SavedMode
);
2010 message
[0] = PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2012 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
2013 FreePool(message
[0]);
2014 console_restore_mode(&SavedMode
);
2016 if (size
== PASSWORD_CRYPT_SIZE
) {
2017 efi_status
= match_password((PASSWORD_CRYPT
*) pwhash
, NULL
, 0,
2018 NULL
, L
"Enter MOK password:");
2020 efi_status
= match_password(NULL
, NULL
, 0, pwhash
,
2021 L
"Enter MOK password:");
2023 if (EFI_ERROR(efi_status
)) {
2024 console_notify(L
"Password limit reached");
2033 static int draw_countdown()
2035 SIMPLE_TEXT_OUTPUT_INTERFACE
*co
= ST
->ConOut
;
2036 SIMPLE_INPUT_INTERFACE
*ci
= ST
->ConIn
;
2037 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
2039 EFI_STATUS efi_status
;
2042 CHAR16
*message
= L
"Press any key to perform MOK management";
2043 void *MokTimeout
= NULL
;
2045 UINTN MokTimeoutSize
= 0;
2046 int timeout
, wait
= 10000000;
2048 efi_status
= get_variable(L
"MokTimeout", (UINT8
**) &MokTimeout
,
2049 &MokTimeoutSize
, SHIM_LOCK_GUID
);
2050 if (EFI_ERROR(efi_status
)) {
2054 timeout
= (int)var
->Timeout
;
2055 FreePool(MokTimeout
);
2056 LibDeleteVariable(L
"MokTimeout", &SHIM_LOCK_GUID
);
2062 console_save_and_set_mode(&SavedMode
);
2064 title
[0] = PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2067 console_print_box_at(title
, -1, 0, 0, -1, -1, 1, 1);
2069 co
->QueryMode(co
, co
->Mode
->Mode
, &cols
, &rows
);
2071 console_print_at((cols
- StrLen(message
)) / 2, rows
/ 2, message
);
2074 console_print_at(2, rows
- 3,
2075 L
"Booting in %d seconds ",
2078 console_print_at(2, rows
- 3,
2079 L
"Booting in %d second ",
2082 efi_status
= WaitForSingleEvent(ci
->WaitForKey
, wait
);
2083 if (efi_status
!= EFI_TIMEOUT
) {
2084 /* Clear the key in the queue */
2085 ci
->ReadKeyStroke(ci
, &key
);
2096 console_restore_mode(&SavedMode
);
2116 static void free_menu(mok_menu_item
* menu_item
, CHAR16
** menu_strings
)
2119 FreePool(menu_strings
);
2122 FreePool(menu_item
);
2125 static EFI_STATUS
enter_mok_menu(EFI_HANDLE image_handle
,
2126 void *MokNew
, UINTN MokNewSize
,
2127 void *MokDel
, UINTN MokDelSize
,
2128 void *MokSB
, UINTN MokSBSize
,
2129 void *MokPW
, UINTN MokPWSize
,
2130 void *MokDB
, UINTN MokDBSize
,
2131 void *MokXNew
, UINTN MokXNewSize
,
2132 void *MokXDel
, UINTN MokXDelSize
)
2134 CHAR16
**menu_strings
= NULL
;
2135 mok_menu_item
*menu_item
= NULL
;
2137 int mok_changed
= 0;
2138 EFI_STATUS efi_status
;
2139 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
2140 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
2143 CHAR16
*mok_mgmt_p
[] = { L
"Perform MOK management", NULL
};
2144 EFI_STATUS ret
= EFI_SUCCESS
;
2146 if (verify_pw(&protected) == FALSE
)
2147 return EFI_ACCESS_DENIED
;
2149 if (protected == FALSE
&& draw_countdown() == 0)
2152 while (choice
>= 0) {
2153 UINTN menucount
= 3, i
= 0;
2155 UINT32 MokDelAuth
= 0;
2156 UINT32 MokXAuth
= 0;
2157 UINT32 MokXDelAuth
= 0;
2159 efi_status
= gRT
->GetVariable(L
"MokAuth", &SHIM_LOCK_GUID
,
2160 &attributes
, &auth_size
, auth
);
2161 if (!EFI_ERROR(efi_status
) &&
2162 (auth_size
== SHA256_DIGEST_SIZE
||
2163 auth_size
== PASSWORD_CRYPT_SIZE
))
2166 efi_status
= gRT
->GetVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
,
2167 &attributes
, &auth_size
, auth
);
2168 if (!EFI_ERROR(efi_status
) &&
2169 (auth_size
== SHA256_DIGEST_SIZE
||
2170 auth_size
== PASSWORD_CRYPT_SIZE
))
2173 efi_status
= gRT
->GetVariable(L
"MokXAuth", &SHIM_LOCK_GUID
,
2174 &attributes
, &auth_size
, auth
);
2175 if (!EFI_ERROR(efi_status
) &&
2176 (auth_size
== SHA256_DIGEST_SIZE
||
2177 auth_size
== PASSWORD_CRYPT_SIZE
))
2180 efi_status
= gRT
->GetVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
,
2181 &attributes
, &auth_size
, auth
);
2182 if (!EFI_ERROR(efi_status
) &&
2183 (auth_size
== SHA256_DIGEST_SIZE
||
2184 auth_size
== PASSWORD_CRYPT_SIZE
))
2187 if (MokNew
|| MokAuth
)
2190 if (MokDel
|| MokDelAuth
)
2193 if (MokXNew
|| MokXAuth
)
2196 if (MokXDel
|| MokXDelAuth
)
2208 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) *
2211 return EFI_OUT_OF_RESOURCES
;
2213 menu_item
= AllocateZeroPool(sizeof(mok_menu_item
) * menucount
);
2215 FreePool(menu_strings
);
2216 return EFI_OUT_OF_RESOURCES
;
2220 menu_strings
[i
] = L
"Reboot";
2222 menu_strings
[i
] = L
"Continue boot";
2223 menu_item
[i
] = MOK_BOOT
;
2227 if (MokNew
|| MokAuth
) {
2229 menu_strings
[i
] = L
"Reset MOK";
2230 menu_item
[i
] = MOK_RESET_MOK
;
2232 menu_strings
[i
] = L
"Enroll MOK";
2233 menu_item
[i
] = MOK_ENROLL_MOK
;
2238 if (MokDel
|| MokDelAuth
) {
2239 menu_strings
[i
] = L
"Delete MOK";
2240 menu_item
[i
] = MOK_DELETE_MOK
;
2244 if (MokXNew
|| MokXAuth
) {
2246 menu_strings
[i
] = L
"Reset MOKX";
2247 menu_item
[i
] = MOK_RESET_MOKX
;
2249 menu_strings
[i
] = L
"Enroll MOKX";
2250 menu_item
[i
] = MOK_ENROLL_MOKX
;
2255 if (MokXDel
|| MokXDelAuth
) {
2256 menu_strings
[i
] = L
"Delete MOKX";
2257 menu_item
[i
] = MOK_DELETE_MOKX
;
2262 menu_strings
[i
] = L
"Change Secure Boot state";
2263 menu_item
[i
] = MOK_CHANGE_SB
;
2268 menu_strings
[i
] = L
"Set MOK password";
2269 menu_item
[i
] = MOK_SET_PW
;
2274 menu_strings
[i
] = L
"Change DB state";
2275 menu_item
[i
] = MOK_CHANGE_DB
;
2279 menu_strings
[i
] = L
"Enroll key from disk";
2280 menu_item
[i
] = MOK_KEY_ENROLL
;
2283 menu_strings
[i
] = L
"Enroll hash from disk";
2284 menu_item
[i
] = MOK_HASH_ENROLL
;
2287 menu_strings
[i
] = NULL
;
2289 choice
= console_select(mok_mgmt_p
, menu_strings
, 0);
2293 switch (menu_item
[choice
]) {
2297 efi_status
= mok_reset_prompt(FALSE
);
2299 case MOK_ENROLL_MOK
:
2301 console_print(L
"MokManager: internal error: %s",
2302 L
"MokNew was !NULL but is now NULL\n");
2306 efi_status
= mok_enrollment_prompt(MokNew
, MokNewSize
,
2308 if (!EFI_ERROR(efi_status
))
2311 case MOK_DELETE_MOK
:
2313 console_print(L
"MokManager: internal error: %s",
2314 L
"MokDel was !NULL but is now NULL\n");
2318 efi_status
= mok_deletion_prompt(MokDel
, MokDelSize
,
2320 if (!EFI_ERROR(efi_status
))
2323 case MOK_RESET_MOKX
:
2324 efi_status
= mok_reset_prompt(TRUE
);
2326 case MOK_ENROLL_MOKX
:
2328 console_print(L
"MokManager: internal error: %s",
2329 L
"MokXNew was !NULL but is now NULL\n");
2333 efi_status
= mok_enrollment_prompt(MokXNew
, MokXNewSize
,
2335 if (!EFI_ERROR(efi_status
))
2338 case MOK_DELETE_MOKX
:
2340 console_print(L
"MokManager: internal error: %s",
2341 L
"MokXDel was !NULL but is now NULL\n");
2345 efi_status
= mok_deletion_prompt(MokXDel
, MokXDelSize
,
2347 if (!EFI_ERROR(efi_status
))
2352 console_print(L
"MokManager: internal error: %s",
2353 L
"MokSB was !NULL but is now NULL\n");
2357 efi_status
= mok_sb_prompt(MokSB
, MokSBSize
);
2358 if (!EFI_ERROR(efi_status
))
2363 console_print(L
"MokManager: internal error: %s",
2364 L
"MokPW was !NULL but is now NULL\n");
2368 efi_status
= mok_pw_prompt(MokPW
, MokPWSize
);
2369 if (!EFI_ERROR(efi_status
))
2374 console_print(L
"MokManager: internal error: %s",
2375 L
"MokDB was !NULL but is now NULL\n");
2379 efi_status
= mok_db_prompt(MokDB
, MokDBSize
);
2380 if (!EFI_ERROR(efi_status
))
2383 case MOK_KEY_ENROLL
:
2384 efi_status
= mok_key_enroll();
2386 case MOK_HASH_ENROLL
:
2387 efi_status
= mok_hash_enroll();
2391 if (!EFI_ERROR(efi_status
))
2394 free_menu(menu_item
, menu_strings
);
2396 menu_strings
= NULL
;
2400 free_menu(menu_item
, menu_strings
);
2403 return reset_system();
2410 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
2412 UINTN MokNewSize
= 0, MokDelSize
= 0, MokSBSize
= 0, MokPWSize
= 0;
2413 UINTN MokDBSize
= 0, MokXNewSize
= 0, MokXDelSize
= 0;
2414 void *MokNew
= NULL
;
2415 void *MokDel
= NULL
;
2419 void *MokXNew
= NULL
;
2420 void *MokXDel
= NULL
;
2421 EFI_STATUS efi_status
;
2423 efi_status
= get_variable(L
"MokNew", (UINT8
**) & MokNew
, &MokNewSize
,
2425 if (!EFI_ERROR(efi_status
)) {
2426 efi_status
= LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
2427 if (EFI_ERROR(efi_status
))
2428 console_notify(L
"Failed to delete MokNew");
2429 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2430 console_error(L
"Could not retrieve MokNew", efi_status
);
2433 efi_status
= get_variable(L
"MokDel", (UINT8
**) & MokDel
, &MokDelSize
,
2435 if (!EFI_ERROR(efi_status
)) {
2436 efi_status
= LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
2437 if (EFI_ERROR(efi_status
))
2438 console_notify(L
"Failed to delete MokDel");
2439 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2440 console_error(L
"Could not retrieve MokDel", efi_status
);
2443 efi_status
= get_variable(L
"MokSB", (UINT8
**) & MokSB
, &MokSBSize
,
2445 if (!EFI_ERROR(efi_status
)) {
2446 efi_status
= LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
2447 if (EFI_ERROR(efi_status
))
2448 console_notify(L
"Failed to delete MokSB");
2449 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2450 console_error(L
"Could not retrieve MokSB", efi_status
);
2453 efi_status
= get_variable(L
"MokPW", (UINT8
**) & MokPW
, &MokPWSize
,
2455 if (!EFI_ERROR(efi_status
)) {
2456 efi_status
= LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
2457 if (EFI_ERROR(efi_status
))
2458 console_notify(L
"Failed to delete MokPW");
2459 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2460 console_error(L
"Could not retrieve MokPW", efi_status
);
2463 efi_status
= get_variable(L
"MokDB", (UINT8
**) & MokDB
, &MokDBSize
,
2465 if (!EFI_ERROR(efi_status
)) {
2466 efi_status
= LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
2467 if (EFI_ERROR(efi_status
))
2468 console_notify(L
"Failed to delete MokDB");
2469 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2470 console_error(L
"Could not retrieve MokDB", efi_status
);
2473 efi_status
= get_variable(L
"MokXNew", (UINT8
**) & MokXNew
,
2474 &MokXNewSize
, SHIM_LOCK_GUID
);
2475 if (!EFI_ERROR(efi_status
)) {
2476 efi_status
= LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
2477 if (EFI_ERROR(efi_status
))
2478 console_notify(L
"Failed to delete MokXNew");
2479 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2480 console_error(L
"Could not retrieve MokXNew", efi_status
);
2483 efi_status
= get_variable(L
"MokXDel", (UINT8
**) & MokXDel
,
2484 &MokXDelSize
, SHIM_LOCK_GUID
);
2485 if (!EFI_ERROR(efi_status
)) {
2486 efi_status
= LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
2487 if (EFI_ERROR(efi_status
))
2488 console_notify(L
"Failed to delete MokXDel");
2489 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2490 console_error(L
"Could not retrieve MokXDel", efi_status
);
2493 enter_mok_menu(image_handle
, MokNew
, MokNewSize
, MokDel
, MokDelSize
,
2494 MokSB
, MokSBSize
, MokPW
, MokPWSize
, MokDB
, MokDBSize
,
2495 MokXNew
, MokXNewSize
, MokXDel
, MokXDelSize
);
2518 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
2519 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
2520 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
2521 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
2526 static EFI_STATUS
setup_rand(void)
2529 EFI_STATUS efi_status
;
2533 efi_status
= gRT
->GetTime(&time
, NULL
);
2534 if (EFI_ERROR(efi_status
))
2537 seed
= ((UINT64
) time
.Year
<< 48) | ((UINT64
) time
.Month
<< 40) |
2538 ((UINT64
) time
.Day
<< 32) | ((UINT64
) time
.Hour
<< 24) |
2539 ((UINT64
) time
.Minute
<< 16) | ((UINT64
) time
.Second
<< 8) |
2540 ((UINT64
) time
.Daylight
);
2542 status
= RandomSeed((UINT8
*) & seed
, sizeof(seed
));
2549 EFI_STATUS
efi_main(EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
* systab
)
2551 EFI_STATUS efi_status
;
2553 InitializeLib(image_handle
, systab
);
2557 efi_status
= check_mok_request(image_handle
);