726e61c3b1f1dd7722e560e53b58cf08cd0f6793
[mirror_edk2.git] / SecurityPkg / UserIdentification / UsbCredentialProviderDxe / UsbCredentialProvider.c
1 /** @file
2 Usb Credential Provider driver implemenetation.
3
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "UsbCredentialProvider.h"
16
17 CREDENTIAL_TABLE *mUsbTable = NULL;
18 USB_PROVIDER_CALLBACK_INFO *mCallbackInfo = NULL;
19 USB_CREDENTIAL_INFO *mUsbInfoHandle = NULL;
20
21 EFI_USER_CREDENTIAL_PROTOCOL gUsbCredentialProviderDriver = {
22 USB_CREDENTIAL_PROVIDER_GUID,
23 EFI_USER_CREDENTIAL_CLASS_SECURE_CARD,
24 CredentialEnroll,
25 CredentialForm,
26 CredentialTile,
27 CredentialTitle,
28 CredentialUser,
29 CredentialSelect,
30 CredentialDeselect,
31 CredentialDefault,
32 CredentialGetInfo,
33 CredentialGetNextInfo
34 };
35
36
37 /**
38 Get string by string id from HII Interface.
39
40
41 @param[in] Id String ID to get the string from.
42
43 @retval CHAR16 * String from ID.
44 @retval NULL If error occurs.
45
46 **/
47 CHAR16 *
48 GetStringById (
49 IN EFI_STRING_ID Id
50 )
51 {
52 //
53 // Get the current string for the current Language
54 //
55 return HiiGetString (mCallbackInfo->HiiHandle, Id, NULL);
56 }
57
58
59 /**
60 Expand password table size.
61
62 **/
63 VOID
64 ExpandTableSize (
65 VOID
66 )
67 {
68 CREDENTIAL_TABLE *NewTable;
69 UINTN Count;
70
71 Count = mUsbTable->MaxCount + USB_TABLE_INC;
72 //
73 // Create new credential table.
74 //
75 NewTable = AllocateZeroPool (
76 sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) +
77 Count * sizeof (USB_INFO)
78 );
79 ASSERT (NewTable != NULL);
80
81 NewTable->MaxCount = Count;
82 NewTable->Count = mUsbTable->Count;
83
84 //
85 // Copy old entries.
86 //
87 CopyMem (
88 &NewTable->UserInfo,
89 &mUsbTable->UserInfo,
90 mUsbTable->Count * sizeof (USB_INFO)
91 );
92 FreePool (mUsbTable);
93 mUsbTable = NewTable;
94 }
95
96
97 /**
98 Add or delete info in table, and sync with NV variable.
99
100 @param[in] Index The index of the password in table. The index begin from 1.
101 If index is found in table, delete the info, else add the
102 into to table.
103 @param[in] Info The new password info to add into table.
104
105 @retval EFI_INVALID_PARAMETER Info is NULL when save the info.
106 @retval EFI_SUCCESS Modify the table successfully.
107 @retval Others Failed to modify the table.
108
109 **/
110 EFI_STATUS
111 ModifyTable (
112 IN UINTN Index,
113 IN USB_INFO * Info OPTIONAL
114 )
115 {
116 EFI_STATUS Status;
117
118 if (Index < mUsbTable->Count) {
119 //
120 // Delete the specified entry
121 //
122 mUsbTable->Count--;
123 if (Index != mUsbTable->Count) {
124 CopyMem (
125 &mUsbTable->UserInfo[Index],
126 &mUsbTable->UserInfo[mUsbTable->Count],
127 sizeof (USB_INFO)
128 );
129 }
130 } else {
131 //
132 // Add a new entry
133 //
134 if (Info == NULL) {
135 return EFI_INVALID_PARAMETER;
136 }
137
138 if (mUsbTable->Count >= mUsbTable->MaxCount) {
139 ExpandTableSize ();
140 }
141
142 CopyMem (
143 &mUsbTable->UserInfo[mUsbTable->Count],
144 Info,
145 sizeof (USB_INFO)
146 );
147 mUsbTable->Count++;
148 }
149
150 //
151 // Save the credential table.
152 //
153 Status = gRT->SetVariable (
154 L"UsbCredential",
155 &gUsbCredentialProviderGuid,
156 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
157 mUsbTable->Count * sizeof (USB_INFO),
158 &mUsbTable->UserInfo
159 );
160 return Status;
161 }
162
163
164 /**
165 Create a credential table
166
167 @retval EFI_SUCCESS Create a credential table successfully.
168 @retval Others Failed to create a password.
169
170 **/
171 EFI_STATUS
172 InitCredentialTable (
173 VOID
174 )
175 {
176 EFI_STATUS Status;
177 UINT8 *Var;
178 UINTN VarSize;
179
180 //
181 // Get Usb credential data from NV variable.
182 //
183 VarSize = 0;
184 Var = NULL;
185 Status = gRT->GetVariable (
186 L"UsbCredential",
187 &gUsbCredentialProviderGuid,
188 NULL,
189 &VarSize,
190 Var
191 );
192 if (Status == EFI_BUFFER_TOO_SMALL) {
193 Var = AllocateZeroPool (VarSize);
194 if (Var == NULL) {
195 return EFI_OUT_OF_RESOURCES;
196 }
197 Status = gRT->GetVariable (
198 L"UsbCredential",
199 &gUsbCredentialProviderGuid,
200 NULL,
201 &VarSize,
202 Var
203 );
204 }
205 if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
206 return Status;
207 }
208
209 //
210 // Init Usb credential table.
211 //
212 mUsbTable = AllocateZeroPool (
213 sizeof (CREDENTIAL_TABLE) - sizeof (USB_INFO) +
214 USB_TABLE_INC * sizeof (USB_INFO) +
215 VarSize
216 );
217 if (mUsbTable == NULL) {
218 FreePool (Var);
219 return EFI_OUT_OF_RESOURCES;
220 }
221
222 mUsbTable->Count = VarSize / sizeof (USB_INFO);
223 mUsbTable->MaxCount = mUsbTable->Count + USB_TABLE_INC;
224 if (Var != NULL) {
225 CopyMem (mUsbTable->UserInfo, Var, VarSize);
226 FreePool (Var);
227 }
228 return EFI_SUCCESS;
229 }
230
231
232 /**
233 Read the specified file by FileName in the Usb key and return the file size in BufferSize
234 and file content in Buffer.
235 Note: the caller is responsible to free the buffer memory.
236
237 @param FileName File to read.
238 @param Buffer Returned with data read from the file.
239 @param BufferSize Size of the data buffer.
240
241 @retval EFI_SUCCESS The command completed successfully.
242 @retval EFI_OUT_OF_RESOURCES Resource allocation failed.
243 @retval EFI_NOT_FOUND File not found.
244 @retval EFI_DEVICE_ERROR Device I/O error.
245
246 **/
247 EFI_STATUS
248 GetFileData (
249 IN CHAR16 *FileName,
250 OUT VOID **Buffer,
251 OUT UINTN *BufferSize
252 )
253 {
254 EFI_STATUS Status;
255 UINTN Index;
256 UINTN HandleCount;
257 UINTN ScratchBufferSize;
258 EFI_HANDLE *HandleBuffer;
259 EFI_FILE *RootFs;
260 EFI_FILE *FileHandle;
261 EFI_FILE_INFO *FileInfo;
262 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
263 EFI_BLOCK_IO_PROTOCOL *BlkIo;
264
265 FileInfo = NULL;
266 FileHandle = NULL;
267
268 Status = gBS->LocateHandleBuffer (
269 ByProtocol,
270 &gEfiSimpleFileSystemProtocolGuid,
271 NULL,
272 &HandleCount,
273 &HandleBuffer
274 );
275 if (EFI_ERROR (Status)) {
276 DEBUG ((DEBUG_ERROR, "Can not Locate SimpleFileSystemProtocol\n"));
277 goto Done;
278 }
279
280 //
281 // Find and open the file in removable media disk.
282 //
283 for (Index = 0; Index < HandleCount; Index++) {
284 Status = gBS->HandleProtocol (
285 HandleBuffer[Index],
286 &gEfiBlockIoProtocolGuid,
287 (VOID **) &BlkIo
288 );
289 if (EFI_ERROR (Status)) {
290 continue;
291 }
292
293 if (BlkIo->Media->RemovableMedia) {
294 Status = gBS->HandleProtocol (
295 HandleBuffer[Index],
296 &gEfiSimpleFileSystemProtocolGuid,
297 (VOID **) &SimpleFileSystem
298 );
299 if (EFI_ERROR (Status)) {
300 continue;
301 }
302
303 Status = SimpleFileSystem->OpenVolume (
304 SimpleFileSystem,
305 &RootFs
306 );
307 if (EFI_ERROR (Status)) {
308 continue;
309 }
310
311 Status = RootFs->Open (
312 RootFs,
313 &FileHandle,
314 FileName,
315 EFI_FILE_MODE_READ,
316 0
317 );
318 if (!EFI_ERROR (Status)) {
319 break;
320 }
321 }
322 }
323
324 FreePool (HandleBuffer);
325
326 if (Index >= HandleCount) {
327 DEBUG ((DEBUG_ERROR, "Can not found the token file!\n"));
328 Status = EFI_NOT_FOUND;
329 goto Done;
330 }
331
332 //
333 // Figure out how big the file is.
334 //
335 ScratchBufferSize = 0;
336 Status = FileHandle->GetInfo (
337 FileHandle,
338 &gEfiFileInfoGuid,
339 &ScratchBufferSize,
340 NULL
341 );
342 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
343 DEBUG ((DEBUG_ERROR, "Can not obtain file size info!\n"));
344 Status = EFI_DEVICE_ERROR;
345 goto Done;
346 }
347
348 FileInfo = AllocateZeroPool (ScratchBufferSize);
349 if (FileInfo == NULL) {
350 DEBUG ((DEBUG_ERROR, "Can not allocate enough memory for the token file!\n"));
351 Status = EFI_OUT_OF_RESOURCES;
352 goto Done;
353 }
354
355 Status = FileHandle->GetInfo (
356 FileHandle,
357 &gEfiFileInfoGuid,
358 &ScratchBufferSize,
359 FileInfo
360 );
361 if (EFI_ERROR (Status)) {
362 DEBUG ((DEBUG_ERROR, "Can not obtain file info from the token file!\n"));
363 Status = EFI_DEVICE_ERROR;
364 goto Done;
365 }
366
367 //
368 // Allocate a buffer for the file.
369 //
370 *BufferSize = (UINT32) FileInfo->FileSize;
371 *Buffer = AllocateZeroPool (*BufferSize);
372 if (*Buffer == NULL) {
373 DEBUG ((DEBUG_ERROR, "Can not allocate a buffer for the file!\n"));
374 Status = EFI_OUT_OF_RESOURCES;
375 goto Done;
376 }
377
378 //
379 // Load file into the allocated memory.
380 //
381 Status = FileHandle->Read (FileHandle, BufferSize, *Buffer);
382 if (EFI_ERROR (Status)) {
383 FreePool (*Buffer);
384 DEBUG ((DEBUG_ERROR, "Can not read the token file!\n"));
385 Status = EFI_DEVICE_ERROR;
386 goto Done;
387 }
388
389 //
390 // Close file.
391 //
392 Status = FileHandle->Close (FileHandle);
393 if (EFI_ERROR (Status)) {
394 FreePool (*Buffer);
395 DEBUG ((DEBUG_ERROR, "Can not close the token file !\n"));
396 Status = EFI_DEVICE_ERROR;
397 }
398
399 Done:
400
401 if (FileInfo != NULL) {
402 FreePool (FileInfo);
403 }
404
405 return Status;
406 }
407
408
409 /**
410 Hash the data to get credential.
411
412 @param[in] Buffer Points to the data buffer
413 @param[in] BufferSize The size of data in buffer, in bytes.
414 @param[out] Credential Points to the hashed result
415
416 @retval TRUE Hash the data successfully.
417 @retval FALSE Failed to hash the data.
418
419 **/
420 BOOLEAN
421 GenerateCredential (
422 IN UINT8 *Buffer,
423 IN UINTN BufferSize,
424 OUT UINT8 *Credential
425 )
426 {
427 BOOLEAN Status;
428 UINTN HashSize;
429 VOID *Hash;
430
431 HashSize = Sha1GetContextSize ();
432 Hash = AllocatePool (HashSize);
433 ASSERT (Hash != NULL);
434
435 Status = Sha1Init (Hash);
436 if (!Status) {
437 goto Done;
438 }
439
440 Status = Sha1Update (Hash, Buffer, BufferSize);
441 if (!Status) {
442 goto Done;
443 }
444
445 Status = Sha1Final (Hash, Credential);
446
447 Done:
448 FreePool (Hash);
449 return Status;
450 }
451
452
453 /**
454 Read the token file, and default the Token is saved at the begining of the file.
455
456 @param[out] Token Token read from a Token file.
457
458 @retval EFI_SUCCESS Read a Token successfully.
459 @retval Others Fails to read a Token.
460
461 **/
462 EFI_STATUS
463 GetToken (
464 OUT UINT8 *Token
465 )
466 {
467 EFI_STATUS Status;
468 UINT8 *Buffer;
469 UINTN BufSize;
470 CHAR16 *TokenFile;
471
472 BufSize = 0;
473 Buffer = NULL;
474 TokenFile = FixedPcdGetPtr (PcdFixedUsbCredentialProviderTokenFileName);
475 Status = GetFileData (TokenFile, (VOID *)&Buffer, &BufSize);
476 if (EFI_ERROR (Status)) {
477 DEBUG ((DEBUG_ERROR, "Read file %s from USB error! Status=(%r)\n", TokenFile, Status));
478 return Status;
479 }
480
481 if (!GenerateCredential (Buffer, BufSize, Token)) {
482 DEBUG ((DEBUG_ERROR, "Generate credential from read data failed!\n"));
483 FreePool (Buffer);
484 return EFI_SECURITY_VIOLATION;
485 }
486
487 FreePool (Buffer);
488 return EFI_SUCCESS;
489 }
490
491
492 /**
493 Find a user infomation record by the information record type.
494
495 This function searches all user information records of User from beginning
496 until either the information is found or there are no more user infomation
497 record. A match occurs when a Info.InfoType field matches the user information
498 record type.
499
500 @param[in] User Points to the user profile record to search.
501 @param[in] InfoType The infomation type to be searched.
502 @param[out] Info Points to the user info found, the caller is responsible
503 to free.
504
505 @retval EFI_SUCCESS Find the user information successfully.
506 @retval Others Fail to find the user information.
507
508 **/
509 EFI_STATUS
510 FindUserInfoByType (
511 IN EFI_USER_PROFILE_HANDLE User,
512 IN UINT8 InfoType,
513 OUT EFI_USER_INFO **Info
514 )
515 {
516 EFI_STATUS Status;
517 EFI_USER_INFO *UserInfo;
518 UINTN UserInfoSize;
519 EFI_USER_INFO_HANDLE UserInfoHandle;
520 EFI_USER_MANAGER_PROTOCOL *UserManager;
521
522 //
523 // Find user information by information type.
524 //
525 if (Info == NULL) {
526 return EFI_INVALID_PARAMETER;
527 }
528
529 Status = gBS->LocateProtocol (
530 &gEfiUserManagerProtocolGuid,
531 NULL,
532 (VOID **) &UserManager
533 );
534 if (EFI_ERROR (Status)) {
535 return EFI_NOT_FOUND;
536 }
537
538 //
539 // Get each user information.
540 //
541
542 UserInfoHandle = NULL;
543 UserInfo = NULL;
544 UserInfoSize = 0;
545 while (TRUE) {
546 Status = UserManager->GetNextInfo (UserManager, User, &UserInfoHandle);
547 if (EFI_ERROR (Status)) {
548 break;
549 }
550 //
551 // Get information.
552 //
553 Status = UserManager->GetInfo (
554 UserManager,
555 User,
556 UserInfoHandle,
557 UserInfo,
558 &UserInfoSize
559 );
560 if (Status == EFI_BUFFER_TOO_SMALL) {
561 if (UserInfo != NULL) {
562 FreePool (UserInfo);
563 }
564 UserInfo = AllocateZeroPool (UserInfoSize);
565 if (UserInfo == NULL) {
566 return EFI_OUT_OF_RESOURCES;
567 }
568 Status = UserManager->GetInfo (
569 UserManager,
570 User,
571 UserInfoHandle,
572 UserInfo,
573 &UserInfoSize
574 );
575 }
576 if (EFI_ERROR (Status)) {
577 break;
578 }
579
580 ASSERT (UserInfo != NULL);
581 if (UserInfo->InfoType == InfoType) {
582 *Info = UserInfo;
583 return EFI_SUCCESS;
584 }
585 }
586
587 if (UserInfo != NULL) {
588 FreePool (UserInfo);
589 }
590 return Status;
591 }
592
593
594 /**
595 This function initialize the data mainly used in form browser.
596
597 @retval EFI_SUCCESS Initialize form data successfully.
598 @retval Others Fail to Initialize form data.
599
600 **/
601 EFI_STATUS
602 InitFormBrowser (
603 VOID
604 )
605 {
606 USB_PROVIDER_CALLBACK_INFO *CallbackInfo;
607
608 //
609 // Initialize driver private data.
610 //
611 CallbackInfo = AllocateZeroPool (sizeof (USB_PROVIDER_CALLBACK_INFO));
612 if (CallbackInfo == NULL) {
613 return EFI_OUT_OF_RESOURCES;
614 }
615
616 CallbackInfo->DriverHandle = NULL;
617
618 //
619 // Publish HII data.
620 //
621 CallbackInfo->HiiHandle = HiiAddPackages (
622 &gUsbCredentialProviderGuid,
623 CallbackInfo->DriverHandle,
624 UsbCredentialProviderStrings,
625 NULL
626 );
627 if (CallbackInfo->HiiHandle == NULL) {
628 return EFI_OUT_OF_RESOURCES;
629 }
630 mCallbackInfo = CallbackInfo;
631
632 return EFI_SUCCESS;
633 }
634
635
636 /**
637 Enroll a user on a credential provider.
638
639 This function enrolls and deletes a user profile using this credential provider.
640 If a user profile is successfully enrolled, it calls the User Manager Protocol
641 function Notify() to notify the user manager driver that credential information
642 has changed. If an enrolled user does exist, delete the user on the credential
643 provider.
644
645 @param[in] This Points to this instance of EFI_USER_CREDENTIAL_PROTOCOL.
646 @param[in] User The user profile to enroll.
647
648 @retval EFI_SUCCESS User profile was successfully enrolled.
649 @retval EFI_ACCESS_DENIED Current user profile does not permit enrollment on the
650 user profile handle. Either the user profile cannot enroll
651 on any user profile or cannot enroll on a user profile
652 other than the current user profile.
653 @retval EFI_UNSUPPORTED This credential provider does not support enrollment in
654 the pre-OS.
655 @retval EFI_DEVICE_ERROR The new credential could not be created because of a device
656 error.
657 @retval EFI_INVALID_PARAMETER User does not refer to a valid user profile handle.
658
659 **/
660 EFI_STATUS
661 EFIAPI
662 CredentialEnroll (
663 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
664 IN EFI_USER_PROFILE_HANDLE User
665 )
666 {
667 EFI_STATUS Status;
668 UINTN Index;
669 USB_INFO UsbInfo;
670 EFI_USER_INFO *UserInfo;
671 EFI_INPUT_KEY Key;
672 EFI_USER_MANAGER_PROTOCOL *UserManager;
673 UINT8 *UserId;
674 UINT8 *NewUserId;
675 EFI_TPL OldTpl;
676 CHAR16 *QuestionStr;
677 CHAR16 *PromptStr;
678
679 if ((This == NULL) || (User == NULL)) {
680 return EFI_INVALID_PARAMETER;
681 }
682
683 Status = gBS->LocateProtocol (
684 &gEfiUserManagerProtocolGuid,
685 NULL,
686 (VOID **) &UserManager
687 );
688 if (EFI_ERROR (Status)) {
689 return EFI_UNSUPPORTED;
690 }
691
692 //
693 // Get User Identifier
694 //
695 UserInfo = NULL;
696 Status = FindUserInfoByType (
697 User,
698 EFI_USER_INFO_IDENTIFIER_RECORD,
699 &UserInfo
700 );
701 if (EFI_ERROR (Status)) {
702 return EFI_INVALID_PARAMETER;
703 }
704
705 //
706 // If User exists in mUsbTable, delete User.
707 //
708 for (Index = 0; Index < mUsbTable->Count; Index++) {
709 UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
710 NewUserId = (UINT8 *) (UserInfo + 1);
711 if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
712 //
713 // Delete the exist Token.
714 //
715 FreePool (UserInfo);
716 return ModifyTable (Index, NULL);
717 }
718 }
719
720 //
721 // Get Token and User ID to UsbInfo.
722 //
723 Status = GetToken (UsbInfo.Token);
724 if (EFI_ERROR (Status)) {
725 QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR));
726 PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN));
727 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
728 gBS->RestoreTPL (TPL_APPLICATION);
729 CreatePopUp (
730 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
731 &Key,
732 QuestionStr,
733 L"",
734 PromptStr,
735 NULL
736 );
737 gBS->RaiseTPL (OldTpl);
738 FreePool (QuestionStr);
739 FreePool (PromptStr);
740 FreePool (UserInfo);
741 return Status;
742 }
743 CopyMem (
744 UsbInfo.UserId,
745 (UINT8 *) (UserInfo + 1),
746 sizeof (EFI_USER_INFO_IDENTIFIER)
747 );
748 FreePool (UserInfo);
749
750 //
751 // Save the new added entry.
752 //
753 Status = ModifyTable (mUsbTable->Count, &UsbInfo);
754 if (EFI_ERROR (Status)) {
755 return Status;
756 }
757
758 //
759 // Notify the user manager driver that credential information has changed.
760 //
761 UserManager->Notify (UserManager, mCallbackInfo->DriverHandle);
762
763 return EFI_SUCCESS;
764 }
765
766
767 /**
768 Returns the user interface information used during user identification.
769
770 This function returns information about the form used when interacting with the
771 user during user identification. The form is the first enabled form in the form-set
772 class EFI_HII_USER_CREDENTIAL_FORMSET_GUID installed on the HII handle HiiHandle. If
773 the user credential provider does not require a form to identify the user, then this
774 function should return EFI_NOT_FOUND.
775
776 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
777 @param[out] Hii On return, holds the HII database handle.
778 @param[out] FormSetId On return, holds the identifier of the form set which contains
779 the form used during user identification.
780 @param[out] FormId On return, holds the identifier of the form used during user
781 identification.
782
783 @retval EFI_SUCCESS Form returned successfully.
784 @retval EFI_NOT_FOUND Form not returned.
785 @retval EFI_INVALID_PARAMETER Hii is NULL or FormSetId is NULL or FormId is NULL.
786
787 **/
788 EFI_STATUS
789 EFIAPI
790 CredentialForm (
791 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
792 OUT EFI_HII_HANDLE *Hii,
793 OUT EFI_GUID *FormSetId,
794 OUT EFI_FORM_ID *FormId
795 )
796 {
797 if ((This == NULL) || (Hii == NULL) ||
798 (FormSetId == NULL) || (FormId == NULL)) {
799 return EFI_INVALID_PARAMETER;
800 }
801 return EFI_NOT_FOUND;
802 }
803
804
805 /**
806 Returns bitmap used to describe the credential provider type.
807
808 This optional function returns a bitmap which is less than or equal to the number
809 of pixels specified by Width and Height. If no such bitmap exists, then EFI_NOT_FOUND
810 is returned.
811
812 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
813 @param[in, out] Width On entry, points to the desired bitmap width. If NULL then no
814 bitmap information will be returned. On exit, points to the
815 width of the bitmap returned.
816 @param[in, out] Height On entry, points to the desired bitmap height. If NULL then no
817 bitmap information will be returned. On exit, points to the
818 height of the bitmap returned.
819 @param[out] Hii On return, holds the HII database handle.
820 @param[out] Image On return, holds the HII image identifier.
821
822 @retval EFI_SUCCESS Image identifier returned successfully.
823 @retval EFI_NOT_FOUND Image identifier not returned.
824 @retval EFI_INVALID_PARAMETER Hii is NULL or Image is NULL.
825
826 **/
827 EFI_STATUS
828 EFIAPI
829 CredentialTile (
830 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
831 IN OUT UINTN *Width,
832 IN OUT UINTN *Height,
833 OUT EFI_HII_HANDLE *Hii,
834 OUT EFI_IMAGE_ID *Image
835 )
836 {
837 if ((This == NULL) || (Hii == NULL) || (Image == NULL)) {
838 return EFI_INVALID_PARAMETER;
839 }
840 return EFI_NOT_FOUND;
841 }
842
843
844 /**
845 Returns string used to describe the credential provider type.
846
847 This function returns a string which describes the credential provider. If no
848 such string exists, then EFI_NOT_FOUND is returned.
849
850 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
851 @param[out] Hii On return, holds the HII database handle.
852 @param[out] String On return, holds the HII string identifier.
853
854 @retval EFI_SUCCESS String identifier returned successfully.
855 @retval EFI_NOT_FOUND String identifier not returned.
856 @retval EFI_INVALID_PARAMETER Hii is NULL or String is NULL.
857
858 **/
859 EFI_STATUS
860 EFIAPI
861 CredentialTitle (
862 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
863 OUT EFI_HII_HANDLE *Hii,
864 OUT EFI_STRING_ID *String
865 )
866 {
867 if ((This == NULL) || (Hii == NULL) || (String == NULL)) {
868 return EFI_INVALID_PARAMETER;
869 }
870 //
871 // Set Hii handle and String ID.
872 //
873 *Hii = mCallbackInfo->HiiHandle;
874 *String = STRING_TOKEN (STR_CREDENTIAL_TITLE);
875
876 return EFI_SUCCESS;
877 }
878
879
880 /**
881 Return the user identifier associated with the currently authenticated user.
882
883 This function returns the user identifier of the user authenticated by this credential
884 provider. This function is called after the credential-related information has been
885 submitted on a form OR after a call to Default() has returned that this credential is
886 ready to log on.
887
888 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
889 @param[in] User The user profile handle of the user profile currently being
890 considered by the user identity manager. If NULL, then no user
891 profile is currently under consideration.
892 @param[out] Identifier On return, points to the user identifier.
893
894 @retval EFI_SUCCESS User identifier returned successfully.
895 @retval EFI_NOT_READY No user identifier can be returned.
896 @retval EFI_ACCESS_DENIED The user has been locked out of this user credential.
897 @retval EFI_INVALID_PARAMETER This is NULL, or Identifier is NULL.
898 @retval EFI_NOT_FOUND User is not NULL, and the specified user handle can't be
899 found in user profile database.
900
901 **/
902 EFI_STATUS
903 EFIAPI
904 CredentialUser (
905 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
906 IN EFI_USER_PROFILE_HANDLE User,
907 OUT EFI_USER_INFO_IDENTIFIER *Identifier
908 )
909 {
910 EFI_STATUS Status;
911 UINTN Index;
912 EFI_USER_INFO *UserInfo;
913 UINT8 *UserId;
914 UINT8 *NewUserId;
915 UINT8 *UserToken;
916 UINT8 ReadToken[HASHED_CREDENTIAL_LEN];
917 EFI_INPUT_KEY Key;
918 EFI_TPL OldTpl;
919 CHAR16 *QuestionStr;
920 CHAR16 *PromptStr;
921
922 if ((This == NULL) || (Identifier == NULL)) {
923 return EFI_INVALID_PARAMETER;
924 }
925
926 if (User == NULL) {
927 //
928 // Verify the auto logon user, get user id by matched token.
929 //
930 if (mUsbTable->Count == 0) {
931 return EFI_NOT_READY;
932 }
933
934 //
935 // No user selected, get token first and verify the user existed in user database.
936 //
937 Status = GetToken (ReadToken);
938 if (EFI_ERROR (Status)) {
939 return EFI_NOT_READY;
940 }
941
942 for (Index = 0; Index < mUsbTable->Count; Index++) {
943 //
944 // find the specified credential in the Usb credential database.
945 //
946 UserToken = mUsbTable->UserInfo[Index].Token;
947 if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) {
948 UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
949 CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
950 return EFI_SUCCESS;
951 }
952 }
953
954 return EFI_NOT_READY;
955 }
956
957 //
958 // User is not NULL here. Read a token, and check whether the token matches with
959 // the selected user's Token. If not, try to find a token in token DB to matches
960 // with read token.
961 //
962
963 Status = GetToken (ReadToken);
964 if (EFI_ERROR (Status)) {
965 QuestionStr = GetStringById (STRING_TOKEN (STR_READ_USB_TOKEN_ERROR));
966 PromptStr = GetStringById (STRING_TOKEN (STR_INSERT_USB_TOKEN));
967 OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
968 gBS->RestoreTPL (TPL_APPLICATION);
969 CreatePopUp (
970 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
971 &Key,
972 QuestionStr,
973 L"",
974 PromptStr,
975 NULL
976 );
977 gBS->RaiseTPL (OldTpl);
978 FreePool (QuestionStr);
979 FreePool (PromptStr);
980 return EFI_NOT_FOUND;
981 }
982
983 //
984 // Get the selected user's identifier.
985 //
986 Status = FindUserInfoByType (User, EFI_USER_INFO_IDENTIFIER_RECORD, &UserInfo);
987 if (EFI_ERROR (Status)) {
988 return EFI_NOT_FOUND;
989 }
990
991 //
992 // Check the selected user's Token with the read token.
993 //
994 for (Index = 0; Index < mUsbTable->Count; Index++) {
995 UserId = (UINT8 *) &mUsbTable->UserInfo[Index].UserId;
996 NewUserId = (UINT8 *) (UserInfo + 1);
997 if (CompareMem (UserId, NewUserId, sizeof (EFI_USER_INFO_IDENTIFIER)) == 0) {
998 //
999 // The user's ID is found in the UsbTable.
1000 //
1001 UserToken = mUsbTable->UserInfo[Index].Token;
1002 if (CompareMem (UserToken, ReadToken, HASHED_CREDENTIAL_LEN) == 0) {
1003 //
1004 // The read token matches with the one in UsbTable.
1005 //
1006 CopyMem (Identifier, UserId, sizeof (EFI_USER_INFO_IDENTIFIER));
1007 FreePool (UserInfo);
1008 return EFI_SUCCESS;
1009 }
1010 }
1011 }
1012
1013 FreePool (UserInfo);
1014
1015 return EFI_NOT_READY;
1016 }
1017
1018
1019 /**
1020 Indicate that user interface interaction has begun for the specified credential.
1021
1022 This function is called when a credential provider is selected by the user. If
1023 AutoLogon returns FALSE, then the user interface will be constructed by the User
1024 Identity Manager.
1025
1026 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
1027 @param[out] AutoLogon On return, points to the credential provider's capabilities
1028 after the credential provider has been selected by the user.
1029
1030 @retval EFI_SUCCESS Credential provider successfully selected.
1031 @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
1032
1033 **/
1034 EFI_STATUS
1035 EFIAPI
1036 CredentialSelect (
1037 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
1038 OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
1039 )
1040 {
1041 if ((This == NULL) || (AutoLogon == NULL)) {
1042 return EFI_INVALID_PARAMETER;
1043 }
1044
1045 *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO;
1046
1047 return EFI_SUCCESS;
1048 }
1049
1050
1051 /**
1052 Indicate that user interface interaction has ended for the specified credential.
1053
1054 This function is called when a credential provider is deselected by the user.
1055
1056 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
1057
1058 @retval EFI_SUCCESS Credential provider successfully deselected.
1059
1060 **/
1061 EFI_STATUS
1062 EFIAPI
1063 CredentialDeselect (
1064 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This
1065 )
1066 {
1067 if (This == NULL) {
1068 return EFI_INVALID_PARAMETER;
1069 }
1070 return EFI_SUCCESS;
1071 }
1072
1073
1074 /**
1075 Return the default logon behavior for this user credential.
1076
1077 This function reports the default login behavior regarding this credential provider.
1078
1079 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
1080 @param[out] AutoLogon On return, holds whether the credential provider should be used
1081 by default to automatically log on the user.
1082
1083 @retval EFI_SUCCESS Default information successfully returned.
1084 @retval EFI_INVALID_PARAMETER AutoLogon is NULL.
1085
1086 **/
1087 EFI_STATUS
1088 EFIAPI
1089 CredentialDefault (
1090 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
1091 OUT EFI_CREDENTIAL_LOGON_FLAGS *AutoLogon
1092 )
1093 {
1094 if ((This == NULL) || (AutoLogon == NULL)) {
1095 return EFI_INVALID_PARAMETER;
1096 }
1097
1098 *AutoLogon = EFI_CREDENTIAL_LOGON_FLAG_DEFAULT | EFI_CREDENTIAL_LOGON_FLAG_AUTO;
1099 return EFI_SUCCESS;
1100 }
1101
1102
1103 /**
1104 Return information attached to the credential provider.
1105
1106 This function returns user information.
1107
1108 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
1109 @param[in] UserInfo Handle of the user information data record.
1110 @param[out] Info On entry, points to a buffer of at least *InfoSize bytes. On
1111 exit, holds the user information. If the buffer is too small
1112 to hold the information, then EFI_BUFFER_TOO_SMALL is returned
1113 and InfoSize is updated to contain the number of bytes actually
1114 required.
1115 @param[in, out] InfoSize On entry, points to the size of Info. On return, points to the
1116 size of the user information.
1117
1118 @retval EFI_SUCCESS Information returned successfully.
1119 @retval EFI_BUFFER_TOO_SMALL The size specified by InfoSize is too small to hold all of the
1120 user information. The size required is returned in *InfoSize.
1121 @retval EFI_INVALID_PARAMETER Info is NULL or InfoSize is NULL.
1122 @retval EFI_NOT_FOUND The specified UserInfo does not refer to a valid user info handle.
1123
1124 **/
1125 EFI_STATUS
1126 EFIAPI
1127 CredentialGetInfo (
1128 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
1129 IN EFI_USER_INFO_HANDLE UserInfo,
1130 OUT EFI_USER_INFO *Info,
1131 IN OUT UINTN *InfoSize
1132 )
1133 {
1134 EFI_USER_INFO *CredentialInfo;
1135 UINTN Index;
1136
1137 if ((This == NULL) || (InfoSize == NULL) || (Info == NULL)) {
1138 return EFI_INVALID_PARAMETER;
1139 }
1140
1141 if ((UserInfo == NULL) || (mUsbInfoHandle == NULL)) {
1142 return EFI_NOT_FOUND;
1143 }
1144
1145 //
1146 // Find information handle in credential info table.
1147 //
1148 for (Index = 0; Index < mUsbInfoHandle->Count; Index++) {
1149 CredentialInfo = mUsbInfoHandle->Info[Index];
1150 if (UserInfo == (EFI_USER_INFO_HANDLE)CredentialInfo) {
1151 //
1152 // The handle is found, copy the user info.
1153 //
1154 if (CredentialInfo->InfoSize > *InfoSize) {
1155 *InfoSize = CredentialInfo->InfoSize;
1156 return EFI_BUFFER_TOO_SMALL;
1157 }
1158
1159 CopyMem (Info, CredentialInfo, CredentialInfo->InfoSize);
1160 return EFI_SUCCESS;
1161 }
1162 }
1163
1164 return EFI_NOT_FOUND;
1165 }
1166
1167
1168 /**
1169 Enumerate all of the user informations on the credential provider.
1170
1171 This function returns the next user information record. To retrieve the first user
1172 information record handle, point UserInfo at a NULL. Each subsequent call will retrieve
1173 another user information record handle until there are no more, at which point UserInfo
1174 will point to NULL.
1175
1176 @param[in] This Points to this instance of the EFI_USER_CREDENTIAL_PROTOCOL.
1177 @param[in, out] UserInfo On entry, points to the previous user information handle or NULL
1178 to start enumeration. On exit, points to the next user information
1179 handle or NULL if there is no more user information.
1180
1181 @retval EFI_SUCCESS User information returned.
1182 @retval EFI_NOT_FOUND No more user information found.
1183 @retval EFI_INVALID_PARAMETER UserInfo is NULL.
1184
1185 **/
1186 EFI_STATUS
1187 EFIAPI
1188 CredentialGetNextInfo (
1189 IN CONST EFI_USER_CREDENTIAL_PROTOCOL *This,
1190 IN OUT EFI_USER_INFO_HANDLE *UserInfo
1191 )
1192 {
1193 EFI_USER_INFO *Info;
1194 CHAR16 *ProvNameStr;
1195 UINTN InfoLen;
1196 UINTN Index;
1197 UINTN ProvStrLen;
1198
1199 if ((This == NULL) || (UserInfo == NULL)) {
1200 return EFI_INVALID_PARAMETER;
1201 }
1202
1203 if (mUsbInfoHandle == NULL) {
1204 //
1205 // Initilized user info table. There are 4 user info records in the table.
1206 //
1207 InfoLen = sizeof (USB_CREDENTIAL_INFO) + (4 - 1) * sizeof (EFI_USER_INFO *);
1208 mUsbInfoHandle = AllocateZeroPool (InfoLen);
1209 if (mUsbInfoHandle == NULL) {
1210 *UserInfo = NULL;
1211 return EFI_NOT_FOUND;
1212 }
1213
1214 //
1215 // The first information, Credential Provider info.
1216 //
1217 InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
1218 Info = AllocateZeroPool (InfoLen);
1219 ASSERT (Info != NULL);
1220
1221 Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_RECORD;
1222 Info->InfoSize = (UINT32) InfoLen;
1223 Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
1224 CopyGuid (&Info->Credential, &gUsbCredentialProviderGuid);
1225 CopyGuid ((EFI_GUID *)(Info + 1), &gUsbCredentialProviderGuid);
1226
1227 mUsbInfoHandle->Info[0] = Info;
1228 mUsbInfoHandle->Count++;
1229
1230 //
1231 // The second information, Credential Provider name info.
1232 //
1233 ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_NAME));
1234 ProvStrLen = StrSize (ProvNameStr);
1235 InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
1236 Info = AllocateZeroPool (InfoLen);
1237 ASSERT (Info != NULL);
1238
1239 Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
1240 Info->InfoSize = (UINT32) InfoLen;
1241 Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
1242 CopyGuid (&Info->Credential, &gUsbCredentialProviderGuid);
1243 CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
1244 FreePool (ProvNameStr);
1245
1246 mUsbInfoHandle->Info[1] = Info;
1247 mUsbInfoHandle->Count++;
1248
1249 //
1250 // The third information, Credential Provider type info.
1251 //
1252 InfoLen = sizeof (EFI_USER_INFO) + sizeof (EFI_GUID);
1253 Info = AllocateZeroPool (InfoLen);
1254 ASSERT (Info != NULL);
1255
1256 Info->InfoType = EFI_USER_INFO_CREDENTIAL_TYPE_RECORD;
1257 Info->InfoSize = (UINT32) InfoLen;
1258 Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
1259 CopyGuid (&Info->Credential, &gUsbCredentialProviderGuid);
1260 CopyGuid ((EFI_GUID *)(Info + 1), &gEfiUserCredentialClassSecureCardGuid);
1261
1262 mUsbInfoHandle->Info[2] = Info;
1263 mUsbInfoHandle->Count++;
1264
1265 //
1266 // The fourth information, Credential Provider type name info.
1267 //
1268 ProvNameStr = GetStringById (STRING_TOKEN (STR_PROVIDER_TYPE_NAME));
1269 ProvStrLen = StrSize (ProvNameStr);
1270 InfoLen = sizeof (EFI_USER_INFO) + ProvStrLen;
1271 Info = AllocateZeroPool (InfoLen);
1272 ASSERT (Info != NULL);
1273
1274 Info->InfoType = EFI_USER_INFO_CREDENTIAL_PROVIDER_NAME_RECORD;
1275 Info->InfoSize = (UINT32) InfoLen;
1276 Info->InfoAttribs = EFI_USER_INFO_PROTECTED;
1277 CopyGuid (&Info->Credential, &gUsbCredentialProviderGuid);
1278 CopyMem ((UINT8*)(Info + 1), ProvNameStr, ProvStrLen);
1279 FreePool (ProvNameStr);
1280
1281 mUsbInfoHandle->Info[3] = Info;
1282 mUsbInfoHandle->Count++;
1283 }
1284
1285 if (*UserInfo == NULL) {
1286 //
1287 // Return the first info handle.
1288 //
1289 *UserInfo = (EFI_USER_INFO_HANDLE) mUsbInfoHandle->Info[0];
1290 return EFI_SUCCESS;
1291 }
1292
1293 //
1294 // Find information handle in credential info table.
1295 //
1296 for (Index = 0; Index < mUsbInfoHandle->Count; Index++) {
1297 Info = mUsbInfoHandle->Info[Index];
1298 if (*UserInfo == (EFI_USER_INFO_HANDLE)Info) {
1299 //
1300 // The handle is found, get the next one.
1301 //
1302 if (Index == mUsbInfoHandle->Count - 1) {
1303 //
1304 // Already last one.
1305 //
1306 *UserInfo = NULL;
1307 return EFI_NOT_FOUND;
1308 }
1309 Index++;
1310 *UserInfo = (EFI_USER_INFO_HANDLE)mUsbInfoHandle->Info[Index];
1311 return EFI_SUCCESS;
1312 }
1313 }
1314
1315 *UserInfo = NULL;
1316 return EFI_NOT_FOUND;
1317 }
1318
1319
1320 /**
1321 Main entry for this driver.
1322
1323 @param ImageHandle Image handle this driver.
1324 @param SystemTable Pointer to SystemTable.
1325
1326 @retval EFI_SUCESS This function always complete successfully.
1327
1328 **/
1329 EFI_STATUS
1330 EFIAPI
1331 UsbProviderInit (
1332 IN EFI_HANDLE ImageHandle,
1333 IN EFI_SYSTEM_TABLE *SystemTable
1334 )
1335 {
1336 EFI_STATUS Status;
1337
1338 //
1339 // Init credential table.
1340 //
1341 Status = InitCredentialTable ();
1342 if (EFI_ERROR (Status)) {
1343 return Status;
1344 }
1345
1346 //
1347 // Init Form Browser
1348 //
1349 Status = InitFormBrowser ();
1350 if (EFI_ERROR (Status)) {
1351 return Status;
1352 }
1353
1354 //
1355 // Install protocol interfaces for the Usb Credential Provider.
1356 //
1357 Status = gBS->InstallProtocolInterface (
1358 &mCallbackInfo->DriverHandle,
1359 &gEfiUserCredentialProtocolGuid,
1360 EFI_NATIVE_INTERFACE,
1361 &gUsbCredentialProviderDriver
1362 );
1363 return Status;
1364 }