From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 9BA7482124 for ; Wed, 8 Feb 2017 17:03:59 -0800 (PST) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga102.fm.intel.com with ESMTP; 08 Feb 2017 17:03:59 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,349,1484035200"; d="scan'208,217";a="63542564" Received: from fmsmsx107.amr.corp.intel.com ([10.18.124.205]) by fmsmga006.fm.intel.com with ESMTP; 08 Feb 2017 17:03:58 -0800 Received: from fmsmsx126.amr.corp.intel.com (10.18.125.43) by fmsmsx107.amr.corp.intel.com (10.18.124.205) with Microsoft SMTP Server (TLS) id 14.3.248.2; Wed, 8 Feb 2017 17:03:58 -0800 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by FMSMSX126.amr.corp.intel.com (10.18.125.43) with Microsoft SMTP Server (TLS) id 14.3.248.2; Wed, 8 Feb 2017 17:03:56 -0800 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.88]) by SHSMSX104.ccr.corp.intel.com ([10.239.4.70]) with mapi id 14.03.0248.002; Thu, 9 Feb 2017 09:03:53 +0800 From: "Yao, Jiewen" To: "Long, Qin" , "edk2-devel@lists.01.org" CC: "Zhang, Chao B" Thread-Topic: [PATCH V2 5/6] SecurityPkg/Password: Add Password based UserAuthentication modules. Thread-Index: AQHSgm5VSRWhTCaXCUWMLT3/7LwXy6Ff2hYQ Date: Thu, 9 Feb 2017 01:03:53 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A8EB797@shsmsx102.ccr.corp.intel.com> References: <1486455866-7896-1-git-send-email-jiewen.yao@intel.com> <1486455866-7896-6-git-send-email-jiewen.yao@intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 X-Content-Filtered-By: Mailman/MimeDel 2.1.21 Subject: Re: [PATCH V2 5/6] SecurityPkg/Password: Add Password based UserAuthentication modules. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Feb 2017 01:04:00 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Good question. 1) I will remove the unused code. 2) If BaseMemoryLib is used, the malicious code may guess which byte is inc= orrect by analyzing time on error returned - technically. The SlowCompareMem is designed to mitigate time-attack for comparison. It a= lways compare the full memory even the first byte is different. Thank you Yao Jiewen From: Long, Qin Sent: Wednesday, February 8, 2017 4:49 PM To: Yao, Jiewen ; edk2-devel@lists.01.org Cc: Zhang, Chao B Subject: RE: [PATCH V2 5/6] SecurityPkg/Password: Add Password based UserAu= thentication modules. Some comments: 1. I didn't see any usage of KeyLibGenerateLib interface. Remove or just de= signed for future usage? 2. Why need one extra KeyLibSlowCompareMem? Instead of using one in BaseMem= oryLib? And if necessary, please add extra ASSERT handling as the comments. Reviewed-by: Qin Long > Best Regards & Thanks, LONG, Qin > -----Original Message----- > From: Yao, Jiewen > Sent: Tuesday, February 7, 2017 12:24 AM > To: edk2-devel@lists.01.org > Cc: Long, Qin >; Zhang, Cha= o B > > > Subject: [PATCH V2 5/6] SecurityPkg/Password: Add Password based > UserAuthentication modules. > > This password based user authentication is to verify user when a user > wants to enter BIOS setup page. > > The DXE driver registers report status code listener. > When it gets (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) > progress > code, it will let the user input password. > If and only if the user inputs the right password, the status code handle= r > will return and let the setup driver continue running. > If the user inputs the wrong password, the status code handler will let > user try again. > If the user inputs the wrong password 3 times, the status code handler wi= ll > reset the system. > > The DXE driver also register a setup page in setup browser, so that > user may update the password. > > The DXE driver uses SMI to let SMM driver do the password verification > and management. > > The SMM driver registers SMI handler to perform the request from DXE. > The password must meet below criteria: > 1) Length >=3D 8 char > 2) It must include lower case, upper case, number and symbol. > 3) It must not duplicate with 5 previous password. > If above criteria is met, the password will be saved to a read only UEFI > variable. The format is password hash+salt, which is generated by > Pkcs5HashPassword algorithm (SHA256+1000 iteration). > > If the SMM driver gets wrong password 3 times, the interface is locked > and does not accept more request. > > If the SMM driver will detect IsPasswordCleared() at the entry point and > clear the password if IsPasswordCleared() is TRUE. This can be used when > the user forgets the password. > > Cc: Qin Long > > Cc: Chao Zhang > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiewen Yao > > --- > SecurityPkg/Password/UserAuthentication/KeyService.c = | 210 > ++++++ > SecurityPkg/Password/UserAuthentication/KeyService.h = | 122 > ++++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.c = | > 718 ++++++++++++++++++++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.h = | > 115 ++++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.inf = | > 79 +++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.uni = | > 22 + > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExtra.uni > | 20 + > > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeFormset. > h | 30 + > > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePasswor > d.c | 301 ++++++++ > > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeStrings.u > ni | 29 + > SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeVfr.vfr > | 38 ++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationGuid.h = | > 65 ++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.c = | > 672 ++++++++++++++++++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.inf > | 70 ++ > SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.uni > | 22 + > > SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmExtra.un > i | 20 + > 16 files changed, 2533 insertions(+) > > diff --git a/SecurityPkg/Password/UserAuthentication/KeyService.c > b/SecurityPkg/Password/UserAuthentication/KeyService.c > new file mode 100644 > index 0000000..81aa2f9 > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/KeyService.c > @@ -0,0 +1,210 @@ > +/** @file > + Password key service. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include "KeyService.h" > + > +#define DEFAULT_AES_KEY_BIT_SIZE 256 > +#define DEFAULT_PBKDF2_ITERATION_COUNT 1000 > + > +/** > + Compares the contents of two buffers with slow algorithm > + > + This function compares Length bytes of SourceBuffer to Length bytes of > DestinationBuffer. > + If all Length bytes of the two buffers are identical, then 0 is return= ed. > Otherwise, the > + value returned is the first mismatched byte in SourceBuffer subtracted > from the first > + mismatched byte in DestinationBuffer. > + > + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). > + If Length > 0 and SourceBuffer is NULL, then ASSERT(). > + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then > ASSERT(). > + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then > ASSERT(). > + > + @param DestinationBuffer The pointer to the destination buffer to > compare. > + @param SourceBuffer The pointer to the source buffer to compare. > + @param Length The number of bytes to compare. > + > + @return 0 All Length bytes of the two buffers are iden= tical. > + @retval -1 The SourceBuffer is not identical to Destina= tionBuffer. > + > +**/ > +INTN > +EFIAPI > +KeyLibSlowCompareMem ( > + IN CONST VOID *DestinationBuffer, > + IN CONST VOID *SourceBuffer, > + IN UINTN Length > + ) > +{ > + UINT8 Delta; > + UINTN Index; > + UINT8 *Destination; > + UINT8 *Source; > + > + Destination =3D (UINT8 *)DestinationBuffer; > + Source =3D (UINT8 *)SourceBuffer; > + Delta =3D 0; > + for (Index =3D 0; Index < Length; Index++) { > + Delta |=3D Destination[Index] ^ Source[Index]; > + } > + if (Delta =3D=3D 0) { > + return 0; > + } else { > + return -1; > + } > +} > + > +/** > + Generate Salt value. > + > + @param[in, out] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + > + @retval TRUE Salt is generated. > + @retval FALSE Salt is not generated. > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGenerateSalt ( > + IN OUT UINT8 *SaltValue, > + IN UINTN SaltSize > + ) > +{ > + if (SaltValue =3D=3D NULL) { > + return FALSE; > + } > + RandomSeed(NULL, 0); > + RandomBytes(SaltValue, SaltSize); > + return TRUE; > +} > + > +/** > + Hash the data. > + > + @param[in] HashType Hash type > + @param[in] Key Points to the key buffer > + @param[in] KeySize Key buffer size > + @param[in] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + @param[out] KeyHash Points to the hashed result > + @param[in] KeyHashSize Size of the hash buffer > + > + @retval TRUE Hash the data successfully. > + @retval FALSE Failed to hash the data. > + > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGenerateHash( > + IN UINT32 HashType, > + IN VOID *Key, > + IN UINTN KeySize, > + IN UINT8 *SaltValue, > + IN UINTN SaltSize, > + OUT UINT8 *KeyHash, > + IN UINTN KeyHashSize > + ) > +{ > + BOOLEAN Status; > + UINTN HashSize; > + VOID *HashContext; > + > + if (HashType !=3D HASH_TYPE_SHA256) { > + return FALSE; > + } > + if (KeyHashSize !=3D SHA256_DIGEST_SIZE) { > + return FALSE; > + } > + > + if ((Key =3D=3D NULL) || (SaltValue =3D=3D NULL) || (KeyHash =3D=3D NU= LL)) { > + return FALSE; > + } > + > + HashSize =3D Sha256GetContextSize (); > + HashContext =3D AllocateZeroPool (HashSize); > + if (HashContext =3D=3D NULL) { > + return FALSE; > + } > + > + Status =3D Sha256Init(HashContext); > + if (!Status) { > + goto Done; > + } > + > + Status =3D Sha256Update(HashContext, SaltValue, SaltSize); > + if (!Status) { > + goto Done; > + } > + Status =3D Sha256Update(HashContext, Key, KeySize); > + if (!Status) { > + goto Done; > + } > + > + Status =3D Sha256Final(HashContext, KeyHash); > +Done: > + FreePool (HashContext); > + return Status; > +} > + > +/** > + Hash the password with PBKDF2. > + > + @param[in] HashType Hash type > + @param[in] Key Points to the key buffer > + @param[in] KeySize Key buffer size > + @param[in] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + @param[out] KeyHash Points to the hashed result > + @param[in] KeyHashSize Size of the hash buffer > + > + @retval TRUE Hash the data successfully. > + @retval FALSE Failed to hash the data. > + > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGeneratePBKDF2Hash ( > + IN UINT32 HashType, > + IN VOID *Key, > + IN UINTN KeySize, > + IN UINT8 *SaltValue, > + IN UINTN SaltSize, > + OUT UINT8 *KeyHash, > + IN UINTN KeyHashSize > + ) > +{ > + BOOLEAN Result; > + > + if (HashType !=3D HASH_TYPE_SHA256) { > + return FALSE; > + } > + if (KeyHashSize !=3D SHA256_DIGEST_SIZE) { > + return FALSE; > + } > + > + Result =3D Pkcs5HashPassword ( > + KeySize, > + Key, > + SaltSize, > + SaltValue, > + DEFAULT_PBKDF2_ITERATION_COUNT, > + SHA256_DIGEST_SIZE, > + KeyHashSize, > + KeyHash > + ); > + return Result; > +} > diff --git a/SecurityPkg/Password/UserAuthentication/KeyService.h > b/SecurityPkg/Password/UserAuthentication/KeyService.h > new file mode 100644 > index 0000000..f287953 > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/KeyService.h > @@ -0,0 +1,122 @@ > +/** @file > + Header file for key service. > + > + Copyright (c) 2017, Intel Corporation. All rights reserved.
> + This program and the accompanying materials > + are licensed and made available under the terms and conditions of the = BSD > License > + which accompanies this distribution. The full text of the license may= be > found at > + http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#ifndef __KEY_LIB_H__ > +#define __KEY_LIB_H__ > + > +/** > + Compares the contents of two buffers with slow algorithm > + > + This function compares Length bytes of SourceBuffer to Length bytes of > DestinationBuffer. > + If all Length bytes of the two buffers are identical, then 0 is return= ed. > Otherwise, the > + value returned is the first mismatched byte in SourceBuffer subtracted > from the first > + mismatched byte in DestinationBuffer. > + > + If Length > 0 and DestinationBuffer is NULL, then ASSERT(). > + If Length > 0 and SourceBuffer is NULL, then ASSERT(). > + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then > ASSERT(). > + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then > ASSERT(). > + > + @param DestinationBuffer The pointer to the destination buffer to > compare. > + @param SourceBuffer The pointer to the source buffer to compare. > + @param Length The number of bytes to compare. > + > + @return 0 All Length bytes of the two buffers are iden= tical. > + @retval -1 The SourceBuffer is not identical to Destina= tionBuffer. > + > +**/ > +INTN > +EFIAPI > +KeyLibSlowCompareMem ( > + IN CONST VOID *DestinationBuffer, > + IN CONST VOID *SourceBuffer, > + IN UINTN Length > + ); > + > +/** > + Generate Salt value. > + > + @param[in, out] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + > + @retval TRUE Salt is generated. > + @retval FALSE Salt is not generated. > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGenerateSalt( > + IN OUT UINT8 *SaltValue, > + IN UINTN SaltSize > + ); > + > +#define HASH_TYPE_SHA256 0x000B > + > +#define SHA256_DIGEST_SIZE 32 > + > +/** > + Hash the data. > + > + @param[in] HashType Hash type > + @param[in] Key Points to the key buffer > + @param[in] KeySize Key buffer size > + @param[in] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + @param[out] KeyHash Points to the hashed result > + @param[in] KeyHashSize Size of the hash buffer > + > + @retval TRUE Hash the data successfully. > + @retval FALSE Failed to hash the data. > + > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGenerateHash( > + IN UINT32 HashType, > + IN VOID *Key, > + IN UINTN KeySize, > + IN UINT8 *SaltValue, > + IN UINTN SaltSize, > + OUT UINT8 *KeyHash, > + IN UINTN KeyHashSize > + ); > + > +/** > + Hash the password with PBKDF2. > + > + @param[in] HashType Hash type > + @param[in] Key Points to the key buffer > + @param[in] KeySize Key buffer size > + @param[in] SaltValue Points to the salt buffer > + @param[in] SaltSize Size of the salt buffer > + @param[out] KeyHash Points to the hashed result > + @param[in] KeyHashSize Size of the hash buffer > + > + @retval TRUE Hash the data successfully. > + @retval FALSE Failed to hash the data. > + > +**/ > +BOOLEAN > +EFIAPI > +KeyLibGeneratePBKDF2Hash ( > + IN UINT32 HashType, > + IN VOID *Key, > + IN UINTN KeySize, > + IN UINT8 *SaltValue, > + IN UINTN SaltSize, > + OUT UINT8 *KeyHash, > + IN UINTN KeyHashSize > + ); > + > +#endif > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.c > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.c > new file mode 100644 > index 0000000..3836eac > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.c > @@ -0,0 +1,718 @@ > +/** @file > + This Driver mainly do user authentication before entering Setup. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include "UserAuthenticationDxe.h" > + > +EFI_EVENT mExitBootServicesEvent =3D NULL; > +EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol =3D NULL; > +USER_AUTHENTICATION_PRIVATE_DATA *mUserAuthenticationData =3D > NULL; > + > +UINTN mAdminPasswordTryCount; > + > +EFI_GUID gAdminAuthenticationGuid =3D ADMIN_AUTHENTICATION_GUID; > + > +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath =3D { > + { > + { > + HARDWARE_DEVICE_PATH, > + HW_VENDOR_DP, > + { > + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), > + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) > + } > + }, > + USER_AUTHENTICATION_FORMSET_GUID > + }, > + { > + END_DEVICE_PATH_TYPE, > + END_ENTIRE_DEVICE_PATH_SUBTYPE, > + { > + (UINT8) (END_DEVICE_PATH_LENGTH), > + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) > + } > + } > +}; > + > +/** > + Get a user input string. > + > + @param[in] PopUpString A popup string to inform user. > + @param[in, out] UserInput The user input string > + @param[in] UserInputMaxLen The max unicode count of the > UserInput without NULL terminator. > +**/ > +EFI_STATUS > +GetUserInput ( > + IN CHAR16 *PopUpString, > + IN OUT CHAR16 *UserInput, > + IN UINTN UserInputMaxLen > + ) > +{ > + EFI_INPUT_KEY InputKey; > + UINTN InputLength; > + CHAR16 *Mask; > + > + UserInput[0] =3D 0; > + Mask =3D AllocateZeroPool ((UserInputMaxLen + 1) * sizeof(CHAR16)); > + if (Mask =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + InputLength =3D 0; > + > + while (TRUE) { > + Mask[InputLength] =3D L'_'; > + CreatePopUp ( > + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, > + &InputKey, > + PopUpString, > + L"---------------------", > + Mask, > + NULL > + ); > + if (InputKey.ScanCode =3D=3D SCAN_NULL) { > + // > + // Check whether finish inputing password. > + // > + if (InputKey.UnicodeChar =3D=3D CHAR_CARRIAGE_RETURN && InputLengt= h > > 0) { > + // > + // Add the null terminator. > + // > + UserInput[InputLength] =3D 0; > + break; > + } else if ((InputKey.UnicodeChar =3D=3D CHAR_NULL) || > + (InputKey.UnicodeChar =3D=3D CHAR_TAB) || > + (InputKey.UnicodeChar =3D=3D CHAR_LINEFEED) || > + (InputKey.UnicodeChar =3D=3D CHAR_CARRIAGE_RETURN) > + ) { > + continue; > + } else { > + // > + // delete last key entered > + // > + if (InputKey.UnicodeChar =3D=3D CHAR_BACKSPACE) { > + if (InputLength > 0) { > + UserInput[InputLength] =3D 0; > + Mask[InputLength] =3D 0; > + InputLength--; > + } > + } else { > + // > + // add Next key entry > + // > + UserInput[InputLength] =3D InputKey.UnicodeChar; > + Mask[InputLength] =3D L'*'; > + InputLength++; > + if (InputLength =3D=3D UserInputMaxLen) { > + // > + // Add the null terminator. > + // > + UserInput[InputLength] =3D 0; > + Mask[InputLength] =3D 0; > + break; > + } > + } > + } > + } > + } > + FreePool (Mask); > + return EFI_SUCCESS; > +} > + > +/** > + Display a message box to end user. > + > + @param[in] DisplayString The string in message box. > +**/ > +VOID > +MessageBox ( > + IN CHAR16 *DisplayString > + ) > +{ > + EFI_INPUT_KEY Key; > + > + do { > + CreatePopUp ( > + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, > + &Key, > + L"", > + DisplayString, > + L"Press ENTER to continue ...", > + L"", > + NULL > + ); > + } while (Key.UnicodeChar !=3D CHAR_CARRIAGE_RETURN); > +} > + > +/** > + Force system reset. > +**/ > +VOID > +ForceSystemReset ( > + VOID > + ) > +{ > + MessageBox (L"Password retry count reach, reset system!"); > + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); > + CpuDeadLoop(); > +} > + > +/** > + Display message for set password. > + > + @param[in] ReturnStatus The return status for set password. > +**/ > +VOID > +PrintPasswordStatus ( > + IN EFI_STATUS ReturnStatus > + ) > +{ > + CHAR16 *DisplayString; > + > + if (ReturnStatus =3D=3D EFI_SUCCESS) { > + DisplayString =3D L"New password is updated successfully!"; > + } else if (ReturnStatus =3D=3D EFI_UNSUPPORTED) { > + DisplayString =3D L"New password is not strong enough!"; > + } else if (ReturnStatus =3D=3D EFI_ALREADY_STARTED) { > + DisplayString =3D L"New password is found in history!"; > + } else { > + DisplayString =3D L"New password update fails!"; > + } > + > + MessageBox (DisplayString); > +} > + > +/** > + Require user input password. > + > + @param[in] UserGuid The user GUID of the password. > + > + @retval TRUE User input correct password successfully. > + @retval FALSE The password is not set. > +**/ > +BOOLEAN > +RequireUserPassword ( > + IN EFI_GUID *UserGuid > + ) > +{ > + EFI_STATUS Status; > + CHAR16 UserInputPw[MAX_PASSWORD_LEN + 1]; > + CHAR16 TmpPassword[MAX_PASSWORD_LEN + 1]; > + CHAR16 *PopUpString; > + UINTN *PasswordTryCount; > + > + Status =3D EFI_SUCCESS; > + ZeroMem(UserInputPw, sizeof(UserInputPw)); > + ZeroMem(TmpPassword, sizeof(TmpPassword)); > + > + if (!IsPasswordSet(UserGuid)) { > + return FALSE; > + } > + > + if (CompareGuid (UserGuid, &gAdminAuthenticationGuid)) { > + PopUpString =3D L"Please input admin password"; > + PasswordTryCount =3D &mAdminPasswordTryCount; > + } else { > + DEBUG ((DEBUG_ERROR, "Invalid User Guid - %g\n", UserGuid)); > + return FALSE; > + } > + > + while (TRUE) { > + gST->ConOut->ClearScreen(gST->ConOut); > + GetUserInput (PopUpString, UserInputPw, MAX_PASSWORD_LEN); > + > + CopyGuid (UserGuid, &gAdminAuthenticationGuid); > + Status =3D ValidatePassword (UserGuid, UserInputPw, > StrSize(UserInputPw)); > + if (!EFI_ERROR(Status)) { > + break; > + } > + *PasswordTryCount =3D *PasswordTryCount + 1; > + if (*PasswordTryCount >=3D PASSWORD_MAX_TRY_COUNT) { > + ForceSystemReset (); > + } > + MessageBox (L"Incorrect password!"); > + } > + *PasswordTryCount =3D 0; > + > + ZeroMem(UserInputPw, sizeof(UserInputPw)); > + ZeroMem(TmpPassword, sizeof(TmpPassword)); > + > + gST->ConOut->ClearScreen(gST->ConOut); > + > + return TRUE; > +} > + > +/** > + Set user password. > + > + @param[in] UserGuid The user GUID of the password. > + > + @retval TRUE The password is set. > + @retval FALSE The password is not set. > +**/ > +BOOLEAN > +SetUserPassword ( > + IN EFI_GUID *UserGuid > + ) > +{ > + EFI_STATUS Status; > + CHAR16 UserInputPw[MAX_PASSWORD_LEN + 1]; > + CHAR16 TmpPassword[MAX_PASSWORD_LEN + 1]; > + CHAR16 *PopUpString; > + CHAR16 *PopUpString2; > + > + Status =3D EFI_SUCCESS; > + ZeroMem(UserInputPw, sizeof(UserInputPw)); > + ZeroMem(TmpPassword, sizeof(TmpPassword)); > + > + if (CompareGuid (UserGuid, &gAdminAuthenticationGuid)) { > + PopUpString =3D L"Please set admin password"; > + } else { > + DEBUG ((DEBUG_ERROR, "Invalid User Guid - %g\n", UserGuid)); > + return FALSE; > + } > + > + while (TRUE) { > + gST->ConOut->ClearScreen(gST->ConOut); > + GetUserInput (PopUpString, UserInputPw, MAX_PASSWORD_LEN); > + > + PopUpString2 =3D L"Please confirm your new password"; > + gST->ConOut->ClearScreen(gST->ConOut); > + GetUserInput (PopUpString2, TmpPassword, MAX_PASSWORD_LEN); > + if (StrCmp (TmpPassword, UserInputPw) !=3D 0) { > + MessageBox (L"Password are not the same!"); > + continue; > + } > + > + Status =3D SetPassword (UserGuid, UserInputPw, StrSize(UserInputPw), > NULL, 0); > + PrintPasswordStatus (Status); > + if (!EFI_ERROR(Status)) { > + break; > + } > + } > + > + ZeroMem(UserInputPw, sizeof(UserInputPw)); > + ZeroMem(TmpPassword, sizeof(TmpPassword)); > + > + return EFI_SUCCESS; > +} > + > +/** > + Check password before entering into setup. > + > + @param CodeType Indicates the type of status code being reported= . > Type EFI_STATUS_CODE_TYPE is defined in "Related Definitions" below. > + > + @param Value Describes the current status of a hardware or so= ftware > entity. > + This included information about the class and su= bclass that is > used to classify the entity > + as well as an operation. For progress codes, th= e operation is the > current activity. > + For error codes, it is the exception. For debug= codes, it is not > defined at this time. > + Type EFI_STATUS_CODE_VALUE is defined in "Relate= d > Definitions" below. > + Specific values are discussed in the Intel? Plat= form Innovation > Framework for EFI Status Code Specification. > + > + @param Instance The enumeration of a hardware or software entity > within the system. > + A system may contain multiple entities that matc= h a > class/subclass pairing. > + The instance differentiates between them. An in= stance of 0 > indicates that instance information is unavailable, > + not meaningful, or not relevant. Valid instance= numbers start > with 1. > + > + > + @param CallerId This optional parameter may be used to identify = the > caller. > + This parameter allows the status code driver to = apply different > rules to different callers. > + Type EFI_GUID is defined in InstallProtocolInter= face() in the > UEFI 2.0 Specification. > + > + > + @param Data This optional parameter may be used to pass addi= tional > data > + > + @retval EFI_SUCCESS Status code is what we expected. > + @retval EFI_UNSUPPORTED Status code not supported. > + > +**/ > +EFI_STATUS > +EFIAPI > +CheckForPassword ( > + IN EFI_STATUS_CODE_TYPE CodeType, > + IN EFI_STATUS_CODE_VALUE Value, > + IN UINT32 Instance, > + IN EFI_GUID *CallerId, OPTIONAL > + IN EFI_STATUS_CODE_DATA *Data OPTIONAL > + ) > +{ > + BOOLEAN PasswordSet; > + > + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) =3D=3D > EFI_PROGRESS_CODE) && > + (Value =3D=3D (EFI_SOFTWARE_DXE_BS_DRIVER | > EFI_SW_PC_USER_SETUP))) { > + // > + // Check whether enter setup page. > + // > + PasswordSet =3D RequireUserPassword (&gAdminAuthenticationGuid); > + if (PasswordSet) { > + DEBUG ((DEBUG_INFO, "Welcome Admin!\n")); > + } else { > + DEBUG ((DEBUG_INFO, "Admin password is not set!\n")); > + if (NeedEnrollPassword()) { > + SetUserPassword (&gAdminAuthenticationGuid); > + } > + } > + > + return EFI_SUCCESS; > + } else{ > + return EFI_UNSUPPORTED; > + } > +} > + > +/** > + This function allows a caller to extract the current configuration for= one > + or more named elements from the target driver. > + > + @param This Points to the EFI_HII_CONFIG_ACCESS_PRO= TOCOL. > + @param Request A null-terminated Unicode string in > + format. > + @param Progress On return, points to a character in the= Request > + string. Points to the string's null ter= minator if > + request was successful. Points to the m= ost recent > + '&' before the first failing name/value= pair (or > + the beginning of the string if the fail= ure is in > + the first name/value pair) if the reque= st was not > + successful. > + @param Results A null-terminated Unicode string in > + format which has all va= lues filled > + in for the names in the Request string.= String to > + be allocated by the called function. > + > + @retval EFI_SUCCESS The Results is filled with the requeste= d values. > + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the > results. > + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown > name. > + @retval EFI_NOT_FOUND Routing data doesn't match any storage = in > this > + driver. > + > +**/ > +EFI_STATUS > +EFIAPI > +ExtractConfig ( > + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, > + IN CONST EFI_STRING Request, > + OUT EFI_STRING *Progress, > + OUT EFI_STRING *Results > + ) > +{ > + if (Progress =3D=3D NULL || Results =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + *Progress =3D Request; > + return EFI_NOT_FOUND; > +} > + > + > +/** > + This function processes the results of changes in configuration. > + > + @param This Points to the EFI_HII_CONFIG_ACCESS_PRO= TOCOL. > + @param Configuration A null-terminated Unicode string in > > + format. > + @param Progress A pointer to a string filled in with th= e offset of > + the most recent '&' before the first fa= iling > + name/value pair (or the beginning of th= e string if > + the failure is in the first name/value = pair) or > + the terminating NULL if all was success= ful. > + > + @retval EFI_SUCCESS The Results is processed successfully. > + @retval EFI_INVALID_PARAMETER Configuration is NULL. > + @retval EFI_NOT_FOUND Routing data doesn't match any storage = in > this > + driver. > + > +**/ > +EFI_STATUS > +EFIAPI > +RouteConfig ( > + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, > + IN CONST EFI_STRING Configuration, > + OUT EFI_STRING *Progress > + ) > +{ > + if (Configuration =3D=3D NULL || Progress =3D=3D NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + *Progress =3D Configuration; > + > + return EFI_NOT_FOUND; > +} > + > +/** > + This function processes the results of changes in configuration. > + > + @param This Points to the EFI_HII_CONFIG_ACCESS_PRO= TOCOL. > + @param Action Specifies the type of action taken by t= he browser. > + @param QuestionId A unique value which is sent to the ori= ginal > + exporting driver so that it can identif= y the type > + of data to expect. > + @param Type The type of value for the question. > + @param Value A pointer to the data being sent to the= original > + exporting driver. > + @param ActionRequest On return, points to the action request= ed by > the > + callback function. > + > + @retval EFI_SUCCESS The callback successfully handled the a= ction. > + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold > the > + variable and its data. > + @retval EFI_DEVICE_ERROR The variable could not be saved. > + @retval EFI_UNSUPPORTED The specified Action is not supported b= y > the > + callback. > + > +**/ > +EFI_STATUS > +EFIAPI > +UserAuthenticationCallback ( > + 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 > + ) > +{ > + EFI_STATUS Status; > + CHAR16 *UserInputPassword; > + EFI_GUID *UserGuid; > + UINTN *PasswordTryCount; > + > + Status =3D EFI_SUCCESS; > + > + if (((Value =3D=3D NULL) && (Action !=3D EFI_BROWSER_ACTION_FORM_OPEN) > && (Action !=3D EFI_BROWSER_ACTION_FORM_CLOSE))|| > + (ActionRequest =3D=3D NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + switch (Action) { > + case EFI_BROWSER_ACTION_CHANGING: > + { > + switch (QuestionId) { > + case ADMIN_PASSWORD_KEY_ID: > + UserGuid =3D &gAdminAuthenticationGuid; > + PasswordTryCount =3D &mAdminPasswordTryCount; > + if ((Type =3D=3D EFI_IFR_TYPE_STRING) && (Value->string =3D=3D 0= ) && > + (mUserAuthenticationData->PasswordState =3D=3D > BROWSER_STATE_SET_PASSWORD)) { > + mUserAuthenticationData->PasswordState =3D > BROWSER_STATE_VALIDATE_PASSWORD; > + ZeroMem (mUserAuthenticationData->OldPassword, > sizeof(mUserAuthenticationData->OldPassword)); > + return EFI_INVALID_PARAMETER; > + } > + // > + // The Callback is responsible for validating old password input= by user, > + // If Callback return EFI_SUCCESS, it indicates validation pass. > + // > + switch (mUserAuthenticationData->PasswordState) { > + case BROWSER_STATE_VALIDATE_PASSWORD: > + UserInputPassword =3D HiiGetString (mUserAuthenticationData- > >HiiHandle, Value->string, NULL); > + if ((StrLen (UserInputPassword) >=3D PASSWORD_MAX_SIZE) || > (UserInputPassword[0] =3D=3D 0)) { > + Status =3D EFI_NOT_READY; > + break; > + } > + Status =3D ValidatePassword (UserGuid, UserInputPassword, StrS= ize > (UserInputPassword)); > + if (Status =3D=3D EFI_SUCCESS) { > + mUserAuthenticationData->PasswordState =3D > BROWSER_STATE_SET_PASSWORD; > + StrCpyS ( > + mUserAuthenticationData->OldPassword, > + sizeof(mUserAuthenticationData->OldPassword)/sizeof(CHAR16= ), > + UserInputPassword > + ); > + *PasswordTryCount =3D 0; > + } else { > + // > + // Old password mismatch, return EFI_NOT_READY to prompt for > error message. > + // > + Status =3D EFI_NOT_READY; > + *PasswordTryCount =3D *PasswordTryCount + 1; > + if (*PasswordTryCount >=3D PASSWORD_MAX_TRY_COUNT) { > + ForceSystemReset (); > + } > + } > + break; > + > + case BROWSER_STATE_SET_PASSWORD: > + UserInputPassword =3D HiiGetString (mUserAuthenticationData- > >HiiHandle, Value->string, NULL); > + if ((StrLen (UserInputPassword) >=3D PASSWORD_MAX_SIZE) || > (UserInputPassword[0] =3D=3D 0)) { > + Status =3D EFI_NOT_READY; > + break; > + } > + Status =3D SetPassword (UserGuid, UserInputPassword, StrSize > (UserInputPassword), mUserAuthenticationData->OldPassword, > StrSize(mUserAuthenticationData->OldPassword)); > + PrintPasswordStatus (Status); > + ZeroMem (mUserAuthenticationData->OldPassword, > sizeof(mUserAuthenticationData->OldPassword)); > + mUserAuthenticationData->PasswordState =3D > BROWSER_STATE_VALIDATE_PASSWORD; > + break; > + > + default: > + break; > + } > + default: > + break; > + } > + } > + default: > + break; > + } > + return Status; > +} > + > +/** > + Unregister status code callback functions. > + > + @param Event Event whose notification function is being invok= ed. > + @param Context Pointer to the notification function's context, = which is > + always zero in current implementation. > + > +**/ > +VOID > +EFIAPI > +UnregisterBootTimeHandlers ( > + IN EFI_EVENT Event, > + IN VOID *Context > + ) > +{ > + mRscHandlerProtocol->Unregister (CheckForPassword); > +} > + > +/** > + User Authentication entry point. > + > + @param ImageHandle The image handle. > + @param SystemTable The system table. > + > + @retval EFI_SUCCESS The entry point is executed successfully. > + @return other Contain some other errors. > + > +**/ > +EFI_STATUS > +EFIAPI > +UserAuthenticationEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE DriverHandle; > + EFI_HII_HANDLE HiiHandle; > + > + DriverHandle =3D NULL; > + > + mUserAuthenticationData =3D AllocateZeroPool (sizeof > (USER_AUTHENTICATION_PRIVATE_DATA)); > + if (mUserAuthenticationData =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + mUserAuthenticationData->ConfigAccess.ExtractConfig =3D ExtractConfig; > + mUserAuthenticationData->ConfigAccess.RouteConfig =3D RouteConfig; > + mUserAuthenticationData->ConfigAccess.Callback =3D > UserAuthenticationCallback; > + mUserAuthenticationData->PasswordState =3D > BROWSER_STATE_VALIDATE_PASSWORD; > + > + // > + // Install Config Access protocol to driver handle. > + // > + Status =3D gBS->InstallMultipleProtocolInterfaces ( > + &DriverHandle, > + &gEfiDevicePathProtocolGuid, > + &mHiiVendorDevicePath, > + &gEfiHiiConfigAccessProtocolGuid, > + &mUserAuthenticationData->ConfigAccess, > + NULL > + ); > + ASSERT_EFI_ERROR (Status); > + mUserAuthenticationData->DriverHandle =3D DriverHandle; > + > + // > + // Add HII data to database. > + // > + HiiHandle =3D HiiAddPackages ( > + &gAdminAuthenticationGuid, > + DriverHandle, > + UserAuthenticationDxeStrings, > + UserAuthenticationDxeVfrBin, > + NULL > + ); > + if (HiiHandle =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + mUserAuthenticationData->HiiHandle =3D HiiHandle; > + > + // > + // Locate report status code protocol. > + // > + Status =3D gBS->LocateProtocol ( > + &gEfiRscHandlerProtocolGuid, > + NULL, > + (VOID **) &mRscHandlerProtocol > + ); > + ASSERT_EFI_ERROR (Status); > + > + // > + //Register the callback function for ReportStatusCode() notification. > + // > + mRscHandlerProtocol->Register (CheckForPassword, TPL_HIGH_LEVEL); > + > + // > + // Unregister boot time report status code listener at ExitBootService > Event. > + // > + Status =3D gBS->CreateEventEx ( > + EVT_NOTIFY_SIGNAL, > + TPL_NOTIFY, > + UnregisterBootTimeHandlers, > + NULL, > + &gEfiEventExitBootServicesGuid, > + &mExitBootServicesEvent > + ); > + ASSERT_EFI_ERROR (Status); > + > + return EFI_SUCCESS; > +} > + > +/** > + Unloads the application and its installed protocol. > + > + @param[in] ImageHandle Handle that identifies the image to be > unloaded. > + > + @retval EFI_SUCCESS The image has been unloaded. > +**/ > +EFI_STATUS > +EFIAPI > +UserAuthenticationUnload ( > + IN EFI_HANDLE ImageHandle > + ) > +{ > + ASSERT (mUserAuthenticationData !=3D NULL); > + > + // > + // Uninstall Config Access Protocol. > + // > + if (mUserAuthenticationData->DriverHandle !=3D NULL) { > + gBS->UninstallMultipleProtocolInterfaces ( > + mUserAuthenticationData->DriverHandle, > + &gEfiDevicePathProtocolGuid, > + &mHiiVendorDevicePath, > + &gEfiHiiConfigAccessProtocolGuid, > + &mUserAuthenticationData->ConfigAccess, > + NULL > + ); > + mUserAuthenticationData->DriverHandle =3D NULL; > + } > + > + // > + // Remove Hii Data. > + // > + if (mUserAuthenticationData->HiiHandle !=3D NULL) { > + HiiRemovePackages (mUserAuthenticationData->HiiHandle); > + } > + > + FreePool (mUserAuthenticationData); > + mUserAuthenticationData =3D NULL; > + > + return EFI_SUCCESS; > +} > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.h > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.h > new file mode 100644 > index 0000000..1bcc2a7 > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.h > @@ -0,0 +1,115 @@ > +/** @file > + Header file for UserAuthenticationDxe. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > + > +**/ > + > +#ifndef _USER_AUTHENTICATION_DXE_H_ > +#define _USER_AUTHENTICATION_DXE_H_ > + > + > +#include > +#include > + > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "UserAuthenticationGuid.h" > +#include "UserAuthenticationDxeFormset.h" > + > +extern UINT8 UserAuthenticationDxeVfrBin[]; > +extern UINT8 UserAuthenticationDxeStrings[]; > + > +typedef struct { > + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; > + EFI_HANDLE DriverHandle; > + EFI_HII_HANDLE HiiHandle; > + UINT8 PasswordState; > + CHAR16 OldPassword[PASSWORD_MAX_SIZE]; > +} USER_AUTHENTICATION_PRIVATE_DATA; > + > +#pragma pack(1) > +/// > +/// HII specific Vendor Device Path definition. > +/// > +typedef struct { > + VENDOR_DEVICE_PATH VendorDevicePath; > + EFI_DEVICE_PATH_PROTOCOL End; > +} HII_VENDOR_DEVICE_PATH; > +#pragma pack() > + > +/** > + Validata if the password is correct. > + > + @param[in] UserGuid The user GUID of the password. > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval EFI_SUCCESS The password is correct. > + @retval EFI_SECURITY_VIOLATION The password is incorrect. > +**/ > +EFI_STATUS > +ValidatePassword ( > + IN EFI_GUID *UserGuid, > + IN CHAR16 *Password, > + IN UINTN PasswordSize > + ); > + > +/** > + Set a new password. > + > + @param[in] UserGuid The user GUID of the password. > + @param[in] NewPassword The user input new password. > + NULL means clear password. > + @param[in] NewPasswordSize The size of NewPassword in byte. > + @param[in] OldPassword The user input old password. > + NULL means no old password. > + @param[in] OldPasswordSize The size of OldPassword in byte. > + > + @retval EFI_SUCCESS The password is correct. > + @retval EFI_SECURITY_VIOLATION The password is incorrect. > + @retval EFI_OUT_OF_RESOURCES Insufficient resources to set the > password. > +**/ > +EFI_STATUS > +SetPassword ( > + IN EFI_GUID *UserGuid, > + IN CHAR16 *NewPassword, OPTIONAL > + IN UINTN NewPasswordSize, > + IN CHAR16 *OldPassword, OPTIONAL > + IN UINTN OldPasswordSize > + ); > + > +/** > + Return if the password is set. > + > + @param[in] UserGuid The user GUID of the password. > + > + @retval TRUE The password is set. > + @retval FALSE The password is not set. > +**/ > +BOOLEAN > +IsPasswordSet ( > + IN EFI_GUID *UserGuid > + ); > + > +#endif > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.inf > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.inf > new file mode 100644 > index 0000000..75a8076 > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.inf > @@ -0,0 +1,79 @@ > +## @file > +# User Authentication Dxe Driver. > +# > +# This Driver mainly does user authentication before entering Setup. > +# > +# Copyright (c) 2017, Intel Corporation. All rights reserved.
> +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the > BSD License > +# which accompanies this distribution. The full text of the license may= be > found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +# > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D UserAuthenticationDxe > + MODULE_UNI_FILE =3D UserAuthenticationDxe.uni > + FILE_GUID =3D 0683FB88-664C-4BA6-9ED4-1C0916EE43A= 4 > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 2.0 > + ENTRY_POINT =3D UserAuthenticationEntry > + ENTRY_POINT =3D PasswordDxeInit > + UNLOAD_IMAGE =3D UserAuthenticationUnload > + > + > +[Sources] > + UserAuthenticationDxe.c > + UserAuthenticationDxe.h > + UserAuthenticationDxePassword.c > + UserAuthenticationDxeFormset.h > + UserAuthenticationGuid.h > + UserAuthenticationDxeVfr.vfr > + UserAuthenticationDxeStrings.uni > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + SecurityPkg/SecurityPkg.dec > + > +[LibraryClasses] > + BaseLib > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + UefiRuntimeServicesTableLib > + BaseMemoryLib > + DebugLib > + UefiLib > + HiiLib > + DevicePathLib > + MemoryAllocationLib > + PlatformPasswordLib > + > +[Guids] > + gEfiEventExitBootServicesGuid ## CONSUMES ## Event > + gEdkiiPiSmmCommunicationRegionTableGuid ## CONSUMES ## > SystemTable > + > +[Protocols] > + gEfiRscHandlerProtocolGuid ## CONSUMES > + gEfiDevicePathProtocolGuid ## PRODUCES > + gEfiHiiConfigAccessProtocolGuid ## PRODUCES > + gEfiSmmCommunicationProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiSimpleTextOutProtocolGuid AND > + gEfiHiiDatabaseProtocolGuid AND > + gEfiSmmCommunicationProtocolGuid AND > + gEfiVariableArchProtocolGuid AND > + gEfiVariableWriteArchProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + UserAuthenticationDxeExtra.uni > + > + > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.uni > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.uni > new file mode 100644 > index 0000000..6b2d292 > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxe.uni > @@ -0,0 +1,22 @@ > +// /** @file > +// User Authentication Dxe Driver. > +// > +// This driver mainly does the user authentication before entering Setup= . > +// > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license may= be > found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "User > Authentication Dxe Driver." > + > +#string STR_MODULE_DESCRIPTION #language en-US "This driver > mainly does user authentication before entering Setup." > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExtra.u > ni > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExtra.u > ni > new file mode 100644 > index 0000000..86c5c9b > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExtra.u > ni > @@ -0,0 +1,20 @@ > +// /** @file > +// User Authentication Dxe Driver. > +// > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license may= be > found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US > +"User Authentication DXE Driver" > + > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeForms > et.h > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeForms > et.h > new file mode 100644 > index 0000000..4d29a5d > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeForms > et.h > @@ -0,0 +1,30 @@ > +/** @file > + Header file for UserAuthentication formset. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > + > +**/ > + > +#ifndef _USER_AUTHENTICATION_DXE_FORMSET_H_ > +#define _USER_AUTHENTICATION_DXE_FORMSET_H_ > + > +// > +// Vendor GUID of the formset > +// > +#define USER_AUTHENTICATION_FORMSET_GUID \ > + { 0x760e3022, 0xf149, 0x4560, {0x9c, 0x6f, 0x33, 0xaa, 0x7d, 0x48, 0x7= 5, > 0xfa} } > + > +#define ADMIN_PASSWORD_KEY_ID 0x2001 > + > +#define MAX_PASSWORD_LEN 20 > +#define MIN_PASSWORD_LEN 8 > + > +#endif > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePassw > ord.c > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePassw > ord.c > new file mode 100644 > index 0000000..00b051a > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePassw > ord.c > @@ -0,0 +1,301 @@ > +/** @file > + UserAuthentication DXE password wrapper. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include "UserAuthenticationDxe.h" > +#include > +#include > + > +EFI_SMM_COMMUNICATION_PROTOCOL *mSmmCommunication =3D NULL; > + > +/** > + Initialize the communicate buffer using DataSize and Function. > + > + @param[out] DataPtr Points to the data in the communicat= e buffer. > + @param[in] DataSize The data size to send to SMM. > + @param[in] Function The function number to initialize th= e > communicate header. > + @param[in] UserGuid The user GUID of the password. > + > + @retval EFI_INVALID_PARAMETER The data size is too big. > + @retval EFI_SUCCESS Find the specified variable. > +**/ > +VOID* > +InitCommunicateBuffer ( > + OUT VOID **DataPtr OPTIONAL, > + IN UINTN DataSize, > + IN UINTN Function, > + IN EFI_GUID *UserGuid > + ) > +{ > + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; > + SMM_PASSWORD_COMMUNICATE_HEADER > *SmmPasswordFunctionHeader; > + VOID *Buffer; > + EDKII_PI_SMM_COMMUNICATION_REGION_TABLE > *SmmCommRegionTable; > + EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion; > + UINTN Index; > + UINTN Size; > + EFI_STATUS Status; > + > + Buffer =3D NULL; > + Status =3D EfiGetSystemConfigurationTable ( > + &gEdkiiPiSmmCommunicationRegionTableGuid, > + (VOID **) &SmmCommRegionTable > + ); > + if (EFI_ERROR (Status)) { > + return NULL; > + } > + ASSERT (SmmCommRegionTable !=3D NULL); > + SmmCommMemRegion =3D (EFI_MEMORY_DESCRIPTOR *) > (SmmCommRegionTable + 1); > + Size =3D 0; > + for (Index =3D 0; Index < SmmCommRegionTable->NumberOfEntries; > Index++) { > + if (SmmCommMemRegion->Type =3D=3D EfiConventionalMemory) { > + Size =3D EFI_PAGES_TO_SIZE ((UINTN) SmmCommMemRegion- > >NumberOfPages); > + if (Size >=3D (DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, > Data) + sizeof (SMM_PASSWORD_COMMUNICATE_HEADER))) { > + break; > + } > + } > + SmmCommMemRegion =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) > SmmCommMemRegion + SmmCommRegionTable->DescriptorSize); > + } > + ASSERT (Index < SmmCommRegionTable->NumberOfEntries); > + > + Buffer =3D (VOID*)(UINTN)SmmCommMemRegion->PhysicalStart; > + ASSERT (Buffer !=3D NULL); > + SmmCommunicateHeader =3D (EFI_SMM_COMMUNICATE_HEADER *) > Buffer; > + CopyGuid (&SmmCommunicateHeader->HeaderGuid, UserGuid); > + SmmCommunicateHeader->MessageLength =3D DataSize + sizeof > (SMM_PASSWORD_COMMUNICATE_HEADER); > + > + SmmPasswordFunctionHeader =3D > (SMM_PASSWORD_COMMUNICATE_HEADER *) SmmCommunicateHeader- > >Data; > + ZeroMem (SmmPasswordFunctionHeader, DataSize + sizeof > (SMM_PASSWORD_COMMUNICATE_HEADER)); > + SmmPasswordFunctionHeader->Function =3D Function; > + CopyGuid (&SmmPasswordFunctionHeader->UserGuid, UserGuid); > + if (DataPtr !=3D NULL) { > + *DataPtr =3D SmmPasswordFunctionHeader + 1; > + } > + > + return Buffer; > +} > + > +/** > + Send the data in communicate buffer to SMM. > + > + @param[in] Buffer Points to the data in the communic= ate buffer. > + @param[in] DataSize This size of the function header a= nd the data. > + > + @retval EFI_SUCCESS Success is returned from the funct= in in SMM. > + @retval Others Failure is returned from the funct= ion in SMM. > + > +**/ > +EFI_STATUS > +SendCommunicateBuffer ( > + IN VOID *Buffer, > + IN UINTN DataSize > + ) > +{ > + EFI_STATUS Status; > + UINTN CommSize; > + EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; > + SMM_PASSWORD_COMMUNICATE_HEADER > *SmmPasswordFunctionHeader; > + > + CommSize =3D DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, > Data) + sizeof (SMM_PASSWORD_COMMUNICATE_HEADER); > + > + Status =3D mSmmCommunication->Communicate (mSmmCommunication, > Buffer, &CommSize); > + ASSERT_EFI_ERROR (Status); > + > + SmmCommunicateHeader =3D (EFI_SMM_COMMUNICATE_HEADER *) > Buffer; > + SmmPasswordFunctionHeader =3D > (SMM_PASSWORD_COMMUNICATE_HEADER *)SmmCommunicateHeader- > >Data; > + return SmmPasswordFunctionHeader->ReturnStatus; > +} > + > +/** > + Validata if the password is correct. > + > + @param[in] UserGuid The user GUID of the password. > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval EFI_SUCCESS The password is correct. > + @retval EFI_SECURITY_VIOLATION The password is incorrect. > +**/ > +EFI_STATUS > +ValidatePassword ( > + IN EFI_GUID *UserGuid, > + IN CHAR16 *Password, > + IN UINTN PasswordSize > + ) > +{ > + EFI_STATUS Status; > + VOID *Buffer; > + SMM_PASSWORD_COMMUNICATE_VERIFY_PASSWORD > *VerifyPassword; > + > + ASSERT (Password !=3D NULL); > + > + if (PasswordSize > sizeof(VerifyPassword->Password) * sizeof(CHAR16)) = { > + return EFI_INVALID_PARAMETER; > + } > + > + Buffer =3D InitCommunicateBuffer ( > + (VOID**)&VerifyPassword, > + sizeof(*VerifyPassword), > + SMM_PASSWORD_FUNCTION_VERIFY_PASSWORD, > + UserGuid > + ); > + if (Buffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + Status =3D UnicodeStrToAsciiStrS (Password, VerifyPassword->Password, > sizeof(VerifyPassword->Password)); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + > + Status =3D SendCommunicateBuffer (Buffer, sizeof(*VerifyPassword)); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > +EXIT: > + ZeroMem (VerifyPassword, sizeof(*VerifyPassword)); > + return Status; > +} > + > +/** > + Set a new password. > + > + @param[in] UserGuid The user GUID of the password. > + @param[in] NewPassword The user input new password. > + NULL means clear password. > + @param[in] NewPasswordSize The size of NewPassword in byte. > + @param[in] OldPassword The user input old password. > + NULL means no old password. > + @param[in] OldPasswordSize The size of OldPassword in byte. > + > + @retval EFI_SUCCESS The password is correct. > + @retval EFI_SECURITY_VIOLATION The password is incorrect. > + @retval EFI_OUT_OF_RESOURCES Insufficient resources to set the > password. > +**/ > +EFI_STATUS > +SetPassword ( > + IN EFI_GUID *UserGuid, > + IN CHAR16 *NewPassword, OPTIONAL > + IN UINTN NewPasswordSize, > + IN CHAR16 *OldPassword, OPTIONAL > + IN UINTN OldPasswordSize > + ) > +{ > + EFI_STATUS Status; > + VOID *Buffer; > + SMM_PASSWORD_COMMUNICATE_SET_PASSWORD *SetPassword; > + > + if (NewPasswordSize > sizeof(SetPassword->NewPassword) * > sizeof(CHAR16)) { > + return EFI_INVALID_PARAMETER; > + } > + if (OldPasswordSize > sizeof(SetPassword->OldPassword) * > sizeof(CHAR16)) { > + return EFI_INVALID_PARAMETER; > + } > + > + Buffer =3D InitCommunicateBuffer ( > + (VOID**)&SetPassword, > + sizeof(*SetPassword), > + SMM_PASSWORD_FUNCTION_SET_PASSWORD, > + UserGuid > + ); > + if (Buffer =3D=3D NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + if (NewPassword !=3D NULL) { > + Status =3D UnicodeStrToAsciiStrS (NewPassword, SetPassword- > >NewPassword, sizeof(SetPassword->NewPassword)); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + } else { > + SetPassword->NewPassword[0] =3D 0; > + } > + > + if (OldPassword !=3D NULL) { > + Status =3D UnicodeStrToAsciiStrS (OldPassword, SetPassword- > >OldPassword, sizeof(SetPassword->OldPassword)); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + } else { > + SetPassword->OldPassword[0] =3D 0; > + } > + > + Status =3D SendCommunicateBuffer (Buffer, sizeof(*SetPassword)); > + if (EFI_ERROR (Status)) { > + goto EXIT; > + } > + > +EXIT: > + ZeroMem (SetPassword, sizeof(*SetPassword)); > + return Status; > +} > + > +/** > + Return if the password is set. > + > + @param[in] UserGuid The user GUID of the password. > + > + @retval TRUE The password is set. > + @retval FALSE The password is not set. > +**/ > +BOOLEAN > +IsPasswordSet ( > + IN EFI_GUID *UserGuid > + ) > +{ > + EFI_STATUS Status; > + VOID *Buffer; > + > + Buffer =3D InitCommunicateBuffer ( > + NULL, > + 0, > + SMM_PASSWORD_FUNCTION_IS_PASSWORD_SET, > + UserGuid > + ); > + if (Buffer =3D=3D NULL) { > + return FALSE; > + } > + > + Status =3D SendCommunicateBuffer (Buffer, 0); > + if (EFI_ERROR (Status)) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Main entry for this driver. > + > + @param ImageHandle Image handle this driver. > + @param SystemTable Pointer to SystemTable. > + > + @retval EFI_SUCESS This function always complete successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +PasswordDxeInit ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, > NULL, (VOID **) &mSmmCommunication); > + ASSERT_EFI_ERROR (Status); > + > + return EFI_SUCCESS; > +} > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeStrings. > uni > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeStrings > .uni > new file mode 100644 > index 0000000..86fde22 > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeStrings > .uni > @@ -0,0 +1,29 @@ > +/** @file > +// String definitions for User Authentication formset. > + > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license ma= y be > found at > +// http://opensource.org/licenses/bsd-license.php > + > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#langdef en-US "English" > +#langdef fr-FR "Francais" > + > + > +#string STR_FORM_SET_TITLE #language en-US "User Password > Management" > + #language fr-FR "User Password Ma= nagement" > +#string STR_FORM_SET_TITLE_HELP #language en-US "This Driver > mainly handle user's password" > + #language fr-FR "This Driver main= ly handle user's > password" > +#string STR_FORM_TITLE #language en-US "Password Managem= ent > Form" > + #language fr-FR "Password Managem= ent Form" > +#string STR_ADMIN_PASSWORD_PROMPT #language en-US "Change > Admin Password" > + #language fr-FR "Change Admin Pas= sword" > +#string STR_ADMIN_PASSWORD_HELP #language en-US "Input old > admin password, then you can change the password to a new one. After the > change action, you need input the new password when you enter UI. The > new password must be at least 8 char and include lowercase, uppercase > alphabetic, numbers, and symbols." > + #language fr-FR "Input old admin = password, then you > can change the password to a new one. After the change action, you need > input the new password when you enter UI. The new password must be at > least 8 char and include lowercase, uppercase alphabetic, numbers, and > symbols." > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeVfr.vfr > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeVfr.vfr > new file mode 100644 > index 0000000..4741fe3 > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeVfr.vfr > @@ -0,0 +1,38 @@ > +///** @file > +// UserAuthentication formset. > +// > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license ma= y be > found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +//**/ > + > +#include > +#include "UserAuthenticationDxeFormset.h" > + > +formset > + guid =3D USER_AUTHENTICATION_FORMSET_GUID, > + title =3D STRING_TOKEN(STR_FORM_SET_TITLE), > + help =3D STRING_TOKEN(STR_FORM_SET_TITLE_HELP), > + classguid =3D EFI_HII_PLATFORM_SETUP_FORMSET_GUID, > + > + form formid =3D 1, > + title =3D STRING_TOKEN(STR_FORM_TITLE); > + > + password > + prompt =3D STRING_TOKEN(STR_ADMIN_PASSWORD_PROMPT), > + help =3D STRING_TOKEN(STR_ADMIN_PASSWORD_HELP), > + flags =3D INTERACTIVE, > + key =3D ADMIN_PASSWORD_KEY_ID, > + minsize =3D MIN_PASSWORD_LEN, > + maxsize =3D MAX_PASSWORD_LEN, > + endpassword; > + > + endform; > + > +endformset; > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationGuid.h > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationGuid.h > new file mode 100644 > index 0000000..0a4df01 > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationGuid.h > @@ -0,0 +1,65 @@ > +/** @file > + GUID is for UserPassword variable. > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials are licensed and made > available under > +the terms and conditions of the BSD License that accompanies this > distribution. > +The full text of the license may be found at > +http://opensource.org/licenses/bsd-license.php. > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#ifndef __USER_AUTHENTICATION_GUID_H__ > +#define __USER_AUTHENTICATION_GUID_H__ > + > +#define PASSWORD_MIN_SIZE 9 // MIN number of char of password, > including NULL > +#define PASSWORD_MAX_SIZE 32 // MAX number of char of password, > including NULL > +#define PASSWORD_SALT_SIZE 32 > +#define PASSWORD_HASH_SIZE 32 // SHA256_DIGEST_SIZE > + > +#define PASSWORD_MAX_TRY_COUNT 3 > +#define PASSWORD_HISTORY_CHECK_COUNT 5 > + > +// > +// Vendor GUID of the variable > +// > +#define ADMIN_AUTHENTICATION_GUID \ > + { 0xee24a7f7, 0x606b, 0x4724, { 0xb3, 0xc9, 0xf5, 0xae, 0x4a, 0x3b, 0x= 81, > 0x65} } > + > +// > +// Name of the variable > +// > +#define USER_AUTHENTICATION_VAR_NAME L"Password" > +#define USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME > L"PasswordLast" > + > +// > +// Variable storage > +// > +typedef struct { > + UINT8 PasswordHash[PASSWORD_HASH_SIZE]; > + UINT8 PasswordSalt[PASSWORD_SALT_SIZE]; > +} USER_PASSWORD_VAR_STRUCT; > + > +typedef struct { > + UINTN Function; > + EFI_STATUS ReturnStatus; > + EFI_GUID UserGuid; > +} SMM_PASSWORD_COMMUNICATE_HEADER; > + > +#define SMM_PASSWORD_FUNCTION_IS_PASSWORD_SET 1 > +#define SMM_PASSWORD_FUNCTION_SET_PASSWORD 2 > +#define SMM_PASSWORD_FUNCTION_VERIFY_PASSWORD 3 > + > +typedef struct { > + CHAR8 NewPassword[PASSWORD_MAX_SIZE]; > + CHAR8 OldPassword[PASSWORD_MAX_SIZE]; > +} SMM_PASSWORD_COMMUNICATE_SET_PASSWORD; > + > +typedef struct { > + CHAR8 Password[PASSWORD_MAX_SIZE]; > +} SMM_PASSWORD_COMMUNICATE_VERIFY_PASSWORD; > + > +#endif > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.c > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.c > new file mode 100644 > index 0000000..ffc3d81 > --- /dev/null > +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.c > @@ -0,0 +1,672 @@ > +/** @file > + > +Copyright (c) 2017, Intel Corporation. All rights reserved.
> +This program and the accompanying materials > +are licensed and made available under the terms and conditions of the BS= D > License > +which accompanies this distribution. The full text of the license may b= e > found at > +http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "KeyService.h" > +#include "UserAuthenticationGuid.h" > + > +EFI_GUID gAdminAuthenticationGuid =3D ADMIN_AUTHENTICATION_GUID; > + > +EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable; > + > +UINTN mAdminPasswordTryCount; > + > +/** > + Verify if the password is correct. > + > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + @param[in] UserPasswordVarStruct The storage of password in variable= . > + > + @retval EFI_SUCCESS The password is correct. > + @retval EFI_SECURITY_VIOLATION The password is incorrect. > +**/ > +EFI_STATUS > +VerifyPassword ( > + IN CHAR8 *Password, > + IN UINTN PasswordSize, > + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct > + ) > +{ > + BOOLEAN HashOk; > + UINT8 HashData[PASSWORD_HASH_SIZE]; > + > + HashOk =3D KeyLibGeneratePBKDF2Hash ( > + HASH_TYPE_SHA256, > + (UINT8 *)Password, > + PasswordSize, > + UserPasswordVarStruct->PasswordSalt, > + sizeof(UserPasswordVarStruct->PasswordSalt), > + HashData, > + sizeof(HashData) > + ); > + if (!HashOk) { > + return EFI_DEVICE_ERROR; > + } > + if (KeyLibSlowCompareMem (UserPasswordVarStruct->PasswordHash, > HashData, PASSWORD_HASH_SIZE) =3D=3D 0) { > + return EFI_SUCCESS; > + } else { > + return EFI_SECURITY_VIOLATION; > + } > +} > + > +/** > + Get hash data of password from non-volatile variable region. > + > + @param[in] UserGuid The user GUID of the password vari= able. > + @param[in] Index The index of the password. > + 0 means current password. > + Non-0 means the password history. > + @param[out] UserPasswordVarStruct The storage of password in variabl= e. > + > + @retval EFI_SUCCESS The password hash is returned successf= ully. > + @retval EFI_NOT_FOUND The password hash is not found. > +**/ > +EFI_STATUS > +GetPasswordHashFromVariable ( > + IN EFI_GUID *UserGuid, > + IN UINTN Index, > + OUT USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct > + ) > +{ > + EFI_STATUS Status; > + UINTN DataSize; > + CHAR16 > PasswordName[sizeof(USER_AUTHENTICATION_VAR_NAME)/sizeof(CHAR1 > 6) + 4]; > + > + if (Index !=3D 0) { > + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s%04x", > USER_AUTHENTICATION_VAR_NAME, Index); > + } else { > + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s", > USER_AUTHENTICATION_VAR_NAME); > + } > + > + DataSize =3D sizeof(*UserPasswordVarStruct); > + Status =3D mSmmVariable->SmmGetVariable ( > + PasswordName, > + UserGuid, > + NULL, > + &DataSize, > + UserPasswordVarStruct > + ); > + if (EFI_ERROR(Status)) { > + return Status; > + } > + > + return Status; > +} > + > +/** > + Save password hash data to non-volatile variable region. > + > + @param[in] UserGuid The user GUID of the password vari= able. > + @param[in] UserPasswordVarStruct The storage of password in variabl= e. > + > + @retval EFI_SUCCESS The password hash is saved successfull= y. > + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the > password hash. > +**/ > +EFI_STATUS > +SavePasswordHashToVariable ( > + IN EFI_GUID *UserGuid, > + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct > + ) > +{ > + EFI_STATUS Status; > + > + if (UserPasswordVarStruct =3D=3D NULL) { > + Status =3D mSmmVariable->SmmSetVariable ( > + USER_AUTHENTICATION_VAR_NAME, > + UserGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_NON_VOLATILE, > + 0, > + NULL > + ); > + } else { > + Status =3D mSmmVariable->SmmSetVariable ( > + USER_AUTHENTICATION_VAR_NAME, > + UserGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_NON_VOLATILE, > + sizeof(*UserPasswordVarStruct), > + UserPasswordVarStruct > + ); > + } > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "SavePasswordHashToVariable fails with %r\n", > Status)); > + } > + > + return Status; > +} > + > +/** > + Save old password hash data to non-volatile variable region as history= . > + > + The number of password history variable is limited. > + If all the password history variables are used, the new password histo= ry > + will override the oldest one. > + > + @param[in] UserGuid The user GUID of the password vari= able. > + @param[in] UserPasswordVarStruct The storage of password in variabl= e. > + > + @retval EFI_SUCCESS The password hash is saved successfull= y. > + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the > password hash. > +**/ > +EFI_STATUS > +SaveOldPasswordToHistory ( > + IN EFI_GUID *UserGuid, > + IN USER_PASSWORD_VAR_STRUCT *UserPasswordVarStruct > + ) > +{ > + EFI_STATUS Status; > + UINTN DataSize; > + UINT32 LastIndex; > + CHAR16 > PasswordName[sizeof(USER_AUTHENTICATION_VAR_NAME)/sizeof(CHAR1 > 6) + 4]; > + > + DEBUG ((DEBUG_INFO, "SaveOldPasswordToHistory\n")); > + > + DataSize =3D sizeof(LastIndex); > + Status =3D mSmmVariable->SmmGetVariable ( > + USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME, > + UserGuid, > + NULL, > + &DataSize, > + &LastIndex > + ); > + if (EFI_ERROR(Status)) { > + LastIndex =3D 0; > + } > + if (LastIndex >=3D PASSWORD_HISTORY_CHECK_COUNT) { > + LastIndex =3D 0; > + } > + > + LastIndex ++; > + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s%04x", > USER_AUTHENTICATION_VAR_NAME, LastIndex); > + > + > + Status =3D mSmmVariable->SmmSetVariable ( > + PasswordName, > + UserGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_NON_VOLATILE, > + sizeof(*UserPasswordVarStruct), > + UserPasswordVarStruct > + ); > + DEBUG ((DEBUG_INFO, " -- to %s, %r\n", PasswordName, Status)); > + if (!EFI_ERROR(Status)) { > + Status =3D mSmmVariable->SmmSetVariable ( > + USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME, > + UserGuid, > + EFI_VARIABLE_BOOTSERVICE_ACCESS | > EFI_VARIABLE_NON_VOLATILE, > + sizeof(LastIndex), > + &LastIndex > + ); > + DEBUG ((DEBUG_INFO, " LastIndex - 0x%04x, %r\n", LastIndex, Status))= ; > + } > + > + return Status; > +} > + > +/** > + Calculate password hash data and save it to non-volatile variable regi= on. > + > + @param[in] UserGuid The user GUID of the password varia= ble. > + @param[in] Password The user input password. > + NULL means delete the password vari= able. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval EFI_SUCCESS The password hash is calculated and sa= ved. > + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the > password hash. > +**/ > +EFI_STATUS > +SavePasswordToVariable ( > + IN EFI_GUID *UserGuid, > + IN CHAR8 *Password, OPTIONAL > + IN UINTN PasswordSize > + ) > +{ > + EFI_STATUS Status; > + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; > + BOOLEAN HashOk; > + > + // > + // If password is NULL, it means we want to clean password field saved= in > variable region. > + // > + if (Password !=3D NULL) { > + KeyLibGenerateSalt (UserPasswordVarStruct.PasswordSalt, > sizeof(UserPasswordVarStruct.PasswordSalt)); > + HashOk =3D KeyLibGeneratePBKDF2Hash ( > + HASH_TYPE_SHA256, > + (UINT8 *)Password, > + PasswordSize, > + UserPasswordVarStruct.PasswordSalt, > + sizeof(UserPasswordVarStruct.PasswordSalt), > + UserPasswordVarStruct.PasswordHash, > + sizeof(UserPasswordVarStruct.PasswordHash) > + ); > + if (!HashOk) { > + return EFI_DEVICE_ERROR; > + } > + Status =3D SavePasswordHashToVariable (UserGuid, > &UserPasswordVarStruct); > + // > + // Save Password data to history variable > + // > + if (!EFI_ERROR(Status)) { > + SaveOldPasswordToHistory (UserGuid, &UserPasswordVarStruct); > + } > + } else { > + Status =3D SavePasswordHashToVariable (UserGuid, NULL); > + } > + > + return Status; > +} > + > +/** > + Verify the password. > + If the password variable does not exist, it passes the verification. > + If the password variable exists, it does verification based upon passw= ord > variable. > + > + @param[in] UserGuid The user GUID of the password varia= ble. > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval TRUE The verification passes. > + @retval FALSE The verification fails. > +**/ > +BOOLEAN > +IsPasswordVerified ( > + IN EFI_GUID *UserGuid, > + IN CHAR8 *Password, > + IN UINTN PasswordSize > + ) > +{ > + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; > + EFI_STATUS Status; > + > + Status =3D GetPasswordHashFromVariable (UserGuid, 0, > &UserPasswordVarStruct); > + if (EFI_ERROR(Status)) { > + return TRUE; > + } > + > + // > + // Old password exists > + // > + Status =3D VerifyPassword (Password, PasswordSize, > &UserPasswordVarStruct); > + if (EFI_ERROR(Status)) { > + return FALSE; > + } > + > + return TRUE; > +} > + > +/** > + Return if the password is set. > + > + @param[in] UserGuid The user GUID of the password varia= ble. > + > + @retval TRUE The password is set. > + @retval FALSE The password is not set. > +**/ > +BOOLEAN > +IsPasswordSet ( > + IN EFI_GUID *UserGuid > + ) > +{ > + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; > + EFI_STATUS Status; > + > + Status =3D GetPasswordHashFromVariable(UserGuid, 0, > &UserPasswordVarStruct); > + if (EFI_ERROR(Status)) { > + return FALSE; > + } > + return TRUE; > +} > + > +/** > + Return if the password is strong. > + Criteria: > + 1) length >=3D PASSWORD_MIN_SIZE > + 2) include lower case, upper case, number, symbol. > + > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval TRUE The password is strong. > + @retval FALSE The password is weak. > +**/ > +BOOLEAN > +IsPasswordStrong ( > + IN CHAR8 *Password, > + IN UINTN PasswordSize > + ) > +{ > + UINTN Index; > + BOOLEAN HasLowerCase; > + BOOLEAN HasUpperCase; > + BOOLEAN HasNumber; > + BOOLEAN HasSymbol; > + > + if (PasswordSize < PASSWORD_MIN_SIZE) { > + return FALSE; > + } > + > + HasLowerCase =3D FALSE; > + HasUpperCase =3D FALSE; > + HasNumber =3D FALSE; > + HasSymbol =3D FALSE; > + for (Index =3D 0; Index < PasswordSize - 1; Index++) { > + if (Password[Index] >=3D 'a' && Password[Index] <=3D 'z') { > + HasLowerCase =3D TRUE; > + } else if (Password[Index] >=3D 'A' && Password[Index] <=3D 'Z') { > + HasUpperCase =3D TRUE; > + } else if (Password[Index] >=3D '0' && Password[Index] <=3D '9') { > + HasNumber =3D TRUE; > + } else { > + HasSymbol =3D TRUE; > + } > + } > + if ((!HasLowerCase) || (!HasUpperCase) || (!HasNumber) || (!HasSymbol)= ) > { > + return FALSE; > + } > + return TRUE; > +} > + > +/** > + Return if the password is set before in > PASSWORD_HISTORY_CHECK_COUNT. > + > + @param[in] UserGuid The user GUID of the password varia= ble. > + @param[in] Password The user input password. > + @param[in] PasswordSize The size of Password in byte. > + > + @retval TRUE The password is set before. > + @retval FALSE The password is not set before. > +**/ > +BOOLEAN > +IsPasswordInHistory ( > + IN EFI_GUID *UserGuid, > + IN CHAR8 *Password, > + IN UINTN PasswordSize > + ) > +{ > + EFI_STATUS Status; > + USER_PASSWORD_VAR_STRUCT UserPasswordVarStruct; > + UINTN Index; > + > + for (Index =3D 1; Index <=3D PASSWORD_HISTORY_CHECK_COUNT; Index++) { > + Status =3D GetPasswordHashFromVariable (UserGuid, Index, > &UserPasswordVarStruct); > + if (!EFI_ERROR(Status)) { > + Status =3D VerifyPassword (Password, PasswordSize, > &UserPasswordVarStruct); > + if (!EFI_ERROR(Status)) { > + return TRUE; > + } > + } > + } > + > + return FALSE; > +} > + > +/** > + Communication service SMI Handler entry. > + > + This SMI handler provides services for password management. > + > + @param[in] DispatchHandle The unique handle assigned to this hand= ler > by SmiHandlerRegister(). > + @param[in] RegisterContext Points to an optional handler context w= hich > was specified when the > + handler was registered. > + @param[in, out] CommBuffer A pointer to a collection of data in > memory that will > + be conveyed from a non-SMM environment = into an SMM > environment. > + @param[in, out] CommBufferSize The size of the CommBuffer. > + > + @retval EFI_SUCCESS The interrupt was handled = and quiesced. > No other handlers > + should still be called. > + @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has > been quiesced but other handlers should > + still be called. > + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still > pending and other handlers should still > + be called. > + @retval EFI_INTERRUPT_PENDING The interrupt could not be > quiesced. > +**/ > +EFI_STATUS > +EFIAPI > +SmmPasswordHandler ( > + IN EFI_HANDLE DispatchHandle, > + IN CONST VOID *RegisterContext, > + IN OUT VOID *CommBuffer, > + IN OUT UINTN *CommBufferSize > + ) > +{ > + EFI_STATUS Status; > + SMM_PASSWORD_COMMUNICATE_HEADER *SmmFunctionHeader; > + UINTN CommBufferPayloadSize; > + UINTN TempCommBufferSize; > + SMM_PASSWORD_COMMUNICATE_SET_PASSWORD > SmmCommunicateSetPassword; > + SMM_PASSWORD_COMMUNICATE_VERIFY_PASSWORD > SmmCommunicateVerifyPassword; > + UINTN PasswordLen; > + EFI_GUID UserGuid; > + UINTN *PasswordTryCount; > + > + // > + // If input is invalid, stop processing this SMI > + // > + if (CommBuffer =3D=3D NULL || CommBufferSize =3D=3D NULL) { > + return EFI_SUCCESS; > + } > + > + TempCommBufferSize =3D *CommBufferSize; > + > + if (TempCommBufferSize < sizeof > (SMM_PASSWORD_COMMUNICATE_HEADER)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: SMM communication > buffer size invalid!\n")); > + return EFI_SUCCESS; > + } > + > + CommBufferPayloadSize =3D TempCommBufferSize - sizeof > (SMM_PASSWORD_COMMUNICATE_HEADER); > + > + Status =3D EFI_SUCCESS; > + SmmFunctionHeader =3D (SMM_PASSWORD_COMMUNICATE_HEADER > *)CommBuffer; > + CopyGuid (&UserGuid, &SmmFunctionHeader->UserGuid); > + > + if (CompareGuid (&UserGuid, &gAdminAuthenticationGuid)) { > + PasswordTryCount =3D &mAdminPasswordTryCount; > + } else { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: Invalid UserGuid\n")); > + PasswordTryCount =3D NULL; > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + > + switch (SmmFunctionHeader->Function) { > + case SMM_PASSWORD_FUNCTION_IS_PASSWORD_SET: > + PasswordTryCount =3D NULL; > + if (CommBufferPayloadSize !=3D 0) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: IS_PASSWORD_SET > payload buffer invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + if (IsPasswordSet(&UserGuid)) { > + Status =3D EFI_SUCCESS; > + } else { > + Status =3D EFI_NOT_FOUND; > + } > + break; > + case SMM_PASSWORD_FUNCTION_SET_PASSWORD: > + if (*PasswordTryCount >=3D PASSWORD_MAX_TRY_COUNT) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: SET_PASSWORD try > count reach!\n")); > + PasswordTryCount =3D NULL; > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + if (CommBufferPayloadSize !=3D > sizeof(SMM_PASSWORD_COMMUNICATE_SET_PASSWORD)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: SET_PASSWORD > payload buffer invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + CopyMem (&SmmCommunicateSetPassword, SmmFunctionHeader + 1, > sizeof(SmmCommunicateSetPassword)); > + > + PasswordLen =3D > AsciiStrnLenS(SmmCommunicateSetPassword.OldPassword, > sizeof(SmmCommunicateSetPassword.OldPassword)); > + if (PasswordLen =3D=3D sizeof(SmmCommunicateSetPassword.OldPassword)= ) > { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: OldPassword > invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + > + if (!IsPasswordVerified (&UserGuid, > SmmCommunicateSetPassword.OldPassword, PasswordLen + 1)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: PasswordVerify - > FAIL\n")); > + Status =3D EFI_SECURITY_VIOLATION; > + goto EXIT; > + } > + > + PasswordLen =3D > AsciiStrnLenS(SmmCommunicateSetPassword.NewPassword, > sizeof(SmmCommunicateSetPassword.NewPassword)); > + if (PasswordLen =3D=3D > sizeof(SmmCommunicateSetPassword.NewPassword)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: NewPassword > invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + if (!IsPasswordStrong (SmmCommunicateSetPassword.NewPassword, > PasswordLen + 1)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: NewPassword too > weak!\n")); > + Status =3D EFI_UNSUPPORTED; > + goto EXIT; > + } > + if (IsPasswordInHistory (&UserGuid, > SmmCommunicateSetPassword.NewPassword, PasswordLen + 1)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: NewPassword in > history!\n")); > + Status =3D EFI_ALREADY_STARTED; > + goto EXIT; > + } > + > + if (PasswordLen =3D=3D 0) { > + Status =3D SavePasswordToVariable (&UserGuid, NULL, 0); > + } else { > + Status =3D SavePasswordToVariable (&UserGuid, > SmmCommunicateSetPassword.NewPassword, PasswordLen + 1); > + } > + break; > + > + case SMM_PASSWORD_FUNCTION_VERIFY_PASSWORD: > + if (*PasswordTryCount >=3D PASSWORD_MAX_TRY_COUNT) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: VERIFY_PASSWORD > try count reach!\n")); > + PasswordTryCount =3D NULL; > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + if (CommBufferPayloadSize !=3D > sizeof(SMM_PASSWORD_COMMUNICATE_VERIFY_PASSWORD)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: VERIFY_PASSWORD > payload buffer invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + CopyMem (&SmmCommunicateVerifyPassword, SmmFunctionHeader + > 1, sizeof(SmmCommunicateVerifyPassword)); > + > + PasswordLen =3D > AsciiStrnLenS(SmmCommunicateVerifyPassword.Password, > sizeof(SmmCommunicateVerifyPassword.Password)); > + if (PasswordLen =3D=3D sizeof(SmmCommunicateVerifyPassword.Password)= ) > { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: Password invalid!\n")); > + Status =3D EFI_INVALID_PARAMETER; > + goto EXIT; > + } > + if (!IsPasswordVerified (&UserGuid, > SmmCommunicateVerifyPassword.Password, PasswordLen + 1)) { > + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: PasswordVerify - > FAIL\n")); > + Status =3D EFI_SECURITY_VIOLATION; > + goto EXIT; > + } > + Status =3D EFI_SUCCESS; > + break; > + > + default: > + PasswordTryCount =3D NULL; > + Status =3D EFI_UNSUPPORTED; > + break; > + } > + > +EXIT: > + if (PasswordTryCount !=3D NULL) { > + if (Status =3D=3D EFI_SUCCESS) { > + *PasswordTryCount =3D 0; > + } else { > + *PasswordTryCount =3D *PasswordTryCount + 1; > + } > + } > + SmmFunctionHeader->ReturnStatus =3D Status; > + > + return EFI_SUCCESS; > +} > + > +/** > + Main entry for this driver. > + > + @param ImageHandle Image handle this driver. > + @param SystemTable Pointer to SystemTable. > + > + @retval EFI_SUCESS This function always complete successfully. > + > +**/ > +EFI_STATUS > +EFIAPI > +PasswordSmmInit ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + EFI_HANDLE SmmHandle; > + EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock; > + CHAR16 > PasswordHistoryName[sizeof(USER_AUTHENTICATION_VAR_NAME)/sizeof( > CHAR16) + 4]; > + UINTN Index; > + > + ASSERT (PASSWORD_HASH_SIZE =3D=3D SHA256_DIGEST_SIZE); > + ASSERT (PASSWORD_HISTORY_CHECK_COUNT < 0xFFFF); > + > + Status =3D gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, > NULL, (VOID**)&mSmmVariable); > + ASSERT_EFI_ERROR (Status); > + > + SmmHandle =3D NULL; > + > + // > + // Make "HddPassword" varible read-only for DXE driver for security > concern. > + // > + Status =3D gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, > (VOID **) &VariableLock); > + if (!EFI_ERROR (Status)) { > + Status =3D VariableLock->RequestToLock (VariableLock, > USER_AUTHENTICATION_VAR_NAME, &gAdminAuthenticationGuid); > + ASSERT_EFI_ERROR (Status); > + > + for (Index =3D 1; Index <=3D PASSWORD_HISTORY_CHECK_COUNT; Index++) = { > + UnicodeSPrint (PasswordHistoryName, sizeof (PasswordHistoryName), > L"%s%04x", USER_AUTHENTICATION_VAR_NAME, Index); > + Status =3D VariableLock->RequestToLock (VariableLock, > PasswordHistoryName, &gAdminAuthenticationGuid); > + ASSERT_EFI_ERROR (Status); > + } > + Status =3D VariableLock->RequestToLock (VariableLock, > USER_AUTHENTICATION_HISTORY_LAST_VAR_NAME, > &gAdminAuthenticationGuid); > + ASSERT_EFI_ERROR (Status); > + } > + > + SmmHandle =3D NULL; > + Status =3D gSmst->SmiHandlerRegister (SmmPasswordHandler, > &gAdminAuthenticationGuid, &SmmHandle); > + ASSERT_EFI_ERROR (Status); > + if (EFI_ERROR (Status)) { > + Status =3D EFI_OUT_OF_RESOURCES; > + goto EXIT; > + } > + > + if (IsPasswordCleared()) { > + DEBUG ((DEBUG_INFO, "IsPasswordCleared\n")); > + SavePasswordToVariable (&gAdminAuthenticationGuid, NULL, 0); > + } > + > + return EFI_SUCCESS; > + > +EXIT: > + if (SmmHandle !=3D NULL) { > + gSmst->SmiHandlerUnRegister (SmmHandle); > + } > + > + return Status; > +} > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.inf > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.inf > new file mode 100644 > index 0000000..460809b > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.inf > @@ -0,0 +1,70 @@ > +## @file > +# User Authentication Smm Driver. > +# > +# This driver provides SMM services for DXE user authentication module. > +# > +# Copyright (c) 2017, Intel Corporation. All rights reserved.
> +# > +# This program and the accompanying materials > +# are licensed and made available under the terms and conditions of the > BSD License > +# which accompanies this distribution. The full text of the license may= be > found at > +# http://opensource.org/licenses/bsd-license.php > +# > +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +# > +# > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D UserAuthenticationSmm > + MODULE_UNI_FILE =3D UserAuthenticationSmm.uni > + FILE_GUID =3D 458B03ED-6E53-414f-9F07-3A829C99064= 1 > + MODULE_TYPE =3D DXE_SMM_DRIVER > + VERSION_STRING =3D 1.0 > + PI_SPECIFICATION_VERSION =3D 0x0001000A > + ENTRY_POINT =3D PasswordSmmInit > + > +# > +# The following information is for reference only and not required by th= e > build tools. > +# > +# VALID_ARCHITECTURES =3D IA32 X64 IPF EBC > +# > + > +[Sources] > + UserAuthenticationSmm.c > + UserAuthenticationGuid.h > + KeyService.c > + KeyService.h > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + CryptoPkg/CryptoPkg.dec > + SecurityPkg/SecurityPkg.dec > + > +[LibraryClasses] > + UefiBootServicesTableLib > + UefiDriverEntryPoint > + DebugLib > + BaseLib > + BaseMemoryLib > + PrintLib > + SmmServicesTableLib > + MemoryAllocationLib > + UefiLib > + BaseCryptLib > + PlatformPasswordLib > + > +[Protocols] > + gEdkiiVariableLockProtocolGuid ## CONSUMES > + gEfiSmmVariableProtocolGuid ## CONSUMES > + > +[Depex] > + gEfiSmmVariableProtocolGuid > + > +[UserExtensions.TianoCore."ExtraFiles"] > + UserAuthenticationDxeExtra.uni > + > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.uni > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.uni > new file mode 100644 > index 0000000..470c75c > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmm.uni > @@ -0,0 +1,22 @@ > +// /** @file > +// User Authentication Smm Driver. > +// > +// This driver provides SMM services for DXE user authentication module. > +// > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license may= be > found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "SMM services fo= r > DXE user authentication module." > + > +#string STR_MODULE_DESCRIPTION #language en-US "This driver > provides SMM services for DXE user authentication module." > + > diff --git > a/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmExtra. > uni > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmExtra. > uni > new file mode 100644 > index 0000000..5e338fe > --- /dev/null > +++ > b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmExtra. > uni > @@ -0,0 +1,20 @@ > +// /** @file > +// User Authentication Smm Driver. > +// > +// Copyright (c) 2017, Intel Corporation. All rights reserved.
> +// > +// This program and the accompanying materials > +// are licensed and made available under the terms and conditions of the > BSD License > +// which accompanies this distribution. The full text of the license may= be > found at > +// http://opensource.org/licenses/bsd-license.php > +// > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" > BASIS, > +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER > EXPRESS OR IMPLIED. > +// > +// **/ > + > +#string STR_PROPERTIES_MODULE_NAME > +#language en-US > +"User Authentication SMM Driver" > + > + > -- > 2.7.4.windows.1