From nobody Sat Nov 2 16:34:14 2024 Delivered-To: importer@patchew.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Authentication-Results: mx.zoho.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org; Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1486455889025420.9863458426461; Tue, 7 Feb 2017 00:24:49 -0800 (PST) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 459AE820B4; Tue, 7 Feb 2017 00:24:40 -0800 (PST) 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 01B10820DB for ; Tue, 7 Feb 2017 00:24:38 -0800 (PST) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga102.fm.intel.com with ESMTP; 07 Feb 2017 00:24:38 -0800 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.21.101]) by orsmga005.jf.intel.com with ESMTP; 07 Feb 2017 00:24:37 -0800 X-Original-To: edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,345,1477983600"; d="scan'208";a="61704887" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Tue, 7 Feb 2017 00:24:25 -0800 Message-Id: <1486455866-7896-6-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1486455866-7896-1-git-send-email-jiewen.yao@intel.com> References: <1486455866-7896-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [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: , Cc: Chao Zhang , Qin Long MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 handler 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 will 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 Reviewed-by: Qin Long > Reviewed-by: Qin Long --- 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/UserAuthenticationDxePassword.c |= 301 ++++++++ SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeStrings.uni |= 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.uni |= 20 + 16 files changed, 2533 insertions(+) diff --git a/SecurityPkg/Password/UserAuthentication/KeyService.c b/Securit= yPkg/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 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 IMPLI= ED. + +**/ + +#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 D= estinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned= . Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted f= rom 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 AS= SERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(= ). + + @param DestinationBuffer The pointer to the destination buffer to compa= re. + @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 identi= cal. + @retval -1 The SourceBuffer is not identical to Destinati= onBuffer. + +**/ +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 NULL= )) { + 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/Securit= yPkg/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 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 IMPLI= ED. + +**/ + +#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 D= estinationBuffer. + If all Length bytes of the two buffers are identical, then 0 is returned= . Otherwise, the + value returned is the first mismatched byte in SourceBuffer subtracted f= rom 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 AS= SERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(= ). + + @param DestinationBuffer The pointer to the destination buffer to compa= re. + @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 identi= cal. + @retval -1 The SourceBuffer is not identical to Destinati= onBuffer. + +**/ +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 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 IMPLI= ED. + +**/ + +#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 && InputLength = > 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(UserInputP= w)); + 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), N= ULL, 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 soft= ware entity. + This included information about the class and subc= lass that is used to classify the entity + as well as an operation. For progress codes, the = operation is the current activity. + For error codes, it is the exception. For debug c= odes, it is not defined at this time. + Type EFI_STATUS_CODE_VALUE is defined in "Related = Definitions" below. + Specific values are discussed in the Intel? Platfo= rm Innovation Framework for EFI Status Code Specification. + + @param Instance The enumeration of a hardware or software entity w= ithin the system. + A system may contain multiple entities that match = a class/subclass pairing. + The instance differentiates between them. An inst= ance of 0 indicates that instance information is unavailable, + not meaningful, or not relevant. Valid instance n= umbers start with 1. + + + @param CallerId This optional parameter may be used to identify th= e caller. + This parameter allows the status code driver to ap= ply different rules to different callers. + Type EFI_GUID is defined in InstallProtocolInterfa= ce() in the UEFI 2.0 Specification. + + + @param Data This optional parameter may be used to pass additi= onal 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 o= ne + or more named elements from the target driver. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTO= COL. + @param Request A null-terminated Unicode string in + format. + @param Progress On return, points to a character in the R= equest + string. Points to the string's null termi= nator if + request was successful. Points to the mos= t recent + '&' before the first failing name/value p= air (or + the beginning of the string if the failur= e is in + the first name/value pair) if the request= was not + successful. + @param Results A null-terminated Unicode string in + format which has all valu= es filled + in for the names in the Request string. S= tring to + be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested = values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown nam= e. + @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_PROTO= COL. + @param Configuration A null-terminated Unicode string in + format. + @param Progress A pointer to a string filled in with the = offset of + the most recent '&' before the first fail= ing + name/value pair (or the beginning of the = string if + the failure is in the first name/value pa= ir) or + the terminating NULL if all was successfu= l. + + @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_PROTO= COL. + @param Action Specifies the type of action taken by the= browser. + @param QuestionId A unique value which is sent to the origi= nal + exporting driver so that it can identify = 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 o= riginal + exporting driver. + @param ActionRequest On return, points to the action requested= by the + callback function. + + @retval EFI_SUCCESS The callback successfully handled the act= ion. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold t= he + variable and its data. + @retval EFI_DEVICE_ERROR The variable could not be saved. + @retval EFI_UNSUPPORTED The specified Action is not supported by = 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_S= ET_PASSWORD)) { + mUserAuthenticationData->PasswordState =3D BROWSER_STATE_VALIDAT= E_PASSWORD; + ZeroMem (mUserAuthenticationData->OldPassword, sizeof(mUserAuthe= nticationData->OldPassword)); + return EFI_INVALID_PARAMETER; + } + // + // The Callback is responsible for validating old password input b= y user, + // If Callback return EFI_SUCCESS, it indicates validation pass. + // + switch (mUserAuthenticationData->PasswordState) { + case BROWSER_STATE_VALIDATE_PASSWORD: + UserInputPassword =3D HiiGetString (mUserAuthenticationData->Hii= Handle, Value->string, NULL); + if ((StrLen (UserInputPassword) >=3D PASSWORD_MAX_SIZE) || (User= InputPassword[0] =3D=3D 0)) { + Status =3D EFI_NOT_READY; + break; + } + Status =3D ValidatePassword (UserGuid, UserInputPassword, StrSiz= e (UserInputPassword)); + if (Status =3D=3D EFI_SUCCESS) { + mUserAuthenticationData->PasswordState =3D BROWSER_STATE_SET_P= ASSWORD; + StrCpyS ( + mUserAuthenticationData->OldPassword, + sizeof(mUserAuthenticationData->OldPassword)/sizeof(CHAR16), + UserInputPassword + ); + *PasswordTryCount =3D 0; + } else { + // + // Old password mismatch, return EFI_NOT_READY to prompt for e= rror 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->Hii= Handle, Value->string, NULL); + if ((StrLen (UserInputPassword) >=3D PASSWORD_MAX_SIZE) || (User= InputPassword[0] =3D=3D 0)) { + Status =3D EFI_NOT_READY; + break; + } + Status =3D SetPassword (UserGuid, UserInputPassword, StrSize (Us= erInputPassword), mUserAuthenticationData->OldPassword, StrSize(mUserAuthen= ticationData->OldPassword)); + PrintPasswordStatus (Status); + ZeroMem (mUserAuthenticationData->OldPassword, sizeof(mUserAuthe= nticationData->OldPassword)); + mUserAuthenticationData->PasswordState =3D BROWSER_STATE_VALIDAT= E_PASSWORD; + break; + + default: + break; + } + default: + break; + } + } + default: + break; + } + return Status; +} + +/** + Unregister status code callback functions. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, wh= ich 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_AUTHENTICATIO= N_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 UserAuthenticationCal= lback; + mUserAuthenticationData->PasswordState =3D BROWSER_STATE_VALIDATE_PASSWO= RD; + + // + // 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 E= vent. + // + 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 unl= oaded. + + @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 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 IMPLI= ED. + + +**/ + +#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 passw= ord. +**/ +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 B= SD 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 IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D UserAuthenticationDxe + MODULE_UNI_FILE =3D UserAuthenticationDxe.uni + FILE_GUID =3D 0683FB88-664C-4BA6-9ED4-1C0916EE43A4 + 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 B= SD 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 IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "User Authenticati= on Dxe Driver." + +#string STR_MODULE_DESCRIPTION #language en-US "This driver mainl= y does user authentication before entering Setup." + diff --git a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeE= xtra.uni b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExt= ra.uni new file mode 100644 index 0000000..86c5c9b --- /dev/null +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeExtra.uni @@ -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 B= SD 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 IM= PLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"User Authentication DXE Driver" + + diff --git a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeF= ormset.h b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeFor= mset.h new file mode 100644 index 0000000..4d29a5d --- /dev/null +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeFormset.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 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 IMPLI= ED. + + +**/ + +#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, 0x75,= 0xfa} } + +#define ADMIN_PASSWORD_KEY_ID 0x2001 + +#define MAX_PASSWORD_LEN 20 +#define MIN_PASSWORD_LEN 8 + +#endif diff --git a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeP= assword.c b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePa= ssword.c new file mode 100644 index 0000000..00b051a --- /dev/null +++ b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxePassword= .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 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 IMPLI= ED. + +**/ + +#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 communicate = buffer. + @param[in] DataSize The data size to send to SMM. + @param[in] Function The function number to initialize the = 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, Dat= a) + sizeof (SMM_PASSWORD_COMMUNICATE_HEADER))) { + break; + } + } + SmmCommMemRegion =3D (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) SmmCommMemRe= gion + 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 *) SmmCom= municateHeader->Data; + ZeroMem (SmmPasswordFunctionHeader, DataSize + sizeof (SMM_PASSWORD_COMM= UNICATE_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 communicat= e buffer. + @param[in] DataSize This size of the function header and= the data. + + @retval EFI_SUCCESS Success is returned from the functin= in SMM. + @retval Others Failure is returned from the functio= n 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) + s= izeof (SMM_PASSWORD_COMMUNICATE_HEADER); + + Status =3D mSmmCommunication->Communicate (mSmmCommunication, Buffer, &C= ommSize); + ASSERT_EFI_ERROR (Status); + + SmmCommunicateHeader =3D (EFI_SMM_COMMUNICATE_HEADER *) Buffer; + SmmPasswordFunctionHeader =3D (SMM_PASSWORD_COMMUNICATE_HEADER *)SmmComm= unicateHeader->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, si= zeof(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 passw= ord. +**/ +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->NewPasswor= d, sizeof(SetPassword->NewPassword)); + if (EFI_ERROR(Status)) { + return Status; + } + } else { + SetPassword->NewPassword[0] =3D 0; + } + + if (OldPassword !=3D NULL) { + Status =3D UnicodeStrToAsciiStrS (OldPassword, SetPassword->OldPasswor= d, 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/UserAuthenticationDxeS= trings.uni b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeS= trings.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 B= SD 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 IM= PLIED. + +**/ + +#langdef en-US "English" +#langdef fr-FR "Francais" + + +#string STR_FORM_SET_TITLE #language en-US "User Password Mana= gement" + #language fr-FR "User Password Mana= gement" +#string STR_FORM_SET_TITLE_HELP #language en-US "This Driver mainly= handle user's password" + #language fr-FR "This Driver mainly= handle user's password" +#string STR_FORM_TITLE #language en-US "Password Managemen= t Form" + #language fr-FR "Password Managemen= t Form" +#string STR_ADMIN_PASSWORD_PROMPT #language en-US "Change Admin Passw= ord" + #language fr-FR "Change Admin Passw= ord" +#string STR_ADMIN_PASSWORD_HELP #language en-US "Input old admin pa= ssword, then you can change the password to a new one. After the change act= ion, you need input the new password when you enter UI. The new password mu= st be at least 8 char and include lowercase, uppercase alphabetic, numbers,= and symbols." + #language fr-FR "Input old admin pa= ssword, then you can change the password to a new one. After the change act= ion, you need input the new password when you enter UI. The new password mu= st be at least 8 char and include lowercase, uppercase alphabetic, numbers,= and symbols." + diff --git a/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeV= fr.vfr b/SecurityPkg/Password/UserAuthentication/UserAuthenticationDxeVfr.v= fr 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 B= SD 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 IM= PLIED. + +//**/ + +#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 availabl= e under +the terms and conditions of the BSD License that accompanies this distribu= tion. +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 IMPLI= ED. + +**/ + +#ifndef __USER_AUTHENTICATION_GUID_H__ +#define __USER_AUTHENTICATION_GUID_H__ + +#define PASSWORD_MIN_SIZE 9 // MIN number of char of password, includi= ng NULL +#define PASSWORD_MAX_SIZE 32 // MAX number of char of password, includi= ng 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, 0x81= , 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 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 IMPLI= ED. + +**/ + +#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 variab= le. + @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 variable. + + @retval EFI_SUCCESS The password hash is returned successful= ly. + @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_AUTHENTICATIO= N_VAR_NAME)/sizeof(CHAR16) + 4]; + + if (Index !=3D 0) { + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s%04x", USER_AU= THENTICATION_VAR_NAME, Index); + } else { + UnicodeSPrint (PasswordName, sizeof (PasswordName), L"%s", USER_AUTHEN= TICATION_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 variab= le. + @param[in] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password hash is saved successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the passw= ord 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_VARIABL= E_NON_VOLATILE, + 0, + NULL + ); + } else { + Status =3D mSmmVariable->SmmSetVariable ( + USER_AUTHENTICATION_VAR_NAME, + UserGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABL= E_NON_VOLATILE, + sizeof(*UserPasswordVarStruct), + UserPasswordVarStruct + ); + } + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "SavePasswordHashToVariable fails with %r\n", Sta= tus)); + } + + 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 history + will override the oldest one. + + @param[in] UserGuid The user GUID of the password variab= le. + @param[in] UserPasswordVarStruct The storage of password in variable. + + @retval EFI_SUCCESS The password hash is saved successfully. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the passw= ord 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_AUTHENTICATIO= N_VAR_NAME)/sizeof(CHAR16) + 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_AUTH= ENTICATION_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_VARIABL= E_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 region. + + @param[in] UserGuid The user GUID of the password variabl= e. + @param[in] Password The user input password. + NULL means delete the password variab= le. + @param[in] PasswordSize The size of Password in byte. + + @retval EFI_SUCCESS The password hash is calculated and save= d. + @retval EFI_OUT_OF_RESOURCES Insufficient resources to save the passw= ord 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 i= n variable region. + // + if (Password !=3D NULL) { + KeyLibGenerateSalt (UserPasswordVarStruct.PasswordSalt, sizeof(UserPas= swordVarStruct.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, &UserPasswordVarStruc= t); + // + // 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 passwor= d variable. + + @param[in] UserGuid The user GUID of the password variabl= e. + @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, &UserPasswordVarStr= uct); + if (EFI_ERROR(Status)) { + return TRUE; + } + + // + // Old password exists + // + Status =3D VerifyPassword (Password, PasswordSize, &UserPasswordVarStruc= t); + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + +/** + Return if the password is set. + + @param[in] UserGuid The user GUID of the password variabl= e. + + @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, &UserPasswordVarStru= ct); + 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 variabl= e. + @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, &UserPassword= VarStruct); + if (!EFI_ERROR(Status)) { + Status =3D VerifyPassword (Password, PasswordSize, &UserPasswordVarS= truct); + 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 handle= r by SmiHandlerRegister(). + @param[in] RegisterContext Points to an optional handler context whi= ch was specified when the + handler was registered. + @param[in, out] CommBuffer A pointer to a collection of data in memo= ry that will + be conveyed from a non-SMM environment in= to an SMM environment. + @param[in, out] CommBufferSize The size of the CommBuffer. + + @retval EFI_SUCCESS The interrupt was handled an= d quiesced. No other handlers + should still be called. + @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quies= ced but other handlers should + still be called. + @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pendi= ng and other handlers should still + be called. + @retval EFI_INTERRUPT_PENDING The interrupt could not be q= uiesced. +**/ +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 siz= e invalid!\n")); + return EFI_SUCCESS; + } + + CommBufferPayloadSize =3D TempCommBufferSize - sizeof (SMM_PASSWORD_COMM= UNICATE_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 bu= ffer 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 rea= ch!\n")); + PasswordTryCount =3D NULL; + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + if (CommBufferPayloadSize !=3D sizeof(SMM_PASSWORD_COMMUNICATE_SET_PAS= SWORD)) { + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: SET_PASSWORD payload buffe= r invalid!\n")); + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + CopyMem (&SmmCommunicateSetPassword, SmmFunctionHeader + 1, sizeof(Smm= CommunicateSetPassword)); + + PasswordLen =3D AsciiStrnLenS(SmmCommunicateSetPassword.OldPassword, s= izeof(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.OldPassw= ord, PasswordLen + 1)) { + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: PasswordVerify - FAIL\n")); + Status =3D EFI_SECURITY_VIOLATION; + goto EXIT; + } + + PasswordLen =3D AsciiStrnLenS(SmmCommunicateSetPassword.NewPassword, s= izeof(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, Password= Len + 1)) { + DEBUG ((DEBUG_ERROR, "SmmPasswordHandler: NewPassword too weak!\n")); + Status =3D EFI_UNSUPPORTED; + goto EXIT; + } + if (IsPasswordInHistory (&UserGuid, SmmCommunicateSetPassword.NewPassw= ord, 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, SmmCommunicateSetPassw= ord.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 bu= ffer invalid!\n")); + Status =3D EFI_INVALID_PARAMETER; + goto EXIT; + } + CopyMem (&SmmCommunicateVerifyPassword, SmmFunctionHeader + 1, sizeof(= SmmCommunicateVerifyPassword)); + + PasswordLen =3D AsciiStrnLenS(SmmCommunicateVerifyPassword.Password, s= izeof(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.Passw= ord, 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_AU= THENTICATION_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 conc= ern. + // + Status =3D gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (= VOID **) &VariableLock); + if (!EFI_ERROR (Status)) { + Status =3D VariableLock->RequestToLock (VariableLock, USER_AUTHENTICAT= ION_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, PasswordHistor= yName, &gAdminAuthenticationGuid); + ASSERT_EFI_ERROR (Status); + } + Status =3D VariableLock->RequestToLock (VariableLock, USER_AUTHENTICAT= ION_HISTORY_LAST_VAR_NAME, &gAdminAuthenticationGuid); + ASSERT_EFI_ERROR (Status); + } + + SmmHandle =3D NULL; + Status =3D gSmst->SmiHandlerRegister (SmmPasswordHandler, &gAdminAuth= enticationGuid, &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 B= SD 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 IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D UserAuthenticationSmm + MODULE_UNI_FILE =3D UserAuthenticationSmm.uni + FILE_GUID =3D 458B03ED-6E53-414f-9F07-3A829C990641 + 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 the = 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 B= SD 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 IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "SMM services for = DXE user authentication module." + +#string STR_MODULE_DESCRIPTION #language en-US "This driver provi= des SMM services for DXE user authentication module." + diff --git a/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmE= xtra.uni b/SecurityPkg/Password/UserAuthentication/UserAuthenticationSmmExt= ra.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 B= SD 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 IM= PLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"User Authentication SMM Driver" + + --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel