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