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