1 // SPDX-License-Identifier: BSD-2-Clause-Patent
6 #include <Library/BaseCryptLib.h>
7 #include <openssl/x509.h>
8 #include <openssl/x509v3.h>
9 #include <openssl/asn1.h>
10 #include <openssl/bn.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 CERT_STRING L"Select an X509 certificate to enroll:\n\n"
27 #define HASH_STRING L"Select a file to trust:\n\n"
29 #define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID))
35 } __attribute__ ((packed
)) MokListNode
;
40 CHAR16 Password
[SB_PASSWORD_LEN
];
41 } __attribute__ ((packed
)) MokSBvar
;
46 CHAR16 Password
[SB_PASSWORD_LEN
];
47 } __attribute__ ((packed
)) MokDBvar
;
51 } __attribute__ ((packed
)) MokTimeoutvar
;
53 static EFI_STATUS
get_sha1sum(void *Data
, int DataSize
, UINT8
* hash
)
55 EFI_STATUS efi_status
;
59 ctxsize
= Sha1GetContextSize();
60 ctx
= AllocatePool(ctxsize
);
63 console_notify(L
"Unable to allocate memory for hash context");
64 return EFI_OUT_OF_RESOURCES
;
68 console_notify(L
"Unable to initialise hash");
69 efi_status
= EFI_OUT_OF_RESOURCES
;
73 if (!(Sha1Update(ctx
, Data
, DataSize
))) {
74 console_notify(L
"Unable to generate hash");
75 efi_status
= EFI_OUT_OF_RESOURCES
;
79 if (!(Sha1Final(ctx
, hash
))) {
80 console_notify(L
"Unable to finalise hash");
81 efi_status
= EFI_OUT_OF_RESOURCES
;
85 efi_status
= EFI_SUCCESS
;
90 static BOOLEAN
is_sha2_hash(EFI_GUID Type
)
92 if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0)
94 else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0)
96 else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0)
98 else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0)
104 static UINT32
sha_size(EFI_GUID Type
)
106 if (CompareGuid(&Type
, &EFI_CERT_SHA1_GUID
) == 0)
107 return SHA1_DIGEST_SIZE
;
108 else if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0)
109 return SHA224_DIGEST_LENGTH
;
110 else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0)
111 return SHA256_DIGEST_SIZE
;
112 else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0)
113 return SHA384_DIGEST_LENGTH
;
114 else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0)
115 return SHA512_DIGEST_LENGTH
;
120 static BOOLEAN
is_valid_siglist(EFI_GUID Type
, UINT32 SigSize
)
122 UINT32 hash_sig_size
;
124 if (CompareGuid (&Type
, &X509_GUID
) == 0 && SigSize
!= 0)
127 if (!is_sha2_hash(Type
))
130 hash_sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
131 if (SigSize
!= hash_sig_size
)
137 static UINT32
count_keys(void *Data
, UINTN DataSize
)
139 EFI_SIGNATURE_LIST
*CertList
= Data
;
140 UINTN dbsize
= DataSize
;
142 void *end
= Data
+ DataSize
;
144 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
145 /* Use ptr arithmetics to ensure bounded access. Do not allow 0
146 * SignatureListSize that will cause endless loop. */
147 if ((void *)(CertList
+ 1) > end
148 || CertList
->SignatureListSize
== 0) {
150 (L
"Invalid MOK detected! Ignoring MOK List.");
154 if (CertList
->SignatureListSize
== 0 ||
155 CertList
->SignatureListSize
<= CertList
->SignatureSize
) {
156 console_errorbox(L
"Corrupted signature list");
160 if (!is_valid_siglist
161 (CertList
->SignatureType
, CertList
->SignatureSize
)) {
162 console_errorbox(L
"Invalid signature list found");
167 dbsize
-= CertList
->SignatureListSize
;
168 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
169 CertList
->SignatureListSize
);
175 static MokListNode
*build_mok_list(UINT32 num
, void *Data
, UINTN DataSize
)
178 EFI_SIGNATURE_LIST
*CertList
= Data
;
179 EFI_SIGNATURE_DATA
*Cert
;
180 UINTN dbsize
= DataSize
;
182 void *end
= Data
+ DataSize
;
184 list
= AllocatePool(sizeof(MokListNode
) * num
);
186 console_notify(L
"Unable to allocate MOK list");
190 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
191 /* CertList out of bounds? */
192 if ((void *)(CertList
+ 1) > end
193 || CertList
->SignatureListSize
== 0) {
198 /* Omit the signature check here since we already did it
201 Cert
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) CertList
) +
202 sizeof(EFI_SIGNATURE_LIST
) +
203 CertList
->SignatureHeaderSize
);
204 /* Cert out of bounds? */
205 if ((void *)(Cert
+ 1) > end
206 || CertList
->SignatureSize
<= sizeof(EFI_GUID
)) {
211 list
[count
].Type
= CertList
->SignatureType
;
212 if (CompareGuid (&CertList
->SignatureType
, &X509_GUID
) == 0) {
213 list
[count
].MokSize
= CertList
->SignatureSize
-
215 list
[count
].Mok
= (void *)Cert
->SignatureData
;
217 list
[count
].MokSize
= CertList
->SignatureListSize
-
218 sizeof(EFI_SIGNATURE_LIST
);
219 list
[count
].Mok
= (void *)Cert
;
222 /* MOK out of bounds? */
223 if (list
[count
].MokSize
> (unsigned long)end
-
224 (unsigned long)list
[count
].Mok
) {
230 dbsize
-= CertList
->SignatureListSize
;
231 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
232 CertList
->SignatureListSize
);
243 static NidName nidname
[] = {
244 {NID_commonName
, L
"CN"},
245 {NID_organizationName
, L
"O"},
246 {NID_countryName
, L
"C"},
247 {NID_stateOrProvinceName
, L
"ST"},
248 {NID_localityName
, L
"L"},
252 static CHAR16
*get_x509_name(X509_NAME
* X509Name
)
254 CHAR16 name
[NAME_LINE_MAX
+ 1];
255 CHAR16 part
[NAME_LINE_MAX
+ 1];
256 char str
[NAME_LINE_MAX
];
257 int i
, len
, rest
, first
;
260 rest
= NAME_LINE_MAX
;
262 for (i
= 0; nidname
[i
].name
!= NULL
; i
++) {
264 len
= X509_NAME_get_text_by_NID(X509Name
, nidname
[i
].nid
,
270 add
= len
+ (int)StrLen(nidname
[i
].name
) + 1;
272 add
= len
+ (int)StrLen(nidname
[i
].name
) + 3;
278 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
"%s=%a",
279 nidname
[i
].name
, str
);
281 SPrint(part
, NAME_LINE_MAX
* sizeof(CHAR16
), L
", %s=%a",
282 nidname
[i
].name
, str
);
289 if (rest
>= 0 && rest
< NAME_LINE_MAX
)
290 return PoolPrint(L
"%s", name
);
295 static CHAR16
*get_x509_time(ASN1_TIME
* time
)
297 BIO
*bio
= BIO_new(BIO_s_mem());
301 ASN1_TIME_print(bio
, time
);
302 len
= BIO_read(bio
, str
, 29);
308 return PoolPrint(L
"%a", str
);
311 static void show_x509_info(X509
* X509Cert
, UINT8
* hash
)
313 ASN1_INTEGER
*serial
;
315 unsigned char hexbuf
[30];
318 CHAR16
*issuer
= NULL
;
319 CHAR16
*subject
= NULL
;
321 CHAR16
*until
= NULL
;
322 EXTENDED_KEY_USAGE
*extusage
;
323 POOL_PRINT hash_string1
;
324 POOL_PRINT hash_string2
;
325 POOL_PRINT serial_string
;
330 ZeroMem(&hash_string1
, sizeof(hash_string1
));
331 ZeroMem(&hash_string2
, sizeof(hash_string2
));
332 ZeroMem(&serial_string
, sizeof(serial_string
));
334 serial
= X509_get_serialNumber(X509Cert
);
337 bnser
= ASN1_INTEGER_to_BN(serial
, NULL
);
338 n
= BN_bn2bin(bnser
, hexbuf
);
339 for (i
= 0; i
< n
; i
++) {
340 CatPrint(&serial_string
, L
"%02x:", hexbuf
[i
]);
344 if (serial_string
.str
)
347 X509Name
= X509_get_issuer_name(X509Cert
);
349 issuer
= get_x509_name(X509Name
);
354 X509Name
= X509_get_subject_name(X509Cert
);
356 subject
= get_x509_name(X509Name
);
361 time
= X509_get_notBefore(X509Cert
);
363 from
= get_x509_time(time
);
368 time
= X509_get_notAfter(X509Cert
);
370 until
= get_x509_time(time
);
375 for (i
= 0; i
< 10; i
++)
376 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
377 for (i
= 10; i
< 20; i
++)
378 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
380 if (hash_string1
.str
)
383 if (hash_string2
.str
)
391 extusage
= X509_get_ext_d2i(X509Cert
, NID_ext_key_usage
, NULL
, NULL
);
392 text
= AllocateZeroPool(sizeof(CHAR16
*) *
394 sk_ASN1_OBJECT_num(extusage
) + 3));
398 text
[i
++] = StrDuplicate(L
"[Extended Key Usage]");
400 for (j
= 0; j
< sk_ASN1_OBJECT_num(extusage
); j
++) {
401 POOL_PRINT extkeyusage
;
402 ASN1_OBJECT
*obj
= sk_ASN1_OBJECT_value(extusage
, j
);
406 ZeroMem(&extkeyusage
, sizeof(extkeyusage
));
408 OBJ_obj2txt(buf
, buflen
, obj
, 0);
409 CatPrint(&extkeyusage
, L
"OID: %a", buf
);
410 text
[i
++] = StrDuplicate(extkeyusage
.str
);
411 FreePool(extkeyusage
.str
);
413 text
[i
++] = StrDuplicate(L
"");
414 EXTENDED_KEY_USAGE_free(extusage
);
417 if (serial_string
.str
) {
418 text
[i
++] = StrDuplicate(L
"[Serial Number]");
419 text
[i
++] = serial_string
.str
;
420 text
[i
++] = StrDuplicate(L
"");
423 text
[i
++] = StrDuplicate(L
"[Issuer]");
425 text
[i
++] = StrDuplicate(L
"");
428 text
[i
++] = StrDuplicate(L
"[Subject]");
430 text
[i
++] = StrDuplicate(L
"");
433 text
[i
++] = StrDuplicate(L
"[Valid Not Before]");
435 text
[i
++] = StrDuplicate(L
"");
438 text
[i
++] = StrDuplicate(L
"[Valid Not After]");
440 text
[i
++] = StrDuplicate(L
"");
442 if (hash_string1
.str
) {
443 text
[i
++] = StrDuplicate(L
"[Fingerprint]");
444 text
[i
++] = hash_string1
.str
;
446 if (hash_string2
.str
) {
447 text
[i
++] = hash_string2
.str
;
448 text
[i
++] = StrDuplicate(L
"");
452 console_print_box(text
, -1);
454 for (i
= 0; text
[i
] != NULL
; i
++)
460 static void show_sha_digest(EFI_GUID Type
, UINT8
* hash
)
463 POOL_PRINT hash_string1
;
464 POOL_PRINT hash_string2
;
468 if (CompareGuid(&Type
, &EFI_CERT_SHA1_GUID
) == 0) {
469 length
= SHA1_DIGEST_SIZE
;
470 text
[0] = L
"SHA1 hash";
471 } else if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0) {
472 length
= SHA224_DIGEST_LENGTH
;
473 text
[0] = L
"SHA224 hash";
474 } else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0) {
475 length
= SHA256_DIGEST_SIZE
;
476 text
[0] = L
"SHA256 hash";
477 } else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0) {
478 length
= SHA384_DIGEST_LENGTH
;
479 text
[0] = L
"SHA384 hash";
480 } else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0) {
481 length
= SHA512_DIGEST_LENGTH
;
482 text
[0] = L
"SHA512 hash";
487 ZeroMem(&hash_string1
, sizeof(hash_string1
));
488 ZeroMem(&hash_string2
, sizeof(hash_string2
));
492 for (i
= 0; i
< length
/ 2; i
++)
493 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
494 for (i
= length
/ 2; i
< length
; i
++)
495 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
497 text
[2] = hash_string1
.str
;
498 text
[3] = hash_string2
.str
;
501 console_print_box(text
, -1);
503 if (hash_string1
.str
)
504 FreePool(hash_string1
.str
);
506 if (hash_string2
.str
)
507 FreePool(hash_string2
.str
);
510 static void show_efi_hash(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
515 CHAR16
**menu_strings
;
516 CHAR16
*selection
[] = { L
"[Hash List]", NULL
};
520 sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
521 if ((MokSize
% sig_size
) != 0) {
522 console_errorbox(L
"Corrupted Hash List");
525 hash_num
= MokSize
/ sig_size
;
528 hash
= (UINT8
*) Mok
+ sizeof(EFI_GUID
);
529 show_sha_digest(Type
, hash
);
533 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (hash_num
+ 2));
535 console_errorbox(L
"Out of Resources");
539 for (i
= 0; i
< hash_num
; i
++) {
540 menu_strings
[i
] = PoolPrint(L
"View hash %d", i
);
542 menu_strings
[i
] = StrDuplicate(L
"Back");
543 menu_strings
[i
+ 1] = NULL
;
545 while (key_num
< hash_num
) {
548 key_num
= rc
= console_select(selection
, menu_strings
, key_num
);
549 if (rc
< 0 || key_num
>= hash_num
)
552 hash
= (UINT8
*) Mok
+ sig_size
* key_num
+ sizeof(EFI_GUID
);
553 show_sha_digest(Type
, hash
);
556 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
557 FreePool(menu_strings
[i
]);
559 FreePool(menu_strings
);
562 static void show_mok_info(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
564 EFI_STATUS efi_status
;
566 if (!Mok
|| MokSize
== 0)
569 if (CompareGuid (&Type
, &X509_GUID
) == 0) {
570 UINT8 hash
[SHA1_DIGEST_SIZE
];
573 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
574 if (EFI_ERROR(efi_status
)) {
575 console_notify(L
"Failed to compute MOK fingerprint");
579 if (X509ConstructCertificate(Mok
, MokSize
,
580 (UINT8
**) & X509Cert
)
581 && X509Cert
!= NULL
) {
582 show_x509_info(X509Cert
, hash
);
585 console_notify(L
"Not a valid X509 certificate");
588 } else if (is_sha2_hash(Type
)) {
589 show_efi_hash(Type
, Mok
, MokSize
);
593 static EFI_STATUS
list_keys(void *KeyList
, UINTN KeyListSize
, CHAR16
* title
)
596 MokListNode
*keys
= NULL
;
598 CHAR16
**menu_strings
;
599 CHAR16
*selection
[] = { title
, NULL
};
602 if (KeyListSize
< (sizeof(EFI_SIGNATURE_LIST
) +
603 sizeof(EFI_SIGNATURE_DATA
))) {
604 console_notify(L
"No MOK keys found");
605 return EFI_NOT_FOUND
;
608 MokNum
= count_keys(KeyList
, KeyListSize
);
610 console_errorbox(L
"Invalid key list");
613 keys
= build_mok_list(MokNum
, KeyList
, KeyListSize
);
615 console_errorbox(L
"Failed to construct key list");
619 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (MokNum
+ 2));
621 return EFI_OUT_OF_RESOURCES
;
623 for (i
= 0; i
< MokNum
; i
++) {
624 menu_strings
[i
] = PoolPrint(L
"View key %d", i
);
626 menu_strings
[i
] = StrDuplicate(L
"Continue");
628 menu_strings
[i
+ 1] = NULL
;
630 while (key_num
< MokNum
) {
632 rc
= key_num
= console_select(selection
, menu_strings
, key_num
);
634 if (rc
< 0 || key_num
>= MokNum
)
637 show_mok_info(keys
[key_num
].Type
, keys
[key_num
].Mok
,
638 keys
[key_num
].MokSize
);
641 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
642 FreePool(menu_strings
[i
]);
643 FreePool(menu_strings
);
649 static EFI_STATUS
get_line(UINT32
* length
, CHAR16
* line
, UINT32 line_max
,
653 EFI_STATUS efi_status
;
654 unsigned int count
= 0;
657 efi_status
= console_get_keystroke(&key
);
658 if (EFI_ERROR(efi_status
)) {
659 console_error(L
"Failed to read the keystroke",
665 if ((count
>= line_max
&&
666 key
.UnicodeChar
!= CHAR_BACKSPACE
) ||
667 key
.UnicodeChar
== CHAR_NULL
||
668 key
.UnicodeChar
== CHAR_TAB
||
669 key
.UnicodeChar
== CHAR_LINEFEED
||
670 key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
674 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
676 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
678 console_print(L
"\b");
680 line
[--count
] = '\0';
685 console_print(L
"%c", key
.UnicodeChar
);
688 line
[count
++] = key
.UnicodeChar
;
689 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
690 console_print(L
"\n");
697 static EFI_STATUS
compute_pw_hash(void *Data
, UINTN DataSize
, UINT8
* password
,
698 UINT32 pw_length
, UINT8
* hash
)
700 EFI_STATUS efi_status
;
701 unsigned int ctxsize
;
704 ctxsize
= Sha256GetContextSize();
705 ctx
= AllocatePool(ctxsize
);
707 console_notify(L
"Unable to allocate memory for hash context");
708 return EFI_OUT_OF_RESOURCES
;
711 if (!Sha256Init(ctx
)) {
712 console_notify(L
"Unable to initialise hash");
713 efi_status
= EFI_OUT_OF_RESOURCES
;
717 if (Data
&& DataSize
) {
718 if (!(Sha256Update(ctx
, Data
, DataSize
))) {
719 console_notify(L
"Unable to generate hash");
720 efi_status
= EFI_OUT_OF_RESOURCES
;
725 if (!(Sha256Update(ctx
, password
, pw_length
))) {
726 console_notify(L
"Unable to generate hash");
727 efi_status
= EFI_OUT_OF_RESOURCES
;
731 if (!(Sha256Final(ctx
, hash
))) {
732 console_notify(L
"Unable to finalise hash");
733 efi_status
= EFI_OUT_OF_RESOURCES
;
737 efi_status
= EFI_SUCCESS
;
742 static INTN
reset_system()
744 gRT
->ResetSystem(EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
745 console_notify(L
"Failed to reboot\n");
749 static UINT32
get_password(CHAR16
* prompt
, CHAR16
* password
, UINT32 max
)
751 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
758 prompt
= L
"Password:";
760 console_save_and_set_mode(&SavedMode
);
762 str
= PoolPrint(L
"%s ", prompt
);
764 console_errorbox(L
"Failed to allocate prompt");
770 length
= StrLen(message
[0]);
771 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
772 get_line(&pw_length
, password
, max
, 0);
774 console_restore_mode(&SavedMode
);
781 static EFI_STATUS
match_password(PASSWORD_CRYPT
* pw_crypt
,
782 void *Data
, UINTN DataSize
,
783 UINT8
* auth
, CHAR16
* prompt
)
785 EFI_STATUS efi_status
;
789 CHAR16 password
[PASSWORD_MAX
];
791 UINT8 fail_count
= 0;
795 auth_hash
= pw_crypt
->hash
;
796 auth_size
= get_hash_size(pw_crypt
->method
);
798 return EFI_INVALID_PARAMETER
;
801 auth_size
= SHA256_DIGEST_SIZE
;
803 return EFI_INVALID_PARAMETER
;
806 while (fail_count
< 3) {
807 pw_length
= get_password(prompt
, password
, PASSWORD_MAX
);
809 if (pw_length
< PASSWORD_MIN
|| pw_length
> PASSWORD_MAX
) {
810 console_errorbox(L
"Invalid password length");
816 * Compute password hash
819 char pw_ascii
[PASSWORD_MAX
+ 1];
820 for (i
= 0; i
< pw_length
; i
++)
821 pw_ascii
[i
] = (char)password
[i
];
822 pw_ascii
[pw_length
] = '\0';
824 efi_status
= password_crypt(pw_ascii
, pw_length
,
828 * For backward compatibility
830 efi_status
= compute_pw_hash(Data
, DataSize
,
832 pw_length
* sizeof(CHAR16
),
835 if (EFI_ERROR(efi_status
)) {
836 console_errorbox(L
"Unable to generate password hash");
841 if (CompareMem(auth_hash
, hash
, auth_size
) != 0) {
842 console_errorbox(L
"Password doesn't match");
851 return EFI_ACCESS_DENIED
;
856 static EFI_STATUS
write_db(CHAR16
* db_name
, void *MokNew
, UINTN MokNewSize
)
858 EFI_STATUS efi_status
;
860 void *old_data
= NULL
;
861 void *new_data
= NULL
;
865 /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares.
866 * ref: https://github.com/rhboot/shim/issues/55
867 * https://github.com/rhboot/shim/issues/105 */
869 efi_status
= get_variable_attr(db_name
, (UINT8
**)&old_data
, &old_size
,
870 SHIM_LOCK_GUID
, &attributes
);
871 if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
875 /* Check if the old db is compromised or not */
876 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
882 new_size
= old_size
+ MokNewSize
;
883 new_data
= AllocatePool(new_size
);
884 if (new_data
== NULL
) {
885 efi_status
= EFI_OUT_OF_RESOURCES
;
889 CopyMem(new_data
, old_data
, old_size
);
890 CopyMem(new_data
+ old_size
, MokNew
, MokNewSize
);
892 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
893 EFI_VARIABLE_NON_VOLATILE
|
894 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
901 if (new_data
!= NULL
) {
908 static EFI_STATUS
store_keys(void *MokNew
, UINTN MokNewSize
, int authenticate
,
911 EFI_STATUS efi_status
;
914 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
915 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
919 db_name
= L
"MokListX";
920 auth_name
= L
"MokXAuth";
922 db_name
= L
"MokList";
923 auth_name
= L
"MokAuth";
927 efi_status
= gRT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
,
928 &attributes
, &auth_size
, auth
);
929 if (EFI_ERROR(efi_status
) ||
930 (auth_size
!= SHA256_DIGEST_SIZE
&&
931 auth_size
!= PASSWORD_CRYPT_SIZE
)) {
933 console_error(L
"Failed to get MokXAuth",
936 console_error(L
"Failed to get MokAuth",
941 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
942 efi_status
= match_password((PASSWORD_CRYPT
*) auth
,
943 NULL
, 0, NULL
, NULL
);
945 efi_status
= match_password(NULL
, MokNew
, MokNewSize
,
948 if (EFI_ERROR(efi_status
))
949 return EFI_ACCESS_DENIED
;
954 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
955 EFI_VARIABLE_NON_VOLATILE
|
956 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
960 efi_status
= write_db(db_name
, MokNew
, MokNewSize
);
963 if (EFI_ERROR(efi_status
)) {
964 console_error(L
"Failed to set variable", efi_status
);
971 static EFI_STATUS
mok_enrollment_prompt(void *MokNew
, UINTN MokNewSize
,
972 int auth
, BOOLEAN MokX
)
974 EFI_STATUS efi_status
;
975 CHAR16
*enroll_p
[] = { L
"Enroll the key(s)?", NULL
};
979 title
= L
"[Enroll MOKX]";
981 title
= L
"[Enroll MOK]";
983 efi_status
= list_keys(MokNew
, MokNewSize
, title
);
984 if (EFI_ERROR(efi_status
))
987 if (console_yes_no(enroll_p
) == 0)
990 efi_status
= store_keys(MokNew
, MokNewSize
, auth
, MokX
);
991 if (EFI_ERROR(efi_status
)) {
992 console_notify(L
"Failed to enroll keys\n");
998 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
999 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1001 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1002 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1009 static EFI_STATUS
mok_reset_prompt(BOOLEAN MokX
)
1011 EFI_STATUS efi_status
;
1012 CHAR16
*prompt
[] = { NULL
, NULL
};
1014 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1017 prompt
[0] = L
"Erase all stored keys in MokListX?";
1019 prompt
[0] = L
"Erase all stored keys in MokList?";
1021 if (console_yes_no(prompt
) == 0)
1024 efi_status
= store_keys(NULL
, 0, TRUE
, MokX
);
1025 if (EFI_ERROR(efi_status
)) {
1026 console_notify(L
"Failed to erase keys\n");
1031 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
1032 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1033 LibDeleteVariable(L
"MokListX", &SHIM_LOCK_GUID
);
1035 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1036 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1037 LibDeleteVariable(L
"MokList", &SHIM_LOCK_GUID
);
1043 static EFI_STATUS
write_back_mok_list(MokListNode
* list
, INTN key_num
,
1046 EFI_STATUS efi_status
;
1047 EFI_SIGNATURE_LIST
*CertList
;
1048 EFI_SIGNATURE_DATA
*CertData
;
1050 void *Data
= NULL
, *ptr
;
1056 db_name
= L
"MokListX";
1058 db_name
= L
"MokList";
1060 dprint(L
"Writing back %s (%d entries)\n", db_name
, key_num
);
1061 for (i
= 0; i
< key_num
; i
++) {
1062 if (list
[i
].Mok
== NULL
)
1065 DataSize
+= sizeof(EFI_SIGNATURE_LIST
);
1066 type
= list
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1067 if (CompareGuid(&type
, &X509_GUID
) == 0)
1068 DataSize
+= sizeof(EFI_GUID
);
1069 DataSize
+= list
[i
].MokSize
;
1071 if (DataSize
== 0) {
1072 dprint(L
"DataSize = 0; deleting variable %s\n", db_name
);
1073 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1074 EFI_VARIABLE_NON_VOLATILE
|
1075 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1077 dprint(L
"efi_status:%llu\n", efi_status
);
1081 Data
= AllocatePool(DataSize
);
1083 return EFI_OUT_OF_RESOURCES
;
1087 for (i
= 0; i
< key_num
; i
++) {
1088 if (list
[i
].Mok
== NULL
)
1091 CertList
= (EFI_SIGNATURE_LIST
*) ptr
;
1092 CertData
= (EFI_SIGNATURE_DATA
*) (((uint8_t *) ptr
) +
1093 sizeof(EFI_SIGNATURE_LIST
));
1095 CertList
->SignatureType
= list
[i
].Type
;
1096 CertList
->SignatureHeaderSize
= 0;
1098 if (CompareGuid(&(CertList
->SignatureType
), &X509_GUID
) == 0) {
1099 CertList
->SignatureListSize
= list
[i
].MokSize
+
1100 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
);
1101 CertList
->SignatureSize
=
1102 list
[i
].MokSize
+ sizeof(EFI_GUID
);
1104 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1105 CopyMem(CertData
->SignatureData
, list
[i
].Mok
,
1108 CertList
->SignatureListSize
= list
[i
].MokSize
+
1109 sizeof(EFI_SIGNATURE_LIST
);
1110 CertList
->SignatureSize
=
1111 sha_size(list
[i
].Type
) + sizeof(EFI_GUID
);
1113 CopyMem(CertData
, list
[i
].Mok
, list
[i
].MokSize
);
1115 ptr
= (uint8_t *) ptr
+ CertList
->SignatureListSize
;
1118 efi_status
= gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1119 EFI_VARIABLE_NON_VOLATILE
|
1120 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1125 if (EFI_ERROR(efi_status
)) {
1126 console_error(L
"Failed to set variable", efi_status
);
1133 static void delete_cert(void *key
, UINT32 key_size
,
1134 MokListNode
* mok
, INTN mok_num
)
1139 for (i
= 0; i
< mok_num
; i
++) {
1140 type
= mok
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1141 if (CompareGuid(&type
, &X509_GUID
) != 0)
1144 if (mok
[i
].MokSize
== key_size
&&
1145 CompareMem(key
, mok
[i
].Mok
, key_size
) == 0) {
1146 /* Remove the key */
1153 static int match_hash(UINT8
* hash
, UINT32 hash_size
, int start
,
1154 void *hash_list
, UINT32 list_num
)
1159 ptr
= hash_list
+ sizeof(EFI_GUID
);
1160 for (i
= start
; i
< list_num
; i
++) {
1161 if (CompareMem(hash
, ptr
, hash_size
) == 0)
1163 ptr
+= hash_size
+ sizeof(EFI_GUID
);
1169 static void mem_move(void *dest
, void *src
, UINTN size
)
1176 for (i
= 0; i
< size
; i
++)
1180 static void delete_hash_in_list(EFI_GUID Type
, UINT8
* hash
, UINT32 hash_size
,
1181 MokListNode
* mok
, INTN mok_num
)
1190 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1192 for (i
= 0; i
< mok_num
; i
++) {
1193 type
= mok
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1194 if ((CompareGuid(&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
;
1253 CHAR16
*err_strs
[] = { NULL
, NULL
, NULL
};
1254 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
1255 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
1257 UINT8
*MokListData
= NULL
;
1258 UINTN MokListDataSize
= 0;
1259 MokListNode
*mok
= NULL
, *del_key
= NULL
;
1260 INTN mok_num
, del_num
;
1264 db_name
= L
"MokListX";
1265 auth_name
= L
"MokXDelAuth";
1267 db_name
= L
"MokList";
1268 auth_name
= L
"MokDelAuth";
1271 efi_status
= gRT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
, &attributes
,
1273 if (EFI_ERROR(efi_status
) ||
1274 (auth_size
!= SHA256_DIGEST_SIZE
1275 && auth_size
!= PASSWORD_CRYPT_SIZE
)) {
1277 console_error(L
"Failed to get MokXDelAuth", efi_status
);
1279 console_error(L
"Failed to get MokDelAuth", efi_status
);
1283 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
1284 dprint(L
"matching password with CRYPT");
1285 efi_status
= match_password((PASSWORD_CRYPT
*) auth
, NULL
, 0,
1287 dprint(L
"match_password(0x%llx, NULL, 0, NULL, NULL) = %lu\n", auth
, efi_status
);
1289 dprint(L
"matching password as sha256sum");
1291 match_password(NULL
, MokDel
, MokDelSize
, auth
, NULL
);
1292 dprint(L
"match_password(NULL, 0x%llx, %llu, 0x%llx, NULL) = %lu\n", MokDel
, MokDelSize
, auth
, efi_status
);
1294 if (EFI_ERROR(efi_status
))
1295 return EFI_ACCESS_DENIED
;
1297 efi_status
= get_variable_attr(db_name
, &MokListData
, &MokListDataSize
,
1298 SHIM_LOCK_GUID
, &attributes
);
1299 if (EFI_ERROR(efi_status
)) {
1301 console_errorbox(L
"Failed to retrieve MokListX");
1303 console_errorbox(L
"Failed to retrieve MokList");
1305 } else if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
1307 err_strs
[0] = L
"MokListX is compromised!";
1308 err_strs
[1] = L
"Erase all keys in MokListX!";
1310 err_strs
[0] = L
"MokList is compromised!";
1311 err_strs
[1] = L
"Erase all keys in MokList!";
1313 console_alertbox(err_strs
);
1314 gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1315 EFI_VARIABLE_NON_VOLATILE
|
1316 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1317 efi_status
= EFI_ACCESS_DENIED
;
1322 if (!MokListData
|| MokListDataSize
== 0)
1325 /* Construct lists */
1326 mok_num
= count_keys(MokListData
, MokListDataSize
);
1329 err_strs
[0] = L
"Failed to construct the key list of MokListX";
1330 err_strs
[1] = L
"Reset MokListX!";
1332 err_strs
[0] = L
"Failed to construct the key list of MokList";
1333 err_strs
[1] = L
"Reset MokList!";
1335 console_alertbox(err_strs
);
1336 gRT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1337 EFI_VARIABLE_NON_VOLATILE
|
1338 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1339 efi_status
= EFI_ABORTED
;
1342 mok
= build_mok_list(mok_num
, MokListData
, MokListDataSize
);
1344 console_errorbox(L
"Failed to construct key list");
1345 efi_status
= EFI_ABORTED
;
1348 del_num
= count_keys(MokDel
, MokDelSize
);
1350 console_errorbox(L
"Invalid key delete list");
1351 efi_status
= EFI_ABORTED
;
1354 del_key
= build_mok_list(del_num
, MokDel
, MokDelSize
);
1356 console_errorbox(L
"Failed to construct key list");
1357 efi_status
= EFI_ABORTED
;
1361 /* Search and destroy */
1362 dprint(L
"deleting certs from %a\n", MokX
? "MokListX" : "MokList");
1363 for (i
= 0; i
< del_num
; i
++) {
1364 type
= del_key
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1365 if (CompareGuid(&type
, &X509_GUID
) == 0) {
1366 dprint(L
"deleting key %d (total %d):\n", i
, mok_num
);
1367 dhexdumpat(del_key
[i
].Mok
, del_key
[i
].MokSize
, 0);
1368 delete_cert(del_key
[i
].Mok
, del_key
[i
].MokSize
,
1370 } else if (is_sha2_hash(del_key
[i
].Type
)) {
1371 dprint(L
"deleting hash %d (total %d):\n", i
, mok_num
);
1372 dhexdumpat(del_key
[i
].Mok
, del_key
[i
].MokSize
, 0);
1373 delete_hash_list(del_key
[i
].Type
, del_key
[i
].Mok
,
1374 del_key
[i
].MokSize
, mok
, mok_num
);
1378 efi_status
= write_back_mok_list(mok
, mok_num
, MokX
);
1382 FreePool(MokListData
);
1391 static EFI_STATUS
mok_deletion_prompt(void *MokDel
, UINTN MokDelSize
,
1394 EFI_STATUS efi_status
;
1395 CHAR16
*delete_p
[] = { L
"Delete the key(s)?", NULL
};
1399 title
= L
"[Delete MOKX]";
1401 title
= L
"[Delete MOK]";
1403 efi_status
= list_keys(MokDel
, MokDelSize
, title
);
1404 if (EFI_ERROR(efi_status
))
1407 if (console_yes_no(delete_p
) == 0)
1410 efi_status
= delete_keys(MokDel
, MokDelSize
, MokX
);
1411 if (EFI_ERROR(efi_status
)) {
1412 console_notify(L
"Failed to delete keys");
1417 LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
1418 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
1420 LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
1421 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
1430 static CHAR16
get_password_charater(CHAR16
* prompt
)
1432 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1433 EFI_STATUS efi_status
;
1435 CHAR16 character
= 0;
1440 prompt
= L
"Password charater: ";
1442 console_save_and_set_mode(&SavedMode
);
1444 message
[0] = prompt
;
1446 length
= StrLen(message
[0]);
1447 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
1448 efi_status
= get_line(&pw_length
, &character
, 1, 0);
1449 if (EFI_ERROR(efi_status
))
1452 console_restore_mode(&SavedMode
);
1457 static EFI_STATUS
mok_sb_prompt(void *MokSB
, UINTN MokSBSize
)
1459 EFI_STATUS efi_status
;
1460 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1461 MokSBvar
*var
= MokSB
;
1463 CHAR16 pass1
, pass2
, pass3
;
1465 UINT8 fail_count
= 0;
1467 UINT8 pos1
, pos2
, pos3
;
1469 CHAR16
*disable_sb
[] = { L
"Disable Secure Boot", NULL
};
1470 CHAR16
*enable_sb
[] = { L
"Enable Secure Boot", NULL
};
1472 if (MokSBSize
!= sizeof(MokSBvar
)) {
1473 console_notify(L
"Invalid MokSB variable contents");
1474 return EFI_INVALID_PARAMETER
;
1477 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1479 message
[0] = L
"Change Secure Boot state";
1482 console_save_and_set_mode(&SavedMode
);
1483 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1484 console_restore_mode(&SavedMode
);
1486 while (fail_count
< 3) {
1487 RandomBytes(&pos1
, sizeof(pos1
));
1488 pos1
= (pos1
% var
->PWLen
);
1491 RandomBytes(&pos2
, sizeof(pos2
));
1492 pos2
= (pos2
% var
->PWLen
);
1493 } while (pos2
== pos1
);
1496 RandomBytes(&pos3
, sizeof(pos3
));
1497 pos3
= (pos3
% var
->PWLen
);
1498 } while (pos3
== pos2
|| pos3
== pos1
);
1500 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1502 console_errorbox(L
"Failed to allocate buffer");
1503 return EFI_OUT_OF_RESOURCES
;
1505 pass1
= get_password_charater(str
);
1508 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1510 console_errorbox(L
"Failed to allocate buffer");
1511 return EFI_OUT_OF_RESOURCES
;
1513 pass2
= get_password_charater(str
);
1516 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1518 console_errorbox(L
"Failed to allocate buffer");
1519 return EFI_OUT_OF_RESOURCES
;
1521 pass3
= get_password_charater(str
);
1524 if (pass1
!= var
->Password
[pos1
] ||
1525 pass2
!= var
->Password
[pos2
] ||
1526 pass3
!= var
->Password
[pos3
]) {
1527 console_print(L
"Invalid character\n");
1534 if (fail_count
>= 3) {
1535 console_notify(L
"Password limit reached");
1536 return EFI_ACCESS_DENIED
;
1539 if (var
->MokSBState
== 0)
1540 ret
= console_yes_no(disable_sb
);
1542 ret
= console_yes_no(enable_sb
);
1545 LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
1549 if (var
->MokSBState
== 0) {
1550 efi_status
= gRT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1551 EFI_VARIABLE_NON_VOLATILE
|
1552 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1554 if (EFI_ERROR(efi_status
)) {
1555 console_notify(L
"Failed to set Secure Boot state");
1559 efi_status
= gRT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1560 EFI_VARIABLE_NON_VOLATILE
|
1561 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1563 if (EFI_ERROR(efi_status
)) {
1564 console_notify(L
"Failed to delete Secure Boot state");
1572 static EFI_STATUS
mok_db_prompt(void *MokDB
, UINTN MokDBSize
)
1574 EFI_STATUS efi_status
;
1575 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1576 MokDBvar
*var
= MokDB
;
1578 CHAR16 pass1
, pass2
, pass3
;
1580 UINT8 fail_count
= 0;
1582 UINT8 pos1
, pos2
, pos3
;
1584 CHAR16
*ignore_db
[] = { L
"Ignore DB certs/hashes", NULL
};
1585 CHAR16
*use_db
[] = { L
"Use DB certs/hashes", NULL
};
1587 if (MokDBSize
!= sizeof(MokDBvar
)) {
1588 console_notify(L
"Invalid MokDB variable contents");
1589 return EFI_INVALID_PARAMETER
;
1592 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1594 message
[0] = L
"Change DB state";
1597 console_save_and_set_mode(&SavedMode
);
1598 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1599 console_restore_mode(&SavedMode
);
1601 while (fail_count
< 3) {
1602 RandomBytes(&pos1
, sizeof(pos1
));
1603 pos1
= (pos1
% var
->PWLen
);
1606 RandomBytes(&pos2
, sizeof(pos2
));
1607 pos2
= (pos2
% var
->PWLen
);
1608 } while (pos2
== pos1
);
1611 RandomBytes(&pos3
, sizeof(pos3
));
1612 pos3
= (pos3
% var
->PWLen
);
1613 } while (pos3
== pos2
|| pos3
== pos1
);
1615 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1617 console_errorbox(L
"Failed to allocate buffer");
1618 return EFI_OUT_OF_RESOURCES
;
1620 pass1
= get_password_charater(str
);
1623 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1625 console_errorbox(L
"Failed to allocate buffer");
1626 return EFI_OUT_OF_RESOURCES
;
1628 pass2
= get_password_charater(str
);
1631 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1633 console_errorbox(L
"Failed to allocate buffer");
1634 return EFI_OUT_OF_RESOURCES
;
1636 pass3
= get_password_charater(str
);
1639 if (pass1
!= var
->Password
[pos1
] ||
1640 pass2
!= var
->Password
[pos2
] ||
1641 pass3
!= var
->Password
[pos3
]) {
1642 console_print(L
"Invalid character\n");
1649 if (fail_count
>= 3) {
1650 console_notify(L
"Password limit reached");
1651 return EFI_ACCESS_DENIED
;
1654 if (var
->MokDBState
== 0)
1655 ret
= console_yes_no(ignore_db
);
1657 ret
= console_yes_no(use_db
);
1660 LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
1664 if (var
->MokDBState
== 0) {
1665 efi_status
= gRT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1666 EFI_VARIABLE_NON_VOLATILE
|
1667 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1669 if (EFI_ERROR(efi_status
)) {
1670 console_notify(L
"Failed to set DB state");
1674 efi_status
= gRT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1675 EFI_VARIABLE_NON_VOLATILE
|
1676 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1678 if (EFI_ERROR(efi_status
)) {
1679 console_notify(L
"Failed to delete DB state");
1687 static EFI_STATUS
mok_pw_prompt(void *MokPW
, UINTN MokPWSize
)
1689 EFI_STATUS efi_status
;
1690 UINT8 hash
[PASSWORD_CRYPT_SIZE
];
1692 CHAR16
*clear_p
[] = { L
"Clear MOK password?", NULL
};
1693 CHAR16
*set_p
[] = { L
"Set MOK password?", NULL
};
1695 if (MokPWSize
!= SHA256_DIGEST_SIZE
&& MokPWSize
!= PASSWORD_CRYPT_SIZE
) {
1696 console_notify(L
"Invalid MokPW variable contents");
1697 return EFI_INVALID_PARAMETER
;
1700 ST
->ConOut
->ClearScreen(ST
->ConOut
);
1702 SetMem(hash
, PASSWORD_CRYPT_SIZE
, 0);
1704 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1705 if (CompareMem(MokPW
, hash
, PASSWORD_CRYPT_SIZE
) == 0)
1708 if (CompareMem(MokPW
, hash
, SHA256_DIGEST_SIZE
) == 0)
1713 if (console_yes_no(clear_p
) == 0)
1716 gRT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1717 EFI_VARIABLE_NON_VOLATILE
|
1718 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1722 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1723 efi_status
= match_password((PASSWORD_CRYPT
*) MokPW
, NULL
, 0,
1724 NULL
, L
"Confirm MOK passphrase: ");
1726 efi_status
= match_password(NULL
, NULL
, 0, MokPW
,
1727 L
"Confirm MOK passphrase: ");
1730 if (EFI_ERROR(efi_status
)) {
1731 console_notify(L
"Password limit reached");
1735 if (console_yes_no(set_p
) == 0)
1738 efi_status
= gRT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1739 EFI_VARIABLE_NON_VOLATILE
|
1740 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1742 if (EFI_ERROR(efi_status
)) {
1743 console_notify(L
"Failed to set MOK password");
1748 LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
1753 static BOOLEAN
verify_certificate(UINT8
* cert
, UINTN size
)
1757 if (!cert
|| size
< 4)
1761 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
1762 * the number of length bytes, and the number of value bytes.
1763 * The size of a x509 certificate is usually between 127 bytes
1764 * and 64KB. For convenience, assume the number of value bytes
1765 * is 2, i.e. the second byte is 0x82.
1767 if (cert
[0] != 0x30 || cert
[1] != 0x82) {
1768 console_notify(L
"Not a DER encoding X509 certificate");
1772 length
= (cert
[2] << 8 | cert
[3]);
1773 if (length
!= (size
- 4)) {
1774 console_notify(L
"Invalid X509 certificate: Inconsistent size");
1778 if (!(X509ConstructCertificate(cert
, size
, (UINT8
**) & X509Cert
)) ||
1780 console_notify(L
"Invalid X509 certificate");
1784 X509_free(X509Cert
);
1788 static EFI_STATUS
enroll_file(void *data
, UINTN datasize
, BOOLEAN hash
)
1790 EFI_STATUS efi_status
= EFI_SUCCESS
;
1791 EFI_SIGNATURE_LIST
*CertList
;
1792 EFI_SIGNATURE_DATA
*CertData
;
1793 UINTN mokbuffersize
;
1794 void *mokbuffer
= NULL
;
1797 UINT8 sha256
[SHA256_DIGEST_SIZE
];
1798 UINT8 sha1
[SHA1_DIGEST_SIZE
];
1799 SHIM_LOCK
*shim_lock
;
1800 PE_COFF_LOADER_IMAGE_CONTEXT context
;
1802 efi_status
= LibLocateProtocol(&SHIM_LOCK_GUID
,
1803 (VOID
**) &shim_lock
);
1804 if (EFI_ERROR(efi_status
))
1807 mokbuffersize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
) +
1810 mokbuffer
= AllocatePool(mokbuffersize
);
1814 efi_status
= shim_lock
->Context(data
, datasize
, &context
);
1815 if (EFI_ERROR(efi_status
))
1818 efi_status
= shim_lock
->Hash(data
, datasize
, &context
, sha256
,
1820 if (EFI_ERROR(efi_status
))
1823 CertList
= mokbuffer
;
1824 CertList
->SignatureType
= EFI_CERT_SHA256_GUID
;
1825 CertList
->SignatureSize
= 16 + SHA256_DIGEST_SIZE
;
1826 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1827 sizeof(EFI_SIGNATURE_LIST
));
1828 CopyMem(CertData
->SignatureData
, sha256
, SHA256_DIGEST_SIZE
);
1830 mokbuffersize
= datasize
+ sizeof(EFI_SIGNATURE_LIST
) +
1832 mokbuffer
= AllocatePool(mokbuffersize
);
1837 CertList
= mokbuffer
;
1838 CertList
->SignatureType
= X509_GUID
;
1839 CertList
->SignatureSize
= 16 + datasize
;
1841 memcpy(mokbuffer
+ sizeof(EFI_SIGNATURE_LIST
) + 16, data
,
1844 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1845 sizeof(EFI_SIGNATURE_LIST
));
1848 CertList
->SignatureListSize
= mokbuffersize
;
1849 CertList
->SignatureHeaderSize
= 0;
1850 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1853 if (!verify_certificate(CertData
->SignatureData
, datasize
))
1857 efi_status
= mok_enrollment_prompt(mokbuffer
, mokbuffersize
,
1861 FreePool(mokbuffer
);
1866 static EFI_STATUS
mok_hash_enroll(void)
1868 EFI_STATUS efi_status
;
1869 CHAR16
*file_name
= NULL
;
1870 EFI_HANDLE im
= NULL
;
1871 EFI_FILE
*file
= NULL
;
1874 CHAR16
*selections
[] = {
1877 L
"The Selected Binary will have its hash Enrolled",
1878 L
"This means it will subsequently Boot with no prompting",
1879 L
"Remember to make sure it is a genuine binary before enrolling its hash",
1883 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
1886 return EFI_INVALID_PARAMETER
;
1888 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1889 if (EFI_ERROR(efi_status
)) {
1890 console_error(L
"Unable to open file", efi_status
);
1894 simple_file_read_all(file
, &filesize
, &data
);
1897 console_error(L
"Unable to read file", efi_status
);
1898 return EFI_BAD_BUFFER_SIZE
;
1901 efi_status
= enroll_file(data
, filesize
, TRUE
);
1902 if (EFI_ERROR(efi_status
))
1904 L
"Hash failed (did you select a valid EFI binary?)",
1912 static CHAR16
*der_suffix
[] = {
1919 static BOOLEAN
check_der_suffix(CHAR16
* file_name
)
1924 if (!file_name
|| StrLen(file_name
) <= 4)
1928 StrnCat(suffix
, file_name
+ StrLen(file_name
) - 4, 4);
1931 for (i
= 0; der_suffix
[i
] != NULL
; i
++) {
1932 if (StrCmp(suffix
, der_suffix
[i
]) == 0) {
1940 static EFI_STATUS
mok_key_enroll(void)
1942 EFI_STATUS efi_status
;
1943 CHAR16
*file_name
= NULL
;
1944 EFI_HANDLE im
= NULL
;
1945 EFI_FILE
*file
= NULL
;
1948 CHAR16
*selections
[] = {
1951 L
"The selected key will be enrolled into the MOK database",
1952 L
"This means any binaries signed with it will be run without prompting",
1953 L
"Remember to make sure it is a genuine key before Enrolling it",
1957 L
"Unsupported Format",
1959 L
"Only DER encoded certificate (*.cer/der/crt) is supported",
1963 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
1966 return EFI_INVALID_PARAMETER
;
1968 if (!check_der_suffix(file_name
)) {
1969 console_alertbox(alert
);
1970 return EFI_UNSUPPORTED
;
1973 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
1974 if (EFI_ERROR(efi_status
)) {
1975 console_error(L
"Unable to open file", efi_status
);
1979 simple_file_read_all(file
, &filesize
, &data
);
1982 console_error(L
"Unable to read file", efi_status
);
1983 return EFI_BAD_BUFFER_SIZE
;
1986 efi_status
= enroll_file(data
, filesize
, FALSE
);
1992 static BOOLEAN
verify_pw(BOOLEAN
* protected)
1994 EFI_STATUS efi_status
;
1995 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1996 UINT8 pwhash
[PASSWORD_CRYPT_SIZE
];
1997 UINTN size
= PASSWORD_CRYPT_SIZE
;
2003 efi_status
= gRT
->GetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
, &attributes
,
2006 * If anything can attack the password it could just set it to a
2007 * known value, so there's no safety advantage in failing to validate
2008 * purely because of a failure to read the variable
2010 if (EFI_ERROR(efi_status
) ||
2011 (size
!= SHA256_DIGEST_SIZE
&& size
!= PASSWORD_CRYPT_SIZE
))
2014 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)
2017 ST
->ConOut
->ClearScreen(ST
->ConOut
);
2019 /* Draw the background */
2020 console_save_and_set_mode(&SavedMode
);
2021 message
[0] = PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2023 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
2024 FreePool(message
[0]);
2025 console_restore_mode(&SavedMode
);
2027 if (size
== PASSWORD_CRYPT_SIZE
) {
2028 efi_status
= match_password((PASSWORD_CRYPT
*) pwhash
, NULL
, 0,
2029 NULL
, L
"Enter MOK password:");
2031 efi_status
= match_password(NULL
, NULL
, 0, pwhash
,
2032 L
"Enter MOK password:");
2034 if (EFI_ERROR(efi_status
)) {
2035 console_notify(L
"Password limit reached");
2044 static int draw_countdown()
2046 CHAR16
*message
= L
"Press any key to perform MOK management";
2048 void *MokTimeout
= NULL
;
2050 UINTN MokTimeoutSize
= 0;
2052 EFI_STATUS efi_status
;
2054 efi_status
= get_variable(L
"MokTimeout", (UINT8
**) &MokTimeout
,
2055 &MokTimeoutSize
, SHIM_LOCK_GUID
);
2056 if (!EFI_ERROR(efi_status
)) {
2058 timeout
= (int)var
->Timeout
;
2059 FreePool(MokTimeout
);
2060 LibDeleteVariable(L
"MokTimeout", &SHIM_LOCK_GUID
);
2066 title
= PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2067 timeout
= console_countdown(title
, message
, timeout
);
2088 static void free_menu(mok_menu_item
* menu_item
, CHAR16
** menu_strings
)
2091 FreePool(menu_strings
);
2094 FreePool(menu_item
);
2097 static EFI_STATUS
enter_mok_menu(EFI_HANDLE image_handle
,
2098 void *MokNew
, UINTN MokNewSize
,
2099 void *MokDel
, UINTN MokDelSize
,
2100 void *MokSB
, UINTN MokSBSize
,
2101 void *MokPW
, UINTN MokPWSize
,
2102 void *MokDB
, UINTN MokDBSize
,
2103 void *MokXNew
, UINTN MokXNewSize
,
2104 void *MokXDel
, UINTN MokXDelSize
)
2106 CHAR16
**menu_strings
= NULL
;
2107 mok_menu_item
*menu_item
= NULL
;
2109 int mok_changed
= 0;
2110 EFI_STATUS efi_status
;
2111 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
2112 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
2115 CHAR16
*mok_mgmt_p
[] = { L
"Perform MOK management", NULL
};
2116 EFI_STATUS ret
= EFI_SUCCESS
;
2118 if (verify_pw(&protected) == FALSE
)
2119 return EFI_ACCESS_DENIED
;
2121 if (protected == FALSE
&& draw_countdown() == 0)
2124 while (choice
>= 0) {
2125 UINTN menucount
= 3, i
= 0;
2127 UINT32 MokDelAuth
= 0;
2128 UINT32 MokXAuth
= 0;
2129 UINT32 MokXDelAuth
= 0;
2131 efi_status
= gRT
->GetVariable(L
"MokAuth", &SHIM_LOCK_GUID
,
2132 &attributes
, &auth_size
, auth
);
2133 if (!EFI_ERROR(efi_status
) &&
2134 (auth_size
== SHA256_DIGEST_SIZE
||
2135 auth_size
== PASSWORD_CRYPT_SIZE
))
2138 efi_status
= gRT
->GetVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
,
2139 &attributes
, &auth_size
, auth
);
2140 if (!EFI_ERROR(efi_status
) &&
2141 (auth_size
== SHA256_DIGEST_SIZE
||
2142 auth_size
== PASSWORD_CRYPT_SIZE
))
2145 efi_status
= gRT
->GetVariable(L
"MokXAuth", &SHIM_LOCK_GUID
,
2146 &attributes
, &auth_size
, auth
);
2147 if (!EFI_ERROR(efi_status
) &&
2148 (auth_size
== SHA256_DIGEST_SIZE
||
2149 auth_size
== PASSWORD_CRYPT_SIZE
))
2152 efi_status
= gRT
->GetVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
,
2153 &attributes
, &auth_size
, auth
);
2154 if (!EFI_ERROR(efi_status
) &&
2155 (auth_size
== SHA256_DIGEST_SIZE
||
2156 auth_size
== PASSWORD_CRYPT_SIZE
))
2159 if (MokNew
|| MokAuth
)
2162 if (MokDel
|| MokDelAuth
)
2165 if (MokXNew
|| MokXAuth
)
2168 if (MokXDel
|| MokXDelAuth
)
2180 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) *
2183 return EFI_OUT_OF_RESOURCES
;
2185 menu_item
= AllocateZeroPool(sizeof(mok_menu_item
) * menucount
);
2187 FreePool(menu_strings
);
2188 return EFI_OUT_OF_RESOURCES
;
2192 menu_strings
[i
] = L
"Reboot";
2194 menu_strings
[i
] = L
"Continue boot";
2195 menu_item
[i
] = MOK_BOOT
;
2199 if (MokNew
|| MokAuth
) {
2201 menu_strings
[i
] = L
"Reset MOK";
2202 menu_item
[i
] = MOK_RESET_MOK
;
2204 menu_strings
[i
] = L
"Enroll MOK";
2205 menu_item
[i
] = MOK_ENROLL_MOK
;
2210 if (MokDel
|| MokDelAuth
) {
2211 menu_strings
[i
] = L
"Delete MOK";
2212 menu_item
[i
] = MOK_DELETE_MOK
;
2216 if (MokXNew
|| MokXAuth
) {
2218 menu_strings
[i
] = L
"Reset MOKX";
2219 menu_item
[i
] = MOK_RESET_MOKX
;
2221 menu_strings
[i
] = L
"Enroll MOKX";
2222 menu_item
[i
] = MOK_ENROLL_MOKX
;
2227 if (MokXDel
|| MokXDelAuth
) {
2228 menu_strings
[i
] = L
"Delete MOKX";
2229 menu_item
[i
] = MOK_DELETE_MOKX
;
2234 menu_strings
[i
] = L
"Change Secure Boot state";
2235 menu_item
[i
] = MOK_CHANGE_SB
;
2240 menu_strings
[i
] = L
"Set MOK password";
2241 menu_item
[i
] = MOK_SET_PW
;
2246 menu_strings
[i
] = L
"Change DB state";
2247 menu_item
[i
] = MOK_CHANGE_DB
;
2251 menu_strings
[i
] = L
"Enroll key from disk";
2252 menu_item
[i
] = MOK_KEY_ENROLL
;
2255 menu_strings
[i
] = L
"Enroll hash from disk";
2256 menu_item
[i
] = MOK_HASH_ENROLL
;
2259 menu_strings
[i
] = NULL
;
2261 choice
= console_select(mok_mgmt_p
, menu_strings
, 0);
2265 switch (menu_item
[choice
]) {
2269 efi_status
= mok_reset_prompt(FALSE
);
2271 case MOK_ENROLL_MOK
:
2273 console_print(L
"MokManager: internal error: %s",
2274 L
"MokNew was !NULL but is now NULL\n");
2278 efi_status
= mok_enrollment_prompt(MokNew
, MokNewSize
,
2280 if (!EFI_ERROR(efi_status
))
2283 case MOK_DELETE_MOK
:
2285 console_print(L
"MokManager: internal error: %s",
2286 L
"MokDel was !NULL but is now NULL\n");
2290 efi_status
= mok_deletion_prompt(MokDel
, MokDelSize
,
2292 if (!EFI_ERROR(efi_status
))
2295 case MOK_RESET_MOKX
:
2296 efi_status
= mok_reset_prompt(TRUE
);
2298 case MOK_ENROLL_MOKX
:
2300 console_print(L
"MokManager: internal error: %s",
2301 L
"MokXNew was !NULL but is now NULL\n");
2305 efi_status
= mok_enrollment_prompt(MokXNew
, MokXNewSize
,
2307 if (!EFI_ERROR(efi_status
))
2310 case MOK_DELETE_MOKX
:
2312 console_print(L
"MokManager: internal error: %s",
2313 L
"MokXDel was !NULL but is now NULL\n");
2317 efi_status
= mok_deletion_prompt(MokXDel
, MokXDelSize
,
2319 if (!EFI_ERROR(efi_status
))
2324 console_print(L
"MokManager: internal error: %s",
2325 L
"MokSB was !NULL but is now NULL\n");
2329 efi_status
= mok_sb_prompt(MokSB
, MokSBSize
);
2330 if (!EFI_ERROR(efi_status
))
2335 console_print(L
"MokManager: internal error: %s",
2336 L
"MokPW was !NULL but is now NULL\n");
2340 efi_status
= mok_pw_prompt(MokPW
, MokPWSize
);
2341 if (!EFI_ERROR(efi_status
))
2346 console_print(L
"MokManager: internal error: %s",
2347 L
"MokDB was !NULL but is now NULL\n");
2351 efi_status
= mok_db_prompt(MokDB
, MokDBSize
);
2352 if (!EFI_ERROR(efi_status
))
2355 case MOK_KEY_ENROLL
:
2356 efi_status
= mok_key_enroll();
2358 case MOK_HASH_ENROLL
:
2359 efi_status
= mok_hash_enroll();
2363 if (!EFI_ERROR(efi_status
))
2366 free_menu(menu_item
, menu_strings
);
2368 menu_strings
= NULL
;
2372 free_menu(menu_item
, menu_strings
);
2375 return reset_system();
2382 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
2384 UINTN MokNewSize
= 0, MokDelSize
= 0, MokSBSize
= 0, MokPWSize
= 0;
2385 UINTN MokDBSize
= 0, MokXNewSize
= 0, MokXDelSize
= 0;
2386 void *MokNew
= NULL
;
2387 void *MokDel
= NULL
;
2391 void *MokXNew
= NULL
;
2392 void *MokXDel
= NULL
;
2393 EFI_STATUS efi_status
;
2395 efi_status
= get_variable(L
"MokNew", (UINT8
**) & MokNew
, &MokNewSize
,
2397 if (!EFI_ERROR(efi_status
)) {
2398 efi_status
= LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
2399 if (EFI_ERROR(efi_status
))
2400 console_notify(L
"Failed to delete MokNew");
2401 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2402 console_error(L
"Could not retrieve MokNew", efi_status
);
2405 efi_status
= get_variable(L
"MokDel", (UINT8
**) & MokDel
, &MokDelSize
,
2407 if (!EFI_ERROR(efi_status
)) {
2408 efi_status
= LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
2409 if (EFI_ERROR(efi_status
))
2410 console_notify(L
"Failed to delete MokDel");
2411 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2412 console_error(L
"Could not retrieve MokDel", efi_status
);
2415 efi_status
= get_variable(L
"MokSB", (UINT8
**) & MokSB
, &MokSBSize
,
2417 if (!EFI_ERROR(efi_status
)) {
2418 efi_status
= LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
2419 if (EFI_ERROR(efi_status
))
2420 console_notify(L
"Failed to delete MokSB");
2421 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2422 console_error(L
"Could not retrieve MokSB", efi_status
);
2425 efi_status
= get_variable(L
"MokPW", (UINT8
**) & MokPW
, &MokPWSize
,
2427 if (!EFI_ERROR(efi_status
)) {
2428 efi_status
= LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
2429 if (EFI_ERROR(efi_status
))
2430 console_notify(L
"Failed to delete MokPW");
2431 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2432 console_error(L
"Could not retrieve MokPW", efi_status
);
2435 efi_status
= get_variable(L
"MokDB", (UINT8
**) & MokDB
, &MokDBSize
,
2437 if (!EFI_ERROR(efi_status
)) {
2438 efi_status
= LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
2439 if (EFI_ERROR(efi_status
))
2440 console_notify(L
"Failed to delete MokDB");
2441 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2442 console_error(L
"Could not retrieve MokDB", efi_status
);
2445 efi_status
= get_variable(L
"MokXNew", (UINT8
**) & MokXNew
,
2446 &MokXNewSize
, SHIM_LOCK_GUID
);
2447 if (!EFI_ERROR(efi_status
)) {
2448 efi_status
= LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
2449 if (EFI_ERROR(efi_status
))
2450 console_notify(L
"Failed to delete MokXNew");
2451 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2452 console_error(L
"Could not retrieve MokXNew", efi_status
);
2455 efi_status
= get_variable(L
"MokXDel", (UINT8
**) & MokXDel
,
2456 &MokXDelSize
, SHIM_LOCK_GUID
);
2457 if (!EFI_ERROR(efi_status
)) {
2458 efi_status
= LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
2459 if (EFI_ERROR(efi_status
))
2460 console_notify(L
"Failed to delete MokXDel");
2461 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2462 console_error(L
"Could not retrieve MokXDel", efi_status
);
2465 enter_mok_menu(image_handle
, MokNew
, MokNewSize
, MokDel
, MokDelSize
,
2466 MokSB
, MokSBSize
, MokPW
, MokPWSize
, MokDB
, MokDBSize
,
2467 MokXNew
, MokXNewSize
, MokXDel
, MokXDelSize
);
2490 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
2491 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
2492 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
2493 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
2498 static EFI_STATUS
setup_rand(void)
2501 EFI_STATUS efi_status
;
2505 efi_status
= gRT
->GetTime(&time
, NULL
);
2506 if (EFI_ERROR(efi_status
))
2509 seed
= ((UINT64
) time
.Year
<< 48) | ((UINT64
) time
.Month
<< 40) |
2510 ((UINT64
) time
.Day
<< 32) | ((UINT64
) time
.Hour
<< 24) |
2511 ((UINT64
) time
.Minute
<< 16) | ((UINT64
) time
.Second
<< 8) |
2512 ((UINT64
) time
.Daylight
);
2514 status
= RandomSeed((UINT8
*) & seed
, sizeof(seed
));
2521 EFI_STATUS
efi_main(EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
* systab
)
2523 EFI_STATUS efi_status
;
2525 InitializeLib(image_handle
, systab
);
2530 console_mode_handle();
2532 efi_status
= check_mok_request(image_handle
);