3 #include <Library/BaseCryptLib.h>
4 #include <openssl/x509.h>
9 #define PASSWORD_MAX 16
10 #define PASSWORD_MIN 8
13 #define SHIM_VENDOR L"Shim"
16 #define EFI_VARIABLE_APPEND_WRITE 0x00000040
20 INTN (* callback
)(void *data
, void *data2
, void *data3
);
30 } __attribute__ ((packed
)) MokListNode
;
32 static EFI_INPUT_KEY
get_keystroke (void)
37 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
,
39 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, &key
);
44 static EFI_STATUS
get_sha1sum (void *Data
, int DataSize
, UINT8
*hash
)
50 ctxsize
= Sha1GetContextSize();
51 ctx
= AllocatePool(ctxsize
);
54 Print(L
"Unable to allocate memory for hash context\n");
55 return EFI_OUT_OF_RESOURCES
;
59 Print(L
"Unable to initialise hash\n");
60 status
= EFI_OUT_OF_RESOURCES
;
64 if (!(Sha1Update(ctx
, Data
, DataSize
))) {
65 Print(L
"Unable to generate hash\n");
66 status
= EFI_OUT_OF_RESOURCES
;
70 if (!(Sha1Final(ctx
, hash
))) {
71 Print(L
"Unable to finalise hash\n");
72 status
= EFI_OUT_OF_RESOURCES
;
81 static MokListNode
*build_mok_list(UINT32 num
, void *Data
, UINTN DataSize
) {
83 EFI_SIGNATURE_LIST
*CertList
= Data
;
84 EFI_SIGNATURE_DATA
*Cert
;
85 EFI_GUID CertType
= EfiCertX509Guid
;
86 EFI_GUID HashType
= EfiHashSha256Guid
;
87 UINTN dbsize
= DataSize
;
90 list
= AllocatePool(sizeof(MokListNode
) * num
);
93 Print(L
"Unable to allocate MOK list\n");
97 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
98 if ((CompareGuid (&CertList
->SignatureType
, &CertType
) != 0) &&
99 (CompareGuid (&CertList
->SignatureType
, &HashType
) != 0)) {
100 dbsize
-= CertList
->SignatureListSize
;
101 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*) CertList
+
102 CertList
->SignatureSize
);
106 if ((CompareGuid (&CertList
->SignatureType
, &HashType
) == 0) &&
107 (CertList
->SignatureSize
!= 48)) {
108 dbsize
-= CertList
->SignatureListSize
;
109 CertList
= (EFI_SIGNATURE_LIST
*)((UINT8
*) CertList
+
110 CertList
->SignatureSize
);
114 Cert
= (EFI_SIGNATURE_DATA
*) (((UINT8
*) CertList
) +
115 sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
117 list
[count
].MokSize
= CertList
->SignatureSize
;
118 list
[count
].Mok
= (void *)Cert
->SignatureData
;
121 dbsize
-= CertList
->SignatureListSize
;
122 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
123 CertList
->SignatureSize
);
129 static void print_x509_name (X509_NAME
*X509Name
, CHAR16
*name
)
133 str
= X509_NAME_oneline(X509Name
, NULL
, 0);
135 Print(L
" %s:\n %a\n", name
, str
);
140 static const char *mon
[12]= {
141 "Jan","Feb","Mar","Apr","May","Jun",
142 "Jul","Aug","Sep","Oct","Nov","Dec"
145 static void print_x509_GENERALIZEDTIME_time (ASN1_TIME
*time
, CHAR16
*time_string
)
150 int y
= 0,M
= 0,d
= 0,h
= 0,m
= 0,s
= 0;
155 v
=(char *)time
->data
;
163 for (i
=0; i
<12; i
++) {
164 if ((v
[i
] > '9') || (v
[i
] < '0'))
168 y
= (v
[0]-'0')*1000+(v
[1]-'0')*100 + (v
[2]-'0')*10+(v
[3]-'0');
169 M
= (v
[4]-'0')*10+(v
[5]-'0');
171 if ((M
> 12) || (M
< 1))
174 d
= (v
[6]-'0')*10+(v
[7]-'0');
175 h
= (v
[8]-'0')*10+(v
[9]-'0');
176 m
= (v
[10]-'0')*10+(v
[11]-'0');
178 if (time
->length
>= 14 &&
179 (v
[12] >= '0') && (v
[12] <= '9') &&
180 (v
[13] >= '0') && (v
[13] <= '9')) {
181 s
= (v
[12]-'0')*10+(v
[13]-'0');
182 /* Check for fractions of seconds. */
183 if (time
->length
>= 15 && v
[14] == '.') {
184 int l
= time
->length
;
185 f
= &v
[14]; /* The decimal point. */
187 while (14 + f_len
< l
&& f
[f_len
] >= '0' &&
193 SPrint(time_string
, 0, L
"%a %2d %02d:%02d:%02d%.*a %d%a",
194 mon
[M
-1], d
, h
, m
, s
, f_len
, f
, y
, (gmt
)?" GMT":"");
199 static void print_x509_UTCTIME_time (ASN1_TIME
*time
, CHAR16
*time_string
)
204 int y
= 0,M
= 0,d
= 0,h
= 0,m
= 0,s
= 0;
207 v
=(char *)time
->data
;
216 if ((v
[i
] > '9') || (v
[i
] < '0'))
219 y
= (v
[0]-'0')*10+(v
[1]-'0');
224 M
= (v
[2]-'0')*10+(v
[3]-'0');
226 if ((M
> 12) || (M
< 1))
229 d
= (v
[4]-'0')*10+(v
[5]-'0');
230 h
= (v
[6]-'0')*10+(v
[7]-'0');
231 m
= (v
[8]-'0')*10+(v
[9]-'0');
233 if (time
->length
>=12 &&
234 (v
[10] >= '0') && (v
[10] <= '9') &&
235 (v
[11] >= '0') && (v
[11] <= '9'))
236 s
= (v
[10]-'0')*10+(v
[11]-'0');
238 SPrint(time_string
, 0, L
"%a %2d %02d:%02d:%02d %d%a",
239 mon
[M
-1], d
, h
, m
, s
, y
+1900, (gmt
)?" GMT":"");
244 static void print_x509_time (ASN1_TIME
*time
, CHAR16
*name
)
246 CHAR16 time_string
[30];
248 if (time
->type
== V_ASN1_UTCTIME
) {
249 print_x509_UTCTIME_time(time
, time_string
);
250 } else if (time
->type
== V_ASN1_GENERALIZEDTIME
) {
251 print_x509_GENERALIZEDTIME_time(time
, time_string
);
253 time_string
[0] = '\0';
256 Print(L
" %s:\n %s\n", name
, time_string
);
259 static void show_x509_info (X509
*X509Cert
)
261 ASN1_INTEGER
*serial
;
263 unsigned char hexbuf
[30];
267 serial
= X509_get_serialNumber(X509Cert
);
270 bnser
= ASN1_INTEGER_to_BN(serial
, NULL
);
271 n
= BN_bn2bin(bnser
, hexbuf
);
272 Print(L
" Serial Number:\n ");
273 for (i
= 0; i
< n
-1; i
++) {
274 Print(L
"%02x:", hexbuf
[i
]);
276 Print(L
"%02x\n", hexbuf
[n
-1]);
279 X509Name
= X509_get_issuer_name(X509Cert
);
281 print_x509_name(X509Name
, L
"Issuer");
284 X509Name
= X509_get_subject_name(X509Cert
);
286 print_x509_name(X509Name
, L
"Subject");
289 time
= X509_get_notBefore(X509Cert
);
291 print_x509_time(time
, L
"Validity from");
294 time
= X509_get_notAfter(X509Cert
);
296 print_x509_time(time
, L
"Validity till");
300 static void show_mok_info (void *Mok
, UINTN MokSize
)
302 EFI_STATUS efi_status
;
303 UINT8 hash
[SHA1_DIGEST_SIZE
];
307 if (!Mok
|| MokSize
== 0)
311 if (X509ConstructCertificate(Mok
, MokSize
, (UINT8
**) &X509Cert
) &&
313 show_x509_info(X509Cert
);
316 Print(L
" Not a valid X509 certificate: %x\n\n",
321 Print(L
"SHA256 hash:\n ");
322 for (i
= 0; i
< SHA256_DIGEST_SIZE
; i
++) {
323 Print(L
" %02x", ((UINT8
*)Mok
)[i
]);
329 efi_status
= get_sha1sum(Mok
, MokSize
, hash
);
331 if (efi_status
!= EFI_SUCCESS
) {
332 Print(L
"Failed to compute MOK fingerprint\n");
336 Print(L
" Fingerprint (SHA1):\n ");
337 for (i
= 0; i
< SHA1_DIGEST_SIZE
; i
++) {
338 Print(L
" %02x", hash
[i
]);
345 static INTN
get_number ()
347 EFI_INPUT_KEY input_key
;
352 input_key
= get_keystroke();
354 if ((input_key
.UnicodeChar
< '0' ||
355 input_key
.UnicodeChar
> '9' ||
357 input_key
.UnicodeChar
!= CHAR_BACKSPACE
) {
361 if (count
== 0 && input_key
.UnicodeChar
== CHAR_BACKSPACE
)
364 Print(L
"%c", input_key
.UnicodeChar
);
366 if (input_key
.UnicodeChar
== CHAR_BACKSPACE
) {
367 input
[--count
] = '\0';
371 input
[count
++] = input_key
.UnicodeChar
;
372 } while (input_key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
379 return (INTN
)Atoi(input
);
382 static UINT8
list_keys (void *MokNew
, UINTN MokNewSize
)
385 MokListNode
*keys
= NULL
;
388 EFI_SIGNATURE_LIST
*CertList
= MokNew
;
389 EFI_GUID CertType
= EfiCertX509Guid
;
390 EFI_GUID HashType
= EfiHashSha256Guid
;
391 UINTN dbsize
= MokNewSize
;
393 if (MokNewSize
< (sizeof(EFI_SIGNATURE_LIST
) +
394 sizeof(EFI_SIGNATURE_DATA
))) {
400 while ((dbsize
> 0) && (dbsize
>= CertList
->SignatureListSize
)) {
401 if ((CompareGuid (&CertList
->SignatureType
, &CertType
) != 0) &&
402 (CompareGuid (&CertList
->SignatureType
, &HashType
) != 0)) {
403 Print(L
"Doesn't look like a key or hash\n");
404 dbsize
-= CertList
->SignatureListSize
;
405 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
406 CertList
->SignatureSize
);
410 if ((CompareGuid (&CertList
->SignatureType
, &CertType
) != 0) &&
411 (CertList
->SignatureSize
!= 48)) {
412 Print(L
"Doesn't look like a valid hash\n");
413 dbsize
-= CertList
->SignatureListSize
;
414 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
415 CertList
->SignatureSize
);
420 dbsize
-= CertList
->SignatureListSize
;
421 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+
422 CertList
->SignatureSize
);
425 keys
= build_mok_list(MokNum
, MokNew
, MokNewSize
);
428 Print(L
"Failed to construct key list in MokNew\n");
433 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
434 Print(L
"Input the key number to show the details of the key or\n"
435 L
"type \'0\' to continue\n\n");
436 Print(L
"%d key(s) in the new key list\n\n", MokNum
);
438 if (key_num
> MokNum
) {
439 Print(L
"[Key %d]\n", key_num
);
440 Print(L
"No such key\n\n");
441 } else if (initial
!= 1 && key_num
> 0){
442 Print(L
"[Key %d]\n", key_num
);
443 show_mok_info(keys
[key_num
-1].Mok
, keys
[key_num
-1].MokSize
);
446 Print(L
"Key Number: ");
448 key_num
= get_number();
456 } while (key_num
!= 0);
463 static UINT8
get_line (UINT32
*length
, CHAR16
*line
, UINT32 line_max
, UINT8 show
)
469 key
= get_keystroke();
471 if ((count
>= line_max
&&
472 key
.UnicodeChar
!= CHAR_BACKSPACE
) ||
473 key
.UnicodeChar
== CHAR_NULL
||
474 key
.UnicodeChar
== CHAR_TAB
||
475 key
.UnicodeChar
== CHAR_LINEFEED
||
476 key
.UnicodeChar
== CHAR_CARRIAGE_RETURN
) {
480 if (count
== 0 && key
.UnicodeChar
== CHAR_BACKSPACE
) {
482 } else if (key
.UnicodeChar
== CHAR_BACKSPACE
) {
486 line
[--count
] = '\0';
491 Print(L
"%c", key
.UnicodeChar
);
494 line
[count
++] = key
.UnicodeChar
;
495 } while (key
.UnicodeChar
!= CHAR_CARRIAGE_RETURN
);
503 static EFI_STATUS
compute_pw_hash (void *MokNew
, UINTN MokNewSize
, CHAR16
*password
,
504 UINT32 pw_length
, UINT8
*hash
)
507 unsigned int ctxsize
;
510 ctxsize
= Sha256GetContextSize();
511 ctx
= AllocatePool(ctxsize
);
514 Print(L
"Unable to allocate memory for hash context\n");
515 return EFI_OUT_OF_RESOURCES
;
518 if (!Sha256Init(ctx
)) {
519 Print(L
"Unable to initialise hash\n");
520 status
= EFI_OUT_OF_RESOURCES
;
524 if (MokNew
&& MokNewSize
) {
525 if (!(Sha256Update(ctx
, MokNew
, MokNewSize
))) {
526 Print(L
"Unable to generate hash\n");
527 status
= EFI_OUT_OF_RESOURCES
;
532 if (!(Sha256Update(ctx
, password
, pw_length
* sizeof(CHAR16
)))) {
533 Print(L
"Unable to generate hash\n");
534 status
= EFI_OUT_OF_RESOURCES
;
538 if (!(Sha256Final(ctx
, hash
))) {
539 Print(L
"Unable to finalise hash\n");
540 status
= EFI_OUT_OF_RESOURCES
;
544 status
= EFI_SUCCESS
;
549 static EFI_STATUS
store_keys (void *MokNew
, UINTN MokNewSize
, int authenticate
)
551 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
552 EFI_STATUS efi_status
;
553 UINT8 hash
[SHA256_DIGEST_SIZE
];
554 UINT8 auth
[SHA256_DIGEST_SIZE
];
557 CHAR16 password
[PASSWORD_MAX
];
559 UINT8 fail_count
= 0;
562 auth_size
= SHA256_DIGEST_SIZE
;
563 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokAuth",
565 &attributes
, &auth_size
, auth
);
568 if (efi_status
!= EFI_SUCCESS
|| auth_size
!= SHA256_DIGEST_SIZE
) {
569 Print(L
"Failed to get MokAuth %d\n", efi_status
);
573 while (fail_count
< 3) {
574 Print(L
"Password(%d-%d characters): ",
575 PASSWORD_MIN
, PASSWORD_MAX
);
576 get_line(&pw_length
, password
, PASSWORD_MAX
, 0);
579 Print(L
"At least %d characters for the password\n",
583 efi_status
= compute_pw_hash(MokNew
, MokNewSize
, password
,
586 if (efi_status
!= EFI_SUCCESS
) {
590 if (CompareMem(auth
, hash
, SHA256_DIGEST_SIZE
) != 0) {
591 Print(L
"Password doesn't match\n");
599 return EFI_ACCESS_DENIED
;
604 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, L
"MokList",
606 EFI_VARIABLE_NON_VOLATILE
607 | EFI_VARIABLE_BOOTSERVICE_ACCESS
608 | EFI_VARIABLE_APPEND_WRITE
,
612 efi_status
= uefi_call_wrapper(RT
->SetVariable
, 5, L
"MokList",
614 EFI_VARIABLE_NON_VOLATILE
615 | EFI_VARIABLE_BOOTSERVICE_ACCESS
616 | EFI_VARIABLE_APPEND_WRITE
,
620 if (efi_status
!= EFI_SUCCESS
) {
621 Print(L
"Failed to set variable %d\n", efi_status
);
628 static UINTN
mok_enrollment_prompt (void *MokNew
, UINTN MokNewSize
, int auth
) {
631 EFI_STATUS efi_status
;
634 if (!list_keys(MokNew
, MokNewSize
)) {
638 Print(L
"Enroll the key(s)? (y/n): ");
640 get_line (&length
, line
, 1, 1);
642 if (line
[0] == 'Y' || line
[0] == 'y') {
643 efi_status
= store_keys(MokNew
, MokNewSize
, auth
);
645 if (efi_status
!= EFI_SUCCESS
) {
646 Print(L
"Failed to enroll keys\n");
651 } while (line
[0] != 'N' && line
[0] != 'n');
655 static INTN
mok_enrollment_prompt_callback (void *MokNew
, void *data2
,
657 return mok_enrollment_prompt(MokNew
, (UINTN
)data2
, TRUE
);
660 static INTN
mok_deletion_prompt (void *MokNew
, void *data2
, void *data3
) {
663 EFI_STATUS efi_status
;
665 Print(L
"Erase all stored keys? (y/N): ");
667 get_line (&length
, line
, 1, 1);
669 if (line
[0] == 'Y' || line
[0] == 'y') {
670 efi_status
= store_keys(NULL
, 0, TRUE
);
672 if (efi_status
!= EFI_SUCCESS
) {
673 Print(L
"Failed to erase keys\n");
681 static UINTN
draw_menu (struct menu_item
*items
, UINTN count
) {
684 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
686 uefi_call_wrapper(ST
->ConOut
->SetAttribute
, 2, ST
->ConOut
,
687 EFI_WHITE
| EFI_BACKGROUND_BLACK
);
689 Print(L
"%s UEFI key management\n\n", SHIM_VENDOR
);
691 for (i
= 0; i
< count
; i
++) {
692 uefi_call_wrapper(ST
->ConOut
->SetAttribute
, 2, ST
->ConOut
,
693 items
[i
].colour
| EFI_BACKGROUND_BLACK
);
694 Print(L
" %s\n", items
[i
].text
);
697 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3, ST
->ConOut
, 0, 0);
698 uefi_call_wrapper(ST
->ConOut
->EnableCursor
, 2, ST
->ConOut
, TRUE
);
703 static void free_menu (struct menu_item
*items
, UINTN count
) {
706 for (i
=0; i
<count
; i
++) {
708 FreePool(items
[i
].text
);
714 static void run_menu (struct menu_item
*items
, UINTN count
, UINTN timeout
) {
715 UINTN index
, pos
= 0, wait
= 0, offset
;
723 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
725 offset
= draw_menu (items
, count
);
727 uefi_call_wrapper(ST
->ConOut
->SetAttribute
, 2,
729 EFI_WHITE
| EFI_BACKGROUND_BLACK
);
732 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3,
733 ST
->ConOut
, 0, count
+ 1 + offset
);
735 Print(L
"Booting in %d seconds\n", timeout
);
737 Print(L
"Booting in %d second\n", timeout
);
740 uefi_call_wrapper(ST
->ConOut
->SetCursorPosition
, 3, ST
->ConOut
,
742 status
= WaitForSingleEvent(ST
->ConIn
->WaitForKey
, wait
);
744 if (status
== EFI_TIMEOUT
) {
747 free_menu(items
, count
);
756 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1,
757 &ST
->ConIn
->WaitForKey
, &index
);
758 uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
,
761 switch(key
.ScanCode
) {
769 if (pos
== (count
- 1))
776 switch(key
.UnicodeChar
) {
778 case CHAR_CARRIAGE_RETURN
:
779 if (items
[pos
].callback
== NULL
) {
780 free_menu(items
, count
);
784 items
[pos
].callback(items
[pos
].data
, items
[pos
].data2
,
786 draw_menu (items
, count
);
793 static UINTN
verify_certificate(void *cert
, UINTN size
)
796 if (!cert
|| size
== 0)
799 if (!(X509ConstructCertificate(cert
, size
, (UINT8
**) &X509Cert
)) ||
801 Print(L
"Invalid X509 certificate\n");
810 static INTN
file_callback (void *data
, void *data2
, void *data3
) {
811 EFI_FILE_INFO
*buffer
= NULL
;
812 UINTN buffersize
= 0, mokbuffersize
;
815 CHAR16
*filename
= data
;
816 EFI_FILE
*parent
= data2
;
817 BOOLEAN hash
= !!data3
;
818 EFI_GUID file_info_guid
= EFI_FILE_INFO_ID
;
819 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
820 EFI_SIGNATURE_LIST
*CertList
;
821 EFI_SIGNATURE_DATA
*CertData
;
822 void *mokbuffer
= NULL
;
824 status
= uefi_call_wrapper(parent
->Open
, 5, parent
, &file
, filename
,
825 EFI_FILE_MODE_READ
, 0);
827 if (status
!= EFI_SUCCESS
)
830 status
= uefi_call_wrapper(file
->GetInfo
, 4, file
, &file_info_guid
,
831 &buffersize
, buffer
);
833 if (status
== EFI_BUFFER_TOO_SMALL
) {
834 buffer
= AllocatePool(buffersize
);
835 status
= uefi_call_wrapper(file
->GetInfo
, 4, file
,
836 &file_info_guid
, &buffersize
,
843 buffersize
= buffer
->FileSize
;
847 UINT8 sha256
[SHA256_DIGEST_SIZE
];
848 UINT8 sha1
[SHA1_DIGEST_SIZE
];
849 SHIM_LOCK
*shim_lock
;
850 EFI_GUID shim_guid
= SHIM_LOCK_GUID
;
851 PE_COFF_LOADER_IMAGE_CONTEXT context
;
853 status
= LibLocateProtocol(&shim_guid
, (VOID
**)&shim_lock
);
855 if (status
!= EFI_SUCCESS
)
858 mokbuffersize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_GUID
) +
861 mokbuffer
= AllocatePool(mokbuffersize
);
866 binary
= AllocatePool(buffersize
);
868 status
= uefi_call_wrapper(file
->Read
, 3, file
, &buffersize
,
871 if (status
!= EFI_SUCCESS
)
874 status
= shim_lock
->Context(binary
, buffersize
, &context
);
876 if (status
!= EFI_SUCCESS
)
879 status
= shim_lock
->Hash(binary
, buffersize
, &context
, sha256
,
882 if (status
!= EFI_SUCCESS
)
885 CertList
= mokbuffer
;
886 CertList
->SignatureType
= EfiHashSha256Guid
;
887 CertList
->SignatureSize
= 16 + SHA256_DIGEST_SIZE
;
888 CertData
= (EFI_SIGNATURE_DATA
*)(((UINT8
*)mokbuffer
) +
889 sizeof(EFI_SIGNATURE_LIST
));
890 CopyMem(CertData
->SignatureData
, sha256
, SHA256_DIGEST_SIZE
);
892 mokbuffersize
= buffersize
+ sizeof(EFI_SIGNATURE_LIST
) +
894 mokbuffer
= AllocatePool(mokbuffersize
);
899 CertList
= mokbuffer
;
900 CertList
->SignatureType
= EfiCertX509Guid
;
901 CertList
->SignatureSize
= 16 + buffersize
;
902 status
= uefi_call_wrapper(file
->Read
, 3, file
, &buffersize
,
903 mokbuffer
+ sizeof(EFI_SIGNATURE_LIST
) + 16);
905 if (status
!= EFI_SUCCESS
)
907 CertData
= (EFI_SIGNATURE_DATA
*)(((UINT8
*)mokbuffer
) +
908 sizeof(EFI_SIGNATURE_LIST
));
911 CertList
->SignatureListSize
= mokbuffersize
;
912 CertList
->SignatureHeaderSize
= 0;
913 CertData
->SignatureOwner
= shim_lock_guid
;
916 if (!verify_certificate(CertData
->SignatureData
, buffersize
))
920 mok_enrollment_prompt(mokbuffer
, mokbuffersize
, FALSE
);
931 static INTN
directory_callback (void *data
, void *data2
, void *data3
) {
932 EFI_FILE_INFO
*buffer
= NULL
;
933 UINTN buffersize
= 0;
935 UINTN dircount
= 0, i
= 0;
936 struct menu_item
*dircontent
;
938 CHAR16
*filename
= data
;
939 EFI_FILE
*root
= data2
;
941 status
= uefi_call_wrapper(root
->Open
, 5, root
, &dir
, filename
,
942 EFI_FILE_MODE_READ
, 0);
944 if (status
!= EFI_SUCCESS
)
948 status
= uefi_call_wrapper(dir
->Read
, 3, dir
, &buffersize
,
951 if (status
== EFI_BUFFER_TOO_SMALL
) {
952 buffer
= AllocatePool(buffersize
);
953 status
= uefi_call_wrapper(dir
->Read
, 3, dir
,
954 &buffersize
, buffer
);
957 if (status
!= EFI_SUCCESS
)
963 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
964 (StrCmp(buffer
->FileName
, L
"..") == 0))
975 dircontent
= AllocatePool(sizeof(struct menu_item
) * dircount
);
977 dircontent
[0].text
= StrDuplicate(L
"..");
978 dircontent
[0].callback
= NULL
;
979 dircontent
[0].colour
= EFI_YELLOW
;
982 uefi_call_wrapper(dir
->SetPosition
, 2, dir
, 0);
985 status
= uefi_call_wrapper(dir
->Read
, 3, dir
, &buffersize
,
988 if (status
== EFI_BUFFER_TOO_SMALL
) {
989 buffer
= AllocatePool(buffersize
);
990 status
= uefi_call_wrapper(dir
->Read
, 3, dir
,
991 &buffersize
, buffer
);
994 if (status
!= EFI_SUCCESS
)
1000 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
1001 (StrCmp(buffer
->FileName
, L
"..") == 0))
1004 if (buffer
->Attribute
& EFI_FILE_DIRECTORY
) {
1005 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
1006 dircontent
[i
].callback
= directory_callback
;
1007 dircontent
[i
].data
= dircontent
[i
].text
;
1008 dircontent
[i
].data2
= dir
;
1009 dircontent
[i
].data3
= data3
;
1010 dircontent
[i
].colour
= EFI_YELLOW
;
1012 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
1013 dircontent
[i
].callback
= file_callback
;
1014 dircontent
[i
].data
= dircontent
[i
].text
;
1015 dircontent
[i
].data2
= dir
;
1016 dircontent
[i
].data3
= data3
;
1017 dircontent
[i
].colour
= EFI_WHITE
;
1026 run_menu(dircontent
, dircount
, 0);
1031 static INTN
filesystem_callback (void *data
, void *data2
, void *data3
) {
1032 EFI_FILE_INFO
*buffer
= NULL
;
1033 UINTN buffersize
= 0;
1035 UINTN dircount
= 0, i
= 0;
1036 struct menu_item
*dircontent
;
1037 EFI_FILE
*root
= data
;
1039 uefi_call_wrapper(root
->SetPosition
, 2, root
, 0);
1042 status
= uefi_call_wrapper(root
->Read
, 3, root
, &buffersize
,
1045 if (status
== EFI_BUFFER_TOO_SMALL
) {
1046 buffer
= AllocatePool(buffersize
);
1047 status
= uefi_call_wrapper(root
->Read
, 3, root
,
1048 &buffersize
, buffer
);
1051 if (status
!= EFI_SUCCESS
)
1057 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
1058 (StrCmp(buffer
->FileName
, L
"..") == 0))
1069 dircontent
= AllocatePool(sizeof(struct menu_item
) * dircount
);
1071 dircontent
[0].text
= StrDuplicate(L
"Return to filesystem list");
1072 dircontent
[0].callback
= NULL
;
1073 dircontent
[0].colour
= EFI_YELLOW
;
1076 uefi_call_wrapper(root
->SetPosition
, 2, root
, 0);
1079 status
= uefi_call_wrapper(root
->Read
, 3, root
, &buffersize
,
1082 if (status
== EFI_BUFFER_TOO_SMALL
) {
1083 buffer
= AllocatePool(buffersize
);
1084 status
= uefi_call_wrapper(root
->Read
, 3, root
,
1085 &buffersize
, buffer
);
1088 if (status
!= EFI_SUCCESS
)
1094 if ((StrCmp(buffer
->FileName
, L
".") == 0) ||
1095 (StrCmp(buffer
->FileName
, L
"..") == 0))
1098 if (buffer
->Attribute
& EFI_FILE_DIRECTORY
) {
1099 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
1100 dircontent
[i
].callback
= directory_callback
;
1101 dircontent
[i
].data
= dircontent
[i
].text
;
1102 dircontent
[i
].data2
= root
;
1103 dircontent
[i
].data3
= data3
;
1104 dircontent
[i
].colour
= EFI_YELLOW
;
1106 dircontent
[i
].text
= StrDuplicate(buffer
->FileName
);
1107 dircontent
[i
].callback
= file_callback
;
1108 dircontent
[i
].data
= dircontent
[i
].text
;
1109 dircontent
[i
].data2
= root
;
1110 dircontent
[i
].data3
= data3
;
1111 dircontent
[i
].colour
= EFI_WHITE
;
1120 run_menu(dircontent
, dircount
, 0);
1125 static INTN
find_fs (void *data
, void *data2
, void *data3
) {
1126 EFI_GUID fs_guid
= SIMPLE_FILE_SYSTEM_PROTOCOL
;
1128 UINTN OldSize
, NewSize
;
1129 EFI_HANDLE
**filesystem_handles
;
1130 struct menu_item
*filesystems
;
1132 uefi_call_wrapper(BS
->LocateHandleBuffer
, 5, ByProtocol
, &fs_guid
,
1133 NULL
, &count
, &filesystem_handles
);
1135 if (!count
|| !filesystem_handles
) {
1136 Print(L
"No filesystems?\n");
1142 filesystems
= AllocatePool(sizeof(struct menu_item
) * count
);
1144 filesystems
[0].text
= StrDuplicate(L
"Exit");
1145 filesystems
[0].callback
= NULL
;
1146 filesystems
[0].colour
= EFI_YELLOW
;
1148 for (i
=1; i
<count
; i
++) {
1149 EFI_HANDLE
*fs
= filesystem_handles
[i
-1];
1150 EFI_FILE_IO_INTERFACE
*fs_interface
;
1151 EFI_DEVICE_PATH
*path
;
1154 CHAR16
*VolumeLabel
= NULL
;
1155 EFI_FILE_SYSTEM_INFO
*buffer
= NULL
;
1156 UINTN buffersize
= 0;
1157 EFI_GUID file_info_guid
= EFI_FILE_INFO_ID
;
1159 status
= uefi_call_wrapper(BS
->HandleProtocol
, 3, fs
, &fs_guid
,
1162 if (status
!= EFI_SUCCESS
|| !fs_interface
)
1165 path
= DevicePathFromHandle(fs
);
1167 status
= uefi_call_wrapper(fs_interface
->OpenVolume
, 2,
1168 fs_interface
, &root
);
1170 if (status
!= EFI_SUCCESS
|| !root
)
1173 status
= uefi_call_wrapper(root
->GetInfo
, 4, root
,
1174 &file_info_guid
, &buffersize
,
1177 if (status
== EFI_BUFFER_TOO_SMALL
) {
1178 buffer
= AllocatePool(buffersize
);
1179 status
= uefi_call_wrapper(root
->GetInfo
, 4, root
,
1181 &buffersize
, buffer
);
1184 if (status
== EFI_SUCCESS
)
1185 VolumeLabel
= buffer
->VolumeLabel
;
1188 filesystems
[i
].text
= DevicePathToStr(path
);
1190 filesystems
[i
].text
= StrDuplicate(L
"Unknown device\n");
1192 OldSize
= (StrLen(filesystems
[i
].text
) + 1) * sizeof(CHAR16
);
1193 NewSize
= OldSize
+ StrLen(VolumeLabel
) * sizeof(CHAR16
);
1194 filesystems
[i
].text
= ReallocatePool(filesystems
[i
].text
,
1196 StrCat(filesystems
[i
].text
, VolumeLabel
);
1202 filesystems
[i
].data
= root
;
1203 filesystems
[i
].data2
= NULL
;
1204 filesystems
[i
].data3
= data3
;
1205 filesystems
[i
].callback
= filesystem_callback
;
1206 filesystems
[i
].colour
= EFI_YELLOW
;
1209 uefi_call_wrapper(BS
->FreePool
, 1, filesystem_handles
);
1211 run_menu(filesystems
, count
, 0);
1216 static EFI_STATUS
enter_mok_menu(EFI_HANDLE image_handle
, void *MokNew
,
1219 struct menu_item
*menu_item
;
1221 UINTN menucount
= 0;
1222 EFI_STATUS efi_status
;
1223 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
1224 UINT8 auth
[SHA256_DIGEST_SIZE
];
1225 UINTN auth_size
= SHA256_DIGEST_SIZE
;
1228 efi_status
= uefi_call_wrapper(RT
->GetVariable
, 5, L
"MokAuth",
1230 &attributes
, &auth_size
, auth
);
1232 if ((efi_status
== EFI_SUCCESS
) && (auth_size
== SHA256_DIGEST_SIZE
))
1235 if (MokNew
|| MokAuth
)
1236 menu_item
= AllocateZeroPool(sizeof(struct menu_item
) * 4);
1238 menu_item
= AllocateZeroPool(sizeof(struct menu_item
) * 3);
1241 return EFI_OUT_OF_RESOURCES
;
1243 menu_item
[0].text
= StrDuplicate(L
"Continue boot");
1244 menu_item
[0].colour
= EFI_WHITE
;
1245 menu_item
[0].callback
= NULL
;
1249 if (MokNew
|| MokAuth
) {
1251 menu_item
[1].text
= StrDuplicate(L
"Delete MOK");
1252 menu_item
[1].colour
= EFI_WHITE
;
1253 menu_item
[1].callback
= mok_deletion_prompt
;
1255 menu_item
[1].text
= StrDuplicate(L
"Enroll MOK");
1256 menu_item
[1].colour
= EFI_WHITE
;
1257 menu_item
[1].data
= MokNew
;
1258 menu_item
[1].data2
= (void *)MokNewSize
;
1259 menu_item
[1].callback
= mok_enrollment_prompt_callback
;
1264 menu_item
[menucount
].text
= StrDuplicate(L
"Enroll key from disk");
1265 menu_item
[menucount
].colour
= EFI_WHITE
;
1266 menu_item
[menucount
].callback
= find_fs
;
1267 menu_item
[menucount
].data3
= (void *)FALSE
;
1271 menu_item
[menucount
].text
= StrDuplicate(L
"Enroll hash from disk");
1272 menu_item
[menucount
].colour
= EFI_WHITE
;
1273 menu_item
[menucount
].callback
= find_fs
;
1274 menu_item
[menucount
].data3
= (void *)TRUE
;
1278 run_menu(menu_item
, menucount
, 10);
1280 uefi_call_wrapper(ST
->ConOut
->ClearScreen
, 1, ST
->ConOut
);
1285 static EFI_STATUS
check_mok_request(EFI_HANDLE image_handle
)
1287 EFI_GUID shim_lock_guid
= SHIM_LOCK_GUID
;
1288 UINTN MokNewSize
= 0;
1289 void *MokNew
= NULL
;
1291 MokNew
= LibGetVariableAndSize(L
"MokNew", &shim_lock_guid
, &MokNewSize
);
1293 enter_mok_menu(image_handle
, MokNew
, MokNewSize
);
1296 if (LibDeleteVariable(L
"MokNew", &shim_lock_guid
) != EFI_SUCCESS
) {
1297 Print(L
"Failed to delete MokNew\n");
1301 LibDeleteVariable(L
"MokAuth", &shim_lock_guid
);
1306 EFI_STATUS
efi_main (EFI_HANDLE image_handle
, EFI_SYSTEM_TABLE
*systab
)
1308 EFI_STATUS efi_status
;
1310 InitializeLib(image_handle
, systab
);
1312 efi_status
= check_mok_request(image_handle
);