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