From b36e1e403b916d3263959f5c84ca5061f683e804 Mon Sep 17 00:00:00 2001 From: Konstantin Aladyshev Date: Tue, 20 Feb 2024 11:11:39 +0300 Subject: Add PasswordFormWithHash source code Signed-off-by: Konstantin Aladyshev --- UefiLessonsPkg/PasswordFormWithHash/Data.h | 20 ++ UefiLessonsPkg/PasswordFormWithHash/Form.vfr | 31 ++ .../PasswordFormWithHash/PasswordFormWithHash.c | 317 +++++++++++++++++++++ .../PasswordFormWithHash/PasswordFormWithHash.inf | 28 ++ UefiLessonsPkg/PasswordFormWithHash/Strings.uni | 9 + 5 files changed, 405 insertions(+) create mode 100644 UefiLessonsPkg/PasswordFormWithHash/Data.h create mode 100644 UefiLessonsPkg/PasswordFormWithHash/Form.vfr create mode 100644 UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c create mode 100644 UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf create mode 100644 UefiLessonsPkg/PasswordFormWithHash/Strings.uni (limited to 'UefiLessonsPkg/PasswordFormWithHash') diff --git a/UefiLessonsPkg/PasswordFormWithHash/Data.h b/UefiLessonsPkg/PasswordFormWithHash/Data.h new file mode 100644 index 0000000..a83476d --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Data.h @@ -0,0 +1,20 @@ +#ifndef _DATA_H_ +#define _DATA_H_ + +#define FORMSET_GUID {0xe54b953d, 0x7ddc, 0x455c, {0x8c, 0x1a, 0x59, 0x92, 0xbb, 0xc7, 0x72, 0xc4}} +#define DATAPATH_GUID {0xb289cf9f, 0xf911, 0x41fd, {0x9b, 0xad, 0x2c, 0x92, 0x57, 0x68, 0x86, 0x64}} +#define STORAGE_GUID {0xe7f2d73c, 0x699a, 0x4606, {0x92, 0xb6, 0xa3, 0x5e, 0x49, 0x27, 0xc4, 0xd4}} + +#define PASSWORD_MIN_LEN 6 +#define PASSWORD_MAX_LEN 8 +#define HASHED_PASSWORD_SIZE 64 + +#define KEY_PASSWORD 0x1234 + +#pragma pack(1) +typedef struct { + UINT8 Password[HASHED_PASSWORD_SIZE]; +} VARIABLE_STRUCTURE; +#pragma pack() + +#endif diff --git a/UefiLessonsPkg/PasswordFormWithHash/Form.vfr b/UefiLessonsPkg/PasswordFormWithHash/Form.vfr new file mode 100644 index 0000000..10c1d1f --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Form.vfr @@ -0,0 +1,31 @@ +#include +#include "Data.h" + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(FORMSET_TITLE), + help = STRING_TOKEN(FORMSET_HELP), + + varstore VARIABLE_STRUCTURE, + name = FormData, + guid = STORAGE_GUID; + + defaultstore StandardDefault, + prompt = STRING_TOKEN(STANDARD_DEFAULT_PROMPT), + attribute = 0x0000; + + form + formid = 1, + title = STRING_TOKEN(FORMID1_TITLE); + + password + varid = FormData.Password, + prompt = STRING_TOKEN(PASSWORD_PROMPT), + help = STRING_TOKEN(PASSWORD_HELP), + flags = INTERACTIVE, + key = KEY_PASSWORD, + minsize = PASSWORD_MIN_LEN, + maxsize = PASSWORD_MAX_LEN, + endpassword; + endform; +endformset; diff --git a/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c new file mode 100644 index 0000000..8b3a4fa --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.c @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Data.h" + +extern UINT8 FormBin[]; + +#pragma pack(1) +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; +#pragma pack() + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + DATAPATH_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + + +EFI_HII_HANDLE mHiiHandle = NULL; +EFI_HANDLE mDriverHandle = NULL; +EFI_HII_CONFIG_ACCESS_PROTOCOL mConfigAccess; +EFI_GUID StorageGuid = STORAGE_GUID; +EFI_STRING StorageName = L"FormData"; + +VARIABLE_STRUCTURE FormStorage; + +EFI_SERVICE_BINDING_PROTOCOL* hash2ServiceBinding; +EFI_HASH2_PROTOCOL* hash2Protocol; +EFI_HANDLE hash2ChildHandle = NULL; + +STATIC +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 +) +{ + BOOLEAN AllocatedRequest = FALSE; + + if (Progress == NULL || Results == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((Request != NULL) && !HiiIsConfigHdrMatch(Request, &StorageGuid, StorageName)) { + return EFI_NOT_FOUND; + } + + EFI_STRING ConfigRequest = Request; + if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { + EFI_STRING ConfigRequestHdr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINTN Size = (StrLen(ConfigRequestHdr) + StrLen(L"&OFFSET=0&WIDTH=") + sizeof(UINTN)*2 + 1) * sizeof(CHAR16); + ConfigRequest = AllocateZeroPool(Size); + AllocatedRequest = TRUE; + UnicodeSPrint(ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, sizeof(VARIABLE_STRUCTURE)); + FreePool(ConfigRequestHdr); + } + EFI_STATUS Status = gHiiConfigRouting->BlockToConfig(gHiiConfigRouting, + ConfigRequest, + (UINT8*)&FormStorage, + sizeof(VARIABLE_STRUCTURE), + Results, + Progress); + + if (AllocatedRequest) { + FreePool(ConfigRequest); + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr(Request, L"OFFSET") == NULL) { + *Progress = Request + StrLen(Request); + } + } + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +RouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress +) +{ + if (Configuration == NULL || Progress == NULL) { + return EFI_INVALID_PARAMETER; + } + + UINTN BlockSize = sizeof(VARIABLE_STRUCTURE); + EFI_STATUS Status = gHiiConfigRouting->ConfigToBlock(gHiiConfigRouting, + Configuration, + (UINT8*)&FormStorage, + &BlockSize, + Progress); + + return Status; +} + +BOOLEAN OldPasswordVerified = FALSE; + +EFI_STATUS ComputeStringHash(EFI_STRING Password, UINT8* HashedPassword) +{ + EFI_GUID HashGuid = EFI_HASH_ALGORITHM_SHA512_GUID; + EFI_HASH2_OUTPUT Hash; + EFI_STATUS Status = hash2Protocol->Hash(hash2Protocol, + &HashGuid, + (UINT8*)Password, + StrLen(Password)*sizeof(CHAR16), + &Hash); + if (EFI_ERROR(Status)) { + return Status; + } + CopyMem(HashedPassword, Hash.Sha512Hash, HASHED_PASSWORD_SIZE); + return EFI_SUCCESS; +} + +EFI_STATUS HandlePasswordInput(EFI_STRING Password) +{ + EFI_STATUS Status; + + if (Password[0] == 0) { + // Form Browser checks if password exists + if (FormStorage.Password[0] != 0) { + return EFI_ALREADY_STARTED; + } else { + return EFI_SUCCESS; + } + } else { + // Form Browser sends password value + // It can be old password to check or initial/updated password to set + + if (FormStorage.Password[0] == 0) { + // Set initial password + ComputeStringHash(Password, FormStorage.Password); + if (EFI_ERROR(Status)) { + return Status; + } + return EFI_SUCCESS; + } + + if (!OldPasswordVerified) { + // Check old password + UINT8 TempHash[HASHED_PASSWORD_SIZE]; + ComputeStringHash(Password, TempHash); + if (CompareMem(TempHash, FormStorage.Password, HASHED_PASSWORD_SIZE)) + return EFI_NOT_READY; + + OldPasswordVerified = TRUE; + return EFI_SUCCESS; + } + + // Update password + Status = ComputeStringHash(Password, FormStorage.Password); + if (EFI_ERROR(Status)) { + return Status; + } + OldPasswordVerified = FALSE; + return EFI_SUCCESS; + } +} + +STATIC +EFI_STATUS +EFIAPI +Callback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID QuestionId, + IN UINT8 Type, + IN OUT EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_STATUS Status; + if ((QuestionId == KEY_PASSWORD) && (Action == EFI_BROWSER_ACTION_CHANGING)) { + if (Value->string == 0) { + return EFI_UNSUPPORTED; + } + + EFI_STRING Password = HiiGetString(mHiiHandle, Value->string, "en-US"); + Status = HandlePasswordInput(Password); + FreePool(Password); + return Status; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +PasswordFormWithHashUnload ( + EFI_HANDLE ImageHandle + ) +{ + hash2ServiceBinding->DestroyChild(hash2ServiceBinding, hash2ChildHandle); + + if (mHiiHandle != NULL) + HiiRemovePackages(mHiiHandle); + + EFI_STATUS Status = gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +PasswordFormWithHashEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + Status = gBS->LocateProtocol(&gEfiHash2ServiceBindingProtocolGuid, + NULL, + (VOID **)&hash2ServiceBinding); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't locate gEfiHash2ServiceBindingProtocolGuid: %r\n", Status); + return Status; + } + + Status = hash2ServiceBinding->CreateChild(hash2ServiceBinding, + &hash2ChildHandle); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't create child on gEfiHash2ServiceBindingProtocolGuid: %r\n", Status); + return Status; + } + + Status = gBS->OpenProtocol(hash2ChildHandle, + &gEfiHash2ProtocolGuid, + (VOID **)&hash2Protocol, + NULL, + hash2ChildHandle, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL); + if (EFI_ERROR(Status)) { + Print(L"Error! Can't open gEfiHashProtocolGuid: %r\n", Status); + return Status; + } + + mConfigAccess.ExtractConfig = &ExtractConfig; + mConfigAccess.RouteConfig = &RouteConfig; + mConfigAccess.Callback = &Callback; + + Status = gBS->InstallMultipleProtocolInterfaces( + &mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + mHiiHandle = HiiAddPackages( + &gEfiCallerIdGuid, + mDriverHandle, + PasswordFormWithHashStrings, + FormBin, + NULL + ); + if (mHiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces( + mDriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mConfigAccess, + NULL); + return EFI_OUT_OF_RESOURCES; + } + + EFI_STRING ConfigStr = HiiConstructConfigHdr(&StorageGuid, StorageName, mDriverHandle); + UINT16 DefaultId = 0; + if (!HiiSetToDefaults(ConfigStr, DefaultId)) { + Print(L"Error! Can't set default configuration #%d\n", DefaultId); + } + + return EFI_SUCCESS; +} diff --git a/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf new file mode 100644 index 0000000..6c25d24 --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/PasswordFormWithHash.inf @@ -0,0 +1,28 @@ +[Defines] + INF_VERSION = 1.25 + BASE_NAME = PasswordFormWithHash + FILE_GUID = 6dfb156a-ec61-47d2-841b-f739084add1d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = PasswordFormWithHashEntryPoint + UNLOAD_IMAGE = PasswordFormWithHashUnload + +[Sources] + PasswordFormWithHash.c + Strings.uni + Form.vfr + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + UefiHiiServicesLib + HiiLib + +[Protocols] + gEfiHiiConfigAccessProtocolGuid + gEfiHash2ServiceBindingProtocolGuid + gEfiHash2ProtocolGuid diff --git a/UefiLessonsPkg/PasswordFormWithHash/Strings.uni b/UefiLessonsPkg/PasswordFormWithHash/Strings.uni new file mode 100644 index 0000000..8e27692 --- /dev/null +++ b/UefiLessonsPkg/PasswordFormWithHash/Strings.uni @@ -0,0 +1,9 @@ +#langdef en-US "English" + +#string FORMSET_TITLE #language en-US "Simple Formset" +#string FORMSET_HELP #language en-US "This is a very simple formset" +#string FORMID1_TITLE #language en-US "Simple Form" +#string STANDARD_DEFAULT_PROMPT #language en-US "Standard default" +#string MFG_DEFAULT_PROMPT #language en-US "Manufacture default" +#string PASSWORD_PROMPT #language en-US "Password prompt" +#string PASSWORD_HELP #language en-US "Password help" -- cgit v1.2.3-18-g5258