1 // SPDX-License-Identifier: BSD-2-Clause-Patent
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>
10 #define PASSWORD_MAX 256
11 #define PASSWORD_MIN 1
12 #define SB_PASSWORD_LEN 16
14 #define NAME_LINE_MAX 70
17 #define SHIM_VENDOR L"Shim"
20 #define CERT_STRING L"Select an X509 certificate to enroll:\n\n"
21 #define HASH_STRING L"Select a file to trust:\n\n"
23 #define CompareMemberGuid(x, y) CompareMem(x, y, sizeof(EFI_GUID))
29 } __attribute__ ((packed
)) MokListNode
;
34 CHAR16 Password
[SB_PASSWORD_LEN
];
35 } __attribute__ ((packed
)) MokSBvar
;
40 CHAR16 Password
[SB_PASSWORD_LEN
];
41 } __attribute__ ((packed
)) MokDBvar
;
46 CHAR16 Password
[SB_PASSWORD_LEN
];
47 } __attribute__ ((packed
)) MokTMLvar
;
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
]);
345 if (serial_string
.str
)
348 X509Name
= X509_get_issuer_name(X509Cert
);
350 issuer
= get_x509_name(X509Name
);
355 X509Name
= X509_get_subject_name(X509Cert
);
357 subject
= get_x509_name(X509Name
);
362 time
= X509_get_notBefore(X509Cert
);
364 from
= get_x509_time(time
);
369 time
= X509_get_notAfter(X509Cert
);
371 until
= get_x509_time(time
);
376 for (i
= 0; i
< 10; i
++)
377 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
378 for (i
= 10; i
< 20; i
++)
379 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
381 if (hash_string1
.str
)
384 if (hash_string2
.str
)
392 extusage
= X509_get_ext_d2i(X509Cert
, NID_ext_key_usage
, NULL
, NULL
);
393 text
= AllocateZeroPool(sizeof(CHAR16
*) *
395 sk_ASN1_OBJECT_num(extusage
) + 3));
399 text
[i
++] = StrDuplicate(L
"[Extended Key Usage]");
401 for (j
= 0; j
< sk_ASN1_OBJECT_num(extusage
); j
++) {
402 POOL_PRINT extkeyusage
;
403 ASN1_OBJECT
*obj
= sk_ASN1_OBJECT_value(extusage
, j
);
407 ZeroMem(&extkeyusage
, sizeof(extkeyusage
));
409 OBJ_obj2txt(buf
, buflen
, obj
, 0);
410 CatPrint(&extkeyusage
, L
"OID: %a", buf
);
411 text
[i
++] = StrDuplicate(extkeyusage
.str
);
412 FreePool(extkeyusage
.str
);
414 text
[i
++] = StrDuplicate(L
"");
415 EXTENDED_KEY_USAGE_free(extusage
);
418 if (serial_string
.str
) {
419 text
[i
++] = StrDuplicate(L
"[Serial Number]");
420 text
[i
++] = serial_string
.str
;
421 text
[i
++] = StrDuplicate(L
"");
424 text
[i
++] = StrDuplicate(L
"[Issuer]");
426 text
[i
++] = StrDuplicate(L
"");
429 text
[i
++] = StrDuplicate(L
"[Subject]");
431 text
[i
++] = StrDuplicate(L
"");
434 text
[i
++] = StrDuplicate(L
"[Valid Not Before]");
436 text
[i
++] = StrDuplicate(L
"");
439 text
[i
++] = StrDuplicate(L
"[Valid Not After]");
441 text
[i
++] = StrDuplicate(L
"");
443 if (hash_string1
.str
) {
444 text
[i
++] = StrDuplicate(L
"[Fingerprint]");
445 text
[i
++] = hash_string1
.str
;
447 if (hash_string2
.str
) {
448 text
[i
++] = hash_string2
.str
;
449 text
[i
++] = StrDuplicate(L
"");
453 console_print_box(text
, -1);
455 for (i
= 0; text
[i
] != NULL
; i
++)
461 static void show_sha_digest(EFI_GUID Type
, UINT8
* hash
)
464 POOL_PRINT hash_string1
;
465 POOL_PRINT hash_string2
;
469 if (CompareGuid(&Type
, &EFI_CERT_SHA1_GUID
) == 0) {
470 length
= SHA1_DIGEST_SIZE
;
471 text
[0] = L
"SHA1 hash";
472 } else if (CompareGuid(&Type
, &EFI_CERT_SHA224_GUID
) == 0) {
473 length
= SHA224_DIGEST_LENGTH
;
474 text
[0] = L
"SHA224 hash";
475 } else if (CompareGuid(&Type
, &EFI_CERT_SHA256_GUID
) == 0) {
476 length
= SHA256_DIGEST_SIZE
;
477 text
[0] = L
"SHA256 hash";
478 } else if (CompareGuid(&Type
, &EFI_CERT_SHA384_GUID
) == 0) {
479 length
= SHA384_DIGEST_LENGTH
;
480 text
[0] = L
"SHA384 hash";
481 } else if (CompareGuid(&Type
, &EFI_CERT_SHA512_GUID
) == 0) {
482 length
= SHA512_DIGEST_LENGTH
;
483 text
[0] = L
"SHA512 hash";
488 ZeroMem(&hash_string1
, sizeof(hash_string1
));
489 ZeroMem(&hash_string2
, sizeof(hash_string2
));
493 for (i
= 0; i
< length
/ 2; i
++)
494 CatPrint(&hash_string1
, L
"%02x ", hash
[i
]);
495 for (i
= length
/ 2; i
< length
; i
++)
496 CatPrint(&hash_string2
, L
"%02x ", hash
[i
]);
498 text
[2] = hash_string1
.str
;
499 text
[3] = hash_string2
.str
;
502 console_print_box(text
, -1);
504 if (hash_string1
.str
)
505 FreePool(hash_string1
.str
);
507 if (hash_string2
.str
)
508 FreePool(hash_string2
.str
);
511 static void show_efi_hash(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
516 CHAR16
**menu_strings
;
517 CHAR16
*selection
[] = { L
"[Hash List]", NULL
};
521 sig_size
= sha_size(Type
) + sizeof(EFI_GUID
);
522 if ((MokSize
% sig_size
) != 0) {
523 console_errorbox(L
"Corrupted Hash List");
526 hash_num
= MokSize
/ sig_size
;
529 hash
= (UINT8
*) Mok
+ sizeof(EFI_GUID
);
530 show_sha_digest(Type
, hash
);
534 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (hash_num
+ 2));
536 console_errorbox(L
"Out of Resources");
540 for (i
= 0; i
< hash_num
; i
++) {
541 menu_strings
[i
] = PoolPrint(L
"View hash %d", i
);
543 menu_strings
[i
] = StrDuplicate(L
"Back");
544 menu_strings
[i
+ 1] = NULL
;
546 while (key_num
< hash_num
) {
549 key_num
= rc
= console_select(selection
, menu_strings
, key_num
);
550 if (rc
< 0 || key_num
>= hash_num
)
553 hash
= (UINT8
*) Mok
+ sig_size
* key_num
+ sizeof(EFI_GUID
);
554 show_sha_digest(Type
, hash
);
557 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
558 FreePool(menu_strings
[i
]);
560 FreePool(menu_strings
);
563 static void show_mok_info(EFI_GUID Type
, void *Mok
, UINTN MokSize
)
565 EFI_STATUS efi_status
;
567 if (!Mok
|| MokSize
== 0)
570 if (CompareGuid (&Type
, &X509_GUID
) == 0) {
571 UINT8 hash
[SHA1_DIGEST_SIZE
];
574 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
575 if (EFI_ERROR(efi_status
)) {
576 console_notify(L
"Failed to compute MOK fingerprint");
580 if (X509ConstructCertificate(Mok
, MokSize
,
581 (UINT8
**) & X509Cert
)
582 && X509Cert
!= NULL
) {
583 show_x509_info(X509Cert
, hash
);
586 console_notify(L
"Not a valid X509 certificate");
589 } else if (is_sha2_hash(Type
)) {
590 show_efi_hash(Type
, Mok
, MokSize
);
594 static EFI_STATUS
list_keys(void *KeyList
, UINTN KeyListSize
, CHAR16
* title
)
597 MokListNode
*keys
= NULL
;
599 CHAR16
**menu_strings
;
600 CHAR16
*selection
[] = { title
, NULL
};
603 if (KeyListSize
< (sizeof(EFI_SIGNATURE_LIST
) +
604 sizeof(EFI_SIGNATURE_DATA
))) {
605 console_notify(L
"No MOK keys found");
606 return EFI_NOT_FOUND
;
609 MokNum
= count_keys(KeyList
, KeyListSize
);
611 console_errorbox(L
"Invalid key list");
614 keys
= build_mok_list(MokNum
, KeyList
, KeyListSize
);
616 console_errorbox(L
"Failed to construct key list");
620 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) * (MokNum
+ 2));
622 return EFI_OUT_OF_RESOURCES
;
624 for (i
= 0; i
< MokNum
; i
++) {
625 menu_strings
[i
] = PoolPrint(L
"View key %d", i
);
627 menu_strings
[i
] = StrDuplicate(L
"Continue");
629 menu_strings
[i
+ 1] = NULL
;
631 while (key_num
< MokNum
) {
633 rc
= key_num
= console_select(selection
, menu_strings
, key_num
);
635 if (rc
< 0 || key_num
>= MokNum
)
638 show_mok_info(keys
[key_num
].Type
, keys
[key_num
].Mok
,
639 keys
[key_num
].MokSize
);
642 for (i
= 0; menu_strings
[i
] != NULL
; i
++)
643 FreePool(menu_strings
[i
]);
644 FreePool(menu_strings
);
650 static EFI_STATUS
get_line(UINT32
* length
, CHAR16
* line
, UINT32 line_max
,
654 EFI_STATUS efi_status
;
655 unsigned int count
= 0;
658 efi_status
= console_get_keystroke(&key
);
659 if (EFI_ERROR(efi_status
)) {
660 console_error(L
"Failed to read the keystroke",
666 if ((count
>= line_max
&&
667 key
.UnicodeChar
!= CHAR_BACKSPACE
) ||
668 key
.UnicodeChar
== CHAR_NULL
||
669 key
.UnicodeChar
== CHAR_TAB
||
670 key
.UnicodeChar
== CHAR_LINEFEED
||
671 key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
675 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
677 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
679 console_print(L
"\b");
681 line
[--count
] = '\0';
686 console_print(L
"%c", key
.UnicodeChar
);
689 line
[count
++] = key
.UnicodeChar
;
690 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
691 console_print(L
"\n");
698 static EFI_STATUS
compute_pw_hash(void *Data
, UINTN DataSize
, UINT8
* password
,
699 UINT32 pw_length
, UINT8
* hash
)
701 EFI_STATUS efi_status
;
702 unsigned int ctxsize
;
705 ctxsize
= Sha256GetContextSize();
706 ctx
= AllocatePool(ctxsize
);
708 console_notify(L
"Unable to allocate memory for hash context");
709 return EFI_OUT_OF_RESOURCES
;
712 if (!Sha256Init(ctx
)) {
713 console_notify(L
"Unable to initialise hash");
714 efi_status
= EFI_OUT_OF_RESOURCES
;
718 if (Data
&& DataSize
) {
719 if (!(Sha256Update(ctx
, Data
, DataSize
))) {
720 console_notify(L
"Unable to generate hash");
721 efi_status
= EFI_OUT_OF_RESOURCES
;
726 if (!(Sha256Update(ctx
, password
, pw_length
))) {
727 console_notify(L
"Unable to generate hash");
728 efi_status
= EFI_OUT_OF_RESOURCES
;
732 if (!(Sha256Final(ctx
, hash
))) {
733 console_notify(L
"Unable to finalise hash");
734 efi_status
= EFI_OUT_OF_RESOURCES
;
738 efi_status
= EFI_SUCCESS
;
743 static INTN
reset_system()
745 RT
->ResetSystem(EfiResetWarm
, EFI_SUCCESS
, 0, NULL
);
746 console_notify(L
"Failed to reboot\n");
750 static UINT32
get_password(CHAR16
* prompt
, CHAR16
* password
, UINT32 max
)
752 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
759 prompt
= L
"Password:";
761 console_save_and_set_mode(&SavedMode
);
763 str
= PoolPrint(L
"%s ", prompt
);
765 console_errorbox(L
"Failed to allocate prompt");
771 length
= StrLen(message
[0]);
772 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
773 get_line(&pw_length
, password
, max
, 0);
775 console_restore_mode(&SavedMode
);
782 static EFI_STATUS
match_password(PASSWORD_CRYPT
* pw_crypt
,
783 void *Data
, UINTN DataSize
,
784 UINT8
* auth
, CHAR16
* prompt
)
786 EFI_STATUS efi_status
;
790 CHAR16 password
[PASSWORD_MAX
];
792 UINT8 fail_count
= 0;
796 auth_hash
= pw_crypt
->hash
;
797 auth_size
= get_hash_size(pw_crypt
->method
);
799 return EFI_INVALID_PARAMETER
;
802 auth_size
= SHA256_DIGEST_SIZE
;
804 return EFI_INVALID_PARAMETER
;
807 while (fail_count
< 3) {
808 pw_length
= get_password(prompt
, password
, PASSWORD_MAX
);
810 if (pw_length
< PASSWORD_MIN
|| pw_length
> PASSWORD_MAX
) {
811 console_errorbox(L
"Invalid password length");
817 * Compute password hash
820 char pw_ascii
[PASSWORD_MAX
+ 1];
821 for (i
= 0; i
< pw_length
; i
++)
822 pw_ascii
[i
] = (char)password
[i
];
823 pw_ascii
[pw_length
] = '\0';
825 efi_status
= password_crypt(pw_ascii
, pw_length
,
829 * For backward compatibility
831 efi_status
= compute_pw_hash(Data
, DataSize
,
833 pw_length
* sizeof(CHAR16
),
836 if (EFI_ERROR(efi_status
)) {
837 console_errorbox(L
"Unable to generate password hash");
842 if (CompareMem(auth_hash
, hash
, auth_size
) != 0) {
843 console_errorbox(L
"Password doesn't match");
852 return EFI_ACCESS_DENIED
;
857 static EFI_STATUS
write_db(CHAR16
* db_name
, void *MokNew
, UINTN MokNewSize
)
859 EFI_STATUS efi_status
;
861 void *old_data
= NULL
;
862 void *new_data
= NULL
;
866 /* Do not use EFI_VARIABLE_APPEND_WRITE due to faulty firmwares.
867 * ref: https://github.com/rhboot/shim/issues/55
868 * https://github.com/rhboot/shim/issues/105 */
870 efi_status
= get_variable_attr(db_name
, (UINT8
**)&old_data
, &old_size
,
871 SHIM_LOCK_GUID
, &attributes
);
872 if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
876 /* Check if the old db is compromised or not */
877 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
883 new_size
= old_size
+ MokNewSize
;
884 new_data
= AllocatePool(new_size
);
885 if (new_data
== NULL
) {
886 efi_status
= EFI_OUT_OF_RESOURCES
;
890 CopyMem(new_data
, old_data
, old_size
);
891 CopyMem(new_data
+ old_size
, MokNew
, MokNewSize
);
893 efi_status
= RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
894 EFI_VARIABLE_NON_VOLATILE
|
895 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
902 if (new_data
!= NULL
) {
909 static EFI_STATUS
store_keys(void *MokNew
, UINTN MokNewSize
, int authenticate
,
912 EFI_STATUS efi_status
;
915 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
916 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
920 db_name
= L
"MokListX";
921 auth_name
= L
"MokXAuth";
923 db_name
= L
"MokList";
924 auth_name
= L
"MokAuth";
928 efi_status
= RT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
,
929 &attributes
, &auth_size
, auth
);
930 if (EFI_ERROR(efi_status
) ||
931 (auth_size
!= SHA256_DIGEST_SIZE
&&
932 auth_size
!= PASSWORD_CRYPT_SIZE
)) {
934 console_error(L
"Failed to get MokXAuth",
937 console_error(L
"Failed to get MokAuth",
942 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
943 efi_status
= match_password((PASSWORD_CRYPT
*) auth
,
944 NULL
, 0, NULL
, NULL
);
946 efi_status
= match_password(NULL
, MokNew
, MokNewSize
,
949 if (EFI_ERROR(efi_status
))
950 return EFI_ACCESS_DENIED
;
955 efi_status
= RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
956 EFI_VARIABLE_NON_VOLATILE
|
957 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
961 efi_status
= write_db(db_name
, MokNew
, MokNewSize
);
964 if (EFI_ERROR(efi_status
)) {
965 console_error(L
"Failed to set variable", efi_status
);
972 static EFI_STATUS
mok_enrollment_prompt(void *MokNew
, UINTN MokNewSize
,
973 int auth
, BOOLEAN MokX
)
975 EFI_STATUS efi_status
;
976 CHAR16
*enroll_p
[] = { L
"Enroll the key(s)?", NULL
};
980 title
= L
"[Enroll MOKX]";
982 title
= L
"[Enroll MOK]";
984 efi_status
= list_keys(MokNew
, MokNewSize
, title
);
985 if (EFI_ERROR(efi_status
))
988 if (console_yes_no(enroll_p
) == 0)
991 efi_status
= store_keys(MokNew
, MokNewSize
, auth
, MokX
);
992 if (EFI_ERROR(efi_status
)) {
993 console_notify(L
"Failed to enroll keys\n");
999 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
1000 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1002 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1003 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1010 static EFI_STATUS
mok_reset_prompt(BOOLEAN MokX
)
1012 EFI_STATUS efi_status
;
1013 CHAR16
*prompt
[] = { NULL
, NULL
};
1018 prompt
[0] = L
"Erase all stored keys in MokListX?";
1020 prompt
[0] = L
"Erase all stored keys in MokList?";
1022 if (console_yes_no(prompt
) == 0)
1025 efi_status
= store_keys(NULL
, 0, TRUE
, MokX
);
1026 if (EFI_ERROR(efi_status
)) {
1027 console_notify(L
"Failed to erase keys\n");
1032 LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
1033 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
1034 LibDeleteVariable(L
"MokListX", &SHIM_LOCK_GUID
);
1036 LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
1037 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
1038 LibDeleteVariable(L
"MokList", &SHIM_LOCK_GUID
);
1044 static EFI_STATUS
write_back_mok_list(MokListNode
* list
, INTN key_num
,
1047 EFI_STATUS efi_status
;
1048 EFI_SIGNATURE_LIST
*CertList
;
1049 EFI_SIGNATURE_DATA
*CertData
;
1051 void *Data
= NULL
, *ptr
;
1057 db_name
= L
"MokListX";
1059 db_name
= L
"MokList";
1061 dprint(L
"Writing back %s (%d entries)\n", db_name
, key_num
);
1062 for (i
= 0; i
< key_num
; i
++) {
1063 if (list
[i
].Mok
== NULL
)
1066 DataSize
+= sizeof(EFI_SIGNATURE_LIST
);
1067 type
= list
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1068 if (CompareGuid(&type
, &X509_GUID
) == 0)
1069 DataSize
+= sizeof(EFI_GUID
);
1070 DataSize
+= list
[i
].MokSize
;
1072 if (DataSize
== 0) {
1073 dprint(L
"DataSize = 0; deleting variable %s\n", db_name
);
1074 efi_status
= RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1075 EFI_VARIABLE_NON_VOLATILE
|
1076 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1078 dprint(L
"efi_status:%llu\n", efi_status
);
1082 Data
= AllocatePool(DataSize
);
1084 return EFI_OUT_OF_RESOURCES
;
1088 for (i
= 0; i
< key_num
; i
++) {
1089 if (list
[i
].Mok
== NULL
)
1092 CertList
= (EFI_SIGNATURE_LIST
*) ptr
;
1093 CertData
= (EFI_SIGNATURE_DATA
*) (((uint8_t *) ptr
) +
1094 sizeof(EFI_SIGNATURE_LIST
));
1096 CertList
->SignatureType
= list
[i
].Type
;
1097 CertList
->SignatureHeaderSize
= 0;
1099 if (CompareGuid(&(CertList
->SignatureType
), &X509_GUID
) == 0) {
1100 CertList
->SignatureListSize
= list
[i
].MokSize
+
1101 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
);
1102 CertList
->SignatureSize
=
1103 list
[i
].MokSize
+ sizeof(EFI_GUID
);
1105 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1106 CopyMem(CertData
->SignatureData
, list
[i
].Mok
,
1109 CertList
->SignatureListSize
= list
[i
].MokSize
+
1110 sizeof(EFI_SIGNATURE_LIST
);
1111 CertList
->SignatureSize
=
1112 sha_size(list
[i
].Type
) + sizeof(EFI_GUID
);
1114 CopyMem(CertData
, list
[i
].Mok
, list
[i
].MokSize
);
1116 ptr
= (uint8_t *) ptr
+ CertList
->SignatureListSize
;
1119 efi_status
= RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1120 EFI_VARIABLE_NON_VOLATILE
|
1121 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1126 if (EFI_ERROR(efi_status
)) {
1127 console_error(L
"Failed to set variable", efi_status
);
1134 static void delete_cert(void *key
, UINT32 key_size
,
1135 MokListNode
* mok
, INTN mok_num
)
1140 for (i
= 0; i
< mok_num
; i
++) {
1141 type
= mok
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1142 if (CompareGuid(&type
, &X509_GUID
) != 0)
1145 if (mok
[i
].MokSize
== key_size
&&
1146 CompareMem(key
, mok
[i
].Mok
, key_size
) == 0) {
1147 /* Remove the key */
1154 static int match_hash(UINT8
* hash
, UINT32 hash_size
, int start
,
1155 void *hash_list
, UINT32 list_num
)
1160 ptr
= hash_list
+ sizeof(EFI_GUID
);
1161 for (i
= start
; i
< list_num
; i
++) {
1162 if (CompareMem(hash
, ptr
, hash_size
) == 0)
1164 ptr
+= hash_size
+ sizeof(EFI_GUID
);
1170 static void mem_move(void *dest
, void *src
, UINTN size
)
1177 for (i
= 0; i
< size
; i
++)
1181 static void delete_hash_in_list(EFI_GUID Type
, UINT8
* hash
, UINT32 hash_size
,
1182 MokListNode
* mok
, INTN mok_num
)
1191 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1193 for (i
= 0; i
< mok_num
; i
++) {
1194 type
= mok
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1195 if ((CompareGuid(&type
, &Type
) != 0) ||
1196 (mok
[i
].MokSize
< sig_size
))
1199 list_num
= mok
[i
].MokSize
/ sig_size
;
1201 del_ind
= match_hash(hash
, hash_size
, 0, mok
[i
].Mok
, list_num
);
1202 while (del_ind
>= 0) {
1203 /* Remove the hash */
1204 if (sig_size
== mok
[i
].MokSize
) {
1210 start
= mok
[i
].Mok
+ del_ind
* sig_size
;
1211 end
= start
+ sig_size
;
1212 remain
= mok
[i
].MokSize
- (del_ind
+ 1) * sig_size
;
1214 mem_move(start
, end
, remain
);
1215 mok
[i
].MokSize
-= sig_size
;
1218 del_ind
= match_hash(hash
, hash_size
, del_ind
,
1219 mok
[i
].Mok
, list_num
);
1224 static void delete_hash_list(EFI_GUID Type
, void *hash_list
, UINT32 list_size
,
1225 MokListNode
* mok
, INTN mok_num
)
1233 hash_size
= sha_size(Type
);
1234 sig_size
= hash_size
+ sizeof(EFI_GUID
);
1235 if (list_size
< sig_size
)
1238 hash_num
= list_size
/ sig_size
;
1240 hash
= hash_list
+ sizeof(EFI_GUID
);
1242 for (i
= 0; i
< hash_num
; i
++) {
1243 delete_hash_in_list(Type
, hash
, hash_size
, mok
, mok_num
);
1248 static EFI_STATUS
delete_keys(void *MokDel
, UINTN MokDelSize
, BOOLEAN MokX
)
1250 EFI_STATUS efi_status
;
1254 CHAR16
*err_strs
[] = { NULL
, NULL
, NULL
};
1255 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
1256 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
1258 UINT8
*MokListData
= NULL
;
1259 UINTN MokListDataSize
= 0;
1260 MokListNode
*mok
= NULL
, *del_key
= NULL
;
1261 INTN mok_num
, del_num
;
1265 db_name
= L
"MokListX";
1266 auth_name
= L
"MokXDelAuth";
1268 db_name
= L
"MokList";
1269 auth_name
= L
"MokDelAuth";
1272 efi_status
= RT
->GetVariable(auth_name
, &SHIM_LOCK_GUID
, &attributes
,
1274 if (EFI_ERROR(efi_status
) ||
1275 (auth_size
!= SHA256_DIGEST_SIZE
1276 && auth_size
!= PASSWORD_CRYPT_SIZE
)) {
1278 console_error(L
"Failed to get MokXDelAuth", efi_status
);
1280 console_error(L
"Failed to get MokDelAuth", efi_status
);
1284 if (auth_size
== PASSWORD_CRYPT_SIZE
) {
1285 dprint(L
"matching password with CRYPT");
1286 efi_status
= match_password((PASSWORD_CRYPT
*) auth
, NULL
, 0,
1288 dprint(L
"match_password(0x%llx, NULL, 0, NULL, NULL) = %lu\n", auth
, efi_status
);
1290 dprint(L
"matching password as sha256sum");
1292 match_password(NULL
, MokDel
, MokDelSize
, auth
, NULL
);
1293 dprint(L
"match_password(NULL, 0x%llx, %llu, 0x%llx, NULL) = %lu\n", MokDel
, MokDelSize
, auth
, efi_status
);
1295 if (EFI_ERROR(efi_status
))
1296 return EFI_ACCESS_DENIED
;
1298 efi_status
= get_variable_attr(db_name
, &MokListData
, &MokListDataSize
,
1299 SHIM_LOCK_GUID
, &attributes
);
1300 if (EFI_ERROR(efi_status
)) {
1302 console_errorbox(L
"Failed to retrieve MokListX");
1304 console_errorbox(L
"Failed to retrieve MokList");
1306 } else if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
) {
1308 err_strs
[0] = L
"MokListX is compromised!";
1309 err_strs
[1] = L
"Erase all keys in MokListX!";
1311 err_strs
[0] = L
"MokList is compromised!";
1312 err_strs
[1] = L
"Erase all keys in MokList!";
1314 console_alertbox(err_strs
);
1315 RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1316 EFI_VARIABLE_NON_VOLATILE
|
1317 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1318 efi_status
= EFI_ACCESS_DENIED
;
1323 if (!MokListData
|| MokListDataSize
== 0)
1326 /* Construct lists */
1327 mok_num
= count_keys(MokListData
, MokListDataSize
);
1330 err_strs
[0] = L
"Failed to construct the key list of MokListX";
1331 err_strs
[1] = L
"Reset MokListX!";
1333 err_strs
[0] = L
"Failed to construct the key list of MokList";
1334 err_strs
[1] = L
"Reset MokList!";
1336 console_alertbox(err_strs
);
1337 RT
->SetVariable(db_name
, &SHIM_LOCK_GUID
,
1338 EFI_VARIABLE_NON_VOLATILE
|
1339 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1340 efi_status
= EFI_ABORTED
;
1343 mok
= build_mok_list(mok_num
, MokListData
, MokListDataSize
);
1345 console_errorbox(L
"Failed to construct key list");
1346 efi_status
= EFI_ABORTED
;
1349 del_num
= count_keys(MokDel
, MokDelSize
);
1351 console_errorbox(L
"Invalid key delete list");
1352 efi_status
= EFI_ABORTED
;
1355 del_key
= build_mok_list(del_num
, MokDel
, MokDelSize
);
1357 console_errorbox(L
"Failed to construct key list");
1358 efi_status
= EFI_ABORTED
;
1362 /* Search and destroy */
1363 dprint(L
"deleting certs from %a\n", MokX
? "MokListX" : "MokList");
1364 for (i
= 0; i
< del_num
; i
++) {
1365 type
= del_key
[i
].Type
; /* avoid -Werror=address-of-packed-member */
1366 if (CompareGuid(&type
, &X509_GUID
) == 0) {
1367 dprint(L
"deleting key %d (total %d):\n", i
, mok_num
);
1368 dhexdumpat(del_key
[i
].Mok
, del_key
[i
].MokSize
, 0);
1369 delete_cert(del_key
[i
].Mok
, del_key
[i
].MokSize
,
1371 } else if (is_sha2_hash(del_key
[i
].Type
)) {
1372 dprint(L
"deleting hash %d (total %d):\n", i
, mok_num
);
1373 dhexdumpat(del_key
[i
].Mok
, del_key
[i
].MokSize
, 0);
1374 delete_hash_list(del_key
[i
].Type
, del_key
[i
].Mok
,
1375 del_key
[i
].MokSize
, mok
, mok_num
);
1379 efi_status
= write_back_mok_list(mok
, mok_num
, MokX
);
1383 FreePool(MokListData
);
1392 static EFI_STATUS
mok_deletion_prompt(void *MokDel
, UINTN MokDelSize
,
1395 EFI_STATUS efi_status
;
1396 CHAR16
*delete_p
[] = { L
"Delete the key(s)?", NULL
};
1400 title
= L
"[Delete MOKX]";
1402 title
= L
"[Delete MOK]";
1404 efi_status
= list_keys(MokDel
, MokDelSize
, title
);
1405 if (EFI_ERROR(efi_status
))
1408 if (console_yes_no(delete_p
) == 0)
1411 efi_status
= delete_keys(MokDel
, MokDelSize
, MokX
);
1412 if (EFI_ERROR(efi_status
)) {
1413 console_notify(L
"Failed to delete keys");
1418 LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
1419 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
1421 LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
1422 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
1431 static CHAR16
get_password_charater(CHAR16
* prompt
)
1433 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1434 EFI_STATUS efi_status
;
1436 CHAR16 character
= 0;
1441 prompt
= L
"Password charater: ";
1443 console_save_and_set_mode(&SavedMode
);
1445 message
[0] = prompt
;
1447 length
= StrLen(message
[0]);
1448 console_print_box_at(message
, -1, -length
- 4, -5, length
+ 4, 3, 0, 1);
1449 efi_status
= get_line(&pw_length
, &character
, 1, 0);
1450 if (EFI_ERROR(efi_status
))
1453 console_restore_mode(&SavedMode
);
1458 static EFI_STATUS
mok_sb_prompt(void *MokSB
, UINTN MokSBSize
)
1460 EFI_STATUS efi_status
;
1461 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1462 MokSBvar
*var
= MokSB
;
1464 CHAR16 pass1
, pass2
, pass3
;
1466 UINT8 fail_count
= 0;
1468 UINT8 pos1
, pos2
, pos3
;
1470 CHAR16
*disable_sb
[] = { L
"Disable Secure Boot", NULL
};
1471 CHAR16
*enable_sb
[] = { L
"Enable Secure Boot", NULL
};
1473 if (MokSBSize
!= sizeof(MokSBvar
)) {
1474 console_notify(L
"Invalid MokSB variable contents");
1475 return EFI_INVALID_PARAMETER
;
1480 message
[0] = L
"Change Secure Boot state";
1483 console_save_and_set_mode(&SavedMode
);
1484 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1485 console_restore_mode(&SavedMode
);
1487 while (fail_count
< 3) {
1488 RandomBytes(&pos1
, sizeof(pos1
));
1489 pos1
= (pos1
% var
->PWLen
);
1492 RandomBytes(&pos2
, sizeof(pos2
));
1493 pos2
= (pos2
% var
->PWLen
);
1494 } while (pos2
== pos1
);
1497 RandomBytes(&pos3
, sizeof(pos3
));
1498 pos3
= (pos3
% var
->PWLen
);
1499 } while (pos3
== pos2
|| pos3
== pos1
);
1501 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1503 console_errorbox(L
"Failed to allocate buffer");
1504 return EFI_OUT_OF_RESOURCES
;
1506 pass1
= get_password_charater(str
);
1509 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1511 console_errorbox(L
"Failed to allocate buffer");
1512 return EFI_OUT_OF_RESOURCES
;
1514 pass2
= get_password_charater(str
);
1517 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1519 console_errorbox(L
"Failed to allocate buffer");
1520 return EFI_OUT_OF_RESOURCES
;
1522 pass3
= get_password_charater(str
);
1525 if (pass1
!= var
->Password
[pos1
] ||
1526 pass2
!= var
->Password
[pos2
] ||
1527 pass3
!= var
->Password
[pos3
]) {
1528 console_print(L
"Invalid character\n");
1535 if (fail_count
>= 3) {
1536 console_notify(L
"Password limit reached");
1537 return EFI_ACCESS_DENIED
;
1540 if (var
->MokSBState
== 0)
1541 ret
= console_yes_no(disable_sb
);
1543 ret
= console_yes_no(enable_sb
);
1546 LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
1550 if (var
->MokSBState
== 0) {
1551 efi_status
= RT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1552 EFI_VARIABLE_NON_VOLATILE
|
1553 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1555 if (EFI_ERROR(efi_status
)) {
1556 console_notify(L
"Failed to set Secure Boot state");
1560 efi_status
= RT
->SetVariable(L
"MokSBState", &SHIM_LOCK_GUID
,
1561 EFI_VARIABLE_NON_VOLATILE
|
1562 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1564 if (EFI_ERROR(efi_status
)) {
1565 console_notify(L
"Failed to delete Secure Boot state");
1573 static EFI_STATUS
mok_db_prompt(void *MokDB
, UINTN MokDBSize
)
1575 EFI_STATUS efi_status
;
1576 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1577 MokDBvar
*var
= MokDB
;
1579 CHAR16 pass1
, pass2
, pass3
;
1581 UINT8 fail_count
= 0;
1583 UINT8 pos1
, pos2
, pos3
;
1585 CHAR16
*ignore_db
[] = { L
"Ignore DB certs/hashes", NULL
};
1586 CHAR16
*use_db
[] = { L
"Use DB certs/hashes", NULL
};
1588 if (MokDBSize
!= sizeof(MokDBvar
)) {
1589 console_notify(L
"Invalid MokDB variable contents");
1590 return EFI_INVALID_PARAMETER
;
1595 message
[0] = L
"Change DB state";
1598 console_save_and_set_mode(&SavedMode
);
1599 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1600 console_restore_mode(&SavedMode
);
1602 while (fail_count
< 3) {
1603 RandomBytes(&pos1
, sizeof(pos1
));
1604 pos1
= (pos1
% var
->PWLen
);
1607 RandomBytes(&pos2
, sizeof(pos2
));
1608 pos2
= (pos2
% var
->PWLen
);
1609 } while (pos2
== pos1
);
1612 RandomBytes(&pos3
, sizeof(pos3
));
1613 pos3
= (pos3
% var
->PWLen
);
1614 } while (pos3
== pos2
|| pos3
== pos1
);
1616 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1618 console_errorbox(L
"Failed to allocate buffer");
1619 return EFI_OUT_OF_RESOURCES
;
1621 pass1
= get_password_charater(str
);
1624 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1626 console_errorbox(L
"Failed to allocate buffer");
1627 return EFI_OUT_OF_RESOURCES
;
1629 pass2
= get_password_charater(str
);
1632 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1634 console_errorbox(L
"Failed to allocate buffer");
1635 return EFI_OUT_OF_RESOURCES
;
1637 pass3
= get_password_charater(str
);
1640 if (pass1
!= var
->Password
[pos1
] ||
1641 pass2
!= var
->Password
[pos2
] ||
1642 pass3
!= var
->Password
[pos3
]) {
1643 console_print(L
"Invalid character\n");
1650 if (fail_count
>= 3) {
1651 console_notify(L
"Password limit reached");
1652 return EFI_ACCESS_DENIED
;
1655 if (var
->MokDBState
== 0)
1656 ret
= console_yes_no(ignore_db
);
1658 ret
= console_yes_no(use_db
);
1661 LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
1665 if (var
->MokDBState
== 0) {
1666 efi_status
= RT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1667 EFI_VARIABLE_NON_VOLATILE
|
1668 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1670 if (EFI_ERROR(efi_status
)) {
1671 console_notify(L
"Failed to set DB state");
1675 efi_status
= RT
->SetVariable(L
"MokDBState", &SHIM_LOCK_GUID
,
1676 EFI_VARIABLE_NON_VOLATILE
|
1677 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1679 if (EFI_ERROR(efi_status
)) {
1680 console_notify(L
"Failed to delete DB state");
1688 static EFI_STATUS
mok_tml_prompt(void *MokTML
, UINTN MokTMLSize
)
1690 EFI_STATUS efi_status
;
1691 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
1692 MokTMLvar
*var
= MokTML
;
1694 CHAR16 pass1
, pass2
, pass3
;
1696 UINT8 fail_count
= 0;
1698 UINT8 pos1
, pos2
, pos3
;
1700 CHAR16
*untrust_tml
[] = { L
"Do not trust the MOK list", NULL
};
1701 CHAR16
*trust_tml
[] = { L
"Trust the MOK list", NULL
};
1703 if (MokTMLSize
!= sizeof(MokTMLvar
)) {
1704 console_notify(L
"Invalid MokTML variable contents");
1705 return EFI_INVALID_PARAMETER
;
1710 message
[0] = L
"Change Trusted MOK List Keyring state";
1713 console_save_and_set_mode(&SavedMode
);
1714 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
1715 console_restore_mode(&SavedMode
);
1717 while (fail_count
< 3) {
1718 RandomBytes(&pos1
, sizeof(pos1
));
1719 pos1
= (pos1
% var
->PWLen
);
1722 RandomBytes(&pos2
, sizeof(pos2
));
1723 pos2
= (pos2
% var
->PWLen
);
1724 } while (pos2
== pos1
);
1727 RandomBytes(&pos3
, sizeof(pos3
));
1728 pos3
= (pos3
% var
->PWLen
);
1729 } while (pos3
== pos2
|| pos3
== pos1
);
1731 str
= PoolPrint(L
"Enter password character %d: ", pos1
+ 1);
1733 console_errorbox(L
"Failed to allocate buffer");
1734 return EFI_OUT_OF_RESOURCES
;
1736 pass1
= get_password_charater(str
);
1739 str
= PoolPrint(L
"Enter password character %d: ", pos2
+ 1);
1741 console_errorbox(L
"Failed to allocate buffer");
1742 return EFI_OUT_OF_RESOURCES
;
1744 pass2
= get_password_charater(str
);
1747 str
= PoolPrint(L
"Enter password character %d: ", pos3
+ 1);
1749 console_errorbox(L
"Failed to allocate buffer");
1750 return EFI_OUT_OF_RESOURCES
;
1752 pass3
= get_password_charater(str
);
1755 if (pass1
!= var
->Password
[pos1
] ||
1756 pass2
!= var
->Password
[pos2
] ||
1757 pass3
!= var
->Password
[pos3
]) {
1758 console_print(L
"Invalid character\n");
1765 if (fail_count
>= 3) {
1766 console_notify(L
"Password limit reached");
1767 return EFI_ACCESS_DENIED
;
1770 if (var
->MokTMLState
== 0)
1771 ret
= console_yes_no(trust_tml
);
1773 ret
= console_yes_no(untrust_tml
);
1776 LibDeleteVariable(L
"MokListTrustedNew", &SHIM_LOCK_GUID
);
1780 if (var
->MokTMLState
== 0) {
1781 efi_status
= RT
->SetVariable(L
"MokListTrusted", &SHIM_LOCK_GUID
,
1782 EFI_VARIABLE_NON_VOLATILE
|
1783 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1785 if (EFI_ERROR(efi_status
)) {
1786 console_notify(L
"Failed to set MokListTrusted state");
1790 efi_status
= RT
->SetVariable(L
"MokListTrusted", &SHIM_LOCK_GUID
,
1791 EFI_VARIABLE_NON_VOLATILE
|
1792 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1794 if (EFI_ERROR(efi_status
)) {
1795 console_notify(L
"Failed to delete MokListTrusted state");
1803 static EFI_STATUS
mok_pw_prompt(void *MokPW
, UINTN MokPWSize
)
1805 EFI_STATUS efi_status
;
1806 UINT8 hash
[PASSWORD_CRYPT_SIZE
];
1808 CHAR16
*clear_p
[] = { L
"Clear MOK password?", NULL
};
1809 CHAR16
*set_p
[] = { L
"Set MOK password?", NULL
};
1811 if (MokPWSize
!= SHA256_DIGEST_SIZE
&& MokPWSize
!= PASSWORD_CRYPT_SIZE
) {
1812 console_notify(L
"Invalid MokPW variable contents");
1813 return EFI_INVALID_PARAMETER
;
1818 SetMem(hash
, PASSWORD_CRYPT_SIZE
, 0);
1820 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1821 if (CompareMem(MokPW
, hash
, PASSWORD_CRYPT_SIZE
) == 0)
1824 if (CompareMem(MokPW
, hash
, SHA256_DIGEST_SIZE
) == 0)
1829 if (console_yes_no(clear_p
) == 0)
1832 RT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1833 EFI_VARIABLE_NON_VOLATILE
|
1834 EFI_VARIABLE_BOOTSERVICE_ACCESS
, 0, NULL
);
1838 if (MokPWSize
== PASSWORD_CRYPT_SIZE
) {
1839 efi_status
= match_password((PASSWORD_CRYPT
*) MokPW
, NULL
, 0,
1840 NULL
, L
"Confirm MOK passphrase: ");
1842 efi_status
= match_password(NULL
, NULL
, 0, MokPW
,
1843 L
"Confirm MOK passphrase: ");
1846 if (EFI_ERROR(efi_status
)) {
1847 console_notify(L
"Password limit reached");
1851 if (console_yes_no(set_p
) == 0)
1854 efi_status
= RT
->SetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
,
1855 EFI_VARIABLE_NON_VOLATILE
|
1856 EFI_VARIABLE_BOOTSERVICE_ACCESS
,
1858 if (EFI_ERROR(efi_status
)) {
1859 console_notify(L
"Failed to set MOK password");
1864 LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
1869 static BOOLEAN
verify_certificate(UINT8
* cert
, UINTN size
)
1873 if (!cert
|| size
< 4)
1877 * A DER encoding x509 certificate starts with SEQUENCE(0x30),
1878 * the number of length bytes, and the number of value bytes.
1879 * The size of a x509 certificate is usually between 127 bytes
1880 * and 64KB. For convenience, assume the number of value bytes
1881 * is 2, i.e. the second byte is 0x82.
1883 if (cert
[0] != 0x30 || cert
[1] != 0x82) {
1884 console_notify(L
"Not a DER encoding X509 certificate");
1888 length
= (cert
[2] << 8 | cert
[3]);
1889 if (length
!= (size
- 4)) {
1890 console_notify(L
"Invalid X509 certificate: Inconsistent size");
1894 if (!(X509ConstructCertificate(cert
, size
, (UINT8
**) & X509Cert
)) ||
1896 console_notify(L
"Invalid X509 certificate");
1900 X509_free(X509Cert
);
1904 static EFI_STATUS
enroll_file(void *data
, UINTN datasize
, BOOLEAN hash
)
1906 EFI_STATUS efi_status
= EFI_SUCCESS
;
1907 EFI_SIGNATURE_LIST
*CertList
;
1908 EFI_SIGNATURE_DATA
*CertData
;
1909 UINTN mokbuffersize
;
1910 void *mokbuffer
= NULL
;
1913 UINT8 sha256
[SHA256_DIGEST_SIZE
];
1914 UINT8 sha1
[SHA1_DIGEST_SIZE
];
1915 SHIM_LOCK
*shim_lock
;
1916 PE_COFF_LOADER_IMAGE_CONTEXT context
;
1918 efi_status
= LibLocateProtocol(&SHIM_LOCK_GUID
,
1919 (VOID
**) &shim_lock
);
1920 if (EFI_ERROR(efi_status
))
1923 mokbuffersize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
) +
1926 mokbuffer
= AllocatePool(mokbuffersize
);
1930 efi_status
= shim_lock
->Context(data
, datasize
, &context
);
1931 if (EFI_ERROR(efi_status
))
1934 efi_status
= shim_lock
->Hash(data
, datasize
, &context
, sha256
,
1936 if (EFI_ERROR(efi_status
))
1939 CertList
= mokbuffer
;
1940 CertList
->SignatureType
= EFI_CERT_SHA256_GUID
;
1941 CertList
->SignatureSize
= 16 + SHA256_DIGEST_SIZE
;
1942 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1943 sizeof(EFI_SIGNATURE_LIST
));
1944 CopyMem(CertData
->SignatureData
, sha256
, SHA256_DIGEST_SIZE
);
1946 mokbuffersize
= datasize
+ sizeof(EFI_SIGNATURE_LIST
) +
1948 mokbuffer
= AllocatePool(mokbuffersize
);
1953 CertList
= mokbuffer
;
1954 CertList
->SignatureType
= X509_GUID
;
1955 CertList
->SignatureSize
= 16 + datasize
;
1957 memcpy(mokbuffer
+ sizeof(EFI_SIGNATURE_LIST
) + 16, data
,
1960 CertData
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) mokbuffer
) +
1961 sizeof(EFI_SIGNATURE_LIST
));
1964 CertList
->SignatureListSize
= mokbuffersize
;
1965 CertList
->SignatureHeaderSize
= 0;
1966 CertData
->SignatureOwner
= SHIM_LOCK_GUID
;
1969 if (!verify_certificate(CertData
->SignatureData
, datasize
))
1973 efi_status
= mok_enrollment_prompt(mokbuffer
, mokbuffersize
,
1977 FreePool(mokbuffer
);
1982 static EFI_STATUS
mok_hash_enroll(void)
1984 EFI_STATUS efi_status
;
1985 CHAR16
*file_name
= NULL
;
1986 EFI_HANDLE im
= NULL
;
1987 EFI_FILE
*file
= NULL
;
1990 CHAR16
*selections
[] = {
1993 L
"The Selected Binary will have its hash Enrolled",
1994 L
"This means it will subsequently Boot with no prompting",
1995 L
"Remember to make sure it is a genuine binary before enrolling its hash",
1999 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
2002 return EFI_INVALID_PARAMETER
;
2004 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
2005 if (EFI_ERROR(efi_status
)) {
2006 console_error(L
"Unable to open file", efi_status
);
2010 simple_file_read_all(file
, &filesize
, &data
);
2013 console_error(L
"Unable to read file", efi_status
);
2014 return EFI_BAD_BUFFER_SIZE
;
2017 efi_status
= enroll_file(data
, filesize
, TRUE
);
2018 if (EFI_ERROR(efi_status
))
2020 L
"Hash failed (did you select a valid EFI binary?)",
2028 static CHAR16
*der_suffix
[] = {
2035 static BOOLEAN
check_der_suffix(CHAR16
* file_name
)
2040 if (!file_name
|| StrLen(file_name
) <= 4)
2044 StrnCat(suffix
, file_name
+ StrLen(file_name
) - 4, 4);
2047 for (i
= 0; der_suffix
[i
] != NULL
; i
++) {
2048 if (StrCmp(suffix
, der_suffix
[i
]) == 0) {
2056 static EFI_STATUS
mok_key_enroll(void)
2058 EFI_STATUS efi_status
;
2059 CHAR16
*file_name
= NULL
;
2060 EFI_HANDLE im
= NULL
;
2061 EFI_FILE
*file
= NULL
;
2064 CHAR16
*selections
[] = {
2067 L
"The selected key will be enrolled into the MOK database",
2068 L
"This means any binaries signed with it will be run without prompting",
2069 L
"Remember to make sure it is a genuine key before Enrolling it",
2073 L
"Unsupported Format",
2075 L
"Only DER encoded certificate (*.cer/der/crt) is supported",
2079 simple_file_selector(&im
, selections
, L
"\\", L
"", &file_name
);
2082 return EFI_INVALID_PARAMETER
;
2084 if (!check_der_suffix(file_name
)) {
2085 console_alertbox(alert
);
2086 return EFI_UNSUPPORTED
;
2089 efi_status
= simple_file_open(im
, file_name
, &file
, EFI_FILE_MODE_READ
);
2090 if (EFI_ERROR(efi_status
)) {
2091 console_error(L
"Unable to open file", efi_status
);
2095 simple_file_read_all(file
, &filesize
, &data
);
2098 console_error(L
"Unable to read file", efi_status
);
2099 return EFI_BAD_BUFFER_SIZE
;
2102 efi_status
= enroll_file(data
, filesize
, FALSE
);
2108 static BOOLEAN
verify_pw(BOOLEAN
* protected)
2110 EFI_STATUS efi_status
;
2111 SIMPLE_TEXT_OUTPUT_MODE SavedMode
;
2112 UINT8 pwhash
[PASSWORD_CRYPT_SIZE
];
2113 UINTN size
= PASSWORD_CRYPT_SIZE
;
2119 efi_status
= RT
->GetVariable(L
"MokPWStore", &SHIM_LOCK_GUID
, &attributes
,
2122 * If anything can attack the password it could just set it to a
2123 * known value, so there's no safety advantage in failing to validate
2124 * purely because of a failure to read the variable
2126 if (EFI_ERROR(efi_status
) ||
2127 (size
!= SHA256_DIGEST_SIZE
&& size
!= PASSWORD_CRYPT_SIZE
))
2130 if (attributes
& EFI_VARIABLE_RUNTIME_ACCESS
)
2135 /* Draw the background */
2136 console_save_and_set_mode(&SavedMode
);
2137 message
[0] = PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2139 console_print_box_at(message
, -1, 0, 0, -1, -1, 1, 1);
2140 FreePool(message
[0]);
2141 console_restore_mode(&SavedMode
);
2143 if (size
== PASSWORD_CRYPT_SIZE
) {
2144 efi_status
= match_password((PASSWORD_CRYPT
*) pwhash
, NULL
, 0,
2145 NULL
, L
"Enter MOK password:");
2147 efi_status
= match_password(NULL
, NULL
, 0, pwhash
,
2148 L
"Enter MOK password:");
2150 if (EFI_ERROR(efi_status
)) {
2151 console_notify(L
"Password limit reached");
2160 static int draw_countdown()
2162 CHAR16
*message
= L
"Press any key to perform MOK management";
2164 void *MokTimeout
= NULL
;
2166 UINTN MokTimeoutSize
= 0;
2168 EFI_STATUS efi_status
;
2170 efi_status
= get_variable(L
"MokTimeout", (UINT8
**) &MokTimeout
,
2171 &MokTimeoutSize
, SHIM_LOCK_GUID
);
2172 if (!EFI_ERROR(efi_status
)) {
2174 timeout
= (int)var
->Timeout
;
2175 FreePool(MokTimeout
);
2176 LibDeleteVariable(L
"MokTimeout", &SHIM_LOCK_GUID
);
2182 title
= PoolPrint(L
"%s UEFI key management", SHIM_VENDOR
);
2183 timeout
= console_countdown(title
, message
, timeout
);
2205 static void free_menu(mok_menu_item
* menu_item
, CHAR16
** menu_strings
)
2208 FreePool(menu_strings
);
2211 FreePool(menu_item
);
2214 static EFI_STATUS
enter_mok_menu(EFI_HANDLE image_handle UNUSED
,
2215 void *MokNew
, UINTN MokNewSize
,
2216 void *MokDel
, UINTN MokDelSize
,
2217 void *MokSB
, UINTN MokSBSize
,
2218 void *MokPW
, UINTN MokPWSize
,
2219 void *MokDB
, UINTN MokDBSize
,
2220 void *MokXNew
, UINTN MokXNewSize
,
2221 void *MokXDel
, UINTN MokXDelSize
,
2222 void *MokTML
, UINTN MokTMLSize
)
2224 CHAR16
**menu_strings
= NULL
;
2225 mok_menu_item
*menu_item
= NULL
;
2227 int mok_changed
= 0;
2228 EFI_STATUS efi_status
;
2229 UINT8 auth
[PASSWORD_CRYPT_SIZE
];
2230 UINTN auth_size
= PASSWORD_CRYPT_SIZE
;
2233 CHAR16
*mok_mgmt_p
[] = { L
"Perform MOK management", NULL
};
2234 EFI_STATUS ret
= EFI_SUCCESS
;
2236 if (verify_pw(&protected) == FALSE
)
2237 return EFI_ACCESS_DENIED
;
2239 if (protected == FALSE
&& draw_countdown() == 0)
2242 while (choice
>= 0) {
2243 UINTN menucount
= 3, i
= 0;
2245 UINT32 MokDelAuth
= 0;
2246 UINT32 MokXAuth
= 0;
2247 UINT32 MokXDelAuth
= 0;
2249 efi_status
= RT
->GetVariable(L
"MokAuth", &SHIM_LOCK_GUID
,
2250 &attributes
, &auth_size
, auth
);
2251 if (!EFI_ERROR(efi_status
) &&
2252 (auth_size
== SHA256_DIGEST_SIZE
||
2253 auth_size
== PASSWORD_CRYPT_SIZE
))
2256 efi_status
= RT
->GetVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
,
2257 &attributes
, &auth_size
, auth
);
2258 if (!EFI_ERROR(efi_status
) &&
2259 (auth_size
== SHA256_DIGEST_SIZE
||
2260 auth_size
== PASSWORD_CRYPT_SIZE
))
2263 efi_status
= RT
->GetVariable(L
"MokXAuth", &SHIM_LOCK_GUID
,
2264 &attributes
, &auth_size
, auth
);
2265 if (!EFI_ERROR(efi_status
) &&
2266 (auth_size
== SHA256_DIGEST_SIZE
||
2267 auth_size
== PASSWORD_CRYPT_SIZE
))
2270 efi_status
= RT
->GetVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
,
2271 &attributes
, &auth_size
, auth
);
2272 if (!EFI_ERROR(efi_status
) &&
2273 (auth_size
== SHA256_DIGEST_SIZE
||
2274 auth_size
== PASSWORD_CRYPT_SIZE
))
2277 if (MokNew
|| MokAuth
)
2280 if (MokDel
|| MokDelAuth
)
2283 if (MokXNew
|| MokXAuth
)
2286 if (MokXDel
|| MokXDelAuth
)
2301 menu_strings
= AllocateZeroPool(sizeof(CHAR16
*) *
2304 return EFI_OUT_OF_RESOURCES
;
2306 menu_item
= AllocateZeroPool(sizeof(mok_menu_item
) * menucount
);
2308 FreePool(menu_strings
);
2309 return EFI_OUT_OF_RESOURCES
;
2313 menu_strings
[i
] = L
"Reboot";
2315 menu_strings
[i
] = L
"Continue boot";
2316 menu_item
[i
] = MOK_BOOT
;
2320 if (MokNew
|| MokAuth
) {
2322 menu_strings
[i
] = L
"Reset MOK";
2323 menu_item
[i
] = MOK_RESET_MOK
;
2325 menu_strings
[i
] = L
"Enroll MOK";
2326 menu_item
[i
] = MOK_ENROLL_MOK
;
2331 if (MokDel
|| MokDelAuth
) {
2332 menu_strings
[i
] = L
"Delete MOK";
2333 menu_item
[i
] = MOK_DELETE_MOK
;
2337 if (MokXNew
|| MokXAuth
) {
2339 menu_strings
[i
] = L
"Reset MOKX";
2340 menu_item
[i
] = MOK_RESET_MOKX
;
2342 menu_strings
[i
] = L
"Enroll MOKX";
2343 menu_item
[i
] = MOK_ENROLL_MOKX
;
2348 if (MokXDel
|| MokXDelAuth
) {
2349 menu_strings
[i
] = L
"Delete MOKX";
2350 menu_item
[i
] = MOK_DELETE_MOKX
;
2355 menu_strings
[i
] = L
"Change Secure Boot state";
2356 menu_item
[i
] = MOK_CHANGE_SB
;
2361 menu_strings
[i
] = L
"Set MOK password";
2362 menu_item
[i
] = MOK_SET_PW
;
2367 menu_strings
[i
] = L
"Change DB state";
2368 menu_item
[i
] = MOK_CHANGE_DB
;
2373 menu_strings
[i
] = L
"Change MOK List Trusted State";
2374 menu_item
[i
] = MOK_CHANGE_TML
;
2378 menu_strings
[i
] = L
"Enroll key from disk";
2379 menu_item
[i
] = MOK_KEY_ENROLL
;
2382 menu_strings
[i
] = L
"Enroll hash from disk";
2383 menu_item
[i
] = MOK_HASH_ENROLL
;
2386 menu_strings
[i
] = NULL
;
2388 choice
= console_select(mok_mgmt_p
, menu_strings
, 0);
2392 switch (menu_item
[choice
]) {
2396 efi_status
= mok_reset_prompt(FALSE
);
2398 case MOK_ENROLL_MOK
:
2400 console_print(L
"MokManager: internal error: %s",
2401 L
"MokNew was !NULL but is now NULL\n");
2405 efi_status
= mok_enrollment_prompt(MokNew
, MokNewSize
,
2407 if (!EFI_ERROR(efi_status
))
2410 case MOK_DELETE_MOK
:
2412 console_print(L
"MokManager: internal error: %s",
2413 L
"MokDel was !NULL but is now NULL\n");
2417 efi_status
= mok_deletion_prompt(MokDel
, MokDelSize
,
2419 if (!EFI_ERROR(efi_status
))
2422 case MOK_RESET_MOKX
:
2423 efi_status
= mok_reset_prompt(TRUE
);
2425 case MOK_ENROLL_MOKX
:
2427 console_print(L
"MokManager: internal error: %s",
2428 L
"MokXNew was !NULL but is now NULL\n");
2432 efi_status
= mok_enrollment_prompt(MokXNew
, MokXNewSize
,
2434 if (!EFI_ERROR(efi_status
))
2437 case MOK_DELETE_MOKX
:
2439 console_print(L
"MokManager: internal error: %s",
2440 L
"MokXDel was !NULL but is now NULL\n");
2444 efi_status
= mok_deletion_prompt(MokXDel
, MokXDelSize
,
2446 if (!EFI_ERROR(efi_status
))
2451 console_print(L
"MokManager: internal error: %s",
2452 L
"MokSB was !NULL but is now NULL\n");
2456 efi_status
= mok_sb_prompt(MokSB
, MokSBSize
);
2457 if (!EFI_ERROR(efi_status
))
2462 console_print(L
"MokManager: internal error: %s",
2463 L
"MokPW was !NULL but is now NULL\n");
2467 efi_status
= mok_pw_prompt(MokPW
, MokPWSize
);
2468 if (!EFI_ERROR(efi_status
))
2473 console_print(L
"MokManager: internal error: %s",
2474 L
"MokDB was !NULL but is now NULL\n");
2478 efi_status
= mok_db_prompt(MokDB
, MokDBSize
);
2479 if (!EFI_ERROR(efi_status
))
2482 case MOK_KEY_ENROLL
:
2483 efi_status
= mok_key_enroll();
2485 case MOK_HASH_ENROLL
:
2486 efi_status
= mok_hash_enroll();
2488 case MOK_CHANGE_TML
:
2490 console_print(L
"MokManager: internal error: %s",
2491 L
"MokListTrusted was ! NULL bs is now NULL\n");
2495 efi_status
= mok_tml_prompt(MokTML
, MokTMLSize
);
2496 if (!EFI_ERROR(efi_status
))
2501 if (!EFI_ERROR(efi_status
))
2504 free_menu(menu_item
, menu_strings
);
2506 menu_strings
= NULL
;
2510 free_menu(menu_item
, menu_strings
);
2513 return reset_system();
2520 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
2522 UINTN MokNewSize
= 0, MokDelSize
= 0, MokSBSize
= 0, MokPWSize
= 0;
2523 UINTN MokDBSize
= 0, MokXNewSize
= 0, MokXDelSize
= 0, MokTMLSize
= 0;
2524 void *MokNew
= NULL
;
2525 void *MokDel
= NULL
;
2529 void *MokXNew
= NULL
;
2530 void *MokXDel
= NULL
;
2531 void *MokTML
= NULL
;
2532 EFI_STATUS efi_status
;
2534 efi_status
= get_variable(L
"MokNew", (UINT8
**) & MokNew
, &MokNewSize
,
2536 if (!EFI_ERROR(efi_status
)) {
2537 efi_status
= LibDeleteVariable(L
"MokNew", &SHIM_LOCK_GUID
);
2538 if (EFI_ERROR(efi_status
))
2539 console_notify(L
"Failed to delete MokNew");
2540 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2541 console_error(L
"Could not retrieve MokNew", efi_status
);
2544 efi_status
= get_variable(L
"MokDel", (UINT8
**) & MokDel
, &MokDelSize
,
2546 if (!EFI_ERROR(efi_status
)) {
2547 efi_status
= LibDeleteVariable(L
"MokDel", &SHIM_LOCK_GUID
);
2548 if (EFI_ERROR(efi_status
))
2549 console_notify(L
"Failed to delete MokDel");
2550 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2551 console_error(L
"Could not retrieve MokDel", efi_status
);
2554 efi_status
= get_variable(L
"MokSB", (UINT8
**) & MokSB
, &MokSBSize
,
2556 if (!EFI_ERROR(efi_status
)) {
2557 efi_status
= LibDeleteVariable(L
"MokSB", &SHIM_LOCK_GUID
);
2558 if (EFI_ERROR(efi_status
))
2559 console_notify(L
"Failed to delete MokSB");
2560 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2561 console_error(L
"Could not retrieve MokSB", efi_status
);
2564 efi_status
= get_variable(L
"MokPW", (UINT8
**) & MokPW
, &MokPWSize
,
2566 if (!EFI_ERROR(efi_status
)) {
2567 efi_status
= LibDeleteVariable(L
"MokPW", &SHIM_LOCK_GUID
);
2568 if (EFI_ERROR(efi_status
))
2569 console_notify(L
"Failed to delete MokPW");
2570 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2571 console_error(L
"Could not retrieve MokPW", efi_status
);
2574 efi_status
= get_variable(L
"MokDB", (UINT8
**) & MokDB
, &MokDBSize
,
2576 if (!EFI_ERROR(efi_status
)) {
2577 efi_status
= LibDeleteVariable(L
"MokDB", &SHIM_LOCK_GUID
);
2578 if (EFI_ERROR(efi_status
))
2579 console_notify(L
"Failed to delete MokDB");
2580 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2581 console_error(L
"Could not retrieve MokDB", efi_status
);
2584 efi_status
= get_variable(L
"MokListTrustedNew", (UINT8
**) & MokTML
,
2585 &MokTMLSize
, SHIM_LOCK_GUID
);
2586 if (!EFI_ERROR(efi_status
)) {
2587 efi_status
= LibDeleteVariable(L
"MokListTrustedNew",
2589 if (EFI_ERROR(efi_status
))
2590 console_notify(L
"Failed to delete MokListTrustedNew");
2591 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2592 console_error(L
"Could not retrieve MokListTrustedNew",
2596 efi_status
= get_variable(L
"MokXNew", (UINT8
**) & MokXNew
,
2597 &MokXNewSize
, SHIM_LOCK_GUID
);
2598 if (!EFI_ERROR(efi_status
)) {
2599 efi_status
= LibDeleteVariable(L
"MokXNew", &SHIM_LOCK_GUID
);
2600 if (EFI_ERROR(efi_status
))
2601 console_notify(L
"Failed to delete MokXNew");
2602 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2603 console_error(L
"Could not retrieve MokXNew", efi_status
);
2606 efi_status
= get_variable(L
"MokXDel", (UINT8
**) & MokXDel
,
2607 &MokXDelSize
, SHIM_LOCK_GUID
);
2608 if (!EFI_ERROR(efi_status
)) {
2609 efi_status
= LibDeleteVariable(L
"MokXDel", &SHIM_LOCK_GUID
);
2610 if (EFI_ERROR(efi_status
))
2611 console_notify(L
"Failed to delete MokXDel");
2612 } else if (EFI_ERROR(efi_status
) && efi_status
!= EFI_NOT_FOUND
) {
2613 console_error(L
"Could not retrieve MokXDel", efi_status
);
2616 enter_mok_menu(image_handle
, MokNew
, MokNewSize
, MokDel
, MokDelSize
,
2617 MokSB
, MokSBSize
, MokPW
, MokPWSize
, MokDB
, MokDBSize
,
2618 MokXNew
, MokXNewSize
, MokXDel
, MokXDelSize
, MokTML
, MokTMLSize
);
2644 LibDeleteVariable(L
"MokAuth", &SHIM_LOCK_GUID
);
2645 LibDeleteVariable(L
"MokDelAuth", &SHIM_LOCK_GUID
);
2646 LibDeleteVariable(L
"MokXAuth", &SHIM_LOCK_GUID
);
2647 LibDeleteVariable(L
"MokXDelAuth", &SHIM_LOCK_GUID
);
2652 static EFI_STATUS
setup_rand(void)
2655 EFI_STATUS efi_status
;
2659 efi_status
= RT
->GetTime(&time
, NULL
);
2660 if (EFI_ERROR(efi_status
))
2663 seed
= ((UINT64
) time
.Year
<< 48) | ((UINT64
) time
.Month
<< 40) |
2664 ((UINT64
) time
.Day
<< 32) | ((UINT64
) time
.Hour
<< 24) |
2665 ((UINT64
) time
.Minute
<< 16) | ((UINT64
) time
.Second
<< 8) |
2666 ((UINT64
) time
.Daylight
);
2668 status
= RandomSeed((UINT8
*) & seed
, sizeof(seed
));
2675 EFI_STATUS
efi_main(EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
* systab
)
2677 EFI_STATUS efi_status
;
2679 InitializeLib(image_handle
, systab
);
2684 console_mode_handle();
2686 efi_status
= check_mok_request(image_handle
);