From b87fc6b140772ba3017de311c7063c259424264c Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 15 Aug 2016 17:11:31 +0200 Subject: First public release. Used by VeraCrypt 1.18. --- DcsBml/DcsBml.c | 124 ++ DcsBml/DcsBml.inf | 67 + DcsBoot/DcsBoot.c | 104 ++ DcsBoot/DcsBoot.inf | 64 + DcsCfg/DcsCfg.h | 166 +++ DcsCfg/DcsCfg.inf | 97 ++ DcsCfg/DcsCfg.man | 120 ++ DcsCfg/DcsCfgBeep.c | 47 + DcsCfg/DcsCfgBlockio.c | 52 + DcsCfg/DcsCfgCrypt.c | 1324 ++++++++++++++++++++ DcsCfg/DcsCfgGraphics.c | 81 ++ DcsCfg/DcsCfgMain.c | 650 ++++++++++ DcsCfg/DcsCfgSetup.c | 39 + DcsCfg/DcsCfgTouch.c | 95 ++ DcsInt/DcsInt.c | 1057 ++++++++++++++++ DcsInt/DcsInt.h | 235 ++++ DcsInt/DcsInt.inf | 93 ++ DcsInt/DcsIntName.c | 173 +++ DcsPkg.dec | 29 + DcsPkg.dsc | 96 ++ DcsPkg.uni | 6 + DcsRe/DcsRe.c | 330 +++++ DcsRe/DcsRe.inf | 74 ++ Dcs_bld.bat | 39 + Include/Library/CommonLib.h | 540 ++++++++ Include/Library/DcsCfgLib.h | 213 ++++ Include/Library/GraphLib.h | 200 +++ Include/Library/PasswordLib.h | 108 ++ Include/Protocol/ConsoleControl.h | 123 ++ Include/Protocol/Speaker.h | 84 ++ LegacySpeaker/ComponentName.c | 134 ++ LegacySpeaker/ComponentName.h | 90 ++ LegacySpeaker/LegacySpeaker.c | 238 ++++ LegacySpeaker/LegacySpeaker.h | 101 ++ LegacySpeaker/LegacySpeaker.inf | 46 + Library/CommonLib/CommonLib.inf | 65 + Library/CommonLib/EfiAttrPrint.c | 477 +++++++ Library/CommonLib/EfiBeep.c | 69 + Library/CommonLib/EfiBio.c | 232 ++++ Library/CommonLib/EfiConsole.c | 347 +++++ Library/CommonLib/EfiExec.c | 88 ++ Library/CommonLib/EfiFile.c | 350 ++++++ Library/CommonLib/EfiMem.c | 74 ++ Library/CommonLib/EfiTouch.c | 47 + Library/CommonLib/EfiUsb.c | 88 ++ Library/CommonLib/EfiVar.c | 228 ++++ Library/CommonLib/IA32/EfiCpuHalt.asm | 19 + Library/CommonLib/X64/EfiCpuHalt.asm | 17 + Library/DcsCfgLib/DcsCfgLib.inf | 80 ++ Library/DcsCfgLib/DcsRandom.c | 460 +++++++ Library/DcsCfgLib/GptEdit.c | 935 ++++++++++++++ Library/GraphLib/EfiGraph.c | 670 ++++++++++ Library/GraphLib/GraphLib.inf | 43 + Library/GraphLib/font.c | 586 +++++++++ Library/PasswordLib/ConsolePassword.c | 128 ++ Library/PasswordLib/PasswordLib.inf | 46 + Library/PasswordLib/PicturePassword.c | 629 ++++++++++ Library/PasswordLib/PlatformID.c | 266 ++++ Library/VeraCryptLib/DcsVeraCrypt.c | 391 ++++++ Library/VeraCryptLib/DcsVeraCrypt.h | 84 ++ Library/VeraCryptLib/VeraCryptLib.inf | 120 ++ Library/VeraCryptLib/llmath.c | 383 ++++++ Library/VeraCryptLib/mklinks_src.bat | 112 ++ SecureBoot/certs/DCS_key_exchange.crt | Bin 0 -> 1093 bytes SecureBoot/certs/DCS_platform.crt | Bin 0 -> 1341 bytes SecureBoot/certs/DCS_sign.crt | Bin 0 -> 826 bytes SecureBoot/certs/MicCorUEFCA2011_2011-06-27.crt | Bin 0 -> 1556 bytes SecureBoot/certs/MicWinProPCA2011_2011-10-19.crt | Bin 0 -> 1499 bytes SecureBoot/certs/readme.txt | 3 + SecureBoot/efi_sign.bat | 1 + SecureBoot/readme.txt | 13 + SecureBoot/sb_set_siglists.ps1 | 22 + SecureBoot/siglists/DCS_key_exchange_SigList.bin | Bin 0 -> 1137 bytes .../DCS_key_exchange_SigList_Serialization.bin | Bin 0 -> 1179 bytes .../DCS_key_exchange_SigList_Serialization.bin.p7 | Bin 0 -> 1996 bytes SecureBoot/siglists/DCS_platform_SigList.bin | Bin 0 -> 1385 bytes .../DCS_platform_SigList_Serialization.bin | Bin 0 -> 1425 bytes .../DCS_platform_SigList_Serialization.bin.p7 | Bin 0 -> 1996 bytes SecureBoot/siglists/DCS_sign_SigList.bin | Bin 0 -> 870 bytes .../siglists/DCS_sign_SigList_Serialization.bin | Bin 0 -> 910 bytes .../siglists/DCS_sign_SigList_Serialization.bin.p7 | Bin 0 -> 1492 bytes .../MicCorUEFCA2011_2011-06-27_SigList.bin | Bin 0 -> 1600 bytes ...rUEFCA2011_2011-06-27_SigList_Serialization.bin | Bin 0 -> 1640 bytes ...FCA2011_2011-06-27_SigList_Serialization.bin.p7 | Bin 0 -> 1492 bytes .../MicWinProPCA2011_2011-10-19_SigList.bin | Bin 0 -> 1543 bytes ...ProPCA2011_2011-10-19_SigList_Serialization.bin | Bin 0 -> 1583 bytes ...PCA2011_2011-10-19_SigList_Serialization.bin.p7 | Bin 0 -> 1492 bytes bld.bat | 7 + setenv.bat | 46 + 89 files changed, 14165 insertions(+) create mode 100644 DcsBml/DcsBml.c create mode 100644 DcsBml/DcsBml.inf create mode 100644 DcsBoot/DcsBoot.c create mode 100644 DcsBoot/DcsBoot.inf create mode 100644 DcsCfg/DcsCfg.h create mode 100644 DcsCfg/DcsCfg.inf create mode 100644 DcsCfg/DcsCfg.man create mode 100644 DcsCfg/DcsCfgBeep.c create mode 100644 DcsCfg/DcsCfgBlockio.c create mode 100644 DcsCfg/DcsCfgCrypt.c create mode 100644 DcsCfg/DcsCfgGraphics.c create mode 100644 DcsCfg/DcsCfgMain.c create mode 100644 DcsCfg/DcsCfgSetup.c create mode 100644 DcsCfg/DcsCfgTouch.c create mode 100644 DcsInt/DcsInt.c create mode 100644 DcsInt/DcsInt.h create mode 100644 DcsInt/DcsInt.inf create mode 100644 DcsInt/DcsIntName.c create mode 100644 DcsPkg.dec create mode 100644 DcsPkg.dsc create mode 100644 DcsPkg.uni create mode 100644 DcsRe/DcsRe.c create mode 100644 DcsRe/DcsRe.inf create mode 100644 Dcs_bld.bat create mode 100644 Include/Library/CommonLib.h create mode 100644 Include/Library/DcsCfgLib.h create mode 100644 Include/Library/GraphLib.h create mode 100644 Include/Library/PasswordLib.h create mode 100644 Include/Protocol/ConsoleControl.h create mode 100644 Include/Protocol/Speaker.h create mode 100644 LegacySpeaker/ComponentName.c create mode 100644 LegacySpeaker/ComponentName.h create mode 100644 LegacySpeaker/LegacySpeaker.c create mode 100644 LegacySpeaker/LegacySpeaker.h create mode 100644 LegacySpeaker/LegacySpeaker.inf create mode 100644 Library/CommonLib/CommonLib.inf create mode 100644 Library/CommonLib/EfiAttrPrint.c create mode 100644 Library/CommonLib/EfiBeep.c create mode 100644 Library/CommonLib/EfiBio.c create mode 100644 Library/CommonLib/EfiConsole.c create mode 100644 Library/CommonLib/EfiExec.c create mode 100644 Library/CommonLib/EfiFile.c create mode 100644 Library/CommonLib/EfiMem.c create mode 100644 Library/CommonLib/EfiTouch.c create mode 100644 Library/CommonLib/EfiUsb.c create mode 100644 Library/CommonLib/EfiVar.c create mode 100644 Library/CommonLib/IA32/EfiCpuHalt.asm create mode 100644 Library/CommonLib/X64/EfiCpuHalt.asm create mode 100644 Library/DcsCfgLib/DcsCfgLib.inf create mode 100644 Library/DcsCfgLib/DcsRandom.c create mode 100644 Library/DcsCfgLib/GptEdit.c create mode 100644 Library/GraphLib/EfiGraph.c create mode 100644 Library/GraphLib/GraphLib.inf create mode 100644 Library/GraphLib/font.c create mode 100644 Library/PasswordLib/ConsolePassword.c create mode 100644 Library/PasswordLib/PasswordLib.inf create mode 100644 Library/PasswordLib/PicturePassword.c create mode 100644 Library/PasswordLib/PlatformID.c create mode 100644 Library/VeraCryptLib/DcsVeraCrypt.c create mode 100644 Library/VeraCryptLib/DcsVeraCrypt.h create mode 100644 Library/VeraCryptLib/VeraCryptLib.inf create mode 100644 Library/VeraCryptLib/llmath.c create mode 100644 Library/VeraCryptLib/mklinks_src.bat create mode 100644 SecureBoot/certs/DCS_key_exchange.crt create mode 100644 SecureBoot/certs/DCS_platform.crt create mode 100644 SecureBoot/certs/DCS_sign.crt create mode 100644 SecureBoot/certs/MicCorUEFCA2011_2011-06-27.crt create mode 100644 SecureBoot/certs/MicWinProPCA2011_2011-10-19.crt create mode 100644 SecureBoot/certs/readme.txt create mode 100644 SecureBoot/efi_sign.bat create mode 100644 SecureBoot/readme.txt create mode 100644 SecureBoot/sb_set_siglists.ps1 create mode 100644 SecureBoot/siglists/DCS_key_exchange_SigList.bin create mode 100644 SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin create mode 100644 SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin.p7 create mode 100644 SecureBoot/siglists/DCS_platform_SigList.bin create mode 100644 SecureBoot/siglists/DCS_platform_SigList_Serialization.bin create mode 100644 SecureBoot/siglists/DCS_platform_SigList_Serialization.bin.p7 create mode 100644 SecureBoot/siglists/DCS_sign_SigList.bin create mode 100644 SecureBoot/siglists/DCS_sign_SigList_Serialization.bin create mode 100644 SecureBoot/siglists/DCS_sign_SigList_Serialization.bin.p7 create mode 100644 SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList.bin create mode 100644 SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin create mode 100644 SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin.p7 create mode 100644 SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList.bin create mode 100644 SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin create mode 100644 SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin.p7 create mode 100644 bld.bat create mode 100644 setenv.bat diff --git a/DcsBml/DcsBml.c b/DcsBml/DcsBml.c new file mode 100644 index 0000000..3376936 --- /dev/null +++ b/DcsBml/DcsBml.c @@ -0,0 +1,124 @@ +/** @file + This is DCS boot menu lock application + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include + +typedef struct _BML_GLOBALS { + UINT64 Signature; + UINTN size; +} BML_GLOBALS, *PBML_GLOBALS; + +STATIC PBML_GLOBALS gBmlData = NULL; +STATIC BOOLEAN BootMenuLocked = TRUE; +EFI_EVENT mBmlVirtualAddrChangeEvent; +EFI_SET_VARIABLE orgSetVariable = NULL; + +EFI_STATUS +BmlSetVaribale( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) { + // DcsBoot remove? + if (VariableName != NULL && StrStr(VariableName, L"BootDC5B") == VariableName && DataSize == 0) { + BootMenuLocked = FALSE; + } + + if (BootMenuLocked) { + // Block all Boot* + if (VariableName != NULL && StrStr(VariableName, L"Boot") == VariableName) { + return EFI_ACCESS_DENIED; + } + } + return orgSetVariable(VariableName, VendorGuid, Attributes, DataSize, Data); +} + +/** +Fixup internal data so that EFI can be call in virtual mode. +Call the passed in Child Notify event and convert any pointers in +lib to virtual mode. + +@param[in] Event The Event that is being processed +@param[in] Context Event Context +**/ + +VOID +EFIAPI +BmlVirtualNotifyEvent( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EfiConvertPointer(0x0, (VOID**)&gBmlData); + EfiConvertPointer(0x0, (VOID**)&orgSetVariable); + return; +} + +/** +The actual entry point for the application. + +@param[in] ImageHandle The firmware allocated handle for the EFI image. +@param[in] SystemTable A pointer to the EFI System Table. + +@retval EFI_SUCCESS The entry point executed successfully. +@retval other Some error occur when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +DcsBmlMain( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS res; + + res = gBS->AllocatePool( + EfiRuntimeServicesData, + (UINTN) sizeof(BML_GLOBALS), + (VOID**)&gBmlData + ); + + if (EFI_ERROR(res)) { + Print(L"Allocate runtime globals %r\n", res); + return res; + } + + // + // Register for the virtual address change event + // + res = gBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + BmlVirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mBmlVirtualAddrChangeEvent + ); + + if (EFI_ERROR(res)) { + Print(L"Register notify %r\n", res); + return res; + } + + orgSetVariable = gST->RuntimeServices->SetVariable; + gST->RuntimeServices->SetVariable = BmlSetVaribale; + return EFI_SUCCESS; +} diff --git a/DcsBml/DcsBml.inf b/DcsBml/DcsBml.inf new file mode 100644 index 0000000..10bdfda --- /dev/null +++ b/DcsBml/DcsBml.inf @@ -0,0 +1,67 @@ +## @file +# This is DCS boot loader application +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsBml + FILE_GUID = E0A7843A-828F-4EDC-AC55-75FE3255ABA5 + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DcsBmlMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DcsBml.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiLib + UefiRuntimeLib + UefiBootServicesTableLib + +[Guids] + gEfiGlobalVariableGuid + gEfiDcsVariableGuid + gEfiEventVirtualAddressChangeGuid + +[Protocols] + gEfiBlockIoProtocolGuid + +[BuildOptions.IA32] +RELEASE_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +DEBUG_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +NOOPT_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs + +RELEASE_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +DEBUG_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +NOOPT_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs + +[FeaturePcd] + +[Pcd] + +[Depex] + TRUE diff --git a/DcsBoot/DcsBoot.c b/DcsBoot/DcsBoot.c new file mode 100644 index 0000000..bccf216 --- /dev/null +++ b/DcsBoot/DcsBoot.c @@ -0,0 +1,104 @@ +/** @file + This is DCS boot loader application + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include + +EFI_GUID ImagePartGuid; +EFI_GUID *gEfiExecPartGuid = &ImagePartGuid; +CHAR16 *gEfiExecCmdDefault = L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi"; +CHAR16 *gEfiExecCmd = NULL; +/** +The actual entry point for the application. + +@param[in] ImageHandle The firmware allocated handle for the EFI image. +@param[in] SystemTable A pointer to the EFI System Table. + +@retval EFI_SUCCESS The entry point executed successfully. +@retval other Some error occur when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +DcsBootMain( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS res; + UINTN len; + UINT32 attr; + InitBio(); + res = InitFS(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"InitFS %r\n", res); + } + + // Load all drivers + res = EfiExec(NULL, L"\\EFI\\VeraCrypt\\LegacySpeaker.dcs"); + + res = EfiGetPartGUID(gFileRootHandle, &ImagePartGuid); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nStart partition %r\n", res); + return res; + } + + EfiSetVar(L"DcsExecPartGuid", NULL, &ImagePartGuid, sizeof(EFI_GUID), EFI_VARIABLE_BOOTSERVICE_ACCESS); + EfiSetVar(L"DcsExecCmd", NULL, gEfiExecCmdDefault, (StrLen(gEfiExecCmdDefault) + 1) * 2, EFI_VARIABLE_BOOTSERVICE_ACCESS); + // Authorize + res = EfiExec(NULL, L"\\EFI\\VeraCrypt\\DcsInt.dcs"); + if (EFI_ERROR(res)) { + // ERR_PRINT(L"\nDcsInt.efi %r\n",res); + return res; + } + + res = EfiGetVar(L"DcsExecPartGuid", NULL, &gEfiExecPartGuid, &len, &attr); + if (EFI_ERROR(res)) { + gEfiExecPartGuid = &ImagePartGuid; + } + + res = EfiGetVar(L"DcsExecCmd", NULL, &gEfiExecCmd, &len, &attr); + if (EFI_ERROR(res)) { + gEfiExecCmd = gEfiExecCmdDefault; + } + + // Find new start partition + ConnectAllEfi(); + InitBio(); + res = InitFS(); +// OUT_PRINT(L"."); + res = EfiFindPartByGUID(gEfiExecPartGuid, &gFileRootHandle); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nCan't find start partition %g\n", gEfiExecPartGuid); + EfiCpuHalt(); + } +// OUT_PRINT(L"."); + res = FileOpenRoot(gFileRootHandle, &gFileRoot); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nCan't open start partition\n"); + EfiCpuHalt(); + } +// OUT_PRINT(L"."); + // Try to exec windows loader... + res = EfiExec(NULL, gEfiExecCmd); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nStart %s - %r\n", gEfiExecCmd, res); + EfiCpuHalt(); + } + ERR_PRINT(L"???%r"); + EfiCpuHalt(); + return EFI_INVALID_PARAMETER; +} diff --git a/DcsBoot/DcsBoot.inf b/DcsBoot/DcsBoot.inf new file mode 100644 index 0000000..9459e92 --- /dev/null +++ b/DcsBoot/DcsBoot.inf @@ -0,0 +1,64 @@ +## @file +# This is DCS boot loader application +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsBoot + FILE_GUID = DE8AB4B2-EB47-44E1-A4D7-1001E5E9F0A5 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = DcsBootMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DcsBoot.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + BaseLib + MemoryAllocationLib + CommonLib + +[Guids] + gEfiGlobalVariableGuid + gEfiDcsVariableGuid + gEfiFileInfoGuid + +[Protocols] + gEfiBlockIoProtocolGuid + +[BuildOptions.IA32] +RELEASE_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +DEBUG_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +NOOPT_VS2010x86_IA32_CC_FLAGS = /arch:IA32 /FAcs + +RELEASE_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +DEBUG_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +NOOPT_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs +[FeaturePcd] + +[Pcd] + diff --git a/DcsCfg/DcsCfg.h b/DcsCfg/DcsCfg.h new file mode 100644 index 0000000..2ffd50d --- /dev/null +++ b/DcsCfg/DcsCfg.h @@ -0,0 +1,166 @@ + +/** @file +This is DCS configuration tool. (EFI shell application/wizard) + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#ifndef __DcsCfg_h__ +#define __DcsCfg_h__ + +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Block I/O +////////////////////////////////////////////////////////////////////////// +extern UINTN BioIndexStart; +extern UINTN BioIndexEnd; +extern BOOLEAN BioSkipPartitions; + +void +BioPrintDevicePath( + UINTN bioIndex + ); + +VOID +PrintBioList(); + +EFI_STATUS +BlockRangeWipe( + IN EFI_HANDLE h, + IN UINT64 start, + IN UINT64 end + ); + +////////////////////////////////////////////////////////////////////////// +// System crypt +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +VolumeEncrypt( + IN UINTN index); + +EFI_STATUS +VolumeDecrypt( + IN UINTN index); + +EFI_STATUS +OSRestoreKey(); + +EFI_STATUS +OSDecrypt(); + +EFI_STATUS +VolumeChangePassword( + IN UINTN index); + +EFI_STATUS +CreateVolumeHeaderOnDisk( + IN UINTN index, + OUT VOID **pinfo, + OUT EFI_HANDLE *phDisk, + OUT UINT64 *sector + ); + +EFI_STATUS +GptCryptFile( + IN BOOLEAN crypt + ); + +EFI_STATUS +GptEdit( + IN UINTN index + ); + +////////////////////////////////////////////////////////////////////////// +// Security regions +////////////////////////////////////////////////////////////////////////// +extern UINTN gSecRigonCount; + +EFI_STATUS +SecRigionMark(); + +EFI_STATUS +SecRigionWipe(); + +EFI_STATUS +SecRigionAdd( + IN UINTN regIdx + ); +////////////////////////////////////////////////////////////////////////// +// Set DcsInt parameters +////////////////////////////////////////////////////////////////////////// +VOID +UpdateDcsBoot(); + +////////////////////////////////////////////////////////////////////////// +// DCS authorization check +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +IntCheckVolume( + UINTN index + ); + +VOID +DisksAuthCheck(); + +VOID +TestAuthAsk(); + + +////////////////////////////////////////////////////////////////////////// +// RUD / USB +////////////////////////////////////////////////////////////////////////// +extern UINTN UsbIndex; + +VOID +PrintUsbList(); + +VOID +UsbSelect(); + +////////////////////////////////////////////////////////////////////////// +// Beep +////////////////////////////////////////////////////////////////////////// +VOID +PrintSpeakerList(); + +VOID +TestSpeaker(); + +////////////////////////////////////////////////////////////////////////// +// Graphics +////////////////////////////////////////////////////////////////////////// +VOID +PrintGraphList(); + +////////////////////////////////////////////////////////////////////////// +// Touch +////////////////////////////////////////////////////////////////////////// +extern UINTN TouchIndex; + +VOID +PrintTouchList(); + +VOID +TestTouch(); + +////////////////////////////////////////////////////////////////////////// +// Interactive setup +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +DcsInteractiveSetup(); + + + +#endif // DcsCfg_h__ diff --git a/DcsCfg/DcsCfg.inf b/DcsCfg/DcsCfg.inf new file mode 100644 index 0000000..c7218aa --- /dev/null +++ b/DcsCfg/DcsCfg.inf @@ -0,0 +1,97 @@ +## @file +# This is DCS configuration EFI shell application +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsCfg + FILE_GUID = 4F0E068D-2EA1-4014-943C-3E4B86BB0E43 + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = DcsCfgMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DcsCfg.h + DcsCfgMain.c + DcsCfgCrypt.c + DcsCfgBeep.c + DcsCfgGraphics.c + DcsCfgBlockio.c + DcsCfgTouch.c + DcsCfgSetup.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ShellPkg/ShellPkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + BaseLib + MemoryAllocationLib + CommonLib + GraphLib + PasswordLib + DcsCfgLib + VeraCryptLib + ShellLib + +[Guids] + gEfiGlobalVariableGuid + gEfiDcsVariableGuid + gEfiPartTypeUnusedGuid + gEfiPartTypeSystemPartGuid + +[Protocols] + gEfiBlockIoProtocolGuid + +[BuildOptions.IA32] +RELEASE_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +DEBUG_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI + +RELEASE_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +DEBUG_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI + +[BuildOptions.X64] +RELEASE_VS2010x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2010x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS = /D_UEFI + +RELEASE_VS2015x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2015x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS = /D_UEFI + +DEBUG_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +RELEASE_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +NOOPT_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG + +DEBUG_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +RELEASE_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +NOOPT_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG + +[FeaturePcd] + +[Pcd] + +[Binaries] + UEFI_APP|DcsCfg.man|* diff --git a/DcsCfg/DcsCfg.man b/DcsCfg/DcsCfg.man new file mode 100644 index 0000000..bb6fda4 --- /dev/null +++ b/DcsCfg/DcsCfg.man @@ -0,0 +1,120 @@ +.TH DcsCfg 0 "Configuration tool of DCS" +.SH NAME +Configure boot loader parameters and tests EFI environment for compatibility +.SH SYNOPSIS + +DcsCfg -dl +DcsCfg -dc -ds -de -aa [-rnd rnddata] +DcsCfg -db +DcsCfg -aa +DcsCfg -dec -aa [-rnd rnddata] +DcsCfg -ddc -aa +DcsCfg -dcp +DcsCfg -ul +DcsCfg -tl +DcsCfg -tt +DcsCfg -gl +DcsCfg -gd +DcsCfg -gm +DcsCfg -bl +DcsCfg -bt +DcsCfg -setup +DcsCfg -ds -pl +DcsCfg -pf -pl +DcsCfg -ds -pf -ps +DcsCfg -ds -pf -pa +DcsCfg -pf -pe -aa +DcsCfg -pf -pd -aa +DcsCfg -pf -pmirror -ps +DcsCfg -pf -pnt -phide -ps +DcsCfg -kp +DcsCfg -ds -srm +DcsCfg -ds -srw +DcsCfg -ds -sra +DcsCfg -ds -wipe + +.SH OPTIONS + + -dl - block device list (order numbers are used in -db and -se) + -ds – select device + -de – end device to check (starts from select) + -dc check devices (try to authorize) + -db - boot partition selection + -aa - ask authorization parameters + -ach - create header on block device + -vec - block device encrypt + -vdc - block device decrypt + -vcp - block device change password + -ul - USB device list + -tl - touch device + -tt - Test touch device + -gl - graphics device list + -gd - graphics device select + -gm - graphics mode select + -bl - Beep device list + -bt - Beep device test + -setup - interactive setup + -pl - GPT list + -pf - file with GPT + -ps - save GPT to file + -pa - applay GPT from file to disk + -pe - encrypt GPT + -pd - decrypt GPT + -pnt - partition number as template (from -pl) + -phide - hide partions from to ; - start sector of hidden partition, - end sector of hidden partition + -kp - keys file of platform to save + -srm - mark disk as security regions container(write CRC of platform to 61 sector); - number of possible security regions + -srw - wipe security regions data with random data (write random data [62, 62 + 256 * SRT]) it has to be free! check first partition start sector! + -sra - add to security region + -wipe - write random data to sectors range [SS,SE] + + .SH DESCRIPTION + +NOTES: +This is test tool for DCS developers. Use it with care. + +.SH EXAMPLES + +EXAMPLES: + + * To list block devices + Shell> dcscfg -dl + + * To change password on block device 1 + Shell> dcscfg -aa -scp 1 + + * To list graphics devices + Shell> dcscfg -gl + + * To select graphics devices mode 1 on device 1 + Shell> dcscfg -gd 1 -gm 1 + + * To list GPT + Shell> dcscfg -ds 1 -pl + + * To save GPT + Shell> dcscfg -ds 1 -pf gpt_org -ps + + * To apply GPT to disk + Shell> dcscfg -ds 1 -pf gpt_disk -pa + + * To hide partition [123456,5678910] as template use partition(9) + Shell> dcscfg -pf gpt_disk -pht 9 -phide 123456 5678910 -ps + + * To encrypt GPT before adding to security region + Shell> dcscfg -aa -pf gpt_hidden_boot -pe -ps + + * To mark USB disk(1) as security regions container(write CRC of platform to 61 sector) + Shell> dcscfg -ds 1 -srm 5 + + * To wipe 5 security regions with random data (write random data [62, 62 + 256 * 5]) + Sectors has to free! check first partition start sector! + Shell> dcscfg -ds 1 -srw 5 + + * To add gpt_hidden_boot to security region 2 on device 1 + Shell> dcscfg -ds 1 -pf gpt_hidden_boot -sra 2 + +.SH RETURNVALUES + +RETURN VALUES: + 0 Exited normally diff --git a/DcsCfg/DcsCfgBeep.c b/DcsCfg/DcsCfgBeep.c new file mode 100644 index 0000000..be158ba --- /dev/null +++ b/DcsCfg/DcsCfgBeep.c @@ -0,0 +1,47 @@ +/** @file +This is DCS configuration, speaker beep + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include + +#include "DcsCfg.h" + +////////////////////////////////////////////////////////////////////////// +// Speaker beep +////////////////////////////////////////////////////////////////////////// +void SpeakerPrintDevicePathByIndex(UINTN index) { + OUT_PRINT(L"%V%d%N ", index); + EfiPrintDevicePath(gSpeakerHandles[index]); +} + +void SpeakerPrintDevicePaths(CHAR16* msg) { + UINTN i; + OUT_PRINT(msg); + for (i = 0; i < gSpeakerCount; ++i) { + SpeakerPrintDevicePathByIndex(i); + OUT_PRINT(L"\n"); + } +} + +VOID +PrintSpeakerList() { + InitSpeaker(); + SpeakerPrintDevicePaths(L"%HSpeaker handles%N\n"); +} + +VOID +TestSpeaker() { + SpeakerBeep((UINT16)gBeepToneDefault, gBeepNumberDefault, gBeepDurationDefault, gBeepIntervalDefault); +} \ No newline at end of file diff --git a/DcsCfg/DcsCfgBlockio.c b/DcsCfg/DcsCfgBlockio.c new file mode 100644 index 0000000..ca9ec09 --- /dev/null +++ b/DcsCfg/DcsCfgBlockio.c @@ -0,0 +1,52 @@ +/** @file +DCS configuration block devices + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include + +#include "DcsCfg.h" + +////////////////////////////////////////////////////////////////////////// +// Block I/O +////////////////////////////////////////////////////////////////////////// +UINTN BioIndexStart = 0; +UINTN BioIndexEnd = 0; +BOOLEAN BioSkipPartitions = FALSE; + +void BioPrintDevicePath(UINTN bioIndex) { + OUT_PRINT(L"%V%d%N ", bioIndex); + EfiPrintDevicePath(gBIOHandles[bioIndex]); +} + +void BioPrintDevicePaths(CHAR16* msg) { + UINTN i; + OUT_PRINT(msg); + if (BioIndexStart >= gBIOCount) return; + for (i = BioIndexStart; i < gBIOCount; ++i) { + if(BioSkipPartitions && EfiIsPartition(gBIOHandles[i])) continue; + BioPrintDevicePath(i); + OUT_PRINT(L"\n"); + } +} + +VOID +PrintBioList() { + InitBio(); + BioPrintDevicePaths(L"%HBlock IO handles%N\n"); +} + diff --git a/DcsCfg/DcsCfgCrypt.c b/DcsCfg/DcsCfgCrypt.c new file mode 100644 index 0000000..d43b473 --- /dev/null +++ b/DcsCfg/DcsCfgCrypt.c @@ -0,0 +1,1324 @@ +/** @file +This is DCS configuration, volume crypt + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "common/Tcdefs.h" +#include "common/Endian.h" +#include "common/Crypto.h" +#include "common/Volumes.h" +#include "common/Crc.h" +#include "crypto/cpu.h" +#include "DcsVeraCrypt.h" +#include "BootCommon.h" + +#include "DcsCfg.h" + +PCRYPTO_INFO gAuthCryptInfo = NULL; +PCRYPTO_INFO gHeaderCryptInfo = NULL; +CHAR8 Header[512]; + +EFI_HANDLE SecRegionHandle = NULL; +UINT64 SecRegionSector = 0; +UINT8* SecRegionData = NULL; +UINTN SecRegionSize = 0; +UINTN SecRegionOffset = 0; +PCRYPTO_INFO SecRegionCryptInfo = NULL; + +////////////////////////////////////////////////////////////////////////// +// Crypt helpers +////////////////////////////////////////////////////////////////////////// +int +AskEA() { + int ea; + CHAR16 name[128]; + for (ea = EAGetFirst(); ea != 0; ea = EAGetNext(ea)) + { + EAGetName(name, ea, 1); + OUT_PRINT(L"(%d) %s\n", ea, name); + } + ea = (int)AskUINTN(":", EAGetFirst()); + return ea; +} + +int +AskMode(int ea) { + int mode; + for (mode = EAGetFirstMode(ea); mode != 0; mode = EAGetNextMode(ea, mode)) + { + EAGetModeName(ea, mode, 1); + OUT_PRINT(L"(%d) %s\n", mode, EAGetModeName(ea, mode, 1)); + } + mode = (int)AskUINTN(":", EAGetFirstMode(ea)); + return mode; +} + +int +AskPkcs5() { + int pkcs5 = 1; + Hash *hash; + hash = HashGet(pkcs5); + while (hash != NULL) + { + OUT_PRINT(L"(%d) %s\n", pkcs5, hash->Name); + ++pkcs5; + hash = HashGet(pkcs5); + }; + pkcs5 = (int)AskUINTN(":", gAuthHash); + return pkcs5; +} + +EFI_STATUS +TryHeaderDecrypt( + IN CHAR8* header, + OUT PCRYPTO_INFO *rci, + OUT PCRYPTO_INFO *rhci + ) +{ + int vcres; + PCRYPTO_INFO cryptoInfo; + PCRYPTO_INFO headerCryptoInfo = NULL; + + if (rhci != NULL) { + headerCryptoInfo = crypto_open(); + } + + vcres = ReadVolumeHeader( + gAuthBoot, + header, + &gAuthPassword, + gAuthHash, + gAuthPim, + gAuthTc, + &cryptoInfo, + headerCryptoInfo); + + if (vcres != 0) { + ERR_PRINT(L"Decrypt error(%x)\n", vcres); + return EFI_INVALID_PARAMETER; + } + OUT_PRINT(L"%H" L"Success\n" L"%N", vcres); + OUT_PRINT(L"Start %lld length %lld\nVolumeSize %lld\nhiddenVolumeSize %lld\nflags 0x%x\n", + cryptoInfo->EncryptedAreaStart.Value, (uint64)cryptoInfo->EncryptedAreaLength.Value, + cryptoInfo->VolumeSize, + cryptoInfo->HeaderFlags + ); + if(rci != NULL) *rci = cryptoInfo; + if (rhci != NULL) *rhci = headerCryptoInfo; + return EFI_SUCCESS; +} + +EFI_STATUS +ChangePassword( + IN OUT CHAR8* header + ) +{ + Password newPassword; + Password confirmPassword; + EFI_STATUS res; + PCRYPTO_INFO cryptoInfo, ci; + int vcres; + + res = RndPreapare(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Rnd: %r\n", res); + return res; + } + + if (gAuthPasswordMsg == NULL) { + VCAuthAsk(); + } + + res = TryHeaderDecrypt(header, &cryptoInfo, NULL); + if (EFI_ERROR(res)) return res; + + if (AskConfirm("Change pwd[N]?", 1)) { + return EFI_INVALID_PARAMETER; + } + + do { + ZeroMem(&newPassword, sizeof(newPassword)); + ZeroMem(&confirmPassword, sizeof(newPassword)); + VCAskPwd(AskPwdNew, &newPassword); + VCAskPwd(AskPwdConfirm, &confirmPassword); + if (newPassword.Length == confirmPassword.Length) { + if (CompareMem(newPassword.Text, confirmPassword.Text, confirmPassword.Length) == 0) { + break; + } + } + if (AskConfirm("Password mismatch, retry?", 1)) { + return EFI_INVALID_PARAMETER; + } + } while (TRUE); + + vcres = CreateVolumeHeaderInMemory( + gAuthBoot, header, + cryptoInfo->ea, + cryptoInfo->mode, + &newPassword, + cryptoInfo->pkcs5, + gAuthPim, + cryptoInfo->master_keydata, + &ci, + cryptoInfo->VolumeSize.Value, + cryptoInfo->hiddenVolumeSize, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + gAuthTc ? 0 : cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags, + cryptoInfo->SectorSize, + FALSE); + + if (vcres != 0) { + ERR_PRINT(L"header create error(%x)\n", vcres); + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + +EFI_STATUS +CreateVolumeHeader( + IN OUT CHAR8* header, + OUT PCRYPTO_INFO *rci, + IN UINT64 defaultVS, + IN UINT64 defaultESS, + IN UINT64 defaultESE + ) +{ + INT32 vcres; + int mode = 0; + int ea = 0; + int pkcs5 = 0; + UINT64 encSectorStart = defaultESS; + UINT64 encSectorEnd = defaultESE; + UINT64 hiddenVolumeSize = 0; + UINT64 VolumeSize = defaultVS; + UINT32 HeaderFlags = 0; + int8 master_keydata[MASTER_KEYDATA_SIZE]; + + if (!RandgetBytes(master_keydata, MASTER_KEYDATA_SIZE, FALSE)) { + ERR_PRINT(L"No randoms\n"); + return EFI_CRC_ERROR; + } + + if (gAuthPasswordMsg == NULL) { + VCAuthAsk(); + } + + ea = AskEA(); + mode = AskMode(ea); + pkcs5 = AskPkcs5(); + encSectorStart = AskUINT64("encryption start (sector):", encSectorStart); + encSectorEnd = AskUINT64("encryption end (sector):", encSectorEnd); + VolumeSize = AskUINT64("volume total (sectors):", VolumeSize); + hiddenVolumeSize = AskUINT64("hidden volume total (sectors):", hiddenVolumeSize); + gAuthBoot = AskConfirm("Boot mode[N]?", 1); + HeaderFlags = (UINT32)AskUINTN("flags:", gAuthBoot ? TC_HEADER_FLAG_ENCRYPTED_SYSTEM : 0); + + vcres = CreateVolumeHeaderInMemory( + gAuthBoot, Header, + ea, + mode, + &gAuthPassword, + pkcs5, + gAuthPim, + master_keydata, + rci, + VolumeSize << 9, + hiddenVolumeSize << 9, + encSectorStart << 9, + (encSectorEnd - encSectorStart + 1) << 9, + VERSION_NUM, + HeaderFlags, + 512, + FALSE); + + if (vcres != 0) { + ERR_PRINT(L"Header error %d\n", vcres); + return EFI_CRC_ERROR; + } + return EFI_SUCCESS; +} + +UINT8 +AskChoice( + CHAR8* prompt, + CHAR8* choice, + UINT8 visible) { + CHAR16 buf[2]; + UINTN len = 0; + UINT8 ret = 0; + UINT8 *pos = choice; + while (ret == 0) { + pos = choice; + OUT_PRINT(L"%a", prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, visible); + while (*pos != 0 && ret == 0) { + if (buf[0] == *pos) { + ret = *pos; + break; + } + pos++; + } + } + return ret; +} + +UINT8 +AskARI() { + return AskChoice("[a]bort [r]etry [i]gnore?", "aArRiI", 1); +} + +UINTN gScndTotal = 0; +UINTN gScndCurrent = 0; +VOID +AddSecondsDelta() +{ + EFI_STATUS res; + EFI_TIME time; + UINTN secs; + UINTN secsDelta; + res = gST->RuntimeServices->GetTime(&time, NULL); + if (EFI_ERROR(res)) return; + secs = (UINTN)time.Second + ((UINTN)time.Minute) * 60 + ((UINTN)time.Hour) * 60 * 60; + if (gScndTotal == 0 && gScndCurrent == 0) { + gScndCurrent = secs; + return; + } + if (secs > gScndCurrent) { + secsDelta = secs - gScndCurrent; + } else { + secsDelta = 24 * 60 * 60 - gScndCurrent; + secsDelta += secs; + } + gScndCurrent = secs; + gScndTotal += secsDelta; +} + +VOID +RangeCryptProgress( + IN UINT64 size, + IN UINT64 remains, + IN UINT64 pos, + IN UINT64 remainsOnStart + ) { + UINTN percent; + percent = (UINTN)(100 * (size - remains) / size); + OUT_PRINT(L"%H%d%%%N (%llds %llds) ", percent, pos, remains); + AddSecondsDelta(); + if (gScndTotal > 10) { + UINT64 doneBpS = (remainsOnStart - remains) * 512 / gScndTotal; + if (doneBpS > 1024 * 1024) { + OUT_PRINT(L"%lldMB/s", doneBpS / (1024 * 1024)); + } else if (doneBpS > 1024) { + OUT_PRINT(L"%lldKB/s", doneBpS / 1024); + } else { + OUT_PRINT(L"%lldB/s", doneBpS); + } + if (doneBpS > 0) { + OUT_PRINT(L"(ETA: %lldm)", (remains * 512 / doneBpS) / 60); + } + } + OUT_PRINT(L" \r"); +} + +#define CRYPT_BUF_SECTORS 50*1024*2 +EFI_STATUS +RangeCrypt( + IN EFI_HANDLE disk, + IN UINT64 start, + IN UINT64 size, + IN UINT64 enSize, + IN PCRYPTO_INFO info, + IN BOOL encrypt, + IN PCRYPTO_INFO headerInfo, + IN UINT64 headerSector + ) +{ + EFI_STATUS res; + EFI_BLOCK_IO_PROTOCOL *io; + UINT8* buf; + UINT64 remains; + UINT64 remainsOnStart; + UINT64 pos; + UINTN rd; + + io = EfiGetBlockIO(disk); + if (!io) { + ERR_PRINT(L"no block IO\n"); + return EFI_INVALID_PARAMETER; + } + + buf = MEM_ALLOC(CRYPT_BUF_SECTORS << 9); + if (!buf) { + ERR_PRINT(L"no memory for buffer\n"); + return EFI_INVALID_PARAMETER; + } + + if (encrypt) { + remains = size - enSize; + pos = start + enSize; + } else { + remains = enSize; + rd = (UINTN)((remains > CRYPT_BUF_SECTORS) ? CRYPT_BUF_SECTORS : remains); + pos = start + enSize - rd; + } + remainsOnStart = remains; + // Start second + gScndTotal = 0; + gScndCurrent = 0; + do { + rd = (UINTN)((remains > CRYPT_BUF_SECTORS) ? CRYPT_BUF_SECTORS : remains); + RangeCryptProgress(size, remains, pos, remainsOnStart); + // Read + do { + res = io->ReadBlocks(io, io->Media->MediaId, pos, rd << 9, buf); + if (EFI_ERROR(res)) { + UINT8 ari; + ERR_PRINT(L"Read error: %r\n", res); + ari = AskARI(); + switch (ari) + { + case 'I': + case 'i': + res = EFI_SUCCESS; + break; + case 'A': + case 'a': + goto error; + case 'R': + case 'r': + default: + if (rd > 1) rd >>= 1; + break; + } + } + } while (EFI_ERROR(res)); + + // Crypt + if (encrypt) { + EncryptDataUnits(buf, (UINT64_STRUCT*)&pos, (UINT32)(rd), info); + } else { + DecryptDataUnits(buf, (UINT64_STRUCT*)&pos, (UINT32)(rd), info); + } + + // Write + do { + res = io->WriteBlocks(io, io->Media->MediaId, pos, rd << 9, buf); + if (EFI_ERROR(res)) { + UINT8 ari; + ERR_PRINT(L"Write error: %r\n", res); + ari = AskARI(); + switch (ari) + { + case 'I': + case 'i': + res = EFI_SUCCESS; + break; + case 'A': + case 'a': + goto error; + case 'R': + case 'r': + default: + break; + } + } + } while (EFI_ERROR(res)); + + if (encrypt) { + pos += rd; + } else { + pos -= rd; + } + remains -= rd; + + // Update header + if (headerInfo != NULL) { + res = io->ReadBlocks(io, io->Media->MediaId, headerSector, 512, buf); + if (!EFI_ERROR(res)) { + UINT32 headerCrc32; + UINT64 encryptedAreaLength; + UINT8* headerData; + if (encrypt) { + encryptedAreaLength = (size - remains) << 9; + } else { + encryptedAreaLength = remains << 9; + } + DecryptBuffer(buf + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerInfo); + if (GetHeaderField32(buf, TC_HEADER_OFFSET_MAGIC) == 0x56455241) { + headerData = buf + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH; + mputInt64(headerData, encryptedAreaLength); + headerCrc32 = GetCrc32(buf + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC); + headerData = buf + TC_HEADER_OFFSET_HEADER_CRC; + mputLong(headerData, headerCrc32); + EncryptBuffer(buf + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, headerInfo); + res = io->WriteBlocks(io, io->Media->MediaId, headerSector, 512, buf); + } else { + res = EFI_CRC_ERROR; + } + } + if (EFI_ERROR(res)) { + ERR_PRINT(L"Header update: %r\n", res); + } + } + + // Check ESC + { + EFI_INPUT_KEY key; + res = gBS->CheckEvent(gST->ConIn->WaitForKey); + if(!EFI_ERROR(res)) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + if (key.ScanCode == SCAN_ESC) { + if (AskConfirm("\n\rStop?", 1)) { + res = EFI_NOT_READY; + goto error; + } + } + } + } + } while (remains > 0); + RangeCryptProgress(size, remains, pos, remainsOnStart); + OUT_PRINT(L"\nDone"); + +error: + OUT_PRINT(L"\n"); + MEM_FREE(buf); + return res; +} + +EFI_STATUS +VolumeEncrypt( + IN UINTN index + ) +{ + EFI_STATUS res; + EFI_HANDLE hDisk; + int vcres; + UINT64 headerSector; + EFI_BLOCK_IO_PROTOCOL* io; + + // Write header + res = CreateVolumeHeaderOnDisk(index, NULL, &hDisk, &headerSector); + if (EFI_ERROR(res)) { + return res; + } + + // Verify header + io = EfiGetBlockIO(hDisk); + if (!io) { + ERR_PRINT(L"can not get block IO\n"); + return EFI_INVALID_PARAMETER; + } + + res = io->ReadBlocks(io, io->Media->MediaId, headerSector, 512, Header); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read error %r(%x)\n", res, res); + return res; + } + + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, &gHeaderCryptInfo); + if (EFI_ERROR(res)) { + return res; + } + + // Encrypt range + vcres = AskConfirm("Encrypt?", 1); + if (!vcres) { + ERR_PRINT(L"Encryption stoped\n"); + return EFI_INVALID_PARAMETER; + } + + res = RangeCrypt(hDisk, + gAuthCryptInfo->EncryptedAreaStart.Value >> 9, + gAuthCryptInfo->VolumeSize.Value >> 9, + gAuthCryptInfo->EncryptedAreaLength.Value >> 9, + gAuthCryptInfo, TRUE, + gHeaderCryptInfo, headerSector); + + crypto_close(gAuthCryptInfo); + crypto_close(gHeaderCryptInfo); + return res; +} + +EFI_STATUS +VolumeDecrypt( + IN UINTN index) +{ + EFI_BLOCK_IO_PROTOCOL* io; + EFI_STATUS res; + EFI_LBA vhsector; + BioPrintDevicePath(index); + + io = EfiGetBlockIO(gBIOHandles[index]); + if (!io) { + ERR_PRINT(L"can not get block IO\n"); + return EFI_INVALID_PARAMETER; + } + + if (gAuthPasswordMsg == NULL) { + VCAuthAsk(); + } + + vhsector = AskUINT64("header sector:", gAuthBoot? TC_BOOT_VOLUME_HEADER_SECTOR : 0); + res = io->ReadBlocks(io, io->Media->MediaId, vhsector, 512, Header); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read error %r(%x)\n", res, res); + return res; + } + + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, &gHeaderCryptInfo); + if (EFI_ERROR(res)) { + return res; + } + + if (!AskConfirm("Decrypt?", 1)) { + ERR_PRINT(L"Decryption stoped\n"); + res = EFI_INVALID_PARAMETER; + goto error; + } + + res = RangeCrypt(gBIOHandles[index], + gAuthCryptInfo->EncryptedAreaStart.Value >> 9, + gAuthCryptInfo->VolumeSize.Value >> 9, + gAuthCryptInfo->EncryptedAreaLength.Value >> 9, + gAuthCryptInfo, FALSE, + gHeaderCryptInfo, + vhsector); + +error: + crypto_close(gHeaderCryptInfo); + crypto_close(gAuthCryptInfo); + return res; +} + + +EFI_STATUS +VolumeChangePassword( + IN UINTN index + ) +{ + EFI_BLOCK_IO_PROTOCOL* io; + EFI_STATUS res; + EFI_LBA vhsector; + + BioPrintDevicePath(index); + io = EfiGetBlockIO(gBIOHandles[index]); + if (io == NULL) { + ERR_PRINT(L" No BIO protocol\n"); + return EFI_INVALID_PARAMETER; + } + + vhsector = gAuthBoot ? TC_BOOT_VOLUME_HEADER_SECTOR : 0; + vhsector = AskUINT64("sector:", vhsector); + res = io->ReadBlocks(io, io->Media->MediaId, vhsector, 512, Header); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read error %r(%x)\n", res, res); + return res; + } + + res = ChangePassword(Header); + if (EFI_ERROR(res)) return res; + + if (AskConfirm("Save[N]?", 1)) { + res = io->WriteBlocks(io, io->Media->MediaId, vhsector, 512, Header); + ERR_PRINT(L"Header saved: %r\n", res); + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// OS Rescue +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +OSDecrypt() +{ + + EFI_STATUS res; + UINTN disk; + BOOLEAN doDecrypt = FALSE; + EFI_BLOCK_IO_PROTOCOL* io; + if (gAuthPasswordMsg == NULL) { + VCAuthAsk(); + } + + for (disk = 0; disk < gBIOCount; ++disk) { + if (EfiIsPartition(gBIOHandles[disk])) continue; + io = EfiGetBlockIO(gBIOHandles[disk]); + if (io == NULL) continue; + res = io->ReadBlocks(io, io->Media->MediaId, 62, 512, Header); + if (EFI_ERROR(res)) continue; + BioPrintDevicePath(disk); + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, &gHeaderCryptInfo); + if (EFI_ERROR(res)) continue; + doDecrypt = TRUE; + break; + } + + if (doDecrypt) { + if (!AskConfirm("Decrypt?", 1)) { + ERR_PRINT(L"Decryption stoped\n"); + return EFI_INVALID_PARAMETER; + } + res = RangeCrypt(gBIOHandles[disk], + gAuthCryptInfo->EncryptedAreaStart.Value >> 9, + gAuthCryptInfo->VolumeSize.Value >> 9, + gAuthCryptInfo->EncryptedAreaLength.Value >> 9, + gAuthCryptInfo, FALSE, + gHeaderCryptInfo, + 62); + crypto_close(gHeaderCryptInfo); + crypto_close(gAuthCryptInfo); + } + else { + res = EFI_NOT_FOUND; + } + return res; +} + +CHAR16* sOSKeyBackup = L"EFI\\VeraCrypt\\svh_bak"; +// dirty import from GptEdit +extern DCS_DISK_ENTRY_DISKID DeDiskId; + +EFI_STATUS +OSBackupKeyLoad( + UINTN *DiskOS + ) +{ + EFI_STATUS res; + UINT8 *restoreData = NULL; + UINTN restoreDataSize; + UINTN disk; + UINTN diskOS; + EFI_BLOCK_IO_PROTOCOL* io; + UINT64 startUnit = 0; + INTN deListHdrIdOk; + + if (gAuthPasswordMsg == NULL) { + VCAuthAsk(); + } + + res = FileLoad(NULL, sOSKeyBackup, &SecRegionData, &SecRegionSize); + if (EFI_ERROR(res) || SecRegionSize < 512) { + SecRegionSize = 0; + MEM_FREE(SecRegionData); + } + if (SecRegionSize == 0) { + res = PlatformGetAuthData(&SecRegionData, &SecRegionSize, &SecRegionHandle); + if (EFI_ERROR(res)) { + SecRegionSize = 0; + } + } + + if (SecRegionSize == 0) { + return EFI_INVALID_PARAMETER; + } + + // Try decrypt/locate header (in file or on removable flash) + do { + CopyMem(Header, SecRegionData + SecRegionOffset, 512); + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, NULL); + if (EFI_ERROR(res)) { + SecRegionOffset += 128 * 1024; + if (SecRegionOffset > SecRegionSize) { + MEM_FREE(SecRegionData); + SecRegionOffset = 0; + res = PlatformGetAuthData(&SecRegionData, &SecRegionSize, &SecRegionHandle); + if (EFI_ERROR(res)) { + return EFI_INVALID_PARAMETER; + } + } + } + restoreDataSize = (SecRegionSize - SecRegionOffset >= 128 * 1024)? 128 * 1024 : SecRegionSize - SecRegionOffset; + restoreData = SecRegionData + SecRegionOffset; + } while (EFI_ERROR(res)); + + // Parse DE list if present + SetMem(&DeDiskId.GptID, sizeof(DeDiskId.GptID), 0x55); + SetMem(&DeDiskId.MbrID, sizeof(DeDiskId.MbrID), 0x55); + if (restoreDataSize >= 1024) { + deListHdrIdOk = CompareMem(restoreData + 512, &gDcsDiskEntryListHeaderID, sizeof(gDcsDiskEntryListHeaderID)); + if (deListHdrIdOk != 0) { + DecryptDataUnits(restoreData + 512, (UINT64_STRUCT *)&startUnit, (UINT32)(restoreDataSize >> 9) - 1, gAuthCryptInfo); + deListHdrIdOk = CompareMem(restoreData + 512, &gDcsDiskEntryListHeaderID, sizeof(gDcsDiskEntryListHeaderID)); + if (deListHdrIdOk != 0) { + res = EFI_CRC_ERROR; + goto error; + } + } + res = DeListParseSaved(restoreData); + if (EFI_ERROR(res)) goto error; + } + + // Search and list all disks + diskOS = 999; + for (disk = 0; disk < gBIOCount; ++disk) { + if (EfiIsPartition(gBIOHandles[disk])) continue; + io = EfiGetBlockIO(gBIOHandles[disk]); + if (io == NULL) continue; + res = io->ReadBlocks(io, io->Media->MediaId, 0, 512, Header); + if (EFI_ERROR(res)) continue; + BioPrintDevicePath(disk); + if (DeDiskId.MbrID == *(uint32 *)(Header + 0x1b8)) { + res = io->ReadBlocks(io, io->Media->MediaId, 1, 512, Header); + if (EFI_ERROR(res)) continue; + if (CompareMem(&DeDiskId.GptID, &((EFI_PARTITION_TABLE_HEADER*)Header)->DiskGUID, sizeof(DeDiskId.GptID)) == 0) { + diskOS = disk; + OUT_PRINT(L"%H[found]%N"); + } + } + OUT_PRINT(L"\n"); + } + diskOS = AskUINTN("Select disk:", diskOS); + if (diskOS >= gBIOCount) { + res = EFI_INVALID_PARAMETER; + goto error; + } + + if (EfiIsPartition(gBIOHandles[diskOS])) { + res = EFI_INVALID_PARAMETER; + goto error; + } + *DiskOS = diskOS; + return EFI_SUCCESS; + +error: + MEM_FREE(SecRegionData); + return res; +} + +EFI_STATUS +OSRestoreKey() +{ + EFI_STATUS res; + UINTN disk; + EFI_BLOCK_IO_PROTOCOL* io; + + res = OSBackupKeyLoad(&disk); + if (EFI_ERROR(res)) return res; + + if (!AskConfirm("Restore?", 1)) { + res = EFI_INVALID_PARAMETER; + goto error; + } + + io = EfiGetBlockIO(gBIOHandles[disk]); + if (io == NULL) { + res = EFI_INVALID_PARAMETER; + goto error; + } + + res = io->WriteBlocks(io, io->Media->MediaId, 62, 512, SecRegionData + SecRegionOffset); + +error: + MEM_FREE(SecRegionData); + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Wipe +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +BlockRangeWipe( + IN EFI_HANDLE h, + IN UINT64 start, + IN UINT64 end + ) +{ + EFI_STATUS res; + EFI_BLOCK_IO_PROTOCOL* bio; + VOID* buf; + UINT64 remains; + UINT64 pos; + UINTN rd; + bio = EfiGetBlockIO(h); + if (bio == 0) { + ERR_PRINT(L"No block device"); + return EFI_NOT_FOUND; + } + + res = RndPreapare(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Rnd: %r\n", res); + return res; + } + + EfiPrintDevicePath(h); + + OUT_PRINT(L"\nSectors [%lld, %lld]", start, end); + if (AskConfirm(", Wipe data?", 1) == 0) return EFI_NOT_READY; + buf = MEM_ALLOC(CRYPT_BUF_SECTORS << 9); + if (!buf) { + ERR_PRINT(L"can not get buffer\n"); + return EFI_INVALID_PARAMETER; + } + remains = end -start + 1; + pos = start; + do { + rd = (UINTN)((remains > CRYPT_BUF_SECTORS) ? CRYPT_BUF_SECTORS : remains); + RandgetBytes(buf, (UINT32)(rd << 9), FALSE); + res = bio->WriteBlocks(bio, bio->Media->MediaId, pos, rd << 9, buf); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write error: %r\n", res); + MEM_FREE(buf); + return res; + } + pos += rd; + remains -= rd; + OUT_PRINT(L"%lld %lld \r", pos, remains); + } while (remains > 0); + OUT_PRINT(L"\nDone\n", pos, remains); + return res; +} + +////////////////////////////////////////////////////////////////////////// +// DCS authorization check +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +IntCheckVolume( + UINTN index + ) +{ + EFI_BLOCK_IO_PROTOCOL* pBio; + EFI_STATUS res; + EFI_LBA vhsector; + + BioPrintDevicePath(index); + pBio = EfiGetBlockIO(gBIOHandles[index]); + if (pBio == NULL) { + ERR_PRINT(L" No BIO protocol\n"); + return EFI_NOT_FOUND; + } + + vhsector = gAuthBoot ? TC_BOOT_VOLUME_HEADER_SECTOR : 0; + res = pBio->ReadBlocks(pBio, pBio->Media->MediaId, vhsector, 512, Header); + if (EFI_ERROR(res)) { + ERR_PRINT(L" %r(%x)\n", res, res); + return res; + } + + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, NULL); + if (res != 0) { + if (gAuthBoot == 0) { + OUT_PRINT(L"Try hidden..."); + res = pBio->ReadBlocks(pBio, pBio->Media->MediaId, TC_VOLUME_HEADER_SIZE / 512, 512, Header); + if (EFI_ERROR(res)) { + ERR_PRINT(L" %r(%x)\n", res, res); + return res; + } + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, NULL); + } + } + return res; +} + +VOID +DisksAuthCheck() { + UINTN i; + if (BioIndexStart >= gBIOCount) return; + i = BioIndexStart; + do { + IntCheckVolume(i); + ++i; + } while ((i < gBIOCount) && (i <= BioIndexEnd)); +} + +VOID +TestAuthAsk() { + VCAuthAsk(); +} + +EFI_STATUS +CreateVolumeHeaderOnDisk( + IN UINTN index, + OUT VOID **pinfo, + OUT EFI_HANDLE *phDisk, + OUT UINT64 *sector + ) +{ + EFI_BLOCK_IO_PROTOCOL* bio; + EFI_STATUS res; + UINT64 encSectorStart = 0; + UINT64 encSectorEnd = 0; + UINT64 VolumeSize = 0; + PCRYPTO_INFO ci = 0; + EFI_LBA vhsector; + EFI_HANDLE hDisk = NULL; + HARDDRIVE_DEVICE_PATH hdp; + BOOLEAN isPart; + + BioPrintDevicePath(index); + OUT_PRINT(L"\n"); + + isPart = EfiIsPartition(gBIOHandles[index]); + if (isPart) { + res = EfiGetPartDetails(gBIOHandles[index], &hdp, &hDisk); + if (!EFI_ERROR(res)) { + encSectorEnd = hdp.PartitionSize - encSectorStart - 256; + VolumeSize = hdp.PartitionSize; + } + } + + res = CreateVolumeHeader(Header, &ci, VolumeSize, encSectorStart, encSectorEnd); + if (EFI_ERROR(res)) { + return res; + } + + if (isPart && gAuthBoot) { + OUT_PRINT(L"Boot drive to save is selected. \n"); + EfiPrintDevicePath(hDisk); + OUT_PRINT(L"\n"); + } else { + hDisk = gBIOHandles[index]; + } + + bio = EfiGetBlockIO(hDisk); + if (bio == NULL) { + ERR_PRINT(L"No BIO protocol\n"); + return EFI_NOT_FOUND; + } + + vhsector = AskUINT64("save to sector:", gAuthBoot ? 62 : 0); + if (AskConfirm("Save [N]?", 1)) { + res = bio->WriteBlocks(bio, bio->Media->MediaId, vhsector, 512, Header); + ERR_PRINT(L"Write: %r\n", res); + } + + if (phDisk != NULL) *phDisk = hDisk; + if (pinfo != NULL) { + *pinfo = ci; + } else { + crypto_close(ci); + } + if (sector != NULL)*sector = vhsector; + return res; +} + + +////////////////////////////////////////////////////////////////////////// +// USB +////////////////////////////////////////////////////////////////////////// +UINTN UsbIndex = 0; +void UsbIoPrintDevicePath(UINTN uioIndex) { + CHAR8* id = NULL; + OUT_PRINT(L"%V%d%N ", uioIndex); + EfiPrintDevicePath(gUSBHandles[uioIndex]); + UsbGetId(gUSBHandles[uioIndex], &id); + if (id != NULL) { + UINT32 rud; + rud = (UINT32)GetCrc32((unsigned char*)id, (int)AsciiStrLen(id)); + OUT_PRINT(L" -(%d) %a", rud, id); + MEM_FREE(id); + } +} + +void UsbIoPrintDevicePaths(CHAR16* msg) { + UINTN i; + OUT_PRINT(msg); + for (i = 0; i < gUSBCount; ++i) { + UsbIoPrintDevicePath(i); + OUT_PRINT(L"\n"); + } +} + +VOID +PrintUsbList() { + InitUsb(); + UsbIoPrintDevicePaths(L"%HUSB IO handles%N\n"); +} + + +////////////////////////////////////////////////////////////////////////// +// Set DcsInt parameters +////////////////////////////////////////////////////////////////////////// +VOID +UpdateDcsBoot() { + EFI_STATUS res; + HARDDRIVE_DEVICE_PATH dpVolme; + EFI_HANDLE hDisk; + if (BioIndexStart >= gBIOCount) { + // Delete var + res = EfiSetVar(DCS_BOOT_STR, &gEfiDcsVariableGuid, NULL, 0, 0); + } + else { + // Set var + EFI_DEVICE_PATH *DevicePath; + UINTN len; + BioPrintDevicePath(BioIndexStart); + res = EfiGetPartDetails(gBIOHandles[BioIndexStart], &dpVolme, &hDisk); + if (EFI_ERROR(res)) { + OUT_PRINT(L" %r\n", res); + return; + } + DevicePath = DevicePathFromHandle(hDisk); + len = GetDevicePathSize(DevicePath); +// res = EfiSetVar(DCS_BOOT_STR, NULL, DevicePath, len, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS); + FileSave(NULL, DCS_BOOT_STR, DevicePath, len); + OUT_PRINT(L"Boot:"); + EfiPrintDevicePath(hDisk); + OUT_PRINT(L"\n"); + } + OUT_PRINT(L" %r\n", res); +} + +////////////////////////////////////////////////////////////////////////// +// Security region +////////////////////////////////////////////////////////////////////////// +UINTN gSecRigonCount = 0; + +EFI_STATUS +SecRigionMark() +{ + UINT32 crc; + EFI_STATUS res; + DCS_AUTH_DATA_MARK* adm; + EFI_BLOCK_IO_PROTOCOL* bio; + + res = PlatformGetIDCRC(gBIOHandles[BioIndexStart], &crc); + if (EFI_ERROR(res)) { + ERR_PRINT(L"CRC: %r\n", res); + return res; + } + + adm = (DCS_AUTH_DATA_MARK*)MEM_ALLOC(512); + if (adm == NULL) { + ERR_PRINT(L"no memory\n"); + return EFI_BUFFER_TOO_SMALL; + } + + adm->AuthDataSize = (UINT32)gSecRigonCount; + adm->PlatformCrc = crc; + res = gBS->CalculateCrc32(&adm->PlatformCrc, sizeof(*adm) - 4, &adm->HeaderCrc); + + if (EFI_ERROR(res)) { + ERR_PRINT(L"CRC: %r\n", res); + return res; + } + + bio = EfiGetBlockIO(gBIOHandles[BioIndexStart]); + if (bio == NULL) { + MEM_FREE(adm); + ERR_PRINT(L"No block IO"); + return EFI_ACCESS_DENIED; + } + res = bio->WriteBlocks(bio, bio->Media->MediaId, 61, 512, adm); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + } + MEM_FREE(adm); + return res; +} + +EFI_STATUS +SecRigionWipe() +{ + EFI_STATUS res; + CHAR8* buf; + UINTN i; + EFI_BLOCK_IO_PROTOCOL* bio; + + buf = MEM_ALLOC(128 * 1024); + if (buf == NULL) { + ERR_PRINT(L"no memory\n"); + return EFI_BUFFER_TOO_SMALL; + } + + bio = EfiGetBlockIO(gBIOHandles[BioIndexStart]); + if (bio == NULL) { + ERR_PRINT(L"No block IO"); + res = EFI_ACCESS_DENIED; + goto error; + } + + if (!RandgetBytes(buf, 512, FALSE)) { + ERR_PRINT(L"No randoms\n"); + res = EFI_CRC_ERROR; + goto error; + } + + // Wipe mark + res = bio->WriteBlocks(bio, bio->Media->MediaId, 61, 512, buf); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + + // Wipe region + for (i = 0; i < gSecRigonCount; ++i) { + if (!RandgetBytes(buf, 128 * 1024, FALSE)) { + ERR_PRINT(L"No randoms\n"); + res = EFI_CRC_ERROR; + goto error; + } + res = bio->WriteBlocks(bio, bio->Media->MediaId, 62 + i * (128 * 1024 / 512), 128 * 1024, buf); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + } + return EFI_SUCCESS; + +error: + MEM_FREE(buf); + return res; +} + +EFI_STATUS +SecRigionAdd( + IN UINTN regIdx +) +{ + EFI_STATUS res = EFI_SUCCESS; + EFI_BLOCK_IO_PROTOCOL* bio; + UINT8* regionData; + UINTN regionSize; + INTN deListHdrIdOk; + res = FileLoad(NULL, (CHAR16*)DcsDiskEntrysFileName, ®ionData, ®ionSize); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Load %s: %r\n", DcsDiskEntrysFileName, res); + return res; + } + deListHdrIdOk = CompareMem(regionData + 512, &gDcsDiskEntryListHeaderID, sizeof(gDcsDiskEntryListHeaderID)); + + if (deListHdrIdOk == 0) { + ERR_PRINT(L"GPT has to be encrypted\n"); + res = EFI_CRC_ERROR; + goto error; + } + + bio = EfiGetBlockIO(gBIOHandles[BioIndexStart]); + if (bio == NULL) { + ERR_PRINT(L"No block IO"); + res = EFI_ACCESS_DENIED; + goto error; + } + + res = bio->WriteBlocks(bio, bio->Media->MediaId, 62 + regIdx * (128 * 1024 / 512), regionSize, regionData); + + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + +error: + MEM_FREE(regionData); + return res; +} + +////////////////////////////////////////////////////////////////////////// +// GPT +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +GptCryptFile( + IN BOOLEAN crypt + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINT64 startUnit = 0; + UINT8* regionData; + UINTN regionSize; + INTN deListHdrIdOk; + + res = FileLoad(NULL, (CHAR16*)DcsDiskEntrysFileName, ®ionData, ®ionSize); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Load %s: %r\n", DcsDiskEntrysFileName, res); + return res; + } + deListHdrIdOk = CompareMem(regionData + 512, &gDcsDiskEntryListHeaderID, sizeof(gDcsDiskEntryListHeaderID)); + + if ((deListHdrIdOk != 0) && crypt) { + ERR_PRINT(L"Already encrypted\n"); + res = EFI_CRC_ERROR; + goto error; + } + + if ((deListHdrIdOk == 0) && !crypt) { + ERR_PRINT(L"Already decrypted\n"); + res = EFI_CRC_ERROR; + goto error; + } + + DetectX86Features(); + CopyMem(Header, regionData, sizeof(Header)); + res = TryHeaderDecrypt(Header, &gAuthCryptInfo, NULL); + if(EFI_ERROR(res)){ + goto error; + } + startUnit = 0; + if (crypt) { + EncryptDataUnits(regionData + 512, (UINT64_STRUCT *)&startUnit, (UINT32)(regionSize >> 9) - 1, gAuthCryptInfo); + } + else { + DecryptDataUnits(regionData + 512, (UINT64_STRUCT *)&startUnit, (UINT32)(regionSize >> 9) - 1, gAuthCryptInfo); + } + + res = FileSave(NULL, (CHAR16*)DcsDiskEntrysFileName, regionData, regionSize); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Save %s: %r\n", DcsDiskEntrysFileName, res); + goto error; + } + +error: + MEM_FREE(regionData); + return res; +} + +EFI_STATUS +GptEdit( + IN UINTN index + ) +{ + + EFI_PARTITION_ENTRY* part = &GptMainEntrys[index]; + + /// + /// Null-terminated name of the partition. + /// + CHAR16 PartitionName[36]; + UINTN len; + while (!GptAskGUID("type (msr, data, wre, efi, del or guid)\n\r:", &part->PartitionTypeGUID)); + if (CompareMem(&part->PartitionTypeGUID, &gEfiPartTypeUnusedGuid, sizeof(EFI_GUID)) == 0) { + ZeroMem(part, sizeof(*part)); + GptSqueze(); + GptSort(); + GptSyncMainAlt(); + return EFI_SUCCESS; + } + while (!GptAskGUID("id\n\r:", &part->UniquePartitionGUID)); + part->StartingLBA = AskUINT64("StartingLBA:", part->StartingLBA); + part->EndingLBA = AskUINT64("EndingLBA:", part->EndingLBA); + part->Attributes = AskHexUINT64("Attributes\n\r:", part->Attributes); + OUT_PRINT(L"[%s]\n\r:", part->PartitionName); + GetLine(&len, PartitionName, NULL, sizeof(PartitionName) / 2 - 1, 1); + if (len != 0) { + CopyMem(&part->PartitionName, PartitionName, sizeof(PartitionName)); + } + GptSqueze(); + GptSort(); + GptSyncMainAlt(); + return EFI_SUCCESS; +} diff --git a/DcsCfg/DcsCfgGraphics.c b/DcsCfg/DcsCfgGraphics.c new file mode 100644 index 0000000..3c5addb --- /dev/null +++ b/DcsCfg/DcsCfgGraphics.c @@ -0,0 +1,81 @@ +/** @file +DCS configuration graphics devices + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "DcsCfg.h" + + +////////////////////////////////////////////////////////////////////////// +// Graphics +////////////////////////////////////////////////////////////////////////// + +void GraphPrintDevicePath(EFI_HANDLE handle) { + EFI_GRAPHICS_OUTPUT_PROTOCOL* grfio = NULL; + EFI_STATUS res; + EfiPrintDevicePath(handle); + res = GraphGetIO(handle, &grfio); + if (!EFI_ERROR(res) && grfio != NULL) { + UINT32 i; + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL* cout; + res = ConsoleGetOutput(handle, &cout); + OUT_PRINT(L" - %d [%d (%d,%d) %d] %s", + grfio->Mode->MaxMode, grfio->Mode->Mode, + grfio->Mode->Info->HorizontalResolution, grfio->Mode->Info->VerticalResolution, + grfio->Mode->Info->PixelFormat, + EFI_ERROR(res) ? L"" : L"console" + ); + + for (i = 0; i < grfio->Mode->MaxMode; i++) { + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN szInfo; + res = grfio->QueryMode(grfio, i, &szInfo, &info); + if (!EFI_ERROR(res)) { + OUT_PRINT(L"\n [%d (%d,%d) %d]", + i, + info->HorizontalResolution, info->VerticalResolution, + grfio->Mode->Info->PixelFormat + ); + } + } + } +} + +void GraphPrintDevicePathByIndex(UINTN index) { + OUT_PRINT(L"%V%d%N ", index); + GraphPrintDevicePath(gGraphHandles[index]); +} + +void GraphPrintDevicePaths(CHAR16* msg) { + UINTN i; + OUT_PRINT(msg); + for (i = 0; i < gGraphCount; ++i) { + GraphPrintDevicePathByIndex(i); + OUT_PRINT(L"\n"); + } +} + +VOID +PrintGraphList() { + InitGraph(); + GraphPrintDevicePaths(L"%HGraphics handles%N\n"); +} diff --git a/DcsCfg/DcsCfgMain.c b/DcsCfg/DcsCfgMain.c new file mode 100644 index 0000000..5c2ce2b --- /dev/null +++ b/DcsCfg/DcsCfgMain.c @@ -0,0 +1,650 @@ +/** @file +This is DCS configuration tool. (EFI shell application/TODO:wizard) + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "DcsCfg.h" +#include "Library/PasswordLib.h" + +#include "common/Tcdefs.h" +#include "crypto/cpu.h" +#include "Library/DcsCfgLib.h" + + +////////////////////////////////////////////////////////////////////////// +// Main +////////////////////////////////////////////////////////////////////////// +#define OPT_DISK_CHECK L"-dc" +#define OPT_DISK_LIST L"-dl" +#define OPT_DISK_START L"-ds" +#define OPT_DISK_END L"-de" +#define OPT_DISK_BOOT L"-db" +#define OPT_AUTH_ASK L"-aa" +#define OPT_AUTH_CREATE_HEADER L"-ach" +#define OPT_RND L"-rnd" +#define OPT_RND_GEN L"-rndgen" +#define OPT_RND_LOAD L"-rndload" +#define OPT_RND_SAVE L"-rndsave" +#define OPT_VOLUME_ENCRYPT L"-vec" +#define OPT_VOLUME_DECRYPT L"-vdc" +#define OPT_VOLUME_CHANGEPWD L"-vcp" +#define OPT_USB_LIST L"-ul" +#define OPT_TOUCH_LIST L"-tl" +#define OPT_TOUCH_TEST L"-tt" +#define OPT_GRAPH_LIST L"-gl" +#define OPT_GRAPH_DEVICE L"-gd" +#define OPT_GRAPH_MODE L"-gm" +#define OPT_BEEP_LIST L"-bl" +#define OPT_BEEP_TEST L"-bt" +#define OPT_SETUP L"-setup" +#define OPT_PARTITION_LIST L"-pl" +#define OPT_PARTITION_FILE L"-pf" +#define OPT_PARTITION_SAVE L"-ps" +#define OPT_PARTITION_ZERO L"-pz" +#define OPT_PARTITION_APPLY L"-pa" +#define OPT_PARTITION_ENCRYPT L"-pe" +#define OPT_PARTITION_DECRYPT L"-pd" +#define OPT_PARTITION_IDX_TEMPLATE L"-pnt" +#define OPT_PARTITION_HIDE L"-phide" +#define OPT_PARTITION_EDIT L"-pedt" +#define OPT_PARTITION_EDIT_EXEC L"-pexec" +#define OPT_PARTITION_RND_LOAD L"-prndload" +#define OPT_PARTITION_RND_SAVE L"-prndsave" +#define OPT_PARTITION_EDIT_PWD_CACHE L"-pwdcache" +#define OPT_KEYFILE_PLATFORM L"-kp" +#define OPT_SECREGION_MARK L"-srm" +#define OPT_SECREGION_WIPE L"-srw" +#define OPT_SECREGION_ADD L"-sra" +#define OPT_WIPE L"-wipe" +#define OPT_OS_DECRYPT L"-osdecrypt" +#define OPT_OS_RESTORE_KEY L"-osrestorekey" + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + { OPT_DISK_LIST, TypeValue }, + { OPT_DISK_CHECK, TypeFlag }, + { OPT_DISK_START, TypeValue }, + { OPT_DISK_END, TypeValue }, + { OPT_DISK_BOOT, TypeValue }, + { OPT_AUTH_ASK, TypeFlag }, + { OPT_AUTH_CREATE_HEADER, TypeFlag }, + { OPT_RND, TypeDoubleValue }, + { OPT_RND_GEN, TypeDoubleValue }, + { OPT_RND_LOAD, TypeValue }, + { OPT_RND_SAVE, TypeValue }, + { OPT_VOLUME_ENCRYPT,TypeValue }, + { OPT_VOLUME_DECRYPT,TypeValue }, + { OPT_VOLUME_CHANGEPWD,TypeValue }, + { OPT_USB_LIST, TypeFlag }, + { OPT_TOUCH_LIST, TypeFlag }, + { OPT_TOUCH_TEST, TypeValue }, + { OPT_GRAPH_LIST, TypeFlag }, + { OPT_GRAPH_DEVICE, TypeValue }, + { OPT_GRAPH_MODE, TypeValue }, + { OPT_BEEP_LIST, TypeFlag }, + { OPT_BEEP_TEST, TypeFlag }, + { OPT_SETUP, TypeFlag }, + { OPT_PARTITION_LIST, TypeFlag }, + { OPT_PARTITION_SAVE, TypeFlag }, + { OPT_PARTITION_ZERO, TypeFlag }, + { OPT_PARTITION_FILE, TypeValue }, + { OPT_PARTITION_ENCRYPT,TypeFlag }, + { OPT_PARTITION_DECRYPT,TypeFlag }, + { OPT_PARTITION_APPLY,TypeFlag }, + { OPT_PARTITION_HIDE, TypeDoubleValue }, + { OPT_PARTITION_IDX_TEMPLATE, TypeValue }, + { OPT_PARTITION_EDIT, TypeValue }, + { OPT_PARTITION_EDIT_EXEC, TypeFlag }, + { OPT_PARTITION_EDIT_PWD_CACHE, TypeFlag }, + { OPT_PARTITION_RND_LOAD, TypeFlag }, + { OPT_PARTITION_RND_SAVE, TypeFlag }, + { OPT_KEYFILE_PLATFORM, TypeValue }, + { OPT_SECREGION_MARK, TypeValue }, + { OPT_SECREGION_WIPE, TypeValue }, + { OPT_SECREGION_ADD, TypeValue }, + { OPT_WIPE, TypeDoubleValue }, + { OPT_OS_DECRYPT, TypeFlag }, + { OPT_OS_RESTORE_KEY, TypeFlag }, + { NULL, TypeMax } +}; + +/** +The actual entry point for the application. + +@param[in] ImageHandle The firmware allocated handle for the EFI image. +@param[in] SystemTable A pointer to the EFI System Table. + +@retval EFI_SUCCESS The entry point executed successfully. +@retval other Some error occur when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +DcsCfgMain( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS res; + LIST_ENTRY *Package; + SHELL_STATUS ShellStatus; + UINTN ParamCount; + CHAR16 *ProblemParam; + UINTN Size; + CHAR16 *PrintString; + CHAR16* cmd; + UINTN cmdSize; + UINT32 cmdAttr; + + Size = 0; + ParamCount = 0; + ProblemParam = NULL; + PrintString = NULL; + ShellStatus = SHELL_SUCCESS; + + InitBio(); + InitFS(); + DetectX86Features(); + + // + // initialize the shell lib (we must be in non-auto-init...) + // + res = EfiGetVar(L"dcscfgcmd", NULL, &cmd, &cmdSize, &cmdAttr); + if (!EFI_ERROR(res)) { + res = EfiSetVar(L"dcscfgcmd", NULL, NULL, 0, cmdAttr); + if (StrStr(cmd, OPT_OS_RESTORE_KEY) != NULL) { + return OSRestoreKey(); + } + if (StrStr(cmd, OPT_OS_DECRYPT) != NULL) { + return OSDecrypt(); + } + return EFI_INVALID_PARAMETER; + } + + res = ShellInitialize(); + if (EFI_ERROR(res) || gEfiShellProtocol == NULL) { + EFI_INPUT_KEY key; + key = KeyWait(L"Press any key to start interactive DCS setup %02d\r", 20, 0, 0); + if (key.UnicodeChar != 0) { + return DcsInteractiveSetup(); + } + return EFI_INVALID_PARAMETER; + } + + InitGraph(); + // + // parse the command line + // + res = ShellCommandLineParseEx(ParamList, &Package, &ProblemParam, TRUE, TRUE); + if (EFI_ERROR(res)) { + OUT_PRINT(L"syntax error:%s", ProblemParam); + return res; + } + gShellReady = gEfiShellProtocol != NULL; + if (gShellReady) { + SetShellAPI(gEfiShellProtocol, gEfiShellParametersProtocol); + } + + ParamCount = ShellCommandLineGetCount(Package); + + // Common parameters + if (ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_DISK_START); + BioIndexStart = StrDecimalToUintn(opt); + } + + if (ShellCommandLineGetFlag(Package, OPT_DISK_END)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_DISK_END); + BioIndexEnd = StrDecimalToUintn(opt); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_FILE)) { + DcsDiskEntrysFileName = ShellCommandLineGetValue(Package, OPT_PARTITION_FILE); + } + + if (ShellCommandLineGetFlag(Package, OPT_AUTH_ASK)) { + TestAuthAsk(); + } + + // Rescue + if (ShellCommandLineGetFlag(Package, OPT_OS_DECRYPT)) { + return OSDecrypt(); + } + + if (ShellCommandLineGetFlag(Package, OPT_OS_RESTORE_KEY)) { + return OSRestoreKey(); + } + + // Beep + if (ShellCommandLineGetFlag(Package, OPT_BEEP_LIST)) { + PrintSpeakerList(); + } + + if (ShellCommandLineGetFlag(Package, OPT_BEEP_TEST)) { + TestSpeaker(); + } + + // Touch + if (ShellCommandLineGetFlag(Package, OPT_TOUCH_LIST)) { + PrintTouchList(); + } + + if (ShellCommandLineGetFlag(Package, OPT_TOUCH_TEST)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_TOUCH_TEST); + TouchIndex= StrDecimalToUintn(opt); + TestTouch(); + } + + // Graph + if (ShellCommandLineGetFlag(Package, OPT_GRAPH_DEVICE)) { + CONST CHAR16* opt = NULL; + UINTN index; + opt = ShellCommandLineGetValue(Package, OPT_GRAPH_DEVICE); + index = StrDecimalToUintn(opt); + if (index < gGraphCount) { + GraphGetIO(gGraphHandles[index], &gGraphOut); + } else{ + ERR_PRINT(L"Wrong graph device index"); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_GRAPH_MODE)) { + CONST CHAR16* opt = NULL; + UINTN index; + opt = ShellCommandLineGetValue(Package, OPT_GRAPH_MODE); + index = StrDecimalToUintn(opt); + if (index < gGraphOut->Mode->MaxMode) { + gGraphOut->SetMode(gGraphOut, (UINT32)index); + } else { + ERR_PRINT(L"Wrong graph mode index"); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_GRAPH_LIST)) { + PrintGraphList(); + } + + // USB + if (ShellCommandLineGetFlag(Package, OPT_USB_LIST)) { + PrintUsbList(); + } + + // Create random + if (ShellCommandLineGetFlag(Package, OPT_RND)) { + CONST CHAR16* opt = NULL; + CONST CHAR16* context = NULL; + UINTN rndType; + opt = ShellCommandLineGetValue(Package, OPT_RND); + rndType = StrDecimalToUintn(opt); + context = StrStr(opt, L" "); + if (context != NULL) { + context++; + } + res = RndInit(rndType, (CHAR16*)context, &gRnd); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_RND_LOAD)) { + CONST CHAR16* opt = NULL; + UINT8 temp[4]; + DCS_RND_SAVED *rndSaved; + UINTN rndSavedSize; + opt = ShellCommandLineGetValue(Package, OPT_RND_LOAD); + res = FileLoad(NULL, (CHAR16*)opt, &rndSaved, &rndSavedSize); + if (EFI_ERROR(res) || + rndSavedSize != sizeof(DCS_RND_SAVED) || + EFI_ERROR(res = RndLoad(rndSaved,&gRnd)) || + EFI_ERROR(res = RndPreapare()) || + EFI_ERROR(res = RndGetBytes(temp, sizeof(temp))) + ) { + ERR_PRINT(L"Random: %r\n", res); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_RND_LOAD)) { + UINT8 temp[4]; + if (EFI_ERROR(res = DeListLoadFromFile()) || // Load DeList + EFI_ERROR(res = DeListRndLoad()) || // Try to load gRdn from list + EFI_ERROR(res = RndPreapare()) || // Prepare random + EFI_ERROR(res = RndGetBytes(temp, sizeof(temp))) // Test + ) { + ERR_PRINT(L"Random: %r\n", res); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_RND_GEN)) { + CONST CHAR16* optSize = NULL; + UINTN size; + CONST CHAR16* optFile = NULL; + UINT8* temp; + optSize = ShellCommandLineGetValue(Package, OPT_RND_GEN); + size = StrDecimalToUintn(optSize); + optFile = StrStr(optSize, L" "); + if (optFile != NULL) { + optFile++; + } + res = EFI_BUFFER_TOO_SMALL; + temp = MEM_ALLOC(size); + if (temp == NULL || + EFI_ERROR(res = RndGetBytes(temp, size) || + EFI_ERROR(res = FileSave(NULL, (CHAR16*)optFile, temp, size))) + ) { + ERR_PRINT(L"Random: %r\n", res); + } + MEM_FREE(temp); + } + + if (ShellCommandLineGetFlag(Package, OPT_RND_SAVE)) { + CONST CHAR16* opt = NULL; + UINT8 temp[4]; + DCS_RND_SAVED *rndSaved = NULL; + opt = ShellCommandLineGetValue(Package, OPT_RND_SAVE); + if (EFI_ERROR(res = RndPreapare()) || + EFI_ERROR(res = RndGetBytes(temp, sizeof(temp))) || + EFI_ERROR(res = RndSave(gRnd, &rndSaved)) || + EFI_ERROR(res = FileSave(NULL, (CHAR16*)opt, rndSaved, sizeof(DCS_RND_SAVED))) + ) { + ERR_PRINT(L"Random: %r\n", res); + } + MEM_FREE(rndSaved); + } + + + // Disk + if (ShellCommandLineGetFlag(Package, OPT_DISK_BOOT)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_DISK_BOOT); + BioIndexEnd = BioIndexStart = StrDecimalToUintn(opt); + UpdateDcsBoot(); + } + + if (ShellCommandLineGetFlag(Package, OPT_DISK_LIST)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_DISK_LIST); + if (opt == NULL) { + BioSkipPartitions = FALSE; + } else { + BioSkipPartitions = (opt[0] == 'd'); + } + PrintBioList(); + } + + // Authorization + if (ShellCommandLineGetFlag(Package, OPT_AUTH_CREATE_HEADER)) { + if (ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + res = CreateVolumeHeaderOnDisk(BioIndexStart, NULL, NULL, NULL); + if (EFI_ERROR(res)) { + return res; + } + } else { + ERR_PRINT(L"Select volume\n"); + } + } + + // GPT and DeList + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_RND_SAVE)) { + UINT8 temp[4]; + if (EFI_ERROR(res = DeListLoadFromFile()) || // Load DeList + EFI_ERROR(res = RndGetBytes(temp, sizeof(temp))) || // Test Rnd + EFI_ERROR(res = DeListRndSave()) // Try to save RdnRaw to DeList + ) { + ERR_PRINT(L"Random: %r\n", res); + } + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_HIDE)) { + CONST CHAR16* opt1 = NULL; + CONST CHAR16* opt2 = NULL; + UINTN idx; + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + if (!ShellCommandLineGetFlag(Package, OPT_PARTITION_IDX_TEMPLATE)) { + ERR_PRINT(L"No base partition index\n"); + return EFI_INVALID_PARAMETER; + } + opt1 = ShellCommandLineGetValue(Package, OPT_PARTITION_IDX_TEMPLATE); + idx = StrDecimalToUintn(opt1); + CopyMem(&DcsHidePart, &GptMainEntrys[idx], sizeof(DcsHidePart)); + opt1 = ShellCommandLineGetValue(Package, OPT_PARTITION_HIDE); + DcsHidePart.StartingLBA = StrDecimalToUint64(opt1); + opt2 = StrStr(opt1, L" "); + if (opt2 == NULL) { + EFI_ERROR(L"Select end sector\n"); + return EFI_INVALID_PARAMETER; + } + DcsHidePart.EndingLBA = StrDecimalToUint64(opt2); + GptHideParts(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_EDIT_EXEC)) { + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + DeListExecEdit(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_EDIT_PWD_CACHE)) { + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + DeListPwdCacheEdit(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_EDIT)) { + CONST CHAR16* opt1 = NULL; + UINTN idx; + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + + opt1 = ShellCommandLineGetValue(Package, OPT_PARTITION_EDIT); + idx = StrDecimalToUintn(opt1); + GptEdit(idx); + } + + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_LIST)) { + if (GptMainEntrys == NULL) { + if (ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + res = GptLoadFromDisk(BioIndexStart); + if (EFI_ERROR(res)) { + return res; + } + } else { + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + EFI_ERROR(L"Select file or disk\n"); + return res; + } + } + } + DeListPrint(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_ENCRYPT)) { + GptCryptFile(TRUE); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_DECRYPT)) { + GptCryptFile(FALSE); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_ZERO)) { + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + DeListZero(); + DeListSaveToFile(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_SAVE)) { + if (GptMainEntrys == NULL && DeList == NULL) { + if (!ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + EFI_ERROR(L"Select disk\n"); + return EFI_INVALID_PARAMETER; + } + res = GptLoadFromDisk(BioIndexStart); + if (EFI_ERROR(res)) { + return res; + } + } + DeListSaveToFile(); + } + + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_APPLY)) { + if (ShellCommandLineGetFlag(Package, OPT_DISK_START) && + ShellCommandLineGetFlag(Package, OPT_PARTITION_FILE) + ) { + res = DeListLoadFromFile(); + if (EFI_ERROR(res)) { + return res; + } + DeListApplySectorsToDisk(BioIndexStart); + } else { + EFI_ERROR(L"Select file and disk\n"); + } + } + + // Key file + if (ShellCommandLineGetFlag(Package, OPT_KEYFILE_PLATFORM)) { + CONST CHAR16* opt = NULL; + CHAR8 *buf; + UINTN len; + opt = ShellCommandLineGetValue(Package, OPT_KEYFILE_PLATFORM); + res = SMBIOSGetSerials(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"SMBIOS: %r\n", res); + return res; + } + res = PlatformGetID(gBIOHandles[BioIndexStart], &buf, &len); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Platform ID: %r\n", res); + return res; + } + res = FileSave(NULL, (CHAR16*)opt, buf, len); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Save: %r\n", res); + return res; + } + } + + if (ShellCommandLineGetFlag(Package, OPT_WIPE)) { + CONST CHAR16* opt1 = NULL; + CONST CHAR16* opt2 = NULL; + UINT64 start; + UINT64 end; + if (!ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + ERR_PRINT(L"Select disk\n"); + return EFI_INVALID_PARAMETER; + } + opt1 = ShellCommandLineGetValue(Package, OPT_WIPE); + start = StrDecimalToUint64(opt1); + opt2 = StrStr(opt1, L" ") + 1; + end = StrDecimalToUint64(opt2); + return BlockRangeWipe(gBIOHandles[BioIndexStart], start, end); + } + + + // Security region + if (ShellCommandLineGetFlag(Package, OPT_SECREGION_MARK)) { + if (ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_SECREGION_MARK); + gSecRigonCount = StrDecimalToUintn(opt); + SecRigionMark(); + } else { + ERR_PRINT(L"Select disk and security region count"); + return EFI_INVALID_PARAMETER; + } + } + + if (ShellCommandLineGetFlag(Package, OPT_SECREGION_WIPE)) { + if (ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + CONST CHAR16* opt = NULL; + opt = ShellCommandLineGetValue(Package, OPT_SECREGION_WIPE); + gSecRigonCount = StrDecimalToUintn(opt); + SecRigionWipe(); + } + else { + ERR_PRINT(L"Select disk and security region count"); + return EFI_INVALID_PARAMETER; + } + } + + if (ShellCommandLineGetFlag(Package, OPT_SECREGION_ADD)) { + if (ShellCommandLineGetFlag(Package, OPT_PARTITION_FILE) && + ShellCommandLineGetFlag(Package, OPT_DISK_START)) { + CONST CHAR16* opt = NULL; + UINTN secRegionIdx; + opt = ShellCommandLineGetValue(Package, OPT_SECREGION_ADD); + secRegionIdx = StrDecimalToUintn(opt); + SecRigionAdd(secRegionIdx); + } + else { + ERR_PRINT(L"Select disk and GPT file"); + return EFI_INVALID_PARAMETER; + } + } + + // Encrypt, decrypt, change password + if (ShellCommandLineGetFlag(Package, OPT_DISK_CHECK)) { + DisksAuthCheck(); + } + + if (ShellCommandLineGetFlag(Package, OPT_VOLUME_CHANGEPWD)) { + CONST CHAR16* opt = NULL; + UINTN disk; + opt = ShellCommandLineGetValue(Package, OPT_VOLUME_CHANGEPWD); + disk = StrDecimalToUintn(opt); + VolumeChangePassword(disk); + } + + if (ShellCommandLineGetFlag(Package, OPT_VOLUME_ENCRYPT)) { + CONST CHAR16* opt = NULL; + UINTN disk; + opt = ShellCommandLineGetValue(Package, OPT_VOLUME_ENCRYPT); + disk = StrDecimalToUintn(opt); + VolumeEncrypt(disk); + } + + if (ShellCommandLineGetFlag(Package, OPT_VOLUME_DECRYPT)) { + CONST CHAR16* opt = NULL; + UINTN disk; + opt = ShellCommandLineGetValue(Package, OPT_VOLUME_DECRYPT); + disk = StrDecimalToUintn(opt); + VolumeDecrypt(disk); + } + + + return EFI_SUCCESS; +} diff --git a/DcsCfg/DcsCfgSetup.c b/DcsCfg/DcsCfgSetup.c new file mode 100644 index 0000000..d773fb7 --- /dev/null +++ b/DcsCfg/DcsCfgSetup.c @@ -0,0 +1,39 @@ +/** @file +DCS configuration tool. Interactive setup. + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include + +#include +#include + +#include "DcsCfg.h" + +////////////////////////////////////////////////////////////////////////// +// Interactive setup +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +DcsInteractiveSetup() { + EFI_STATUS res = EFI_SUCCESS; + CHAR8 cmd[128]; + InitBio(); + InitFS(); + InitGraph(); + gST->ConOut->EnableCursor(gST->ConOut, TRUE); + ERR_PRINT(L"\n\rInteractive setup is not implemented! Press enter to continue\n\r"); + AskAsciiString("\rDCS>", cmd, sizeof(cmd), 1); + return res; +} diff --git a/DcsCfg/DcsCfgTouch.c b/DcsCfg/DcsCfgTouch.c new file mode 100644 index 0000000..3553052 --- /dev/null +++ b/DcsCfg/DcsCfgTouch.c @@ -0,0 +1,95 @@ +/** @file +DCS configuration. Touch devices. + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +#include "DcsCfg.h" + +////////////////////////////////////////////////////////////////////////// +// Touch +////////////////////////////////////////////////////////////////////////// +UINTN TouchIndex = 0; + +void TouchPrintDevicePath(EFI_HANDLE handle) { + EFI_ABSOLUTE_POINTER_PROTOCOL* absio = NULL; + EfiPrintDevicePath(handle); + TouchGetIO(handle, &absio); + if (absio != NULL) { + EFI_STATUS res; + EFI_ABSOLUTE_POINTER_STATE aps; + SetMem(&aps, sizeof(aps), 0); + res = absio->GetState(absio, &aps); + OUT_PRINT(L" - X[%lld,%lld] Y[%lld,%lld] Z[%lld,%lld] A[0x%x] S[%r (%lld,%lld,%lld), 0x%x]", + absio->Mode->AbsoluteMinX, absio->Mode->AbsoluteMaxX, + absio->Mode->AbsoluteMinY, absio->Mode->AbsoluteMaxY, + absio->Mode->AbsoluteMinZ, absio->Mode->AbsoluteMaxZ, + absio->Mode->Attributes, + res, aps.CurrentX, aps.CurrentY, aps.CurrentZ, aps.ActiveButtons + ); + } +} + +void TouchPrintDevicePathByIndex(UINTN touchIndex) { + OUT_PRINT(L"%V%d%N ", touchIndex); + TouchPrintDevicePath(gTouchHandles[touchIndex]); +} + +void TouchPrintDevicePaths(CHAR16* msg) { + UINTN i; + OUT_PRINT(msg); + for (i = 0; i < gTouchCount; ++i) { + TouchPrintDevicePathByIndex(i); + OUT_PRINT(L"\n"); + } +} + +VOID +PrintTouchList() { + InitTouch(); + TouchPrintDevicePaths(L"%HTouch handles%N\n"); +} + +VOID +TestTouch() { + EFI_ABSOLUTE_POINTER_PROTOCOL* absio = NULL; + EFI_HANDLE handle; + EFI_STATUS res; + + InitTouch(); + if (TouchIndex >= gTouchCount) return; + handle = gTouchHandles[TouchIndex]; + EfiPrintDevicePath(handle); + TouchGetIO(handle, &absio); + if (absio != NULL) { + EFI_ABSOLUTE_POINTER_STATE aps; + EFI_EVENT events[2]; + UINTN EventIndex; + + events[0] = gST->ConIn->WaitForKey; + events[1] = absio->WaitForInput; + do { + gBS->WaitForEvent(2, events, &EventIndex); + SetMem(&aps, sizeof(aps), 0); + res = absio->GetState(absio, &aps); + OUT_PRINT(L" S[%r (%lld,%lld,%lld), 0x%x]", + res, aps.CurrentX, aps.CurrentY, aps.CurrentZ, aps.ActiveButtons + ); + } while (EventIndex == 1); + } +} + diff --git a/DcsInt/DcsInt.c b/DcsInt/DcsInt.c new file mode 100644 index 0000000..3867067 --- /dev/null +++ b/DcsInt/DcsInt.c @@ -0,0 +1,1057 @@ +/** @file +Block R/W interceptor + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include "DcsInt.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "common/Tcdefs.h" +#include "common/Crypto.h" +#include "common/Volumes.h" +#include "common/Crc.h" +#include "crypto/cpu.h" +#include "BootCommon.h" +#include "DcsVeraCrypt.h" +#include + +// #define TRC_HANDLE_PATH(msg,h) \ +// OUT_PRINT(msg); \ +// EfiPrintDevicePath(h); \ +// OUT_PRINT(L"\n") +#define TRC_HANDLE_PATH(msg,h) + +EFI_DEVICE_PATH* gDcsBoot; +UINTN gDcsBootSize; + +DCSINT_BLOCK_IO* DcsIntBlockIoFirst = NULL; //< List of block I/O head + +EFI_DRIVER_BINDING_PROTOCOL g_DcsIntDriverBinding = { + DcsIntBindingSupported, + DcsIntBindingStart, + DcsIntBindingStop, + DCSINT_DRIVER_VERSION, + NULL, + NULL +}; + +#pragma pack(1) +typedef struct _BOOT_PARAMS { + CHAR8 Offset[TC_BOOT_LOADER_ARGS_OFFSET]; + BootArguments BootArgs; + BOOT_CRYPTO_HEADER BootCryptoInfo; + uint16 pad1; + SECREGION_BOOT_PARAMS SecRegion; +} BOOT_PARAMS, *PBOOT_PARAMS; +#pragma pack() + +UINT32 gHeaderSaltCrc32 = 0; +PBOOT_PARAMS bootParams = NULL; +//#define EFI_BOOTARGS_REGIONS_TEST ,0x9000000, 0xA000000 +#define EFI_BOOTARGS_REGIONS_TEST +UINTN BootArgsRegions[] = { EFI_BOOTARGS_REGIONS_HIGH, EFI_BOOTARGS_REGIONS_LOW EFI_BOOTARGS_REGIONS_TEST }; + +CHAR8 Header[512]; +UINT32 BootDriveSignature; +EFI_GUID BootDriveSignatureGpt; + +EFI_HANDLE SecRegionHandle = NULL; +UINT64 SecRegionSector = 0; +UINT8* SecRegionData = NULL; +UINTN SecRegionSize = 0; +UINTN SecRegionOffset = 0; +PCRYPTO_INFO SecRegionCryptInfo = NULL; + +void HaltPrint(const CHAR16* Msg) +{ + Print(L"%s - system Halted\n", Msg); + EfiCpuHalt(); +} + +////////////////////////////////////////////////////////////////////////// +// Boot params memory +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +GetBootParamsMemory() { + EFI_STATUS status = 0; + UINTN index; + if (bootParams != NULL) return EFI_SUCCESS; + for (index = 0; index < sizeof(BootArgsRegions) / sizeof(BootArgsRegions[1]); ++index) { + status = PrepareMemory(BootArgsRegions[index], sizeof(*bootParams), &bootParams); + if (!EFI_ERROR(status)) { + return status; + } + } + return status; +} + +EFI_STATUS +SetSecRegionParamsMemory() { + EFI_STATUS status = 0; + UINTN index; + UINT8* secRegion = NULL; + UINT32 crc; + if (bootParams == NULL) return EFI_NOT_READY; + + bootParams->SecRegion.Ptr = 0; + bootParams->SecRegion.Size = 0; + if (DeList != NULL) { + for (index = 0; index < sizeof(BootArgsRegions) / sizeof(BootArgsRegions[1]); ++index) { + status = PrepareMemory(BootArgsRegions[index], DeList->DataSize, &secRegion); + if (!EFI_ERROR(status)) { +// OUT_PRINT(L"bootParams %08x SecRegion %08x\n", (UINTN)bootParams, (UINTN)secRegion); + CopyMem(secRegion, SecRegionData + SecRegionOffset, DeList->DataSize); + bootParams->SecRegion.Ptr = (UINT64)secRegion; + bootParams->SecRegion.Size = DeList->DataSize; + break; + } + } + } + status = gBS->CalculateCrc32(&bootParams->SecRegion, sizeof(SECREGION_BOOT_PARAMS) - 4, &crc); + bootParams->SecRegion.Crc = crc; + return status; +} + +EFI_STATUS +PrepareBootParams( + IN UINT32 bootDriveSignature, + IN PCRYPTO_INFO cryptoInfo) +{ + BootArguments *bootArgs; + if (bootParams == NULL) return EFI_UNSUPPORTED; + bootArgs = &bootParams->BootArgs; + TC_SET_BOOT_ARGUMENTS_SIGNATURE(bootArgs->Signature); + bootArgs->BootLoaderVersion = VERSION_NUM; + bootArgs->CryptoInfoOffset = (uint16)(FIELD_OFFSET(BOOT_PARAMS, BootCryptoInfo)); + bootArgs->CryptoInfoLength = (uint16)(sizeof(BOOT_CRYPTO_HEADER) + 2 + sizeof(SECREGION_BOOT_PARAMS)); + bootArgs->HeaderSaltCrc32 = gHeaderSaltCrc32; + CopyMem(&bootArgs->BootPassword, &gAuthPassword, sizeof(gAuthPassword)); + bootArgs->HiddenSystemPartitionStart = 0; + bootArgs->DecoySystemPartitionStart = 0; + bootArgs->BootDriveSignature = bootDriveSignature; + bootArgs->Flags = (uint32)(gAuthPim << 16); + bootArgs->BootArgumentsCrc32 = GetCrc32((byte *)bootArgs, (int)((byte *)&bootArgs->BootArgumentsCrc32 - (byte *)bootArgs)); + bootParams->BootCryptoInfo.ea = (uint16)cryptoInfo->ea; + bootParams->BootCryptoInfo.mode = (uint16)cryptoInfo->mode; + bootParams->BootCryptoInfo.pkcs5 = (uint16)cryptoInfo->pkcs5; + SetSecRegionParamsMemory(); + + // Clean auth data + ZeroMem(&gAuthPassword, sizeof(gAuthPassword)); + gAuthPim = 0; + + return EFI_SUCCESS; +} + +void GetIntersection(uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength) +{ + uint64 end1 = start1 + length1 - 1; + uint64 intersectEnd = (end1 <= end2) ? end1 : end2; + + *intersectStart = (start1 >= start2) ? start1 : start2; + *intersectLength = (uint32)((*intersectStart > intersectEnd) ? 0 : intersectEnd + 1 - *intersectStart); + + if (*intersectLength == 0) + *intersectStart = start1; +} + +VOID UpdateDataBuffer( + IN OUT UINT8* buf, + IN UINT32 bufSize, + IN UINT64 sector + ) { + UINT64 intersectStart; + UINT32 intersectLength; + UINTN i; + if (DeList == NULL) return; + for (i = 0; i < DeList->Count; ++i) { + if (DeList->DE[i].Type == DE_Sectors) { + GetIntersection( + sector << 9, bufSize, + DeList->DE[i].Sectors.Start, DeList->DE[i].Sectors.Start + DeList->DE[i].Sectors.Length - 1, + &intersectStart, &intersectLength + ); + if (intersectLength != 0) { +// OUT_PRINT(L"S %d : %lld, %d\n", i, intersectStart, intersectLength); +// OUT_PRINT(L"S"); + CopyMem( + buf + (intersectStart - (sector << 9)), + SecRegionData + SecRegionOffset + DeList->DE[i].Sectors.Offset + (intersectStart - (sector << 9)), + intersectLength + ); + } + } + } + +} + +////////////////////////////////////////////////////////////////////////// +// List of block I/O +////////////////////////////////////////////////////////////////////////// +DCSINT_BLOCK_IO* +GetBlockIoByHandle( + IN EFI_HANDLE handle) +{ + DCSINT_BLOCK_IO *DcsIntBlockIo = DcsIntBlockIoFirst; + while (DcsIntBlockIo != NULL) { + if (DcsIntBlockIo->Controller == handle) { + return DcsIntBlockIo; + } + DcsIntBlockIo = DcsIntBlockIo->Next; + } + return NULL; +} + +DCSINT_BLOCK_IO* +GetBlockIoByProtocol( + IN EFI_BLOCK_IO_PROTOCOL* protocol) +{ + DCSINT_BLOCK_IO *DcsIntBlockIo = DcsIntBlockIoFirst; + while (DcsIntBlockIo != NULL) { + if (DcsIntBlockIo->BlockIo == protocol) { + return DcsIntBlockIo; + } + DcsIntBlockIo = DcsIntBlockIo->Next; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Read/Write +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +IntBlockIO_Write( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + DCSINT_BLOCK_IO *DcsIntBlockIo = NULL; + EFI_STATUS Status = EFI_SUCCESS; + EFI_LBA startSector; + DcsIntBlockIo = GetBlockIoByProtocol(This); + + if (DcsIntBlockIo) { + startSector = Lba; + startSector += gAuthBoot ? 0 : DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value >> 9; + //Print(L"This[0x%x] mid %x Write: lba=%lld, size=%d %r\n", This, MediaId, Lba, BufferSize, Status); + if ((startSector >= DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value >> 9) && + (startSector < ((DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value + DcsIntBlockIo->CryptInfo->EncryptedAreaLength.Value) >> 9))) { + VOID* writeCrypted; + writeCrypted = MEM_ALLOC(BufferSize); + if (writeCrypted == NULL) { + Status = EFI_BAD_BUFFER_SIZE; + + } + CopyMem(writeCrypted, Buffer, BufferSize); + // Print(L"*"); + UpdateDataBuffer(writeCrypted, (UINT32)BufferSize, startSector); + EncryptDataUnits(writeCrypted, (UINT64_STRUCT*)&startSector, (UINT32)(BufferSize >> 9), DcsIntBlockIo->CryptInfo); + Status = DcsIntBlockIo->LowWrite(This, MediaId, startSector, BufferSize, writeCrypted); + MEM_FREE(writeCrypted); + } + else { + Status = DcsIntBlockIo->LowWrite(This, MediaId, startSector, BufferSize, Buffer); + } + } + else { + Status = EFI_BAD_BUFFER_SIZE; + } + return Status; +} + +EFI_STATUS +IntBlockIO_Read( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +{ + DCSINT_BLOCK_IO *DcsIntBlockIo = NULL; + EFI_STATUS Status = EFI_SUCCESS; + EFI_LBA startSector; + + DcsIntBlockIo = GetBlockIoByProtocol(This); + if (DcsIntBlockIo) { + startSector = Lba; + startSector += gAuthBoot ? 0 : DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value >> 9; + Status = DcsIntBlockIo->LowRead(This, MediaId, startSector, BufferSize, Buffer); + //Print(L"This[0x%x] mid %x ReadBlock: lba=%lld, size=%d %r\n", This, MediaId, Lba, BufferSize, Status); + if ((startSector >= DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value >> 9) && + (startSector < ((DcsIntBlockIo->CryptInfo->EncryptedAreaStart.Value + DcsIntBlockIo->CryptInfo->EncryptedAreaLength.Value) >> 9))) { + // Print(L"."); + DecryptDataUnits(Buffer, (UINT64_STRUCT*)&startSector, (UINT32)(BufferSize >> 9), DcsIntBlockIo->CryptInfo); + } + UpdateDataBuffer(Buffer, (UINT32)BufferSize, startSector); + } + else { + Status = EFI_BAD_BUFFER_SIZE; + } + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// Block IO hook +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +IntBlockIo_Hook( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + DCSINT_BLOCK_IO *DcsIntBlockIo = 0; + EFI_STATUS Status; +// EFI_TPL Tpl; + + // Already hook? + DcsIntBlockIo = GetBlockIoByHandle(DeviceHandle); + if (DcsIntBlockIo != NULL) { + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol( + DeviceHandle, + &gEfiBlockIoProtocolGuid, + (VOID**)&BlockIo, + This->DriverBindingHandle, + DeviceHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR(Status)) { + // Check is this protocol already hooked + DcsIntBlockIo = (DCSINT_BLOCK_IO *)MEM_ALLOC(sizeof(DCSINT_BLOCK_IO)); + if (DcsIntBlockIo == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // construct new DcsIntBlockIo + DcsIntBlockIo->Sign = DCSINT_BLOCK_IO_SIGN; + DcsIntBlockIo->Controller = DeviceHandle; + DcsIntBlockIo->BlockIo = BlockIo; + DcsIntBlockIo->IsReinstalled = 0; + + if (EFI_ERROR(Status)) { + gBS->CloseProtocol( + DeviceHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + MEM_FREE(DcsIntBlockIo); + return EFI_UNSUPPORTED; + } + // Block +// Tpl = gBS->RaiseTPL(TPL_NOTIFY); + // Install new routines + DcsIntBlockIo->CryptInfo = SecRegionCryptInfo; + DcsIntBlockIo->LowRead = BlockIo->ReadBlocks; + DcsIntBlockIo->LowWrite = BlockIo->WriteBlocks; + BlockIo->ReadBlocks = IntBlockIO_Read; + BlockIo->WriteBlocks = IntBlockIO_Write; + + // close protocol before reinstall + gBS->CloseProtocol( + DeviceHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + + // add to global list + if (DcsIntBlockIoFirst == NULL) { + DcsIntBlockIoFirst = DcsIntBlockIo; + } + else { + DcsIntBlockIoFirst->Next = DcsIntBlockIoFirst; + DcsIntBlockIoFirst = DcsIntBlockIo; + } + + // reinstall BlockIo protocol + Status = gBS->ReinstallProtocolInterface( + DeviceHandle, + &gEfiBlockIoProtocolGuid, + BlockIo, + BlockIo + ); + +// gBS->RestoreTPL(Tpl); + DcsIntBlockIo->IsReinstalled = 1; + + Status = EFI_SUCCESS; + } + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// DriverBinding routines +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +DcsIntBindingStart( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + + TRC_HANDLE_PATH(L"t: ", Controller); + + // hook blockIo + Status = IntBlockIo_Hook(This, Controller); + if (EFI_ERROR(Status)) { + HaltPrint(L"Failed"); + } + return Status; +} + +EFI_STATUS +DcsIntBindingSupported( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_DEVICE_PATH *DevicePath; + DevicePath = DevicePathFromHandle(Controller); + if ((DevicePath != NULL) && CompareMem(DevicePath, gDcsBoot, gDcsBootSize) == 0) { + DCSINT_BLOCK_IO* DcsIntBlockIo = NULL; + // Is installed? + DcsIntBlockIo = GetBlockIoByHandle(Controller); + if (DcsIntBlockIo != NULL) { + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; + } + return EFI_UNSUPPORTED; +} + +EFI_STATUS +DcsIntBindingStop( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + TRC_HANDLE_PATH(L"p: ", Controller); + return EFI_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////// +// Security regions +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +SecRegionLoadDefault(EFI_HANDLE partHandle) +{ + EFI_STATUS res = EFI_SUCCESS; + HARDDRIVE_DEVICE_PATH dpVolme; + EFI_BLOCK_IO_PROTOCOL *bio = NULL; + EFI_PARTITION_TABLE_HEADER* gptHdr; + res = EfiGetPartDetails(partHandle, &dpVolme, &SecRegionHandle); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Part details: %r\n,", res); + return res; + } + + // get BlockIo protocol + bio = EfiGetBlockIO(SecRegionHandle); + if (bio == NULL) { + ERR_PRINT(L"Block io not supported\n,"); + return EFI_NOT_FOUND; + } + + SecRegionData = MEM_ALLOC(512); + if (SecRegionData == NULL) { + ERR_PRINT(L"No memory\n,"); + return EFI_BUFFER_TOO_SMALL; + } + SecRegionSize = 512; + + res = bio->ReadBlocks(bio, bio->Media->MediaId, 0, 512, SecRegionData); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read: %r\n", res); + goto error; + } + + BootDriveSignature = *(uint32 *)(SecRegionData + 0x1b8); + + res = bio->ReadBlocks(bio, bio->Media->MediaId, 1, 512, SecRegionData); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read: %r\n", res); + goto error; + } + + gptHdr = (EFI_PARTITION_TABLE_HEADER*)SecRegionData; + CopyMem(&BootDriveSignatureGpt, &gptHdr->DiskGUID, sizeof(BootDriveSignatureGpt)); + + res = bio->ReadBlocks(bio, bio->Media->MediaId, TC_BOOT_VOLUME_HEADER_SECTOR, 512, SecRegionData); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read: %r\n", res); + goto error; + } + + return EFI_SUCCESS; +error: + MEM_FREE(SecRegionData); + SecRegionData = NULL; + SecRegionSize = 0; + return res; +} + +EFI_STATUS +SecRegionChangePwd() { + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL* bio = NULL; + PCRYPTO_INFO cryptoInfo, ci; + Password newPassword; + Password confirmPassword; + INT32 vcres; + + Status = RndPreapare(); + if (EFI_ERROR(Status)) { + ERR_PRINT(L"Rnd: %r\n", Status); + return Status; + } + + do { + ZeroMem(&newPassword, sizeof(newPassword)); + ZeroMem(&confirmPassword, sizeof(newPassword)); + VCAskPwd(AskPwdNew, &newPassword); + if (gAuthPwdCode == AskPwdRetCancel) { + return EFI_NOT_READY; + } + VCAskPwd(AskPwdConfirm, &confirmPassword); + if (gAuthPwdCode == AskPwdRetCancel) { + return EFI_NOT_READY; + } + if (newPassword.Length == confirmPassword.Length) { + if (CompareMem(newPassword.Text, confirmPassword.Text, confirmPassword.Length) == 0) { + break; + } + } + ERR_PRINT(L"Password mismatch"); + } while (TRUE); + + OUT_PRINT(L"Generate...\n\r"); + cryptoInfo = SecRegionCryptInfo; + vcres = CreateVolumeHeaderInMemory( + gAuthBoot, Header, + cryptoInfo->ea, + cryptoInfo->mode, + &newPassword, + cryptoInfo->pkcs5, + gAuthPim, + cryptoInfo->master_keydata, + &ci, + cryptoInfo->VolumeSize.Value, + 0, //(volumeType == TC_VOLUME_TYPE_HIDDEN) ? cryptoInfo->hiddenVolumeSize : 0, + cryptoInfo->EncryptedAreaStart.Value, + cryptoInfo->EncryptedAreaLength.Value, + gAuthTc ? 0 : cryptoInfo->RequiredProgramVersion, + cryptoInfo->HeaderFlags, + cryptoInfo->SectorSize, + FALSE); + + if (vcres != 0) { + ERR_PRINT(L"header create error(%x)\n", vcres); + return EFI_INVALID_PARAMETER; + } + + // get BlockIo protocol + bio = EfiGetBlockIO(SecRegionHandle); + if (bio == NULL) { + ERR_PRINT(L"Block io not supported\n,"); + return EFI_NOT_FOUND; + } + + Status = bio->WriteBlocks(bio, bio->Media->MediaId, SecRegionSector, 512, Header); + if (EFI_ERROR(Status)) { + ERR_PRINT(L"Write: %r\n", Status); + return Status; + } + CopyMem(&gAuthPassword, &newPassword, sizeof(gAuthPassword)); + CopyMem(SecRegionData + SecRegionOffset, Header, 512); + ERR_PRINT(L"Update (%r)\n", Status); + return Status; +} + +EFI_STATUS +SelectDcsBootBySignature() +{ + EFI_STATUS res = EFI_NOT_FOUND; + EFI_BLOCK_IO_PROTOCOL* bio = NULL; + EFI_PARTITION_TABLE_HEADER* gptHdr; + UINTN i; + for (i = 0; i < gBIOCount; ++i) { + if(EfiIsPartition(gBIOHandles[i])) continue; + bio = EfiGetBlockIO(gBIOHandles[i]); + if(bio == NULL) continue; + res = bio->ReadBlocks(bio, bio->Media->MediaId, 0, 512, Header); + if(EFI_ERROR(res)) continue; + if((*(UINT32*)(Header+0x1b8)) != BootDriveSignature) continue; + res = bio->ReadBlocks(bio, bio->Media->MediaId, 1, 512, Header); + if (EFI_ERROR(res)) continue; + gptHdr = (EFI_PARTITION_TABLE_HEADER*)Header; + if (CompareMem(&BootDriveSignatureGpt, &gptHdr->DiskGUID, sizeof(BootDriveSignatureGpt)) != 0) continue; + gDcsBoot = DevicePathFromHandle(gBIOHandles[i]); + gDcsBootSize = GetDevicePathSize(gDcsBoot); + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +SecRegionTryDecrypt() +{ + int vcres = 1; + EFI_STATUS res = EFI_SUCCESS; + + PlatformGetID(SecRegionHandle, &gPlatformKeyFile, &gPlatformKeyFileSize); + + do { + SecRegionOffset = 0; + VCAuthAsk(); + if (gAuthPwdCode == AskPwdRetCancel) { + return EFI_NOT_READY; + } + OUT_PRINT(L"Authorize...\n\r"); + do { + CopyMem(Header, SecRegionData + SecRegionOffset, 512); + vcres = ReadVolumeHeader(gAuthBoot, Header, &gAuthPassword, gAuthHash, gAuthPim, gAuthTc, &SecRegionCryptInfo, NULL); + SecRegionOffset += (vcres != 0) ? 1024 * 128 : 0; + } while (SecRegionOffset < SecRegionSize && vcres != 0); + if (vcres == 0) { + OUT_PRINT(L"Success\n"); + OUT_PRINT(L"start %lld len %lld\n", SecRegionCryptInfo->EncryptedAreaStart.Value, SecRegionCryptInfo->EncryptedAreaLength.Value); + break; + } else { + ERR_PRINT(L"Decript error(%x)\n\r", vcres); + } + } while (vcres != 0 && gAuthRetry != 0); + if (vcres != 0) { + return EFI_CRC_ERROR; + } + + SecRegionSector = 62 + SecRegionOffset / 512; + DeList = NULL; + if (SecRegionSize > 512) { + UINT64 startUnit = 0; + DecryptDataUnits(SecRegionData + SecRegionOffset + 512, (UINT64_STRUCT*)&startUnit,(UINT32)255, SecRegionCryptInfo); + if (CompareMem(SecRegionData + SecRegionOffset + 512, &gDcsDiskEntryListHeaderID, sizeof(gDcsDiskEntryListHeaderID)) != 0) { + ERR_PRINT(L"Wrong DCS list header"); + return EFI_CRC_ERROR; + } + DeList = (DCS_DISK_ENTRY_LIST *)(SecRegionData + SecRegionOffset + 512); + CopyMem(&BootDriveSignature, &DeList->DE[DE_IDX_DISKID].DiskId.MbrID, sizeof(BootDriveSignature)); + CopyMem(&BootDriveSignatureGpt, &DeList->DE[DE_IDX_DISKID].DiskId.GptID, sizeof(BootDriveSignatureGpt)); + + if (DeList->DE[DE_IDX_EXEC].Type == DE_ExecParams) { + DCS_DEP_EXEC *execParams = NULL; + execParams = (DCS_DEP_EXEC *)(SecRegionData + SecRegionOffset + DeList->DE[DE_IDX_EXEC].Offset); + EfiSetVar(L"DcsExecPartGuid", NULL, &execParams->ExecPartGuid, sizeof(EFI_GUID), EFI_VARIABLE_BOOTSERVICE_ACCESS); + EfiSetVar(L"DcsExecCmd", NULL, &execParams->ExecCmd, (StrLen((CHAR16*)&execParams->ExecCmd) + 1) * 2, EFI_VARIABLE_BOOTSERVICE_ACCESS); + } + + if (DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { + DCS_DEP_PWD_CACHE *pwdCache = NULL; + UINT64 sector = 0; + pwdCache = (DCS_DEP_PWD_CACHE *)(SecRegionData + SecRegionOffset + DeList->DE[DE_IDX_PWDCACHE].Offset); + EncryptDataUnits((UINT8*)pwdCache, (UINT64_STRUCT*)§or, 1, SecRegionCryptInfo); + } + + if (DeList->DE[DE_IDX_RND].Type == DE_Rnd) { + UINT8 temp[4]; + UINT64 sector = 0; + DCS_RND_SAVED* rndNewSaved; + DCS_RND_SAVED* rndSaved = (DCS_RND_SAVED*)(SecRegionData + SecRegionOffset + DeList->DE[DE_IDX_RND].Offset); + if (DeList->DE[DE_IDX_RND].Length == sizeof(DCS_RND_SAVED)) { + if (!EFI_ERROR(res = RndLoad(rndSaved, &gRnd)) && + !EFI_ERROR(res = RndGetBytes(temp, sizeof(temp))) && + !EFI_ERROR(res = RndSave(gRnd, &rndNewSaved)) + ) { + EFI_BLOCK_IO_PROTOCOL *bio = NULL; + sector = (DeList->DE[DE_IDX_RND].Offset >> 9) - 1; + OUT_PRINT(L"Last login %H%t%N\n", &rndSaved->SavedAt); + + EncryptDataUnits((UINT8*)rndNewSaved, (UINT64_STRUCT*)§or, 1, SecRegionCryptInfo); + sector = SecRegionSector + (DeList->DE[DE_IDX_RND].Offset >> 9); + + // get BlockIo protocol + bio = EfiGetBlockIO(SecRegionHandle); + if (bio == NULL) { + ERR_PRINT(L"Block io not supported\n,"); + } + + res = bio->WriteBlocks(bio, bio->Media->MediaId, sector, 512, rndNewSaved); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + } + } + } + } + } + + // Select boot device + res = SelectDcsBootBySignature(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Decrypt device not found\n"); + return res; + } + + // Change password if requested + if (gAuthPwdCode == AskPwdRetChange && gRnd != NULL) { + res = RndPreapare(); + if (!EFI_ERROR(res)) { + res = SecRegionChangePwd(); + if (EFI_ERROR(res)) { + return res; + } + } else { + ERR_PRINT(L"Random: %r\n", res); + } + } + gHeaderSaltCrc32 = GetCrc32(SecRegionData + SecRegionOffset, PKCS5_SALT_SIZE); + return EFI_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////// +// Exit action +////////////////////////////////////////////////////////////////////////// +enum OnExitTypes{ + OnExitAuthFaild = 1, + OnExitAuthNotFound, + OnExitSuccess +}; + +BOOLEAN +AsciiCharNCmp( + IN CHAR8 ch1, + IN CHAR8 ch2 + ) +{ + return (ch1 | 0x20) == (ch2 | 0x20); +} + +CHAR8* +AsciiStrNStr( + IN CHAR8* str, + IN CHAR8* pattern) +{ + CHAR8* pos1 = str; + CHAR8* pos2; + CHAR8* posp; + while (*pos1 != 0) { + posp = pattern; + pos2 = pos1; + while (*posp != 0 && *pos2 != 0 && AsciiCharNCmp(*pos2,*posp)) { + ++posp; + ++pos2; + } + if (*pos2 == 0) return NULL; + if (*posp == 0) return pos1; + ++pos1; + } + return NULL; +} + +BOOLEAN +OnExitGetParam( + IN CHAR8 *action, + IN CHAR8 *name, + OUT CHAR8 **value, + OUT CHAR16 **valueU + ) +{ + CHAR8* pos; + UINTN len = 0; + UINTN i = 0; + pos = AsciiStrNStr(action, name); + if (pos == NULL) return FALSE; + pos += AsciiStrLen(name); + if(*pos != '(') return FALSE; + pos++; + while (pos[len] != 0 && pos[len] != ')') len++; + if (pos[len] == 0) return FALSE; + if (value != NULL) *value = MEM_ALLOC(len + 1); + if (valueU != NULL) *valueU = MEM_ALLOC((len + 1) * 2); + for (i = 0; i < len; ++i) { + if (value != NULL) (*value)[i] = pos[i]; + if (valueU != NULL) (*valueU)[i] = pos[i]; + } + return TRUE; +} + +EFI_STATUS +OnExit( + IN CHAR8 *action, + IN UINTN type, + IN EFI_STATUS retValue) +{ + CHAR8* guidStr = NULL; + CHAR8* exitStatusStr = NULL; + CHAR8* messageStr = NULL; + CHAR8* delayStr = NULL; + EFI_GUID *guid = NULL; + CHAR16 *fileStr = NULL; + if (action == NULL) return retValue; + if (OnExitGetParam(action, "guid", &guidStr, NULL)) { + EFI_GUID tmp; + if (AsciiStrToGuid(&tmp, guidStr)) { + guid = MEM_ALLOC(sizeof(EFI_GUID)); + CopyMem(guid, &tmp, sizeof(EFI_GUID)); + } + } + + if (OnExitGetParam(action, "status", &exitStatusStr, NULL)) { + retValue = AsciiStrDecimalToUintn(exitStatusStr); + } + + OnExitGetParam(action, "file", NULL, &fileStr); + + + if (OnExitGetParam(action, "printinfo", NULL, NULL)) { + OUT_PRINT(L"type %d\naction %a\n", type, action); + if (guid != NULL) OUT_PRINT(L"guid %g\n", guid); + if (fileStr != NULL) OUT_PRINT(L"file %s\n", fileStr); + if (exitStatusStr != NULL) OUT_PRINT(L"status %d, %r\n", retValue, retValue); + } + + if (OnExitGetParam(action, "message", &messageStr, NULL)) { + OUT_PRINT(L"%a", messageStr); + } + + if (OnExitGetParam(action, "delay", &delayStr, NULL)) { + UINTN delay; + EFI_INPUT_KEY key; + delay = AsciiStrDecimalToUintn(delayStr); + OUT_PRINT(L"\n"); + key = KeyWait(L"\r%d ", delay, 0, 0); + if (key.UnicodeChar != 0) GetKey(); + } + + if (AsciiStrNStr(action, "halt") == action) { + EfiCpuHalt(); + } + + if (AsciiStrNStr(action, "exec") == action) { + if (guid != NULL) { + EFI_STATUS res; + EFI_HANDLE h; + res = EfiFindPartByGUID(guid, &h); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nCan't find start partition\n"); + EfiCpuHalt(); + } + // Try to exec + res = EfiExec(h, fileStr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"\nStart %s - %r\n", fileStr, res); + EfiCpuHalt(); + } + } + + if (fileStr != NULL) { + EfiSetVar(L"DcsExecCmd", NULL, fileStr, (StrLen(fileStr) + 1) * 2, EFI_VARIABLE_BOOTSERVICE_ACCESS); + } + goto exit; + } + + if (AsciiStrNStr(action, "postexec") == action) { + if (guid != NULL) { + EfiSetVar(L"DcsExecPartGuid", NULL, &guid, sizeof(EFI_GUID), EFI_VARIABLE_BOOTSERVICE_ACCESS); + } + if (fileStr != NULL) { + EfiSetVar(L"DcsExecCmd", NULL, fileStr, (StrLen(fileStr) + 1) * 2, EFI_VARIABLE_BOOTSERVICE_ACCESS); + } + goto exit; + } + + if (AsciiStrStr(action, "exit") == action) { + goto exit; + } + +exit: + MEM_FREE(guidStr); + MEM_FREE(exitStatusStr); + MEM_FREE(messageStr); + MEM_FREE(delayStr); + MEM_FREE(guid); + MEM_FREE(fileStr); + return retValue; +} + +////////////////////////////////////////////////////////////////////////// +// Exit boot loader event +////////////////////////////////////////////////////////////////////////// +EFI_EVENT mVirtualAddrChangeEvent; +VOID +EFIAPI +VirtualNotifyEvent( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // Clean all sensible info and keys before transfer to OS + if (SecRegionCryptInfo != NULL) { + ZeroMem(SecRegionCryptInfo, sizeof(*SecRegionCryptInfo)); + } + + if (gRnd != NULL) { + ZeroMem(gRnd, sizeof(*gRnd)); + } + + if (SecRegionData != NULL) { + ZeroMem(SecRegionData, SecRegionSize); + } +} + +////////////////////////////////////////////////////////////////////////// +// Driver Entry Point +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +UefiMain( + EFI_HANDLE ImageHandle, + EFI_SYSTEM_TABLE *SystemTable) +{ + EFI_STATUS res; + + InitBio(); + InitFS(); + + // Remove BootNext to restore boot order + BootMenuItemRemove(L"BootNext"); + + // Load auth parameters + VCAuthLoadConfig(); + if (gAuthSecRegionSearch) { + res = PlatformGetAuthData(&SecRegionData, &SecRegionSize, &SecRegionHandle); + if (!EFI_ERROR(res)) { + EFI_INPUT_KEY key; + EfiPrintDevicePath(SecRegionHandle); + OUT_PRINT(L"\n"); + key = KeyWait(L"%2d \r", 2, 0, 0); + if (key.UnicodeChar != 0) { + GetKey(); + } + } + } else if (gRUD != 0) { + // RUD defined + UINTN i; + BOOLEAN devFound = FALSE; + InitUsb(); + for (i = 0; i < gUSBCount; ++i) { + CHAR8* id = NULL; + res = UsbGetId(gUSBHandles[i], &id); + if (!EFI_ERROR(res) && id != NULL) { + INT32 rud; + rud = GetCrc32((unsigned char*)id, (int)AsciiStrLen(id)); + MEM_FREE(id); + if (rud == gRUD) { + devFound = TRUE; + break; + } + } + } + if (!devFound) return OnExit(gOnExitNotFound, OnExitAuthNotFound, EFI_NOT_FOUND); + } + + // Try to find by OS partition GUID + if (SecRegionData == NULL && gPartitionGuidOS != NULL) { + UINTN i; + for (i = 0; i < gBIOCount; ++i) { + EFI_GUID guid; + res = EfiGetPartGUID(gBIOHandles[i], &guid); + if(EFI_ERROR(res)) continue; + if (memcmp(gPartitionGuidOS, &guid, sizeof(guid)) == 0) { + res = SecRegionLoadDefault(gBIOHandles[i]); + if (EFI_ERROR(res)) { + return OnExit(gOnExitNotFound, OnExitAuthNotFound, res); + } + } + } + } + + // ask any way? (by DcsBoot flag) + if (SecRegionData == NULL) { + if (gDcsBootForce != 0) { + res = SecRegionLoadDefault(gFileRootHandle); + if (EFI_ERROR(res)) { + return OnExit(gOnExitNotFound, OnExitAuthNotFound, res); + } + } else { + return OnExit(gOnExitNotFound, OnExitAuthNotFound, EFI_NOT_FOUND); + } + } + + res = GetBootParamsMemory(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"No boot args memory: %r\n\r", res); + KeyWait(L"%02d\r", 10, 0, 0); + return res; + } + + DetectX86Features(); + res = SecRegionTryDecrypt(); + if (EFI_ERROR(res)) { + return OnExit(gOnExitFailed, OnExitAuthFaild, res); + } + + res = PrepareBootParams(BootDriveSignature, SecRegionCryptInfo); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can not set params for OS: %r", res); + return OnExit(gOnExitFailed, OnExitAuthFaild, res); + } + + // Lock EFI boot variables + EfiExec(NULL, L"EFI\\VeraCrypt\\DcsBml.dcs"); + + // Install decrypt + res = EfiLibInstallDriverBindingComponentName2( + ImageHandle, + SystemTable, + &g_DcsIntDriverBinding, + ImageHandle, + &gDcsIntComponentName, + &gDcsIntComponentName2); + + if (EFI_ERROR(res)) { + ERR_PRINT(L"Bind %r\n", res); + return OnExit(gOnExitFailed, OnExitAuthFaild, res); + } + + res = gBS->CreateEventEx( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + VirtualNotifyEvent, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddrChangeEvent + ); + + return OnExit(gOnExitSuccess, OnExitSuccess, res); +} diff --git a/DcsInt/DcsInt.h b/DcsInt/DcsInt.h new file mode 100644 index 0000000..ad0e40c --- /dev/null +++ b/DcsInt/DcsInt.h @@ -0,0 +1,235 @@ +/** @file +Block R/W interceptor + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#ifndef __DCSINT_H__ +#define __DCSINT_H__ + +#include +#include +#include +#include +#include + +#define DCSINT_DRIVER_VERSION 1 +#define DCS_SIGNATURE_16(A, B) ((A) | (B << 8)) +#define DCS_SIGNATURE_32(A, B, C, D) (DCS_SIGNATURE_16 (A, B) | (DCS_SIGNATURE_16 (C, D) << 16)) + +#define DCSINT_BLOCK_IO_SIGN DCS_SIGNATURE_32('D','C','S', 'I') + +extern EFI_COMPONENT_NAME_PROTOCOL gDcsIntComponentName; +extern EFI_COMPONENT_NAME2_PROTOCOL gDcsIntComponentName2; + +typedef struct _DCSINT_BLOCK_IO DCSINT_BLOCK_IO, *PDCSINT_BLOCK_IO; +typedef struct CRYPTO_INFO_t CRYPTO_INFO, *PCRYPTO_INFO; + +typedef struct _DCSINT_BLOCK_IO { + UINT32 Sign; + EFI_HANDLE Controller; + + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_READ LowRead; + EFI_BLOCK_WRITE LowWrite; + UINT32 IsReinstalled; + PCRYPTO_INFO CryptInfo; + DCSINT_BLOCK_IO* Next; +} DCSINT_BLOCK_IO, *PDCSINT_BLOCK_IO; + +// +// Functions for Driver Binding Protocol +// + +/** + Check whether the controller is a supported. + + @param This The driver binding protocol. + @param Controller The controller handle to check. + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS The driver supports this controller. + @retval other This device isn't supported. + +**/ +EFI_STATUS +EFIAPI +DcsIntBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Starts the BlockIo device with this driver. + + @param This The driver binding protocol. + @param Controller The Block MMIO device to start on + @param RemainingDevicePath The remaining device path. + + @retval EFI_SUCCESS This driver supports this device. + @retval EFI_UNSUPPORTED This driver does not support this device. + @retval EFI_DEVICE_ERROR This driver cannot be started due to device Error. + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources. + @retval EFI_ALREADY_STARTED This driver has been started. + +**/ +EFI_STATUS +EFIAPI +DcsIntBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +/** + Stop controlling the device. + + @param This The driver binding + @param Controller The device controller controlled by the driver. + @param NumberOfChildren The number of children of this device + @param ChildHandleBuffer The buffer of children handle. + + @retval EFI_SUCCESS The driver stopped from controlling the device. + @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error. + @retval EFI_UNSUPPORTED Block I/O Protocol is not installed on Controller. + @retval Others Failed to stop the driver + +**/ +EFI_STATUS +EFIAPI +DcsIntBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Functions for Block I/O Protocol +// + +// +// EFI Component Name Functions +// + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + @param DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DcsIntComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + @param ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DcsIntComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + + +#endif \ No newline at end of file diff --git a/DcsInt/DcsInt.inf b/DcsInt/DcsInt.inf new file mode 100644 index 0000000..e79dcc6 --- /dev/null +++ b/DcsInt/DcsInt.inf @@ -0,0 +1,93 @@ +# Block R/W interceptor +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = DcsInt + FILE_GUID = 26BC5841-0606-450F-A39B-F2DB0D7E002E + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = UefiMain + + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DcsInt.c + DcsInt.h + DcsIntName.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + UefiDriverEntryPoint + UefiLib + BaseLib + MemoryAllocationLib + GraphLib + CommonLib + PasswordLib + DcsCfgLib + VeraCryptLib + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiDevicePathProtocolGuid + gEfiLoadedImageProtocolGuid + +[Guids] + gEfiGlobalVariableGuid + gEfiDcsVariableGuid + gEfiFileInfoGuid + gEfiPartTypeUnusedGuid + gEfiPartTypeSystemPartGuid + gEfiEventVirtualAddressChangeGuid + +[BuildOptions.IA32] + +RELEASE_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +DEBUG_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI + +RELEASE_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +DEBUG_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI + +[BuildOptions.X64] +RELEASE_VS2010x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2010x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS = /D_UEFI + +RELEASE_VS2015x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2015x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS = /D_UEFI + +DEBUG_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +RELEASE_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +NOOPT_VS2010x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG + +DEBUG_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG +RELEASE_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:4254 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /MERGE:.rdata=.data +NOOPT_VS2015x86_X64_DLINK_FLAGS == /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT:ICF=10 /MAP /ALIGN:64 /SECTION:.xdata,D /SECTION:.pdata,D /Machine:X64 /LTCG /DLL /ENTRY:$(IMAGE_ENTRY_POINT) /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER /SAFESEH:NO /BASE:0 /DRIVER /DEBUG + + +[FeaturePcd] + +[Pcd] + diff --git a/DcsInt/DcsIntName.c b/DcsInt/DcsIntName.c new file mode 100644 index 0000000..ccf8698 --- /dev/null +++ b/DcsInt/DcsIntName.c @@ -0,0 +1,173 @@ +/** @file +Block R/W interceptor + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include "DcsInt.h" +#include +#include +#include + +// +// EFI Component Name Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gDcsIntComponentName = { + DcsIntComponentNameGetDriverName, + DcsIntComponentNameGetControllerName, + "eng" +}; + +// +// EFI Component Name 2 Protocol +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gDcsIntComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) DcsIntComponentNameGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) DcsIntComponentNameGetControllerName, + "en" +}; + +// +// Driver name table for module. +// It is shared by the implementation of ComponentName & ComponentName2 Protocol. +// +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mDcsIntComponentNameDriverNameTable[] = { + { + "eng;en", + (CHAR16 *)L"DCSINT Driver" + }, + { + NULL, + NULL + } +}; + +/** + Retrieves a Unicode string that is the user readable name of the driver. + + This function retrieves the user readable name of a driver in the form of a + Unicode string. If the driver specified by This has a user readable name in + the language specified by Language, then a pointer to the driver name is + returned in DriverName, and EFI_SUCCESS is returned. If the driver specified + by This does not support the language specified by Language, + then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified + in RFC 4646 or ISO 639-2 language code format. + @param DriverName A pointer to the Unicode string to return. + This Unicode string is the name of the + driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by + This and the language specified by Language was + returned in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DcsIntComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDcsIntComponentNameDriverNameTable, + DriverName, + (BOOLEAN)(This == &gDcsIntComponentName) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by a driver. + + This function retrieves the user readable name of the controller specified by + ControllerHandle and ChildHandle in the form of a Unicode string. If the + driver specified by This has a user readable name in the language specified by + Language, then a pointer to the controller name is returned in ControllerName, + and EFI_SUCCESS is returned. If the driver specified by This is not currently + managing the controller specified by ControllerHandle and ChildHandle, + then EFI_UNSUPPORTED is returned. If the driver specified by This does not + support the language specified by Language, then EFI_UNSUPPORTED is returned. + + @param This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or + EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver + specified by This is managing. This handle + specifies the controller whose name is to be + returned. + @param ChildHandle The handle of the child controller to retrieve + the name of. This is an optional parameter that + may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers + that wish to retrieve the name of the bus + controller. It will not be NULL for a bus + driver that wishes to retrieve the name of a + child controller. + @param Language A pointer to a Null-terminated ASCII string + array indicating the language. This is the + language of the driver name that the caller is + requesting, and it must match one of the + languages specified in SupportedLanguages. The + number of languages supported by a driver is up + to the driver writer. Language is specified in + RFC 4646 or ISO 639-2 language code format. + @param ControllerName A pointer to the Unicode string to return. + This Unicode string is the name of the + controller specified by ControllerHandle and + ChildHandle in the language specified by + Language from the point of view of the driver + specified by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in + the language specified by Language for the + driver specified by This was returned in + DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support + the language specified by Language. + +**/ +EFI_STATUS +EFIAPI +DcsIntComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return EFI_UNSUPPORTED; +} \ No newline at end of file diff --git a/DcsPkg.dec b/DcsPkg.dec new file mode 100644 index 0000000..539fda8 --- /dev/null +++ b/DcsPkg.dec @@ -0,0 +1,29 @@ +## @file DcsPkg.dec +# This Package provides all definitions, library classes and libraries instances. +# +## + + +[Defines] + DEC_SPECIFICATION = 0x00010005 + PACKAGE_NAME = DcsPkg + PACKAGE_UNI_FILE = DcsPkg.uni + PACKAGE_GUID = 9974377F-5593-492A-A54E-7B23126DE450 + PACKAGE_VERSION = 1.0 + + +[Includes] + Include + Library/VeraCryptLib + Library/VeraCryptLib/crypto + +[LibraryClasses] + CommonLib|Include/Library/CommonLib.h + GraphLib|Include/Library/GraphLib.h + PasswordLib|Include/Library/PasswordLib.h + DcsCfgLib|Include/Library/DcsCfgLib.h + +[Guids] + # Include/CommonLib.h + # {101F8560-D73A-4FF7-89F6-8170F6615587} + gEfiDcsVariableGuid = { 0x101f8560, 0xd73a, 0x4ff7, { 0x89, 0xf6, 0x81, 0x70, 0xf6, 0x61, 0x55, 0x87 } } diff --git a/DcsPkg.dsc b/DcsPkg.dsc new file mode 100644 index 0000000..e3e4963 --- /dev/null +++ b/DcsPkg.dsc @@ -0,0 +1,96 @@ +################################################################################ +# +# Defines Section - statements that will be processed to create a Makefile. +# +################################################################################ +[Defines] + PLATFORM_NAME = DcsPkg + PLATFORM_GUID = 5a9e7754-d81b-49ea-85ad-69eaa7b1539b + PLATFORM_VERSION = 0.1 + DSC_SPECIFICATION = 0x00010005 + OUTPUT_DIRECTORY = Build/DcsPkg + SUPPORTED_ARCHITECTURES = X64 | IA32 + BUILD_TARGETS = DEBUG|RELEASE + +[BuildOptions] + GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG + GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG + INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG + GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse + +################################################################################ +# +# Library Class section - list of all Library Classes needed by this Platform. +# +################################################################################ +[LibraryClasses] + UefiLib|MdePkg/Library/UefiLib/UefiLib.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + BaseLib|MdePkg/Library/BaseLib/BaseLib.inf + BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf + DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf + + PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf + DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf + DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf + TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf + + IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + + PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf + PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf + + UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf + Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf + TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf + + UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf + UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf + + UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf + HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf + FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf + SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf + + CommonLib|DcsPkg/Library/CommonLib/CommonLib.inf + GraphLib|DcsPkg/Library/GraphLib/GraphLib.inf + PasswordLib|DcsPkg/Library/PasswordLib/PasswordLib.inf + RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf + DcsCfgLib|DcsPkg/Library/DcsCfgLib/DcsCfgLib.inf + VeraCryptLib|DcsPkg/Library/VeraCryptLib/VeraCryptLib.inf + + [LibraryClasses.common.UEFI_APPLICATION] + ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf + ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf + UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf + + [LibraryClasses.common.UEFI_DRIVER] + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf + DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf + MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf + ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf + DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf + PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf + UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf + +[LibraryClasses.common.DXE_RUNTIME_DRIVER] + UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf + UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf + +################################################################################ +# +# Components Section - list of all EDK II Modules needed by this Platform. +# +################################################################################ +[Components] + DcsPkg/DcsInt/DcsInt.inf + DcsPkg/DcsCfg/DcsCfg.inf + DcsPkg/DcsBoot/DcsBoot.inf + DcsPkg/DcsRe/DcsRe.inf + DcsPkg/DcsBml/DcsBml.inf + DcsPkg/LegacySpeaker/LegacySpeaker.inf diff --git a/DcsPkg.uni b/DcsPkg.uni new file mode 100644 index 0000000..61700c9 --- /dev/null +++ b/DcsPkg.uni @@ -0,0 +1,6 @@ +// /** @file +// This Package provides all definitions, library classes and libraries instances. +// +// **/ + +#string STR_PACKAGE_ABSTRACT #language en-US "This Package provides all definitions, library classes and libraries instances." \ No newline at end of file diff --git a/DcsRe/DcsRe.c b/DcsRe/DcsRe.c new file mode 100644 index 0000000..9c59dfc --- /dev/null +++ b/DcsRe/DcsRe.c @@ -0,0 +1,330 @@ +/** @file + This is DCS recovery loader application + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include "common/Tcdefs.h" + +////////////////////////////////////////////////////////////////////////// +// Menu +////////////////////////////////////////////////////////////////////////// +typedef EFI_STATUS(*MENU_ACTION)(); + +typedef struct _MENU_ITEM MENU_ITEM; +typedef struct _MENU_ITEM { + CHAR16 Text[128]; + CHAR16 Select; + MENU_ACTION Action; + MENU_ITEM *Next; +} MENU_ITEM, *PMENU_ITEM; + +BOOLEAN gContiniue = TRUE; +PMENU_ITEM gMenu = NULL; + +PMENU_ITEM +AppendMenu( + IN PMENU_ITEM menu, + IN CHAR16 *text, + IN CHAR16 select, + IN MENU_ACTION action + ) { + PMENU_ITEM item; + item = (PMENU_ITEM)MEM_ALLOC(sizeof(MENU_ITEM)); + if (item == NULL) return item; + item->Action = action; + StrCat(item->Text, text); + item->Select = select; + if (menu != NULL) { + menu->Next = item; + } + return item; +} + +VOID +PrintMenu( + PMENU_ITEM head) { + PMENU_ITEM menu; + UINTN i = 0; + menu = head; + while (menu != NULL) { + OUT_PRINT(L"%H%c%N) %s\n", menu->Select, &menu->Text); + i++; + if (i == 22) { + ConsoleShowTip(L"Pause 60s", 60000000); + i = 0; + } + menu = menu->Next; + } + OUT_PRINT(L"["); + menu = head; + while (menu != NULL) { + OUT_PRINT(L"%H%c%N", menu->Select); + menu = menu->Next; + } + OUT_PRINT(L"]:"); +} +////////////////////////////////////////////////////////////////////////// +// EFI volume +////////////////////////////////////////////////////////////////////////// +UINTN EfiBootVolumeIndex = 0; +EFI_FILE *EfiBootVolume = NULL; +VOID +SelectEfiVolume() +{ + UINTN i; + EFI_STATUS res; + EFI_FILE *file; + EFI_FILE **efiVolumes; + UINTN efiVolumesCount = 0; + EFI_HANDLE startHandle; + if (EfiBootVolume != NULL) return; + res = EfiGetStartDevice(&startHandle); + if (EFI_ERROR(res)) { + ERR_PRINT(L"GetStartDevice %r", res); + return; + } + efiVolumes = MEM_ALLOC(sizeof(EFI_FILE*) * gFSCount); + for (i = 0; i < gFSCount; ++i) { + res = FileOpenRoot(gFSHandles[i], &file); + if(EFI_ERROR(res)) continue; + if (!EFI_ERROR(FileExist(file, L"EFI\\Boot\\bootx64.efi"))) { + efiVolumesCount++; + efiVolumes[i] = file; + if (gFSHandles[i] != startHandle) { + EfiBootVolumeIndex = i; + EfiBootVolume = file; + } + } else { + FileClose(file); + } + } + + for (i = 0; i < gFSCount; ++i) { + OUT_PRINT(L"%H%d)%N ", i); + if (efiVolumes[i] != NULL) { + if (gFSHandles[i] == startHandle) { + OUT_PRINT(L"%V [Boot Rescue] %N"); + } + else { + OUT_PRINT(L"%V [Boot] %N"); + } + EfiPrintDevicePath(gFSHandles[i]); + } + OUT_PRINT(L"\n"); + } + + do { + EfiBootVolumeIndex = AskUINTN("Select EFI boot volume:", EfiBootVolumeIndex); + if (EfiBootVolumeIndex >= gFSCount) continue; + EfiBootVolume = efiVolumes[EfiBootVolumeIndex]; + } while (EfiBootVolume == NULL); + MEM_FREE(efiVolumes); +} + +////////////////////////////////////////////////////////////////////////// +// Actions +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +ActionBootWinPE() { + return EfiExec(NULL, L"EFI\\Boot\\WinPE_bootx64.efi"); +} + +EFI_STATUS +ActionShell() { + return EfiExec(NULL, L"EFI\\Shell\\Shell.efi"); +} + +EFI_STATUS +ActionDcsBoot() { + return EfiExec(NULL, L"EFI\\VeraCrypt\\DcsBoot.efi"); +} + +CHAR16* DcsBootBins[] = { + L"EFI\\VeraCrypt\\DcsBoot.efi", + L"EFI\\VeraCrypt\\DcsInt.dcs", + L"EFI\\VeraCrypt\\DcsBml.dcs", + L"EFI\\VeraCrypt\\DcsCfg.dcs", + L"EFI\\VeraCrypt\\LegacySpeaker.dcs" +}; + +/** +Copy DCS binaries from rescue disk to EFI boot volume +*/ +EFI_STATUS +ActionRestoreDcsLoader() { + EFI_STATUS res = EFI_NOT_READY; + UINTN i; + SelectEfiVolume(); + if (EfiBootVolume == NULL) return EFI_NOT_READY; + for (i = 0; i < sizeof(DcsBootBins) / sizeof(CHAR16*); ++i) { + res = FileCopy(NULL, DcsBootBins[i], EfiBootVolume, DcsBootBins[i], 1024 * 1024); + if (EFI_ERROR(res)) return res; + } + return res; +} + +CHAR16* sDcsBootEfi = L"EFI\\VeraCrypt\\DcsBoot.efi"; +CHAR16* sDcsBootEfiDesc = L"VeraCrypt(DCS) loader"; +/** +Update boot menu +*/ +EFI_STATUS +ActionRestoreDcsBootMenu() +{ + EFI_STATUS res = EFI_NOT_READY; + SelectEfiVolume(); + if (EfiBootVolume == NULL) return EFI_NOT_READY; + // Prepare BootDC5B + res = BootMenuItemCreate(L"BootDC5B", sDcsBootEfiDesc, gFSHandles[EfiBootVolumeIndex], sDcsBootEfi, TRUE); + if (EFI_ERROR(res)) return res; + res = BootOrderInsert(L"BootOrder", 0, 0x0DC5B); + return res; +} + +EFI_STATUS +ActionRemoveDcsBootMenu() +{ + EFI_STATUS res = EFI_NOT_READY; + BootMenuItemRemove(L"BootDC5B"); + res = BootOrderRemove(L"BootOrder", 0x0DC5B); + return res; +} + +/** +Copy DcsProp from rescue disk to EFI boot volume +*/ +EFI_STATUS +ActionRestoreDcsProp() { + SelectEfiVolume(); + if (EfiBootVolume == NULL) return EFI_NOT_READY; + return FileCopy(NULL, L"EFI\\VeraCrypt\\DcsProp", EfiBootVolume, L"EFI\\VeraCrypt\\DcsProp", 1024*1024); +} + +#define OPT_OS_DECRYPT L"-osdecrypt" +#define OPT_OS_RESTORE_KEY L"-osrestorekey" + +CHAR16* sOSDecrypt = OPT_OS_DECRYPT; +CHAR16* sOSRestoreKey = OPT_OS_RESTORE_KEY; +CHAR16* sDcsCfg = L"EFI\\VeraCrypt\\DcsCfg.dcs"; + +EFI_STATUS +ActionRestoreHeader() { + EFI_STATUS res = EFI_NOT_READY; + res = EfiSetVar(L"dcscfgcmd", NULL, sOSRestoreKey, StrSize(sOSRestoreKey), EFI_VARIABLE_BOOTSERVICE_ACCESS); + return EfiExec(NULL, sDcsCfg); +} + +EFI_STATUS +ActionDecryptOS() { + EFI_STATUS res = EFI_NOT_READY; + res = EfiSetVar(L"dcscfgcmd", NULL, sOSDecrypt, StrSize(sOSDecrypt), EFI_VARIABLE_BOOTSERVICE_ACCESS); + return EfiExec(NULL, sDcsCfg); +} + +EFI_STATUS +ActionExit() { + gContiniue = FALSE; + return EFI_SUCCESS; +} + +EFI_STATUS +ActionHelp() { +OUT_PRINT(L"\ +%HRescue disk for VeraCrypt OS encryption%N\n\r\ +Help message to be defined\n\r\ +"); + return EFI_SUCCESS; +} + +/** +The actual entry point for the application. + +@param[in] ImageHandle The firmware allocated handle for the EFI image. +@param[in] SystemTable A pointer to the EFI System Table. + +@retval EFI_SUCCESS The entry point executed successfully. +@retval other Some error occur when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +DcsReMain( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS res; + EFI_INPUT_KEY key; + PMENU_ITEM item = gMenu; + InitBio(); + res = InitFS(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"InitFS %r\n", res); + return res; + } + + item = AppendMenu(NULL, L"Decrypt OS", 'd', ActionDecryptOS); + gMenu = item; + item = AppendMenu(item, L"Restore VeraCrypt loader to boot menu", 'm', ActionRestoreDcsBootMenu); + item = AppendMenu(item, L"Remove VeraCrypt loader from boot menu", 'z' , ActionRemoveDcsBootMenu); + + if (!EFI_ERROR(FileExist(NULL, L"EFI\\VeraCrypt\\DcsProp"))) { + item = AppendMenu(item, L"Restore VeraCrypt loader configuration to system disk", 'c', ActionRestoreDcsProp); + } + + if (!EFI_ERROR(FileExist(NULL, L"EFI\\VeraCrypt\\svh_bak"))) { + item = AppendMenu(item, L"Restore OS header keys", 'k', ActionRestoreHeader); + } + + if (!EFI_ERROR(FileExist(NULL, L"EFI\\VeraCrypt\\DcsBoot.efi"))) { + item = AppendMenu(item, L"Restore VeraCrypt loader binaries to system disk", 'r', ActionRestoreDcsLoader); + item = AppendMenu(item, L"Boot VeraCrypt loader from rescue disk", 'v', ActionDcsBoot); + } + + if (!EFI_ERROR(FileExist(NULL, L"EFI\\Boot\\WinPE_bootx64.efi"))) { + item = AppendMenu(item, L"Boot Windows PE from rescue disk", 'w', ActionBootWinPE); + } + + if (!EFI_ERROR(FileExist(NULL, L"EFI\\Shell\\Shell.efi"))) { + item = AppendMenu(item, L"Boot Shell.efi from rescue disk", 's', ActionShell); + } + + item = AppendMenu(item, L"Help", 'h', ActionHelp); + item = AppendMenu(item, L"Exit", 'e', ActionExit); + OUT_PRINT(L"%V%a rescue disk %a%N\n", TC_APP_NAME, VERSION_STRING); + gBS->SetWatchdogTimer(0, 0, 0, NULL); + do { + PrintMenu(gMenu); + item = NULL; + key.UnicodeChar = 0; + while (item == NULL) { + item = gMenu; + key = GetKey(); + while (item != NULL) { + if (item->Select == key.UnicodeChar) break; + item = item->Next; + } + } + OUT_PRINT(L"%c\n",key.UnicodeChar); + res = item->Action(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + } + } while (gContiniue); + return EFI_INVALID_PARAMETER; +} diff --git a/DcsRe/DcsRe.inf b/DcsRe/DcsRe.inf new file mode 100644 index 0000000..e103865 --- /dev/null +++ b/DcsRe/DcsRe.inf @@ -0,0 +1,74 @@ +## @file +# This is DCS boot loader application +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsRe + FILE_GUID = 31D0F9D8-ABA6-4D43-96BB-C602BAFF26AF + MODULE_TYPE = UEFI_APPLICATION + VERSION_STRING = 1.0 + ENTRY_POINT = DcsReMain + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DcsRe.c + + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + UefiApplicationEntryPoint + UefiLib + BaseLib + MemoryAllocationLib + CommonLib + +[Guids] + gEfiGlobalVariableGuid + gEfiDcsVariableGuid + gEfiFileInfoGuid + +[Protocols] + gEfiBlockIoProtocolGuid + +[BuildOptions.IA32] +RELEASE_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +DEBUG_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS = /FAcs /D_UEFI + +RELEASE_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +DEBUG_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS = /arch:IA32 /FAcs /D_UEFI + +[BuildOptions.X64] +RELEASE_VS2010x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2010x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS = /D_UEFI + +RELEASE_VS2015x86_X64_CC_FLAGS = /D_UEFI +DEBUG_VS2015x86_X64_CC_FLAGS = /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS = /D_UEFI + +[FeaturePcd] + +[Pcd] + diff --git a/Dcs_bld.bat b/Dcs_bld.bat new file mode 100644 index 0000000..ff55c73 --- /dev/null +++ b/Dcs_bld.bat @@ -0,0 +1,39 @@ +pushd "%~dp0" + +set dcsarch=X64 +set dcstype=DEBUG +set dcsbldtoolset=VS2010x86 +set dcspkgpath="%~dp0DcsPkg.dsc" + +if /I NOT ["%1"]==["X64Rel"] goto :IA32 +set dcsarch=X64 +set dcstype=RELEASE +goto :bld + +:IA32 +if /I NOT ["%1"]==["IA32"] goto :IA32Rel +set dcsarch=IA32 +set dcstype=DEBUG +goto :bld + +:IA32Rel +if /I NOT ["%1"]==["IA32rel"] goto :bld +set dcsarch=IA32 +set dcstype=RELEASE + +:bld +if /I ["%2"]==["VS2015"] set dcsbldtoolset=VS2015x86 +call bld.bat -t %dcsbldtoolset% -DSECURE_BOOT_ENABLE=1 -p %dcspkgpath% -b %dcstype% -a %dcsarch% + +if ERRORLEVEL 1 goto :exit +if not exist SecureBoot\keys\DCS_sign.pfx goto :exit + +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\DcsBml.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\DcsBoot.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\DcsCfg.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\DcsInt.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\DcsRe.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt +call SecureBoot\efi_sign.bat ..\Build\DcsPkg\%dcstype%_%dcsbldtoolset%\%dcsarch%\LegacySpeaker.efi SecureBoot\keys\DCS_sign.pfx SecureBoot\certs\DCS_sign.crt + +:exit +popd diff --git a/Include/Library/CommonLib.h b/Include/Library/CommonLib.h new file mode 100644 index 0000000..395d4c4 --- /dev/null +++ b/Include/Library/CommonLib.h @@ -0,0 +1,540 @@ +/** @file +EFI common library (helpers) + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#ifndef __COMMONLIB_H__ +#define __COMMONLIB_H__ + +#include +#include +#include +#include +#include +#include +#include + +#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) +#define FIELD_OFFSET(t, f) ((UINTN)(&((t*)0)->f)) + +////////////////////////////////////////////////////////////////////////// +// Memory procedures wrappers +////////////////////////////////////////////////////////////////////////// + +#define MEM_ALLOC MemAlloc +#define MEM_FREE MemFree +#define MEM_REALLOC MemRealloc + +VOID* +MemAlloc( + IN UINTN size + ); + +VOID +MemFree( + IN VOID* ptr + ); + +VOID* +MemRealloc( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ); + +EFI_STATUS +PrepareMemory( + IN UINTN address, + IN UINTN len, + OUT VOID** mem + ); + +////////////////////////////////////////////////////////////////////////// +// handles +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiGetHandles( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + OUT EFI_HANDLE **Buffer, + OUT UINTN *Count + ); + +EFI_STATUS +EfiGetStartDevice( + OUT EFI_HANDLE* handle + ); +////////////////////////////////////////////////////////////////////////// +// Print handle info +////////////////////////////////////////////////////////////////////////// + +VOID EfiPrintDevicePath( + IN EFI_HANDLE handle + ); + +VOID +EfiPrintProtocols( + IN EFI_HANDLE handle + ); + +////////////////////////////////////////////////////////////////////////// +// Block I/O +////////////////////////////////////////////////////////////////////////// + +EFI_BLOCK_IO_PROTOCOL* +EfiGetBlockIO( + IN EFI_HANDLE handle + ); + +extern EFI_HANDLE* gBIOHandles; +extern UINTN gBIOCount; + +EFI_STATUS +InitBio(); + +BOOLEAN +EfiIsPartition( + IN EFI_HANDLE h + ); + +EFI_STATUS +EfiGetPartDetails( + IN EFI_HANDLE h, + OUT HARDDRIVE_DEVICE_PATH* dpVolme, + OUT EFI_HANDLE* hDisk + ); + +EFI_STATUS +EfiGetPartGUID( + IN EFI_HANDLE h, + OUT EFI_GUID* guid + ); + +EFI_STATUS +EfiFindPartByGUID( + IN EFI_GUID* guid, + OUT EFI_HANDLE* h + ); + +////////////////////////////////////////////////////////////////////////// +// USB +////////////////////////////////////////////////////////////////////////// +extern EFI_HANDLE* gUSBHandles; +extern UINTN gUSBCount; + +EFI_STATUS +InitUsb(); + +EFI_STATUS +UsbGetIO( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo + ); + +EFI_STATUS +UsbGetIOwithDescriptor( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo, + OUT EFI_USB_DEVICE_DESCRIPTOR* UsbDescriptor + ); + +EFI_STATUS +UsbGetId( + IN EFI_HANDLE Handle, + OUT CHAR8** id + ); + +////////////////////////////////////////////////////////////////////////// +// Touch +////////////////////////////////////////////////////////////////////////// + +extern EFI_HANDLE* gTouchHandles; +extern UINTN gTouchCount; +extern int gTouchSimulate; +extern EFI_ABSOLUTE_POINTER_PROTOCOL* gTouchPointer; +extern UINT32 gTouchSimulateStep; + +EFI_STATUS +InitTouch(); + +EFI_STATUS +TouchGetIO( + IN EFI_HANDLE Handle, + OUT EFI_ABSOLUTE_POINTER_PROTOCOL** io + ); + + +////////////////////////////////////////////////////////////////////////// +// Console I/O +////////////////////////////////////////////////////////////////////////// + +#define OUT_PRINT(format, ...) AttrPrintEx(-1,-1, format, ##__VA_ARGS__) +#define ERR_PRINT(format, ...) AttrPrintEx(-1,-1, L"%E" format L"%N" , ##__VA_ARGS__) + +EFI_STATUS +ConsoleGetOutput( + IN EFI_HANDLE handle, + OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL** io + ); + +VOID +FlushInput(); + +VOID +FlushInputDelay( + IN UINTN delay + ); + +EFI_INPUT_KEY +KeyWait( + CHAR16* Prompt, + UINTN mDelay, + UINT16 scanCode, + UINT16 unicodeChar); + +EFI_INPUT_KEY +GetKey(void); + +VOID +ConsoleShowTip( + IN CHAR16* tip, + IN UINTN delay); + +VOID +GetLine( + UINTN *length, + CHAR16 *line, + CHAR8 *asciiLine, + UINTN line_max, + UINT8 show); + +int +AskAsciiString( + CHAR8* prompt, + CHAR8* str, + UINTN max_len, + UINT8 visible); + +int +AskInt( + CHAR8* prompt, + UINT8 visible); + + +UINT8 +AskConfirm( + CHAR8* prompt, + UINT8 visible); + +UINT64 +AskUINT64( + IN char* prompt, + IN UINT64 def); + +UINT64 +AskHexUINT64( + IN char* prompt, + IN UINT64 def); + +UINTN +AskUINTN( + IN char* prompt, + IN UINTN def); + +BOOLEAN +AsciiHexToDigit( + OUT UINT8 *b, + IN CHAR8 *str + ); + +BOOLEAN +AsciiHexToByte( + OUT UINT8 *b, + IN CHAR8 *str + ); + +BOOLEAN +AsciiStrToGuid( + OUT EFI_GUID *guid, + IN CHAR8 *str + ); + + +////////////////////////////////////////////////////////////////////////// +// Attribute print +////////////////////////////////////////////////////////////////////////// + +extern BOOLEAN gShellReady; + +VOID +SetShellAPI( + IN VOID* shellProtocol, + IN VOID* shellParametersProtocol + ); + +/** +Print at a specific location on the screen. + +This function will move the cursor to a given screen location and print the specified string. + +If -1 is specified for either the Row or Col the current screen location for BOTH +will be used. + +If either Row or Col is out of range for the current console, then ASSERT. +If Format is NULL, then ASSERT. + +In addition to the standard %-based flags as supported by UefiLib Print() this supports +the following additional flags: +%N - Set output attribute to normal +%H - Set output attribute to highlight +%E - Set output attribute to error +%B - Set output attribute to blue color +%V - Set output attribute to green color + +Note: The background color is controlled by the shell command cls. + +@param[in] Col the column to print at +@param[in] Row the row to print at +@param[in] Format the format string +@param[in] ... The variable argument list. + +@return EFI_SUCCESS The printing was successful. +@return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +AttrPrintEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + ... + ); + +////////////////////////////////////////////////////////////////////////// +// Console control +////////////////////////////////////////////////////////////////////////// + +extern EFI_HANDLE* gConsoleControlHandles; +extern UINTN gConsoleControlCount; + +EFI_STATUS +InitConsoleControl(); + +////////////////////////////////////////////////////////////////////////// +// Beep +////////////////////////////////////////////////////////////////////////// +extern EFI_HANDLE* gSpeakerHandles; +extern UINTN gSpeakerCount; +extern EFI_GUID gSpeakerGuid; + +extern int gBeepEnabled; +extern BOOLEAN gBeepControlEnabled; +extern int gBeepDevice; +extern int gBeepNumberDefault; +extern int gBeepDurationDefault; +extern int gBeepIntervalDefault; +extern int gBeepToneDefault; + + +EFI_STATUS +InitSpeaker(); + +EFI_STATUS +SpeakerBeep( + IN UINT16 Tone, + IN UINTN NumberOfBeeps, + IN UINTN Duration, + IN UINTN Interval + ); + +EFI_STATUS +SpeakerSelect( + IN UINTN index + ); + +////////////////////////////////////////////////////////////////////////// +// Efi variables +////////////////////////////////////////////////////////////////////////// + +#define DCS_BOOT_STR L"DcsBoot" + +extern EFI_GUID gEfiDcsVariableGuid; + +EFI_STATUS +EfiGetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + OUT VOID** varValue, + OUT UINTN* varSize, + OUT UINT32* varAttr + ); + +EFI_STATUS +EfiSetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + IN VOID* varValue, + IN UINTN varSize, + IN UINT32 varAttr + ); + +EFI_STATUS +BootOrderInsert( + IN CHAR16 *OrderVarName, + IN UINTN index, + UINT16 value); + +EFI_STATUS +BootOrderRemove( + IN CHAR16 *OrderVarName, + UINT16 value + ); + +EFI_STATUS +BootMenuItemCreate( + IN CHAR16 *VarName, + IN CHAR16 *Desc, + IN EFI_HANDLE volumeHandle, + IN CHAR16 *Path, + IN BOOLEAN Reduced + ); + +EFI_STATUS +BootMenuItemRemove( + IN CHAR16 *VarName + ); + + + +////////////////////////////////////////////////////////////////////////// +// File +////////////////////////////////////////////////////////////////////////// + + +extern EFI_FILE* gFileRoot; +extern EFI_HANDLE gFileRootHandle; + +extern EFI_HANDLE* gFSHandles; +extern UINTN gFSCount; + +EFI_STATUS +InitFS(); + +EFI_STATUS +FileOpenRoot( + IN EFI_HANDLE rootHandle, + OUT EFI_FILE** rootFile); + +EFI_STATUS +FileOpen( + IN EFI_FILE* root, + IN CHAR16* name, + OUT EFI_FILE** file, + IN UINT64 mode, + IN UINT64 attributes + ); + +EFI_STATUS +FileClose( + IN EFI_FILE* f); + +EFI_STATUS +FileDelete( + IN EFI_FILE* root, + IN CHAR16* name + ); + +EFI_STATUS +FileRead( + IN EFI_FILE* f, + OUT VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position); + +EFI_STATUS +FileWrite( + IN EFI_FILE* f, + IN VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position); + +EFI_STATUS +FileGetInfo( + IN EFI_FILE* f, + OUT EFI_FILE_INFO** info, + OUT UINTN* size + ); + +EFI_STATUS +FileGetSize( + IN EFI_FILE* f, + OUT UINTN* size + ); + +EFI_STATUS +FileLoad( + IN EFI_FILE* root, + IN CHAR16* name, + OUT VOID** data, + OUT UINTN* size + ); + +EFI_STATUS +FileSave( + IN EFI_FILE* root, + IN CHAR16* name, + IN VOID* data, + IN UINTN size + ); + +EFI_STATUS +FileExist( + IN EFI_FILE* root, + IN CHAR16* name + ); + +EFI_STATUS +FileRename( + IN EFI_FILE* root, + IN CHAR16* src, + IN CHAR16* dst + ); + +EFI_STATUS +FileCopy( + IN EFI_FILE* srcroot, + IN CHAR16* src, + IN EFI_FILE* dstroot, + IN CHAR16* dst, + IN UINTN bufSz + ); + +////////////////////////////////////////////////////////////////////////// +// Exec +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiExec( + IN EFI_HANDLE deviceHandle, + IN CHAR16* path + ); + +EFI_STATUS +ConnectAllEfi( + VOID + ); + +VOID +EfiCpuHalt(); + +#endif \ No newline at end of file diff --git a/Include/Library/DcsCfgLib.h b/Include/Library/DcsCfgLib.h new file mode 100644 index 0000000..6d74729 --- /dev/null +++ b/Include/Library/DcsCfgLib.h @@ -0,0 +1,213 @@ +/** @file +DCS configuration + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the [to be defined License, Version]. The full text of the license may be found at +[opensource license to be defined] +**/ + +#ifndef __DCSCFGLIB_H__ +#define __DCSCFGLIB_H__ + +#include + +////////////////////////////////////////////////////////////////////////// +// DeList and GPT +////////////////////////////////////////////////////////////////////////// +#define EFI_PART_TYPE_BASIC_DATA_PART_GUID \ + { \ + 0xEBD0A0A2, 0xB9E5, 0x4433, { 0x87, 0xC0, 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 } \ + } + +#define EFI_PART_TYPE_MS_RESERVED_PART_GUID \ + { \ + 0xE3C9E316, 0x0B5C, 0x4DB8, { 0x81, 0x7D, 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE } \ + } + +#define EFI_PART_TYPE_MS_RECOVERY_PART_GUID \ + { \ + 0xDE94BBA4, 0x06D1, 0x06D1, { 0xA1, 0x6A, 0xBF, 0xD5, 0x01, 0x79, 0xD6, 0xAC } \ + } + +typedef struct _DCS_DISK_ENTRY_LIST DCS_DISK_ENTRY_LIST; +typedef struct _DCS_DEP_EXEC DCS_DEP_EXEC; + +extern EFI_GUID gEfiPartTypeBasicDataPartGuid; +extern EFI_GUID gEfiPartTypeMsReservedPartGuid; +extern EFI_GUID gEfiPartTypeMsRecoveryPartGuid; + +extern UINT64 gDcsDiskEntryListHeaderID; + +extern DCS_DISK_ENTRY_LIST *DeList; +extern DCS_DEP_EXEC *DeExecParams; + +// DcsCfg data +extern CONST CHAR16* DcsDiskEntrysFileName; +extern EFI_PARTITION_ENTRY DcsHidePart; +extern EFI_PARTITION_ENTRY *GptMainEntrys; +extern UINTN BootPartIdx; +extern UINTN MirrorPartIdx; + +EFI_STATUS +DeListParseSaved( + IN UINT8 *DeBuffer + ); + +EFI_STATUS +DeListLoadFromFile(); + +EFI_STATUS +DeListZero(); + +VOID +DeListPrint(); + +VOID +DeListSaveToFile(); + +EFI_STATUS +DeListApplySectorsToDisk( + IN UINTN diskIdx + ); + +EFI_STATUS +DeListExecEdit(); + +EFI_STATUS +DeListPwdCacheEdit(); + +EFI_STATUS +DeListRndSave(); + +EFI_STATUS +DeListRndLoad(); + +EFI_STATUS +GptLoadFromDisk( + IN UINTN diskIdx + ); + +VOID +GptHideParts(); + +VOID +GptSort(); + +VOID +GptSqueze(); + +EFI_STATUS +GptSyncMainAlt(); + +BOOLEAN +GptAskGUID( + IN char* prompt, + IN OUT EFI_GUID* guid + ); + +BOOLEAN +IsRegionOverlap(UINT64 start1, UINT64 end1, UINT64 start2, UINT64 end2); + +////////////////////////////////////////////////////////////////////////// +// Random +////////////////////////////////////////////////////////////////////////// +enum RndGeneratorTypes { + RndTypeNone = 0, + RndTypeFile, + RndTypeRDRand, + RndTypeDtrmHmacSha512 +}; + +#define RND_HEADER_SIGN SIGNATURE_64('D','C','S','_','R','A','N','D') + +typedef struct _DCS_RND DCS_RND; + +typedef +EFI_STATUS +(*DCS_RND_PREPARE)( + IN OUT DCS_RND *Rnd + ); + +typedef +EFI_STATUS +(*DCS_RND_GET_BYTES)( + IN DCS_RND *Rnd, + OUT UINT8 *buf, + IN UINTN len + ); + +#pragma pack(1) +/* state of DRBG HMAC SHA512 */ +typedef struct _RND_DTRM_HMAC_SHA512_STATE +{ + UINT8 V[64]; /* internal state 10.1.1.1 1a) */ + UINT8 C[64]; /* hmac key */ + UINT64 ReseedCtr; /* Number of RNG requests since last reseed --* 10.1.1.1 1c)*/ +} RND_DTRM_HMAC_SHA512_STATE; + +typedef struct _RND_FILE_STATE +{ + CHAR16 *FileName; + UINT8 *Data; + UINTN Size; + UINTN Pos; +} RND_FILE_STATE; + +typedef union _DCS_RND_STATE { + RND_DTRM_HMAC_SHA512_STATE HMacSha512; + RND_FILE_STATE File; +} DCS_RND_STATE; + +typedef struct _DCS_RND_SAVED { + UINT64 Sign; + UINT32 CRC; + UINT32 Size; + UINT32 Type; + UINT32 Pad; + EFI_TIME SavedAt; + DCS_RND_STATE State; + UINT8 pad[512 - 8 - 4 - 4 - 4 - 4 - sizeof(EFI_TIME) - sizeof(DCS_RND_STATE)]; +} DCS_RND_SAVED; +#pragma pack() +static_assert(sizeof(DCS_RND_SAVED) == 512, "Wrong size DCS_RND_SAVED"); + +typedef struct _DCS_RND { + DCS_RND_PREPARE Prepare; + DCS_RND_GET_BYTES GetBytes; + UINT32 Type; + UINT32 Pad; + DCS_RND_STATE State; +} DCS_RND; + +EFI_STATUS +RndInit( + IN UINTN rndType, + IN VOID* Context, + OUT DCS_RND **rnd); + +// Serialize rnd with state to/from memory +EFI_STATUS +RndLoad( + IN DCS_RND_SAVED *rndSaved, + OUT DCS_RND **rndOut + ); + +EFI_STATUS +RndSave( + DCS_RND *rnd, + DCS_RND_SAVED **rndSaved); + +// Global RND +extern DCS_RND* gRnd; + +EFI_STATUS +RndGetBytes(UINT8 *buf, UINTN len); + +EFI_STATUS +RndPreapare(); + +#endif + diff --git a/Include/Library/GraphLib.h b/Include/Library/GraphLib.h new file mode 100644 index 0000000..49cea5c --- /dev/null +++ b/Include/Library/GraphLib.h @@ -0,0 +1,200 @@ +/** @file +Graph library + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#ifndef __GRAPHLIB_H__ +#define __GRAPHLIB_H__ + +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Graph +////////////////////////////////////////////////////////////////////////// + +extern EFI_HANDLE* gGraphHandles; +extern UINTN gGraphCount; +extern EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphOut; + +EFI_STATUS +InitGraph(); + +EFI_STATUS +GraphGetIO( + IN EFI_HANDLE Handle, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL** io + ); + +EFI_STATUS +GraphGetModeInfo( + IN UINTN mode, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **info, + OUT UINTN* szInfo + ); + +typedef struct _RECT { + UINT32 left; + UINT32 top; + UINT32 right; + UINT32 bottom; +} RECT, *PRECT; + +#pragma pack(1) +typedef struct { + UINT32 Width; + UINT32 Height; + RECT Dirty; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixels[0]; +} BLT_HEADER; +#pragma pack() + +enum DRAW_OPERATION { + DrawOpSet = 0, + DrawOpOr, + DrawOpXor, + DrawOpClear, + DrawOpAlpha +}; + +typedef struct _DRAW_CONTEXT { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Color; + UINT32 Op; + UINT32 DashLine; + UINT32 Alpha; //< 0..255 + EFI_GRAPHICS_OUTPUT_BLT_PIXEL AlphaColor; + INT32* Brush; // brush points(default 1) +} DRAW_CONTEXT, *PDRAW_CONTEXT; + +extern DRAW_CONTEXT gDrawContext; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlack; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorWhite; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlue; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGreen; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorRed; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGray; +extern INT32 gBrush3[5 * 2]; + +EFI_STATUS +ScreenGetSize( + OUT UINTN *Height, + OUT UINTN *Width + ); + +EFI_STATUS ScreenFillRect( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color, + IN UINTN x, + IN UINTN y, + IN UINTN width, + IN UINTN height + ); + +EFI_STATUS ScreenDrawBlt( + IN BLT_HEADER *blt, + IN UINTN x, + IN UINTN y + ); + +EFI_STATUS +ScreenSaveBlt( + OUT BLT_HEADER **bltScreen + ); + +EFI_STATUS ScreenUpdateDirty( + IN BLT_HEADER *blt + ); + +EFI_STATUS +BltDrawBlt( + IN OUT BLT_HEADER* canvas, + IN BLT_HEADER* blt, + IN UINTN x, + IN UINTN y + ); + +EFI_STATUS +RectMarkDirty( + IN OUT PRECT rect, + IN UINTN x, + IN UINTN y + ); + +EFI_STATUS +BltPoint( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN UINTN x, + IN UINTN y + ); + +VOID +BltLine( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1); + +VOID +BltBox( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1); + +VOID +BltCircle( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 xm, + IN INT32 ym, + IN INT32 r, + IN BOOLEAN fill); + +VOID +BltText( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x, + IN INT32 y, + IN INT32 scale, // 0..256 reduce 256... enlarge + IN CONST CHAR8 *text); + + +EFI_STATUS +BmpGetSize( + IN const unsigned char* BmpImage, + IN UINTN BmpImageSize, + OUT UINTN *Height, + OUT UINTN *Width + ); + +EFI_STATUS +BmpToBlt( + IN CONST VOID *BmpImage, + IN UINTN BmpImageSize, + OUT BLT_HEADER **blt + ); + +VOID +BltFill( + IN BLT_HEADER* blt, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL fill, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1 + ); + +#endif \ No newline at end of file diff --git a/Include/Library/PasswordLib.h b/Include/Library/PasswordLib.h new file mode 100644 index 0000000..62cad21 --- /dev/null +++ b/Include/Library/PasswordLib.h @@ -0,0 +1,108 @@ +/** @file +Password library + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#ifndef __PASSWORDLIB_H__ +#define __PASSWORDLIB_H__ + +#include +#include + +extern CHAR16* gPasswordPictureFileName; + +extern CHAR8* gPasswordPictureChars; +extern CHAR8* gPasswordPictureCharsDefault; +extern UINTN gPasswordPictureCharsLen; +extern UINT8 gPasswordVisible; +extern int gPasswordShowMark; + +extern int gPlatformLocked; +extern int gTPMLocked; +extern int gSCLocked; + +enum AskPwdType { + AskPwdLogin = 1, + AskPwdNew, + AskPwdConfirm +}; + +enum AskPwdRetCode { + AskPwdRetCancel = 0, + AskPwdRetLogin = 1, + AskPwdRetChange +}; + +VOID +AskPictPwdInt( + IN UINTN pwdType, + IN UINTN pwdMax, + OUT CHAR8* pwd, + OUT UINT32* pwdLen, + OUT INT32* retCode + ); + +VOID +AskConsolePwdInt( + OUT UINT32 *length, + OUT CHAR8 *asciiLine, + OUT INT32 *retCode, + IN UINTN line_max, + IN UINT8 show + ); + +extern EFI_GUID* gSmbSystemUUID; // Universal unique ID +extern CHAR8* gSmbSystemSerial; // System serial +extern CHAR8* gSmbSystemSKU; // SKU number +extern CHAR8* gSmbBaseBoardSerial; // Base board serial +extern UINT64* gSmbProcessorID; // Processor ID + +EFI_STATUS +SMBIOSGetSerials(); + +EFI_STATUS +PaltformGetIDCRC( + IN EFI_HANDLE handle, + OUT UINT32 *crc32 + ); + +EFI_STATUS +PlatformGetID( + IN EFI_HANDLE handle, + OUT CHAR8 **id, + OUT UINTN *idLen + ); + +EFI_STATUS +PlatformGetIDCRC( + IN EFI_HANDLE handle, + OUT UINT32 *crc32 + ); + +extern UINTN gBioIndexAuth; +extern BOOLEAN gBioIndexAuthOnRemovable; + +typedef struct _DCS_AUTH_DATA_MARK { + UINT32 HeaderCrc; + UINT32 PlatformCrc; + UINT32 AuthDataSize; + UINT32 Reserved; +} DCS_AUTH_DATA_MARK; + + +EFI_STATUS +PlatformGetAuthData( + OUT UINT8 **data, + OUT UINTN *len, + OUT EFI_HANDLE *secRegionHandle + ); + +#endif \ No newline at end of file diff --git a/Include/Protocol/ConsoleControl.h b/Include/Protocol/ConsoleControl.h new file mode 100644 index 0000000..c935970 --- /dev/null +++ b/Include/Protocol/ConsoleControl.h @@ -0,0 +1,123 @@ +/*++ + +Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. +The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ConsoleControl.h + +Abstract: + + Abstraction of a Text mode or GOP/UGA screen + +--*/ + +#ifndef __CONSOLE_CONTROL_H__ +#define __CONSOLE_CONTROL_H__ + +#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21} } + +typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; + + +typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue +} EFI_CONSOLE_CONTROL_SCREEN_MODE; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *GopUgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ) +/*++ + + Routine Description: + Return the current video mode information. Also returns info about existence + of Graphics Output devices or UGA Draw devices in system, and if the Std In + device is locked. All the arguments are optional and only returned if a non + NULL pointer is passed in. + + Arguments: + This - Protocol instance pointer. + Mode - Are we in text of grahics mode. + GopUgaExists - TRUE if Console Spliter has found a GOP or UGA device + StdInLocked - TRUE if StdIn device is keyboard locked + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +/*++ + + Routine Description: + Set the current mode to either text or graphics. Graphics is + for Quiet Boot. + + Arguments: + This - Protocol instance pointer. + Mode - Mode to set the + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +/*++ + + Routine Description: + Lock Std In devices until Password is typed. + + Arguments: + This - Protocol instance pointer. + Password - Password needed to unlock screen. NULL means unlock keyboard + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - Std In not locked + +--*/ +; + + + +struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; +}; + +extern EFI_GUID gEfiConsoleControlProtocolGuid; + +#endif diff --git a/Include/Protocol/Speaker.h b/Include/Protocol/Speaker.h new file mode 100644 index 0000000..938f575 --- /dev/null +++ b/Include/Protocol/Speaker.h @@ -0,0 +1,84 @@ +/*++ + + Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.
+ + + This program and the accompanying materials are licensed and made available under + + the terms and conditions of the BSD License that accompanies this distribution. + + +The full text of the license may be found at + + http://opensource.org/licenses/bsd-license.php. + + + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + + + +Module Name: + + Speaker.h + +Abstract: + + EFI Speaker Interface Protocol + +Revision History + +**/ + +#ifndef _EFI_SPEAKER_H +#define _EFI_SPEAKER_H + +#include +#include +#include + +// +// Global Id for Speaker Interface +// +#define EFI_SPEAKER_INTERFACE_PROTOCOL_GUID \ + { \ + 0x400b4476, 0x3081, 0x11d6, 0x87, 0xed, 0x00, 0x06, 0x29, 0x45, 0xc3, 0xb9 \ + } + +typedef struct _EFI_SPEAKER_IF_PROTOCOL EFI_SPEAKER_IF_PROTOCOL; + +// +// Beep Code +// +typedef +EFI_STATUS +(EFIAPI *EFI_GENERATE_BEEP) ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +// +// Set Frequency +// +typedef +EFI_STATUS +(EFIAPI *EFI_SPEAKER_SET_FREQUENCY) ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ); + +// +// Protocol definition +// +struct _EFI_SPEAKER_IF_PROTOCOL { + EFI_SPEAKER_SET_FREQUENCY SetSpeakerToneFrequency; + EFI_GENERATE_BEEP GenerateBeep; +} ; + +extern EFI_GUID gEfiSpeakerInterfaceProtocolGuid; +#endif diff --git a/LegacySpeaker/ComponentName.c b/LegacySpeaker/ComponentName.c new file mode 100644 index 0000000..0b21270 --- /dev/null +++ b/LegacySpeaker/ComponentName.c @@ -0,0 +1,134 @@ +/** @file + TODO: Brief Description of UEFI Driver LegacySpeaker + + TODO: Detailed Description of UEFI Driver LegacySpeaker + + TODO: Copyright for UEFI Driver LegacySpeaker + + TODO: License for UEFI Driver LegacySpeaker + +**/ + +#include "LegacySpeaker.h" + +/// +/// Component Name Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME_PROTOCOL gLegacySpeakerComponentName = { + (EFI_COMPONENT_NAME_GET_DRIVER_NAME) LegacySpeakerComponentNameGetDriverName, + (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME)LegacySpeakerComponentNameGetControllerName, + "eng" +}; + +/// +/// Component Name 2 Protocol instance +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_COMPONENT_NAME2_PROTOCOL gLegacySpeakerComponentName2 = { + LegacySpeakerComponentNameGetDriverName, + LegacySpeakerComponentNameGetControllerName, + "en" +}; + +/// +/// Table of driver names +/// +GLOBAL_REMOVE_IF_UNREFERENCED +EFI_UNICODE_STRING_TABLE mLegacySpeakerDriverNameTable[] = { + { "eng;en", (CHAR16 *)L"LegacySpeaker" }, + { NULL, NULL } +}; + +/** + Retrieves a Unicode string that is the user-readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three-character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +LegacySpeakerComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mLegacySpeakerDriverNameTable, + DriverName, + (BOOLEAN)(This != &gLegacySpeakerComponentName2) + ); +} + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language, from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +LegacySpeakerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + return Status; +} diff --git a/LegacySpeaker/ComponentName.h b/LegacySpeaker/ComponentName.h new file mode 100644 index 0000000..5f3920b --- /dev/null +++ b/LegacySpeaker/ComponentName.h @@ -0,0 +1,90 @@ +/** @file + TODO: Brief Description of UEFI Driver LegacySpeaker + + TODO: Detailed Description of UEFI Driver LegacySpeaker + + TODO: Copyright for UEFI Driver LegacySpeaker + + TODO: License for UEFI Driver LegacySpeaker + +**/ + +/** + Retrieves a Unicode string that is the user-readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three-character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +LegacySpeakerComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language, from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user-readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is NULL. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +EFI_STATUS +EFIAPI +LegacySpeakerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME2_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); diff --git a/LegacySpeaker/LegacySpeaker.c b/LegacySpeaker/LegacySpeaker.c new file mode 100644 index 0000000..2f7b1b9 --- /dev/null +++ b/LegacySpeaker/LegacySpeaker.c @@ -0,0 +1,238 @@ +/** @file + TODO: Brief Description of UEFI Driver LegacySpeaker + + TODO: Detailed Description of UEFI Driver LegacySpeaker + + TODO: Copyright for UEFI Driver LegacySpeaker + + TODO: License for UEFI Driver LegacySpeaker + +**/ + +#include "LegacySpeaker.h" +#include + +////////////////////////////////////////////////////////////////////////// +// Speaker +////////////////////////////////////////////////////////////////////////// +/** + + This function will enable the speaker to generate beep + + @retval EFI_STATUS + +**/ +EFI_STATUS +TurnOnSpeaker ( + ) +{ + UINT8 Data; + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data |= 0x03; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + +/** + + This function will stop beep from speaker. + + @retval Status + +**/ +EFI_STATUS +TurnOffSpeaker ( + ) +{ + UINT8 Data; + + Data = IoRead8 (EFI_SPEAKER_CONTROL_PORT); + Data &= 0xFC; + IoWrite8(EFI_SPEAKER_CONTROL_PORT, Data); + return EFI_SUCCESS; +} + +/** + Generate beep sound based upon number of beeps and duration of the beep + + @param NumberOfBeeps Number of beeps which user want to produce + @param BeepDuration Duration for speaker gate need to be enabled + @param TimeInterval Interval between each beep + + @retval Does not return if the reset takes place. + EFI_INVALID_PARAMETER If ResetType is invalid. + +**/ +EFI_STATUS +OutputBeep ( + IN UINTN NumberOfBeep, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + UINTN Num; + + for (Num=0; Num < NumberOfBeep; Num++) { + TurnOnSpeaker (); + // + // wait some time,at least 120us + // + gBS->Stall (BeepDuration); + TurnOffSpeaker(); + gBS->Stall (TimeInterval); + } + + return EFI_SUCCESS; +} + +/** + This function will program the speaker tone frequency. The value should be with 64k + boundary since it takes only 16 bit value which gets programmed in two step IO opearattion + + @param Frequency A value which should be 16 bit only. + + @retval EFI_SUCESS + +**/ +EFI_STATUS +EFIAPI +ProgramToneFrequency ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ) +{ + UINT8 Data; + + Data = 0xB6; + IoWrite8(EFI_TIMER_CONTROL_PORT, Data); + + Data = (UINT8)(Frequency & 0x00FF); + IoWrite8(EFI_TIMER_2_PORT, Data); + Data = (UINT8)((Frequency & 0xFF00) >> 8); + IoWrite8(EFI_TIMER_2_PORT, Data); + return EFI_SUCCESS; +} + +/** + This function will generate the beep for specified duration. + + @param NumberOfBeeps Number of beeps which user want to produce + @param BeepDuration Duration for speaker gate need to be enabled + @param TimeInterval Interval between each beep + + @retval EFI_STATUS + +**/ +EFI_STATUS +EFIAPI +GenerateBeepTone ( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ) +{ + + if ((NumberOfBeeps == 1) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOnSpeaker (); + return EFI_SUCCESS; + } + + if ((NumberOfBeeps == 0) && (BeepDuration == 0) && (TimeInterval == 0)) { + TurnOffSpeaker (); + return EFI_SUCCESS; + } + + if (BeepDuration == 0) { + BeepDuration = EFI_DEFAULT_SHORT_BEEP_DURATION; + } + + if (TimeInterval == 0) { + TimeInterval = EFI_DEFAULT_BEEP_TIME_INTERVAL; + } + + OutputBeep (NumberOfBeeps, BeepDuration, TimeInterval); + return EFI_SUCCESS; +} + +GUID gEfiSpeakerInterfaceProtocolGuid = EFI_SPEAKER_INTERFACE_PROTOCOL_GUID; +EFI_SPEAKER_IF_PROTOCOL gEfiSpeakerInterfaceProtocol = { + ProgramToneFrequency, + GenerateBeepTone +}; + +////////////////////////////////////////////////////////////////////////// +// Driver +////////////////////////////////////////////////////////////////////////// + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +LegacySpeakerUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + // + // Uninstall Driver Supported EFI Version Protocol onto ImageHandle + // + Status = gBS->UninstallMultipleProtocolInterfaces( + ImageHandle, + &gEfiSpeakerInterfaceProtocolGuid, &gEfiSpeakerInterfaceProtocol, + NULL + ); + + if (EFI_ERROR(Status)) { + return Status; + } + // Clean up + return EFI_SUCCESS; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including + both device drivers and bus drivers. + + @param ImageHandle The firmware allocated handle for the UEFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +LegacySpeakerDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + // + // Install Speaker protocol onto ImageHandle + // + Status = gBS->InstallMultipleProtocolInterfaces( + &ImageHandle, + &gEfiSpeakerInterfaceProtocolGuid, &gEfiSpeakerInterfaceProtocol, + NULL + ); + ASSERT_EFI_ERROR(Status); +// gEfiSpeakerInterfaceProtocol.SetSpeakerToneFrequency(&gEfiSpeakerInterfaceProtocol, 0x500); +// gEfiSpeakerInterfaceProtocol.GenerateBeep(&gEfiSpeakerInterfaceProtocol, 2, 200000, 200000); + + return Status; +} + diff --git a/LegacySpeaker/LegacySpeaker.h b/LegacySpeaker/LegacySpeaker.h new file mode 100644 index 0000000..6d90b13 --- /dev/null +++ b/LegacySpeaker/LegacySpeaker.h @@ -0,0 +1,101 @@ +/** @file + TODO: Brief Description of UEFI Driver LegacySpeaker + + TODO: Detailed Description of UEFI Driver LegacySpeaker + + TODO: Copyright for UEFI Driver LegacySpeaker + + TODO: License for UEFI Driver LegacySpeaker + +**/ + +#ifndef __EFI_LEGACY_SPEAKER_H__ +#define __EFI_LEGACY_SPEAKER_H__ + +#include + +// +// Libraries +// +#include +#include +#include +#include +#include +#include +#include + +// +// UEFI Driver Model Protocols +// +#include +#include + +// +// Consumed Protocols +// + +// +// Produced Protocols +// +#include + + +// +// Protocol instances +// +extern EFI_COMPONENT_NAME2_PROTOCOL gLegacySpeakerComponentName2; +extern EFI_COMPONENT_NAME_PROTOCOL gLegacySpeakerComponentName; +extern EFI_SPEAKER_IF_PROTOCOL gEfiSpeakerInterfaceProtocol; + +// +// Include files with function prototypes +// +#include "ComponentName.h" + +// +// Speaker Related Port Information +// +#define EFI_TIMER_COUNTER_PORT 0x40 +#define EFI_TIMER_CONTROL_PORT 0x43 +#define EFI_TIMER_2_PORT 0x42 +#define EFI_SPEAKER_CONTROL_PORT 0x61 + +#define EFI_SPEAKER_OFF_MASK 0xFC + +#define EFI_DEFAULT_BEEP_FREQUENCY 0x500 + +// +// Default Intervals/Beep Duration +// +#define EFI_DEFAULT_LONG_BEEP_DURATION 0x70000 +#define EFI_DEFAULT_SHORT_BEEP_DURATION 0x50000 +#define EFI_DEFAULT_BEEP_TIME_INTERVAL 0x20000 + + +EFI_STATUS +EFIAPI +ProgramToneFrequency( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINT16 Frequency + ); + + +EFI_STATUS +EFIAPI +GenerateBeepTone( + IN EFI_SPEAKER_IF_PROTOCOL * This, + IN UINTN NumberOfBeeps, + IN UINTN BeepDuration, + IN UINTN TimeInterval + ); + +EFI_STATUS +TurnOnSpeaker( + ); + +EFI_STATUS +TurnOffSpeaker( + ); + +#endif diff --git a/LegacySpeaker/LegacySpeaker.inf b/LegacySpeaker/LegacySpeaker.inf new file mode 100644 index 0000000..50dfc7f --- /dev/null +++ b/LegacySpeaker/LegacySpeaker.inf @@ -0,0 +1,46 @@ +## @file +# TODO: Brief Description of UEFI Driver LegacySpeaker +# +# TODO: Detailed Description of UEFI Driver LegacySpeaker +# +# TODO: Copyright for UEFI Driver LegacySpeaker +# +# TODO: License for UEFI Driver LegacySpeaker +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = LegacySpeaker + FILE_GUID = f556f20f-1838-11e6-94c2-6067203c4d58 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = LegacySpeakerDriverEntryPoint + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[Sources] + LegacySpeaker.h + LegacySpeaker.c + ComponentName.c + ComponentName.h + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + DevicePathLib + DebugLib + IoLib + +[Protocols] + gEfiComponentName2ProtocolGuid + gEfiComponentNameProtocolGuid + +[Guids] + diff --git a/Library/CommonLib/CommonLib.inf b/Library/CommonLib/CommonLib.inf new file mode 100644 index 0000000..2c379b8 --- /dev/null +++ b/Library/CommonLib/CommonLib.inf @@ -0,0 +1,65 @@ +## @file +# EFI common library (helpers) +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = CommonLib + MODULE_UNI_FILE = CommonLib.uni + FILE_GUID = F779769D-58F4-4A49-A7D7-59473BBD3CCE + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = CommonLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + EfiMem.c + EfiBio.c + EfiVar.c + EfiFile.c + EfiConsole.c + EfiAttrPrint.c + EfiBeep.c + EfiExec.c + EfiUsb.c + EfiTouch.c + +[Sources.IA32] + IA32/EfiCpuHalt.asm + +[Sources.X64] + X64/EfiCpuHalt.asm + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + ShellPkg/ShellPkg.dec + + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + UefiUsbLib + +[Protocols] + gEfiBlockIoProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiLoadedImageProtocolGuid + gEfiUsbIoProtocolGuid + gEfiAbsolutePointerProtocolGuid + gEfiGraphicsOutputProtocolGuid + gEfiSimpleTextOutProtocolGuid diff --git a/Library/CommonLib/EfiAttrPrint.c b/Library/CommonLib/EfiAttrPrint.c new file mode 100644 index 0000000..adcd606 --- /dev/null +++ b/Library/CommonLib/EfiAttrPrint.c @@ -0,0 +1,477 @@ +/** @file +EFI console print with attribute (based on shell print) + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Custom print based on shell print (copied here to avoid runtime limitation) +////////////////////////////////////////////////////////////////////////// + +#define ATTRPRINT_BUFSIZE 4096 + +BOOLEAN gShellReady = FALSE; +EFI_SHELL_PARAMETERS_PROTOCOL* mEfiShellParametersProtocol = NULL; +EFI_SHELL_PROTOCOL* mEfiShellProtocol = NULL; + +VOID +SetShellAPI( + IN VOID* shellProtocol, + IN VOID* shellParametersProtocol) { + mEfiShellParametersProtocol = (EFI_SHELL_PARAMETERS_PROTOCOL*)shellParametersProtocol; + mEfiShellProtocol = (EFI_SHELL_PROTOCOL*)shellProtocol; +} + +/** + Safely append with automatic string resizing given length of Destination and + desired length of copy from Source. + + append the first D characters of Source to the end of Destination, where D is + the lesser of Count and the StrLen() of Source. If appending those D characters + will fit within Destination (whose Size is given as CurrentSize) and + still leave room for a NULL terminator, then those characters are appended, + starting at the original terminating NULL of Destination, and a new terminating + NULL is appended. + + If appending D characters onto Destination will result in a overflow of the size + given in CurrentSize the string will be grown such that the copy can be performed + and CurrentSize will be updated to the new size. + + If Source is NULL, there is nothing to append, just return the current buffer in + Destination. + + if Destination is NULL, then ASSERT() + if Destination's current length (including NULL terminator) is already more then + CurrentSize, then ASSERT() + + @param[in, out] Destination The String to append onto + @param[in, out] CurrentSize on call the number of bytes in Destination. On + return possibly the new size (still in bytes). if NULL + then allocate whatever is needed. + @param[in] Source The String to append from + @param[in] Count Maximum number of characters to append. if 0 then + all are appended. + + @return Destination return the resultant string. +**/ +CHAR16* +EFIAPI +StrnCatGrow2 ( + IN OUT CHAR16 **Destination, + IN OUT UINTN *CurrentSize, + IN CONST CHAR16 *Source, + IN UINTN Count + ) +{ + UINTN DestinationStartSize; + UINTN NewSize; + + // + // ASSERTs + // + ASSERT(Destination != NULL); + + // + // If there's nothing to do then just return Destination + // + if (Source == NULL) { + return (*Destination); + } + + // + // allow for un-initialized pointers, based on size being 0 + // + if (CurrentSize != NULL && *CurrentSize == 0) { + *Destination = NULL; + } + + // + // allow for NULL pointers address as Destination + // + if (*Destination != NULL) { + ASSERT(CurrentSize != 0); + DestinationStartSize = StrSize(*Destination); + ASSERT(DestinationStartSize <= *CurrentSize); + } else { + DestinationStartSize = 0; +// ASSERT(*CurrentSize == 0); + } + + // + // Append all of Source? + // + if (Count == 0) { + Count = StrLen(Source); + } + + // + // Test and grow if required + // + if (CurrentSize != NULL) { + NewSize = *CurrentSize; + if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) { + while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) { + NewSize += 2 * Count * sizeof(CHAR16); + } + *Destination = MEM_REALLOC(*CurrentSize, NewSize, *Destination); + *CurrentSize = NewSize; + } + } else { + NewSize = (Count+1)*sizeof(CHAR16); + *Destination = MEM_ALLOC(NewSize); + } + + // + // Now use standard StrnCat on a big enough buffer + // + if (*Destination == NULL) { + return (NULL); + } + + StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count); + return *Destination; +} + + +/** + This is a find and replace function. Upon successful return the NewString is a copy of + SourceString with each instance of FindTarget replaced with ReplaceWith. + + If SourceString and NewString overlap the behavior is undefined. + + If the string would grow bigger than NewSize it will halt and return error. + + @param[in] SourceString The string with source buffer. + @param[in, out] NewString The string with resultant buffer. + @param[in] NewSize The size in bytes of NewString. + @param[in] FindTarget The string to look for. + @param[in] ReplaceWith The string to replace FindTarget with. + @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^' + immediately before it. + @param[in] ParameterReplacing If TRUE will add "" around items with spaces. + + @retval EFI_INVALID_PARAMETER SourceString was NULL. + @retval EFI_INVALID_PARAMETER NewString was NULL. + @retval EFI_INVALID_PARAMETER FindTarget was NULL. + @retval EFI_INVALID_PARAMETER ReplaceWith was NULL. + @retval EFI_INVALID_PARAMETER FindTarget had length < 1. + @retval EFI_INVALID_PARAMETER SourceString had length < 1. + @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold + the new string (truncation occurred). + @retval EFI_SUCCESS The string was successfully copied with replacement. +**/ +EFI_STATUS +EFIAPI +StrCopySearchAndReplace( + IN CHAR16 CONST *SourceString, + IN OUT CHAR16 *NewString, + IN UINTN NewSize, + IN CONST CHAR16 *FindTarget, + IN CONST CHAR16 *ReplaceWith, + IN CONST BOOLEAN SkipPreCarrot, + IN CONST BOOLEAN ParameterReplacing + ) +{ + UINTN Size; + CHAR16 *Replace; + + if ( (SourceString == NULL) + || (NewString == NULL) + || (FindTarget == NULL) + || (ReplaceWith == NULL) + || (StrLen(FindTarget) < 1) + || (StrLen(SourceString) < 1) + ){ + return (EFI_INVALID_PARAMETER); + } + Replace = NULL; + if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) { + Replace = StrnCatGrow2(&Replace, NULL, ReplaceWith, 0); + } else { + Replace = MEM_ALLOC(StrSize(ReplaceWith) + 2*sizeof(CHAR16)); + if (Replace != NULL) { + UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith); + } + } + if (Replace == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + NewString = ZeroMem(NewString, NewSize); + while (*SourceString != CHAR_NULL) { + // + // if we find the FindTarget and either Skip == FALSE or Skip and we + // dont have a carrot do a replace... + // + if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0 + && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot) + ){ + SourceString += StrLen(FindTarget); + Size = StrSize(NewString); + if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) { + MEM_FREE(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrCatS(NewString, NewSize/sizeof(CHAR16), Replace); + } else { + Size = StrSize(NewString); + if (Size + sizeof(CHAR16) > NewSize) { + MEM_FREE(Replace); + return (EFI_BUFFER_TOO_SMALL); + } + StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1); + SourceString++; + } + } + MEM_FREE(Replace); + return (EFI_SUCCESS); +} + +/** + Internal worker function to output a string. + + This function will output a string to the correct StdOut. + + @param[in] String The string to print out. + + @retval EFI_SUCCESS The operation was successful. + @retval !EFI_SUCCESS The operation failed. +**/ +EFI_STATUS +EFIAPI +AttrPrintTo ( + IN CONST CHAR16 *String + ) +{ + UINTN Size; + Size = StrSize(String) - sizeof(CHAR16); + if (Size == 0) { + return (EFI_SUCCESS); + } + if (mEfiShellParametersProtocol != NULL) { + return (mEfiShellProtocol->WriteFile(mEfiShellParametersProtocol->StdOut, &Size, (VOID*)String)); + } + return gST->ConOut->OutputString(gST->ConOut, (CHAR16*)String); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + if either Row or Col is out of range for the current console, then ASSERT + if Format is NULL, then ASSERT + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] Marker the marker for the variable argument list + + @return EFI_SUCCESS The operation was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +InternalAttrPrintWorker( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + IN VA_LIST Marker + ) +{ + EFI_STATUS Status; + CHAR16 *ResumeLocation; + CHAR16 *FormatWalker; + UINTN OriginalAttribute; + CHAR16 *mPostReplaceFormat; + CHAR16 *mPostReplaceFormat2; + + mPostReplaceFormat = (CHAR16*)MEM_ALLOC (ATTRPRINT_BUFSIZE); + mPostReplaceFormat2 = (CHAR16*)MEM_ALLOC (ATTRPRINT_BUFSIZE); + + if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) { + MEM_FREE(mPostReplaceFormat); + MEM_FREE(mPostReplaceFormat2); + return (EFI_OUT_OF_RESOURCES); + } + + Status = EFI_SUCCESS; + OriginalAttribute = gST->ConOut->Mode->Attribute; + + // + // Back and forth each time fixing up 1 of our flags... + // + Status = StrCopySearchAndReplace(Format, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%N", L"%%N", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, ATTRPRINT_BUFSIZE, L"%E", L"%%E", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%H", L"%%H", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, ATTRPRINT_BUFSIZE, L"%B", L"%%B", FALSE, FALSE); + Status = StrCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, ATTRPRINT_BUFSIZE, L"%V", L"%%V", FALSE, FALSE); + + // + // Use the last buffer from replacing to print from... + // + UnicodeVSPrint (mPostReplaceFormat2, ATTRPRINT_BUFSIZE, mPostReplaceFormat, Marker); + + if (Col != -1 && Row != -1) { + Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row); + } + + FormatWalker = mPostReplaceFormat2; + while (*FormatWalker != CHAR_NULL) { + // + // Find the next attribute change request + // + ResumeLocation = StrStr(FormatWalker, L"%"); + if (ResumeLocation != NULL) { + *ResumeLocation = CHAR_NULL; + } + // + // print the current FormatWalker string + // + if (StrLen(FormatWalker)>0) { + Status = AttrPrintTo(FormatWalker); + if (EFI_ERROR(Status)) { + break; + } + } + + // + // update the attribute + // + if (ResumeLocation != NULL) { + if (*(ResumeLocation-1) == L'^') { + // + // Move cursor back 1 position to overwrite the ^ + // + gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow); + + // + // Print a simple '%' symbol + // + Status = AttrPrintTo(L"%"); + ResumeLocation = ResumeLocation - 1; + } else { + switch (*(ResumeLocation+1)) { + case (L'N'): + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + break; + case (L'E'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'H'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'B'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + case (L'V'): + gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4))); + break; + default: + // + // Print a simple '%' symbol + // + Status = AttrPrintTo(L"%"); + if (EFI_ERROR(Status)) { + break; + } + ResumeLocation = ResumeLocation - 1; + break; + } + } + } else { + // + // reset to normal now... + // + break; + } + + // + // update FormatWalker to Resume + 2 (skip the % and the indicator) + // + FormatWalker = ResumeLocation + 2; + } + + gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute); + + MEM_FREE(mPostReplaceFormat); + MEM_FREE(mPostReplaceFormat2); + return (Status); +} + +/** + Print at a specific location on the screen. + + This function will move the cursor to a given screen location and print the specified string. + + If -1 is specified for either the Row or Col the current screen location for BOTH + will be used. + + If either Row or Col is out of range for the current console, then ASSERT. + If Format is NULL, then ASSERT. + + In addition to the standard %-based flags as supported by UefiLib Print() this supports + the following additional flags: + %N - Set output attribute to normal + %H - Set output attribute to highlight + %E - Set output attribute to error + %B - Set output attribute to blue color + %V - Set output attribute to green color + + Note: The background color is controlled by the shell command cls. + + @param[in] Col the column to print at + @param[in] Row the row to print at + @param[in] Format the format string + @param[in] ... The variable argument list. + + @return EFI_SUCCESS The printing was successful. + @return EFI_DEVICE_ERROR The console device reported an error. +**/ +EFI_STATUS +EFIAPI +AttrPrintEx( + IN INT32 Col OPTIONAL, + IN INT32 Row OPTIONAL, + IN CONST CHAR16 *Format, + ... + ) +{ + VA_LIST Marker; + EFI_STATUS RetVal; + if (Format == NULL) { + return (EFI_INVALID_PARAMETER); + } + VA_START (Marker, Format); + RetVal = InternalAttrPrintWorker(Col, Row, Format, Marker); + VA_END(Marker); + return(RetVal); +} diff --git a/Library/CommonLib/EfiBeep.c b/Library/CommonLib/EfiBeep.c new file mode 100644 index 0000000..2522078 --- /dev/null +++ b/Library/CommonLib/EfiBeep.c @@ -0,0 +1,69 @@ +/** @file +EFI speaker beep helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Beep +////////////////////////////////////////////////////////////////////////// +EFI_HANDLE* gSpeakerHandles = NULL; +UINTN gSpeakerCount = 0; +EFI_SPEAKER_IF_PROTOCOL* gSpeaker = NULL; +EFI_GUID gSpeakerGuid = EFI_SPEAKER_INTERFACE_PROTOCOL_GUID; + +// Beep defaults +int gBeepEnabled = 1; +BOOLEAN gBeepControlEnabled = 1; +int gBeepDevice = -1; +int gBeepNumberDefault = 1; +int gBeepDurationDefault = 100; +int gBeepIntervalDefault = 0; +int gBeepToneDefault = 0x500; + +EFI_STATUS +InitSpeaker() { + EFI_STATUS res; + // Init Console control if supported + res = EfiGetHandles(ByProtocol, &gSpeakerGuid, 0, &gSpeakerHandles, &gSpeakerCount); + if (gSpeakerCount > 0) { + return SpeakerSelect(gSpeakerCount - 1); + } + return res; +} + +EFI_STATUS +SpeakerSelect( + IN UINTN index) { + if (index < gSpeakerCount) { + return gBS->HandleProtocol(gSpeakerHandles[index], &gSpeakerGuid, (VOID**)&gSpeaker); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +SpeakerBeep( + IN UINT16 Tone, + IN UINTN NumberOfBeeps, + IN UINTN Duration, + IN UINTN Interval + ) +{ + if (gSpeaker != NULL) { + gSpeaker->SetSpeakerToneFrequency(gSpeaker, Tone); + return gSpeaker->GenerateBeep(gSpeaker, NumberOfBeeps, Duration, Interval); + } + return EFI_UNSUPPORTED; +} + diff --git a/Library/CommonLib/EfiBio.c b/Library/CommonLib/EfiBio.c new file mode 100644 index 0000000..9577c08 --- /dev/null +++ b/Library/CommonLib/EfiBio.c @@ -0,0 +1,232 @@ +/** @file +EFI block I/O helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Print handle info +////////////////////////////////////////////////////////////////////////// + +VOID +EfiPrintDevicePath( + IN EFI_HANDLE handle) +{ + CHAR16 *StrPath; + EFI_DEVICE_PATH *DevicePath; + OUT_PRINT(L"(%0X): ", handle); + DevicePath = DevicePathFromHandle(handle); + if (DevicePath == NULL) { + ERR_PRINT(L"No path found"); + return; + } + StrPath = ConvertDevicePathToText(DevicePath, FALSE, FALSE); + OUT_PRINT(StrPath); + MEM_FREE(StrPath); +} + +VOID +EfiPrintProtocols( + IN EFI_HANDLE handle) +{ + EFI_GUID **guids; + UINTN count; + EFI_STATUS status; + status = gBS->ProtocolsPerHandle(handle, &guids, &count); + if (!EFI_ERROR(status)) { + UINTN i; + for (i = 0; i < count; ++i) { + OUT_PRINT(L"%d: %g\n", i, guids[i]); + } + FreePool(guids); + } +} + +////////////////////////////////////////////////////////////////////////// +// Handles +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiGetHandles( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + OUT EFI_HANDLE **Buffer, + OUT UINTN *Count + ) +{ + EFI_STATUS res = EFI_BUFFER_TOO_SMALL; + UINTN BufferSize; + if(*Buffer != NULL) MEM_FREE(*Buffer); + *Count = 0; + *Buffer = (EFI_HANDLE*) MEM_ALLOC(sizeof(EFI_HANDLE)); + if (*Buffer) { + BufferSize = sizeof(EFI_HANDLE); + res = gBS->LocateHandle(SearchType, Protocol, SearchKey, &BufferSize, *Buffer); + if (res == RETURN_BUFFER_TOO_SMALL) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)MEM_ALLOC(BufferSize); + if (!Buffer) { + return EFI_OUT_OF_RESOURCES; + } + res = gBS->LocateHandle(SearchType, Protocol, SearchKey, &BufferSize, *Buffer); + if(res != EFI_SUCCESS) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)NULL; + return res; + } + } else if (EFI_ERROR(res)) { + MEM_FREE(*Buffer); + *Buffer = (EFI_HANDLE*)NULL; + return res; + } + *Count = (UINTN)(BufferSize / sizeof(EFI_HANDLE)); + } + return res; +} + +EFI_STATUS +EfiGetStartDevice( + OUT EFI_HANDLE* handle) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + Status = gBS->HandleProtocol(gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage); + if (EFI_ERROR(Status)) { + return Status; + } + *handle = LoadedImage->DeviceHandle; + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// Block I/O +////////////////////////////////////////////////////////////////////////// + +EFI_BLOCK_IO_PROTOCOL* +EfiGetBlockIO( + IN EFI_HANDLE handle + ) +{ + EFI_STATUS res; + EFI_BLOCK_IO_PROTOCOL* blockIOProtocol = NULL; + res = gBS->HandleProtocol(handle, &gEfiBlockIoProtocolGuid, (VOID**)&blockIOProtocol); + if (res == RETURN_SUCCESS && + blockIOProtocol != NULL && + blockIOProtocol->Media->MediaPresent) { + return blockIOProtocol; + } + return NULL; +} + + +EFI_HANDLE* gBIOHandles; +UINTN gBIOCount; + +EFI_STATUS +InitBio() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiBlockIoProtocolGuid, 0, &gBIOHandles, &gBIOCount); + return res; +} + +BOOLEAN +EfiIsPartition( + IN EFI_HANDLE h + ) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + node = DevicePathFromHandle(h); + if (node == NULL) return FALSE; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + return TRUE; + } + node = NextDevicePathNode(node); + } + return FALSE; +} + +EFI_STATUS +EfiGetPartDetails( + IN EFI_HANDLE h, + OUT HARDDRIVE_DEVICE_PATH* dpVolme, + OUT EFI_HANDLE* hDisk) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + EFI_DEVICE_PATH_PROTOCOL* dpVolume; + EFI_DEVICE_PATH_PROTOCOL* dpDisk; + EFI_STATUS res; + dpVolume = DevicePathFromHandle(h); + dpDisk = DuplicateDevicePath(dpVolume); + node = (EFI_DEVICE_PATH_PROTOCOL *)dpDisk; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + CopyMem(dpVolme, node, sizeof(HARDDRIVE_DEVICE_PATH)); + SetDevicePathEndNode(node); + res = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &dpDisk, hDisk); + return res; + } + node = NextDevicePathNode(node); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiGetPartGUID( + IN EFI_HANDLE h, + OUT EFI_GUID* guid) +{ + EFI_DEVICE_PATH_PROTOCOL* node; + EFI_DEVICE_PATH_PROTOCOL* dpVolume; + if (guid == NULL) return EFI_INVALID_PARAMETER; + dpVolume = DevicePathFromHandle(h); + node = (EFI_DEVICE_PATH_PROTOCOL *)dpVolume; + while (!IsDevicePathEnd(node)) { + if (node->Type == MEDIA_DEVICE_PATH && node->SubType == MEDIA_HARDDRIVE_DP) { + HARDDRIVE_DEVICE_PATH* hdpNode = (HARDDRIVE_DEVICE_PATH*)node; + CopyMem(guid, hdpNode->Signature, sizeof(*guid)); + return EFI_SUCCESS; + } + node = NextDevicePathNode(node); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiFindPartByGUID( + IN EFI_GUID* guid, + OUT EFI_HANDLE* h + ) +{ + EFI_STATUS res; + EFI_GUID guidI; + UINTN i; + if (guid == NULL || h == NULL) return EFI_INVALID_PARAMETER; + for (i = 0; i < gBIOCount; ++i) { + res = EfiGetPartGUID(gBIOHandles[i], &guidI); + if (!EFI_ERROR(res)) { + if (CompareMem(&guidI, guid, sizeof(guidI)) == 0) { + *h = gBIOHandles[i]; + return EFI_SUCCESS; + } + } + } + return EFI_NOT_FOUND; +} + + diff --git a/Library/CommonLib/EfiConsole.c b/Library/CommonLib/EfiConsole.c new file mode 100644 index 0000000..8a87ec8 --- /dev/null +++ b/Library/CommonLib/EfiConsole.c @@ -0,0 +1,347 @@ +/** @file +EFI console helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov, Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Print +////////////////////////////////////////////////////////////////////////// + +VOID +FlushInputDelay( + IN UINTN delay + ) +{ + EFI_INPUT_KEY key; + EFI_EVENT InputEvents[2]; + UINTN EventIndex = 0; + + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, delay); + while (EventIndex == 0) { + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + } + gBS->CloseEvent(InputEvents[1]); +} + +VOID +FlushInput() { + FlushInputDelay(1000000); +} + +EFI_INPUT_KEY +KeyWait( + CHAR16* Prompt, + UINTN mDelay, + UINT16 scanCode, + UINT16 unicodeChar) +{ + EFI_INPUT_KEY key; + EFI_EVENT InputEvents[2]; + UINTN EventIndex; + + FlushInput(); + key.ScanCode = scanCode; + key.UnicodeChar = unicodeChar; + + InputEvents[0] = gST->ConIn->WaitForKey; + + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, 10000000); + while (mDelay > 0) { + OUT_PRINT(Prompt, mDelay); + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + break; + } + else { + mDelay--; + } + } + OUT_PRINT(Prompt, mDelay); + gBS->CloseEvent(InputEvents[1]); + return key; +} + +EFI_INPUT_KEY +GetKey(void) +{ + EFI_INPUT_KEY key; + UINTN EventIndex; + + gBS->WaitForEvent(1, &gST->ConIn->WaitForKey, &EventIndex); + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + return key; +} + +VOID +ConsoleShowTip( + IN CHAR16* tip, + IN UINTN delay) +{ + EFI_EVENT InputEvents[2]; + UINTN EventIndex = 0; + UINTN i = 0; + EFI_INPUT_KEY key; + OUT_PRINT(L"%s", tip); + + // delay + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->SetTimer(InputEvents[1], TimerPeriodic, delay); + gBS->WaitForEvent(2, InputEvents, &EventIndex); + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + + // remove tip + for (i = 0; i < StrLen(tip); ++i) { + OUT_PRINT(L"\b \b", tip); + } +} + + +VOID +GetLine ( + UINTN *length, + CHAR16 *line, + CHAR8 *asciiLine, + UINTN line_max, + UINT8 show) +{ + EFI_INPUT_KEY key; + UINT32 count = 0; + + do { + key = GetKey(); + + if ((count >= line_max && + key.UnicodeChar != CHAR_BACKSPACE) || + key.UnicodeChar == CHAR_NULL || + key.UnicodeChar == CHAR_TAB || + key.UnicodeChar == CHAR_LINEFEED || + key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + continue; + } + + if (count == 0 && key.UnicodeChar == CHAR_BACKSPACE) { + continue; + } else if (key.UnicodeChar == CHAR_BACKSPACE) { + OUT_PRINT(L"\b \b"); + if (line != NULL) line[--count] = '\0'; + if (asciiLine != NULL) asciiLine[--count] = '\0'; + continue; + } + + // check size of line + if (count < line_max - 1) { + if (show) { + OUT_PRINT(L"%c", key.UnicodeChar); + } + else { + OUT_PRINT(L"*"); + } + // save char + if (line != NULL) line[count++] = key.UnicodeChar; + if (asciiLine != NULL) asciiLine[count++] = (CHAR8)key.UnicodeChar; + } + } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + OUT_PRINT(L"\n"); + if (length != NULL) *length = count; + // Set end of line + if (line != NULL) line[count] = '\0'; + if (asciiLine != NULL) asciiLine[count] = '\0'; +} + +int +AskAsciiString( + CHAR8* prompt, + CHAR8* str, + UINTN max_len, + UINT8 visible) +{ + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, NULL, str, max_len, visible); + return (UINT32)len; +} + +int +AskInt( + CHAR8* prompt, + UINT8 visible) +{ + CHAR16 buf[32]; + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, visible); + return (UINT32)StrDecimalToUintn(buf); +} + +UINT8 +AskConfirm( + CHAR8* prompt, + UINT8 visible) +{ + CHAR16 buf[2]; + UINTN len = 0; + OUT_PRINT(L"%a", prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, visible); + return (buf[0] == 'y') || (buf[0] == 'Y') ? 1 : 0; +} + +UINT64 +AskUINT64( + IN char* prompt, + IN UINT64 def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[%lld] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : (UINT64)StrDecimalToUint64(buf); +} + +UINT64 +AskHexUINT64( + IN char* prompt, + IN UINT64 def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[0x%llx] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : (UINT64)StrHexToUint64(buf); +} + +UINTN +AskUINTN( + IN char* prompt, + IN UINTN def) +{ + CHAR16 buf[128]; + UINTN len = 0; + OUT_PRINT(L"[%d] %a", def, prompt); + GetLine(&len, buf, NULL, sizeof(buf) / 2, 1); + return (len == 0) ? def : StrDecimalToUintn(buf); +} + +EFI_STATUS +ConsoleGetOutput( + IN EFI_HANDLE handle, + OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL** io + ) { + return gBS->HandleProtocol(handle, &gEfiSimpleTextOutProtocolGuid, (VOID**)io); +} + +////////////////////////////////////////////////////////////////////////// +// Ascii converters +////////////////////////////////////////////////////////////////////////// +BOOLEAN +AsciiHexToDigit( + OUT UINT8 *b, + IN CHAR8 *str + ) +{ + CHAR8 ch; + ch = str[0]; + if (ch >= '0' && ch <= '9') { + *b = ch - '0'; + return TRUE; + } + else { + ch = ch & ~0x20; + if (ch >= 'A' && ch <= 'F') { + *b = ch - 'A' + 10; + return TRUE; + } + } + return FALSE; +} + +BOOLEAN +AsciiHexToByte( + OUT UINT8 *b, + IN CHAR8 *str + ) +{ + UINT8 low = 0; + UINT8 high = 0; + BOOLEAN res; + res = AsciiHexToDigit(&high, str); + res = res && AsciiHexToDigit(&low, str + 1); + *b = low | high << 4; + return res; +} + +BOOLEAN +AsciiStrToGuid( + OUT EFI_GUID *guid, + IN CHAR8 *str + ) +{ + UINT8 b[16]; + BOOLEAN res = TRUE; + int i; + CHAR8* pos = str; + if (guid == NULL || str == NULL) return FALSE; + for (i = 0; i < 16; ++i) { + if (*pos == '-') pos++; + res = res && AsciiHexToByte(&b[i], pos); + pos += 2; + if (!res) return FALSE; + } + guid->Data1 = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]; + guid->Data2 = b[4] << 8 | b[5]; + guid->Data3 = b[6] << 8 | b[7]; + CopyMem(&guid->Data4, &b[8], 8); + return res; +} + + + +////////////////////////////////////////////////////////////////////////// +// Console control +////////////////////////////////////////////////////////////////////////// + +EFI_HANDLE* gConsoleControlHandles = NULL; +UINTN gConsoleControlCount = 0; + +EFI_STATUS +InitConsoleControl() { + EFI_STATUS res; + // Init Console control if supported + EFI_GUID gConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID; + EFI_CONSOLE_CONTROL_PROTOCOL* ConsoleControl; + res = EfiGetHandles(ByProtocol, &gConsoleControlProtocolGuid, 0, &gConsoleControlHandles, &gConsoleControlCount); + if (gConsoleControlCount > 0) { + res = gBS->HandleProtocol(gConsoleControlHandles[0], &gConsoleControlProtocolGuid, (VOID**)&ConsoleControl); + if (!EFI_ERROR(res)) { + // Unlock graphics + ConsoleControl->SetMode(ConsoleControl, EfiConsoleControlScreenGraphics); + } + } + return res; +} diff --git a/Library/CommonLib/EfiExec.c b/Library/CommonLib/EfiExec.c new file mode 100644 index 0000000..ff0aa95 --- /dev/null +++ b/Library/CommonLib/EfiExec.c @@ -0,0 +1,88 @@ +/** @file +EFI execute helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include + +#include +#include +#include +#include + +EFI_STATUS +EfiExec( + IN EFI_HANDLE deviceHandle, + IN CHAR16* path + ) +{ + EFI_STATUS res; + EFI_DEVICE_PATH* DevicePath; + EFI_HANDLE ImageHandle; + UINTN ExitDataSize; + CHAR16 *ExitData; + if (deviceHandle == NULL) { + deviceHandle = gFileRootHandle; + } + if (!path || !deviceHandle) return EFI_INVALID_PARAMETER; + DevicePath = FileDevicePath(deviceHandle, path); + + res = gBS->LoadImage(FALSE, gImageHandle, DevicePath, NULL, 0, &ImageHandle); + if (EFI_ERROR(res)) { + return res; + } + res = gBS->StartImage(ImageHandle, &ExitDataSize, &ExitData); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +/** +This function will connect all current system handles recursively. The +connection will finish until every handle's child handle created if it have. + +@retval EFI_SUCCESS All handles and it's child handle have been +connected +@retval EFI_STATUS Return the status of gBS->LocateHandleBuffer(). + +**/ +EFI_STATUS +ConnectAllEfi( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR(Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController(HandleBuffer[Index], NULL, NULL, TRUE); + } + + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/Library/CommonLib/EfiFile.c b/Library/CommonLib/EfiFile.c new file mode 100644 index 0000000..b1e2076 --- /dev/null +++ b/Library/CommonLib/EfiFile.c @@ -0,0 +1,350 @@ +/** @file +EFI file system helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// EFI file +////////////////////////////////////////////////////////////////////////// + +EFI_FILE* gFileRoot = NULL; +EFI_HANDLE gFileRootHandle = NULL; + +EFI_HANDLE* gFSHandles = NULL; +UINTN gFSCount = 0; + +EFI_STATUS +InitFS() { + EFI_STATUS res; + EfiGetHandles(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, 0, &gFSHandles, &gFSCount); + res = EfiGetStartDevice(&gFileRootHandle); + if (!EFI_ERROR(res)) { + res = FileOpenRoot(gFileRootHandle, &gFileRoot); + } + return res; +} + +EFI_STATUS +FileOpenRoot( + IN EFI_HANDLE rootHandle, + OUT EFI_FILE** rootFile) +{ + EFI_STATUS res = 0; + EFI_FILE_IO_INTERFACE* fSysProtocol = NULL; + res = gBS->HandleProtocol(rootHandle, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&fSysProtocol); + if (res == RETURN_SUCCESS && fSysProtocol != NULL) { + res = fSysProtocol->OpenVolume(fSysProtocol, rootFile); + } + return res; +} + +EFI_STATUS +FileOpen( + IN EFI_FILE* root, + IN CHAR16* name, + OUT EFI_FILE** file, + IN UINT64 mode, + IN UINT64 attributes + ) +{ + EFI_STATUS res; + + if (!name || !file) { return EFI_INVALID_PARAMETER; } + if (!root) root = gFileRoot; + if (!root) { return EFI_INVALID_PARAMETER; } + if (mode == 0) { + mode = EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE; + } + res = root->Open(root, file, name, mode , attributes); + return res; +} + +EFI_STATUS +FileClose( + IN EFI_FILE* f) +{ + if (!f) { return EFI_INVALID_PARAMETER; } + return f->Close(f); +} + +EFI_STATUS +FileDelete( + IN EFI_FILE* root, + IN CHAR16* name + ) +{ + EFI_FILE* f; + EFI_STATUS res; + if (!name) { return EFI_INVALID_PARAMETER; } + res = FileOpen(root, name, &f, 0, 0); + if (EFI_ERROR(res)) { + return res; + } + res = f->Delete(f); +// f->Close(f); + return res; +} + +EFI_STATUS +FileRead( + IN EFI_FILE* f, + OUT VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Read(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileWrite( + IN EFI_FILE* f, + IN VOID* data, + IN OUT UINTN* bytes, + IN OUT UINT64* position) +{ + EFI_STATUS res; + + if (!f || !data || !bytes) { + return EFI_INVALID_PARAMETER; + } + if (position != NULL) { + res = f->SetPosition(f, *position); + if (EFI_ERROR(res)) { + return res; + } + } + res = f->Write(f, bytes, data); + if (position != NULL) { + f->GetPosition(f, position); + } + return res; +} + +EFI_STATUS +FileGetInfo( + IN EFI_FILE* f, + OUT EFI_FILE_INFO** info, + OUT UINTN* size + ) +{ + EFI_STATUS res; + UINTN sz = 0; + if (!f || !info) { return EFI_INVALID_PARAMETER; } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, NULL); + if (res == RETURN_BUFFER_TOO_SMALL) { + *info = (EFI_FILE_INFO*)MEM_ALLOC(sz); + if (!(*info)) { + return res; + } + res = f->GetInfo(f, &gEfiFileInfoGuid, &sz, *info); + if (EFI_ERROR(res)) { + MEM_FREE(*info); + *info = NULL; + sz = 0; + } + } + if (size) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileGetSize( + IN EFI_FILE* f, + OUT UINTN* size + ) +{ + EFI_STATUS res; + EFI_FILE_INFO* info = NULL; + if (!f || !size) { return EFI_INVALID_PARAMETER; } + res = FileGetInfo(f, &info, NULL); + if (!EFI_ERROR(res)) { + *size = (UINTN)info->FileSize; + MEM_FREE(info); + } + return res; +} + +EFI_STATUS +FileLoad( + IN EFI_FILE* root, + IN CHAR16* name, + OUT VOID** data, + OUT UINTN* size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz; + if (!data) { + return EFI_INVALID_PARAMETER; + } + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(file, &sz); + if (EFI_ERROR(res)) { + FileClose(file); + return res; + } + *data = MEM_ALLOC(sz); + if (*data == NULL) { + FileClose(file); + return EFI_BUFFER_TOO_SMALL; + } + res = FileRead(file, *data, &sz, NULL); + if (EFI_ERROR(res)) { + FileClose(file); + MEM_FREE(*data); + return res; + } + FileClose(file); + if (size != NULL) { + *size = sz; + } + return res; +} + +EFI_STATUS +FileSave( + IN EFI_FILE* root, + IN CHAR16* name, + IN VOID* data, + IN UINTN size + ) +{ + EFI_FILE* file; + EFI_STATUS res; + UINTN sz = size; + if (!data || !name) { return EFI_INVALID_PARAMETER; } + FileDelete(root, name); + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) return res; + res = FileWrite(file, data, &sz, NULL); + FileClose(file); + return res; +} + +EFI_STATUS +FileExist( + IN EFI_FILE* root, + IN CHAR16* name) +{ + EFI_FILE* file; + EFI_STATUS res; + res = FileOpen(root, name, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + FileClose(file); + return EFI_SUCCESS; +} + +EFI_STATUS +FileRename( + IN EFI_FILE* root, + IN CHAR16* src, + IN CHAR16* dst) +{ + EFI_STATUS res; + EFI_FILE* file; + EFI_FILE_INFO* info = NULL; + UINTN sz; + EFI_FILE_INFO* dstinfo = NULL; + UINTN dstinfosz; + + res = FileOpen(root, src, &file, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetInfo(file, &info, &sz); + if (EFI_ERROR(res)) return res; + dstinfosz = SIZE_OF_EFI_FILE_INFO + StrSize(dst); + dstinfo = (EFI_FILE_INFO*)MEM_ALLOC(dstinfosz); + if (dstinfo != NULL) { + CopyMem(dstinfo, info, SIZE_OF_EFI_FILE_INFO); + dstinfo->FileName[0] = 0; + StrCat(dstinfo->FileName, dst); + res = file->SetInfo(file, &gEfiFileInfoGuid, dstinfosz, dstinfo); + } else { + res = EFI_BUFFER_TOO_SMALL; + } + + MEM_FREE(info); + MEM_FREE(dstinfo); + FileClose(file); + return res; +} + +EFI_STATUS +FileCopy( + IN EFI_FILE* srcroot, + IN CHAR16* src, + IN EFI_FILE* dstroot, + IN CHAR16* dst, + IN UINTN bufSz + ) +{ + EFI_STATUS res; + EFI_FILE* srcfile = NULL; + EFI_FILE* dstfile = NULL; + UINTN remains; + CHAR8* data = NULL; + UINTN datasz = bufSz; + + res = FileOpen(srcroot, src, &srcfile, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) return res; + res = FileGetSize(srcfile, &remains); + if (EFI_ERROR(res)) return res; + + data = (CHAR8*)MEM_ALLOC(bufSz); + if (data == NULL) { + res = EFI_BUFFER_TOO_SMALL; + goto copyerr; + } + + res = FileOpen(dstroot, dst, &dstfile, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(res)) goto copyerr; + + do { + datasz = remains > bufSz ? bufSz : remains; + res =FileRead(srcfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + res = FileWrite(dstfile, data, &datasz, NULL); + if (EFI_ERROR(res)) goto copyerr; + remains -= datasz; + } while (remains > 0); + +copyerr: + MEM_FREE(data); + FileClose(srcfile); + FileClose(dstfile); + return res; +} diff --git a/Library/CommonLib/EfiMem.c b/Library/CommonLib/EfiMem.c new file mode 100644 index 0000000..d9386c0 --- /dev/null +++ b/Library/CommonLib/EfiMem.c @@ -0,0 +1,74 @@ +/** @file +EFI memory helpers routines/wrappers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include + +#include "Library/CommonLib.h" + + +////////////////////////////////////////////////////////////////////////// +// Memory procedures wrappers +////////////////////////////////////////////////////////////////////////// + +VOID* +MemAlloc( + IN UINTN size + ) { + return AllocateZeroPool(size); +} + +VOID* +MemRealloc( + IN UINTN OldSize, + IN UINTN NewSize, + IN VOID *OldBuffer OPTIONAL + ) { + return ReallocatePool(OldSize, NewSize, OldBuffer); +} + +VOID +MemFree( + IN VOID* ptr + ) { + if(ptr != NULL) FreePool(ptr); +} + +////////////////////////////////////////////////////////////////////////// +// Memory mapped IO +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +PrepareMemory( + IN UINTN address, + IN UINTN len, + OUT VOID** mem) +{ + EFI_STATUS status; + EFI_PHYSICAL_ADDRESS ptr; + VOID* buf; + UINTN pages; + pages = ((len & ~0x0FFF) + 0x1000) >> 12; + ptr = address & ~0x0FFF; +// OUT_PRINT(L"mem try %0x, %0x\n", pages, (UINTN)ptr); + status = gBS->AllocatePages(AllocateAddress, EfiMemoryMappedIO, pages, &ptr); + if (EFI_ERROR(status)) { + return status; + } + buf = (void*)(UINTN)ptr; + SetMem(buf, pages << 12, 0); + *mem = buf; + return status; +} diff --git a/Library/CommonLib/EfiTouch.c b/Library/CommonLib/EfiTouch.c new file mode 100644 index 0000000..9009f82 --- /dev/null +++ b/Library/CommonLib/EfiTouch.c @@ -0,0 +1,47 @@ +/** @file +EFI touch/absolute pointer helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ +#include +#include +#include +#include +#include + +EFI_HANDLE* gTouchHandles = NULL; +UINTN gTouchCount = 0; +int gTouchSimulate = 0; +UINT32 gTouchSimulateStep = 1; + +EFI_ABSOLUTE_POINTER_PROTOCOL* gTouchPointer = NULL; + +EFI_STATUS +InitTouch() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiAbsolutePointerProtocolGuid, 0, &gTouchHandles, &gTouchCount); + if (gTouchCount > 0) { + TouchGetIO(gTouchHandles[gTouchCount - 1], &gTouchPointer); + } + return res; +} + + +EFI_STATUS +TouchGetIO( + IN EFI_HANDLE Handle, + OUT EFI_ABSOLUTE_POINTER_PROTOCOL** io + ) { + if (!io) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiAbsolutePointerProtocolGuid, (VOID**)io); +} + diff --git a/Library/CommonLib/EfiUsb.c b/Library/CommonLib/EfiUsb.c new file mode 100644 index 0000000..b5bdac5 --- /dev/null +++ b/Library/CommonLib/EfiUsb.c @@ -0,0 +1,88 @@ +/** @file +EFI USB helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +EFI_HANDLE* gUSBHandles = NULL; +UINTN gUSBCount = 0; + +EFI_STATUS +InitUsb() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiUsbIoProtocolGuid, 0, &gUSBHandles, &gUSBCount); + return res; +} + +EFI_STATUS +UsbGetIO( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo + ) { + if (!UsbIo) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiUsbIoProtocolGuid, (VOID**)UsbIo); +} + +EFI_STATUS +UsbGetIOwithDescriptor( + IN EFI_HANDLE Handle, + OUT EFI_USB_IO_PROTOCOL** UsbIo, + OUT EFI_USB_DEVICE_DESCRIPTOR* UsbDescriptor + ) { + EFI_STATUS res; + if (!UsbIo || !UsbDescriptor) { + return EFI_INVALID_PARAMETER; + } + res = UsbGetIO(Handle, UsbIo); + if (EFI_ERROR(res)) { + return res; + } + return (*UsbIo)->UsbGetDeviceDescriptor(*UsbIo, UsbDescriptor); +} + +EFI_STATUS +UsbGetId( + IN EFI_HANDLE Handle, + OUT CHAR8** id + ) +{ + EFI_STATUS res; + EFI_USB_IO_PROTOCOL *usbIO = NULL; + EFI_USB_DEVICE_DESCRIPTOR usbDescriptor; + CHAR16* serial = NULL; + CHAR8* buff; + UINTN len; + res = UsbGetIOwithDescriptor(Handle, &usbIO, &usbDescriptor); + if (EFI_ERROR(res)) { + return res; + } +// Print(L" %02x ", (UINTN)usbDescriptor.StrSerialNumber); + res = usbIO->UsbGetStringDescriptor(usbIO, 0x409, usbDescriptor.StrSerialNumber, &serial); + if (!EFI_ERROR(res)) { + len = 11 + StrLen(serial); + buff = (CHAR8*)MEM_ALLOC(len); + AsciiSPrint(buff, len, "%04x_%04x_%s", usbDescriptor.IdVendor, usbDescriptor.IdProduct, serial); + } else { +// Print(L" %04x %r ", res, res); + len = 10; + buff = (CHAR8*)MEM_ALLOC(len); + AsciiSPrint(buff, len, "%04x_%04x", usbDescriptor.IdVendor, usbDescriptor.IdProduct); + } + *id = buff; + return EFI_SUCCESS; +} diff --git a/Library/CommonLib/EfiVar.c b/Library/CommonLib/EfiVar.c new file mode 100644 index 0000000..2a6e59e --- /dev/null +++ b/Library/CommonLib/EfiVar.c @@ -0,0 +1,228 @@ +/** @file +EFI firmware variable helpers + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials are licensed and made available +under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Efi variables +////////////////////////////////////////////////////////////////////////// + +EFI_STATUS +EfiGetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + OUT VOID** varValue, + OUT UINTN* varSize, + OUT UINT32* varAttr + ) { + EFI_STATUS Status; + CHAR8 *varData = NULL; + if (varSize == NULL) return EFI_INVALID_PARAMETER; + *varSize = 0; + if (varGuid == NULL) varGuid = &gEfiDcsVariableGuid; + Status = gST->RuntimeServices->GetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varData); + if (Status == EFI_BUFFER_TOO_SMALL) { + varData = MEM_ALLOC(*varSize); + if (varData == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + Status = gST->RuntimeServices->GetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varData); + *varValue = varData; + } + return Status; +} + + +EFI_STATUS +EfiSetVar( + IN CONST CHAR16* varName, + IN EFI_GUID* varGuid, + IN VOID* varValue, + IN UINTN varSize, + IN UINT32 varAttr + ) { + EFI_STATUS Status; + if (varGuid == NULL) varGuid = &gEfiDcsVariableGuid; + Status = gST->RuntimeServices->SetVariable((CHAR16*)varName, varGuid, varAttr, varSize, varValue); + return Status; +} + +EFI_STATUS +BootOrderInsert( + IN CHAR16 *OrderVarName, + IN UINTN index, + UINT16 value) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT16* varBootOrderNew; + UINT16* varBootOrder; + UINTN varBootOrderSize; + UINT32 varBootOrderAttr; + UINTN BootOrderCount; + UINTN i; + UINTN j; + res = EfiGetVar(OrderVarName, &gEfiGlobalVariableGuid, &varBootOrder, &varBootOrderSize, &varBootOrderAttr); + if (EFI_ERROR(res)) return res; + BootOrderCount = varBootOrderSize / sizeof(UINT16); + varBootOrderNew = MEM_ALLOC((BootOrderCount + 1) * sizeof(UINT16)); + if (BootOrderCount < index) index = BootOrderCount - 1; + for (j = 0, i = 0; i < BootOrderCount; ++i) { + if (j == index) { + varBootOrderNew[j] = value; + j++; + } + if (varBootOrder[i] == value) { + continue; + } + varBootOrderNew[j] = varBootOrder[i]; + ++j; + } + BootOrderCount = j; + + res = EfiSetVar(OrderVarName, &gEfiGlobalVariableGuid, + varBootOrderNew, BootOrderCount * sizeof(UINT16), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + MEM_FREE(varBootOrderNew); + MEM_FREE(varBootOrder); + return res; +} + +EFI_STATUS +BootOrderRemove( + IN CHAR16 *OrderVarName, + UINT16 value) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT16* varBootOrderNew; + UINT16* varBootOrder; + UINTN varBootOrderSize; + UINT32 varBootOrderAttr; + UINTN BootOrderCount; + UINTN i; + UINTN j; + + res = EfiGetVar(OrderVarName, &gEfiGlobalVariableGuid, &varBootOrder, &varBootOrderSize, &varBootOrderAttr); + if (EFI_ERROR(res)) return res; + BootOrderCount = varBootOrderSize / sizeof(UINT16); + varBootOrderNew = MEM_ALLOC((BootOrderCount + 1) * sizeof(UINT16)); + for (j = 0, i = 0; i < BootOrderCount; ++i) { + if (varBootOrder[i] == value) { + continue; + } + varBootOrderNew[j] = varBootOrder[i]; + ++j; + } + BootOrderCount = j; + + res = EfiSetVar(OrderVarName, &gEfiGlobalVariableGuid, + varBootOrderNew, BootOrderCount * sizeof(UINT16), + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + + MEM_FREE(varBootOrderNew); + MEM_FREE(varBootOrder); + return res; +} + +EFI_STATUS +BootMenuItemRemove( + IN CHAR16 *VarName + ) +{ + EFI_STATUS res = EFI_NOT_READY; + res = EfiSetVar( + VarName, &gEfiGlobalVariableGuid, + NULL, 0, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + return res; +} + +EFI_STATUS +BootMenuItemCreate( + IN CHAR16 *VarName, + IN CHAR16 *Desc, + IN EFI_HANDLE volumeHandle, + IN CHAR16 *Path, + IN BOOLEAN Reduced + ) +{ + EFI_STATUS res = EFI_NOT_READY; + UINT8* varBoot; + UINT8* TempByteBuffer; + UINTN DescSize; + UINTN FilePathSize; + EFI_DEVICE_PATH_PROTOCOL* DevPath; + EFI_DEVICE_PATH_PROTOCOL* DevicePath; + EFI_DEVICE_PATH_PROTOCOL* FileNode; + EFI_DEVICE_PATH_PROTOCOL* FilePath; + + // Prepare + DevicePath = DevicePathFromHandle(volumeHandle); + if (Reduced) { + DevPath = DevicePath; + while (!IsDevicePathEnd(DevPath)) { + if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) { + + // + // If we find it use it instead + // + DevicePath = DevPath; + break; + } + DevPath = NextDevicePathNode(DevPath); + } + } + // + // append the file + // + FileNode = FileDevicePath(NULL, Path); + FilePath = AppendDevicePath(DevicePath, FileNode); + FreePool(FileNode); + // + // Add the option + // + DescSize = StrSize(Desc); + FilePathSize = GetDevicePathSize(FilePath); + + varBoot = MEM_ALLOC(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize); + if (varBoot != NULL) { + TempByteBuffer = varBoot; + *((UINT32 *)TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes + TempByteBuffer += sizeof(UINT32); + + *((UINT16 *)TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength + TempByteBuffer += sizeof(UINT16); + + CopyMem(TempByteBuffer, Desc, DescSize); + TempByteBuffer += DescSize; + CopyMem(TempByteBuffer, FilePath, FilePathSize); + + res = EfiSetVar(VarName, &gEfiGlobalVariableGuid, + varBoot, sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + } + else { + return EFI_BUFFER_TOO_SMALL; + } + + MEM_FREE(varBoot); + return res; +} diff --git a/Library/CommonLib/IA32/EfiCpuHalt.asm b/Library/CommonLib/IA32/EfiCpuHalt.asm new file mode 100644 index 0000000..3c5bb0d --- /dev/null +++ b/Library/CommonLib/IA32/EfiCpuHalt.asm @@ -0,0 +1,19 @@ + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuHalt ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiCpuHalt PROC + cli +l: hlt + jmp l + ret +EfiCpuHalt ENDP + + END diff --git a/Library/CommonLib/X64/EfiCpuHalt.asm b/Library/CommonLib/X64/EfiCpuHalt.asm new file mode 100644 index 0000000..7893234 --- /dev/null +++ b/Library/CommonLib/X64/EfiCpuHalt.asm @@ -0,0 +1,17 @@ + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuHalt ( +; VOID +; ); +;------------------------------------------------------------------------------ +EfiCpuHalt PROC + cli +l: hlt + jmp l + ret +EfiCpuHalt ENDP + + END diff --git a/Library/DcsCfgLib/DcsCfgLib.inf b/Library/DcsCfgLib/DcsCfgLib.inf new file mode 100644 index 0000000..8607cb4 --- /dev/null +++ b/Library/DcsCfgLib/DcsCfgLib.inf @@ -0,0 +1,80 @@ +## @file +# Library for DCS configuration +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = DcsCfgLib + MODULE_UNI_FILE = DcsCfgLib.uni + FILE_GUID = 3E61F9E0-0844-44F2-A177-A72FE81D6F07 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DcsCfgLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] +GptEdit.c +DcsRandom.c + +[Sources.X64] + +[Sources.IA32] + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + RngLib + +[Protocols] + + +[BuildOptions.IA32] +DEBUG_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +DEBUG_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +RELEASE_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +RELEASE_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +[BuildOptions.X64] +DEBUG_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +DEBUG_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +RELEASE_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 + +RELEASE_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 diff --git a/Library/DcsCfgLib/DcsRandom.c b/Library/DcsCfgLib/DcsRandom.c new file mode 100644 index 0000000..a269a46 --- /dev/null +++ b/Library/DcsCfgLib/DcsRandom.c @@ -0,0 +1,460 @@ +/** @file +Random number generators for DCS + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 + +!NOTE: Very simple! Need to select several sources of random like user input or other. +**/ + +#include +#include +#include +#include +#include + +#include +#include + +DCS_RND* gRnd = NULL; + +////////////////////////////////////////////////////////////////////////// +// Random data from file +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndFilePrepare( + IN DCS_RND* rnd + ) +{ + EFI_STATUS res = EFI_NOT_READY; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + rnd->State.File.Pos = 0; + res = EFI_SUCCESS; + } + return res; +} + +EFI_STATUS +RndFileGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINTN i; + if (rnd != NULL && rnd->Type == RndTypeFile && rnd->State.File.Data != NULL) { + for (i = 0; i < len; i++, rnd->State.File.Pos++) { + if (rnd->State.File.Pos >= rnd->State.File.Size) { + rnd->State.File.Pos = 0; + } + buf[i] = rnd->State.File.Data[rnd->State.File.Pos]; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndFileInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_NOT_FOUND; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeFile; + rnd->GetBytes = RndFileGetBytes; + rnd->Prepare = RndFilePrepare; + if (Context != NULL) { + res = FileLoad(NULL, (CHAR16*)Context, &rnd->State.File.Data, &rnd->State.File.Size); + if (!EFI_ERROR(res)) { + return rnd->Prepare(rnd); + } + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Random data from CPU RDRAND +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndRDRandPrepare( + IN DCS_RND* rnd + ) +{ + UINT64 rndTmp; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + if (GetRandomNumber64((UINT64*)&rndTmp)) { + return EFI_SUCCESS; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndRDRandGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINT8 tmpRnd[8]; + UINTN i = 0; + UINTN j = 0; + if (rnd != NULL && rnd->Type == RndTypeRDRand) { + for (i = 0; i < len; ++i, ++j) { + j &= 7; + if (j == 0) { + if (!GetRandomNumber64((UINT64*)tmpRnd)) return EFI_NOT_READY; + } + buf[i] = tmpRnd[j]; + } + } else { + return EFI_NOT_READY; + } + return EFI_SUCCESS; +} + +EFI_STATUS +RndRDRandInit( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeRDRand; + rnd->GetBytes = RndRDRandGetBytes; + rnd->Prepare = RndRDRandPrepare; + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// DRBG HMAC (SHA512) (NIST SP 800-90A) (simplified) +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +HmacSha512( + IN UINT8 *k, /* secret key */ + OUT UINT8 *out, /* output buffer */ + ... + ) +{ + sha512_ctx ctx; + char inner[SHA512_DIGEST_SIZE], outer[SHA512_DIGEST_SIZE]; + char key[SHA512_DIGEST_SIZE]; + char buf[SHA512_BLOCK_SIZE]; + int32 i; + int32 lk = SHA512_DIGEST_SIZE; /* length of the key in bytes */ + VA_LIST args; + UINT8* data; + UINTN len; + + /**** Inner Digest ****/ + sha512_begin(&ctx); + + /* Pad the key for inner digest */ + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x36); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x36; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + + VA_START(args, out); + while ((data = VA_ARG(args, UINT8 *)) != NULL) { + len = VA_ARG(args, UINTN); + sha512_hash(data, (UINT32)len, &ctx); + } + VA_END(args); + + sha512_end((unsigned char *)inner, &ctx); + + /**** Outer Digest ****/ + + sha512_begin(&ctx); + + for (i = 0; i < lk; ++i) + buf[i] = (char)(k[i] ^ 0x5C); + for (i = lk; i < SHA512_BLOCK_SIZE; ++i) + buf[i] = 0x5C; + + sha512_hash((unsigned char *)buf, SHA512_BLOCK_SIZE, &ctx); + sha512_hash((unsigned char *)inner, SHA512_DIGEST_SIZE, &ctx); + + sha512_end((unsigned char *)out, &ctx); + + /* Prevent possible leaks. */ + burn(&ctx, sizeof(ctx)); + burn(outer, sizeof(outer)); + burn(inner, sizeof(inner)); + burn(buf, sizeof(buf)); + burn(key, sizeof(key)); + return EFI_SUCCESS; +} + +EFI_STATUS +RndDtrmHmacSha512Update( + RND_DTRM_HMAC_SHA512_STATE *state, + UINT8 *seed, + UINTN seedLen, + BOOLEAN reseed + ) +{ + EFI_STATUS res = EFI_NOT_READY; + int i = 0; + + if (!reseed) + { + /* 10.1.2.3 */ + memset(state->V, 1, SHA512_DIGEST_SIZE); + memset(state->C, 0, SHA512_DIGEST_SIZE); + } + + /* we execute two rounds of V/K massaging */ + for (i = 2; 0 < i; i--) + { + /* first round uses 0x0, second 0x1 */ + unsigned char prefix = 0; + if (1 == i) + prefix = 1; + /* 10.1.2.2 step 1 and 4 -- concatenation and HMAC for key */ + + res = HmacSha512(state->C, state->C, + state->V, SHA512_DIGEST_SIZE, + &prefix, 1, + seed, seedLen, + NULL + ); + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 2 and 5 -- HMAC for V */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL); + + if (EFI_ERROR(res)) + return res; + + /* 10.1.2.2 step 3 */ + if (!seed || 0 == seedLen) + return res; + } + return EFI_SUCCESS; +} + +/* generate function of HMAC DRBG as defined in 10.1.2.5 */ +EFI_STATUS +RndDtrmHmacSha512Generate( + RND_DTRM_HMAC_SHA512_STATE *state, + OUT UINT8 *buf, + IN UINTN buflen, + IN UINT8 *seed, + IN UINTN seedLen + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len = 0; + + /* 10.1.2.5 step 2 */ + if (seed && 0 < seedLen) + { + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + if (EFI_ERROR(res)) + return res; + } + + while (len < buflen) + { + UINTN outlen = 0; + /* 10.1.2.5 step 4.1 */ + res = HmacSha512(state->C, state->V, + state->V, SHA512_DIGEST_SIZE, + NULL + ); + if (EFI_ERROR(res)) + return res; + outlen = (SHA512_DIGEST_SIZE < (buflen - len)) ? + SHA512_DIGEST_SIZE : (buflen - len); + + /* 10.1.2.5 step 4.2 */ + memcpy(buf + len, state->V, outlen); + len += outlen; + } + + /* 10.1.2.5 step 6 */ + res = RndDtrmHmacSha512Update(state, seed, seedLen, 1); + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Prepare( + IN DCS_RND* rnd + ) +{ + if (rnd != NULL && rnd->Type == RndTypeDtrmHmacSha512) { + return EFI_SUCCESS; + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndDtrmHmacSha512GetBytes( + IN DCS_RND* rnd, + UINT8 *buf, + UINTN len + ) +{ + EFI_TIME seed; + EFI_STATUS res = EFI_NOT_READY; + RND_DTRM_HMAC_SHA512_STATE *state = &rnd->State.HMacSha512; + if (state->ReseedCtr < (1LL << 48)) { + gST->RuntimeServices->GetTime(&seed, NULL); + res = RndDtrmHmacSha512Generate(state, buf, len, (UINT8*)&seed, sizeof(seed)); + state->ReseedCtr++; + } + return res; +} + +EFI_STATUS +RndDtrmHmacSha512Init( + IN DCS_RND* rnd, + IN VOID* Context + ) +{ + EFI_STATUS res = EFI_SUCCESS; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeDtrmHmacSha512; + rnd->GetBytes = RndDtrmHmacSha512GetBytes; + rnd->Prepare = RndDtrmHmacSha512Prepare; + + if (Context != NULL) { + CHAR16* type = (CHAR16*)Context; + if (*type == '_') { + UINT8* data; + UINTN size; + type++; + res = FileLoad(NULL, (CHAR16*)type, &data, &size); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + res = RndDtrmHmacSha512Update(&rnd->State.HMacSha512, data, size, 0); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; + } + } + } + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// Random API +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndInit( + IN UINTN rndType, + IN VOID* Context, + OUT DCS_RND **rnd) +{ + if (rnd != NULL) { + DCS_RND *rndTemp; + rndTemp = (DCS_RND*)MEM_ALLOC(sizeof(DCS_RND)); + if (rndTemp != NULL) { + EFI_STATUS res = EFI_NOT_FOUND; + rndTemp->Type = (UINT32)rndType; + switch (rndType) { + case RndTypeFile: + res = RndFileInit(rndTemp, Context); + break; + case RndTypeRDRand: + res = RndRDRandInit(rndTemp, Context); + break; + case RndTypeDtrmHmacSha512: + res = RndDtrmHmacSha512Init(rndTemp, Context); + break; + } + if (EFI_ERROR(res)) { + MEM_FREE(rndTemp); + return res; + } + *rnd = rndTemp; + return res; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndGetBytes( + UINT8 *buf, + UINTN len) +{ + if (gRnd != NULL) { + return gRnd->GetBytes(gRnd, buf, len); + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndPreapare() +{ + if (gRnd != NULL) { + return gRnd->Prepare(gRnd); + } + return EFI_NOT_READY; +} + +UINT64 gRndHeaderSign = RND_HEADER_SIGN; + +EFI_STATUS +RndSave( + IN DCS_RND *rnd, + OUT DCS_RND_SAVED **rndSaved + ) +{ + EFI_STATUS res = EFI_NOT_READY; + DCS_RND_SAVED *RndSaved; + UINT32 crc; + if (rnd != NULL && rndSaved != NULL && rnd->Type != RndTypeFile) { + RndSaved = MEM_ALLOC(sizeof(DCS_RND_SAVED)); + if (RndSaved != NULL) { + RndSaved->Size = sizeof(DCS_RND_SAVED); + CopyMem(&RndSaved->State, &rnd->State, sizeof(DCS_RND_STATE)); + RndSaved->Type = rnd->Type; + RndSaved->Sign = gRndHeaderSign; + gST->RuntimeServices->GetTime(&RndSaved->SavedAt, NULL); + res = gBS->CalculateCrc32(RndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res)) { + MEM_FREE(RndSaved); + return res; + } + RndSaved->CRC = crc; + *rndSaved = RndSaved; + } + } + return res; +} + +EFI_STATUS +RndLoad( + IN DCS_RND_SAVED *rndSaved, + OUT DCS_RND **rndOut + ) { + EFI_STATUS res = EFI_SUCCESS; + UINT32 crc; + UINT32 crcSaved; + + crcSaved = rndSaved->CRC; + rndSaved->CRC = 0; + res = gBS->CalculateCrc32(rndSaved, sizeof(DCS_RND_SAVED), &crc); + if (EFI_ERROR(res) || crc != crcSaved || rndSaved->Sign != gRndHeaderSign) { + return EFI_CRC_ERROR; + } + res = RndInit(rndSaved->Type, NULL, rndOut); + if (!EFI_ERROR(res)) { + CopyMem(&((*rndOut)->State), &rndSaved->State, sizeof(DCS_RND_STATE)); + } + return res; +} diff --git a/Library/DcsCfgLib/GptEdit.c b/Library/DcsCfgLib/GptEdit.c new file mode 100644 index 0000000..702ce5d --- /dev/null +++ b/Library/DcsCfgLib/GptEdit.c @@ -0,0 +1,935 @@ +/** @file +GPT actions + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +EFI_GUID gEfiPartTypeMsReservedPartGuid = EFI_PART_TYPE_MS_RESERVED_PART_GUID; +EFI_GUID gEfiPartTypeBasicDataPartGuid = EFI_PART_TYPE_BASIC_DATA_PART_GUID; +EFI_GUID gEfiPartTypeMsRecoveryPartGuid = EFI_PART_TYPE_MS_RECOVERY_PART_GUID; + +UINT64 gDcsDiskEntryListHeaderID = DCS_DISK_ENTRY_LIST_HEADER_SIGN; +UINT64 gDcsDiskEntryPwdCacheID = DCS_DEP_PWD_CACHE_SIGN; + +DCS_DISK_ENTRY_LIST *DeList = NULL; + +UINT8 *CryptoHeader = NULL; + +EFI_PARTITION_TABLE_HEADER *GptMainHdr = NULL; +EFI_PARTITION_ENTRY *GptMainEntrys = NULL; +EFI_PARTITION_TABLE_HEADER *GptAltHdr = NULL; +EFI_PARTITION_ENTRY *GptAltEntrys = NULL; + +UINT32 DiskIdMbr = 0; +EFI_GUID DiskIdGpt = EFI_PART_TYPE_UNUSED_GUID; +DCS_DISK_ENTRY_DISKID DeDiskId; + +DCS_DEP_EXEC *DeExecParams = NULL; + +DCS_DEP_PWD_CACHE *DePwdCache = NULL; + +DCS_RND_SAVED *DeRndSaved; + +EFI_BLOCK_IO_PROTOCOL* BlockIo = NULL; +CONST CHAR16* DcsDiskEntrysFileName = L"DcsDiskEntrys"; + +EFI_PARTITION_ENTRY DcsHidePart; + +UINTN BootPartIdx; +UINTN MirrorPartIdx; + +////////////////////////////////////////////////////////////////////////// +// Partitions +////////////////////////////////////////////////////////////////////////// + + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Size The size of the table +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrcAltSize( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + UINT32 Crc; + UINT32 OrgCrc; + EFI_STATUS Status; + + Crc = 0; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + + if ((MaxSize != 0) && (Size > MaxSize)) { + return FALSE; + } + // + // clear old crc from header + // + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc); + if (EFI_ERROR(Status)) { + return FALSE; + } + // + // set results + // + Hdr->CRC32 = OrgCrc; + + return (BOOLEAN)(OrgCrc == Crc); +} + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrc( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr); +} + +EFI_STATUS +GptCheckEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return EFI_CRC_ERROR; + } + Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR; + return Status; +} + +EFI_STATUS +GptUpdateCRC( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->PartitionEntryArrayCRC32 = Crc; + PartHeader->Header.CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->Header.CRC32 = Crc; + return Status; +} + +/** +Read GPT +Check if the CRC field in the Partition table header is valid +for Partition entry array. + +@param[in] DiskIo Disk Io Protocol. +@param[in] PartHeader Partition table header structure + +@retval EFI_SUCCESS the CRC is valid +**/ +EFI_STATUS +GptReadEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + OUT EFI_PARTITION_ENTRY **Entrys + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + + // + // Read the EFI Partition Entries + // + Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + Status = BlockIo->ReadBlocks( + BlockIo, + BlockIo->Media->MediaId, + PartHeader->PartitionEntryLBA, + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR(Status)) { + MEM_FREE(Ptr); + return Status; + } + + *Entrys = (EFI_PARTITION_ENTRY*)Ptr; + return GptCheckEntryArray(PartHeader, *Entrys); +} + +EFI_STATUS +GptReadHeader( + IN EFI_LBA HeaderLba, + OUT EFI_PARTITION_TABLE_HEADER **PartHeader + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + UINT32 MediaId; + + BlockSize = BlockIo->Media->BlockSize; + MediaId = BlockIo->Media->MediaId; + PartHdr = MEM_ALLOC(BlockSize); + + res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr); + if (EFI_ERROR(res)) { + MEM_FREE(PartHdr); + return res; + } + + // Check header + if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(BlockSize, &PartHdr->Header) || + PartHdr->MyLBA != HeaderLba || + (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) + ) { + MEM_FREE(PartHdr); + return EFI_CRC_ERROR; + } + *PartHeader = PartHdr; + return EFI_SUCCESS; +} + +VOID +GptPrint( + IN EFI_PARTITION_TABLE_HEADER *PartHdr, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_PARTITION_ENTRY *Entry; + UINTN index; + if (PartHdr == NULL) { + ERR_PRINT(L"No GPT is loaded\n"); + return; + } + Entry = Entrys; + for (index = 0; index < PartHdr->NumberOfPartitionEntries; ++index, ++Entry) { + if (CompareGuid(&Entry->PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + OUT_PRINT(L"%H%02d%N I:%g T:%g [%lld, %lld] %s\n", + index, + &Entry->UniquePartitionGUID, + &Entry->PartitionTypeGUID, + Entry->StartingLBA, + Entry->EndingLBA, + &Entry->PartitionName + ); + } +} + +EFI_STATUS +GptLoadFromDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + InitBio(); + + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + res = GptReadHeader(1, &GptMainHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read main GPT header: %r\n", res); + goto error; + } + + res = GptReadHeader(GptMainHdr->AlternateLBA, &GptAltHdr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read alt GPT header: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptMainHdr, &GptMainEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT error: %r\n", res); + goto error; + } + + res = GptReadEntryArray(GptAltHdr, &GptAltEntrys); + // Read GPT + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT error: %r\n", res); + goto error; + } + + CryptoHeader = MEM_ALLOC(512); + if (CryptoHeader == NULL) { + ERR_PRINT(L"Can't alloc CryptoHeader\n"); + res = EFI_BUFFER_TOO_SMALL; + goto error; + } + + // Load disk IDs + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't MBR \n"); + goto error; + } + + SetMem(&DeDiskId, sizeof(DeDiskId), 0); + DeDiskId.Type = DE_DISKID; + CopyMem(&DeDiskId.MbrID, &CryptoHeader[0x1b8], sizeof(DiskIdMbr)); + CopyMem(&DeDiskId.GptID, &GptMainHdr->DiskGUID, sizeof(DiskIdGpt)); + + // Load crypto header + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 62, 512, CryptoHeader); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Can't read CryptoHeader\n"); + goto error; + } + + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + CHAR16* defExec = L"\\EFI\\Microsoft\\Boot\\Bootmgfw.efi"; + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + ZeroMem(DeExecParams, sizeof(*DeExecParams)); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + CopyMem(&DeExecParams->ExecCmd, defExec, (StrLen(defExec) + 1 ) * 2); + break; + } + } + return res; + +error: + MEM_FREE(GptMainHdr); + MEM_FREE(GptMainEntrys); + MEM_FREE(GptAltHdr); + MEM_FREE(GptAltEntrys); + MEM_FREE(CryptoHeader); + return res; +} + +VOID +DeListPrint() { + OUT_PRINT(L"Diskid %08x, %g\n", DeDiskId.MbrID, &DeDiskId.GptID); + if (DeExecParams != NULL) { + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + } + if (DePwdCache != NULL) { + OUT_PRINT(L"PwdCache %d\n", DePwdCache->Count); + } + if (DeRndSaved != NULL) { + OUT_PRINT(L"Rnd %d\n", DeRndSaved->Type); + } + GptPrint(GptMainHdr, GptMainEntrys); +} + +#define DeList_UPDATE_BEGIN(Data, DEType, Index, Len) \ + if (Data != NULL) { \ + DeData[Index] = Data; \ + DeList->DE[Index].Type = DEType; \ + DeList->DE[Index].Offset = Offset; \ + DeList->DE[Index].Length = Len; \ + Offset += ((Len + 511) >> 9) << 9; + +#define DeList_UPDATE_END \ + } + +VOID +DeListSaveToFile() { + EFI_STATUS res = EFI_SUCCESS; + UINT32 Offset; + VOID* DeData[DE_IDX_TOTAL]; + UINT8* pad512buf = NULL; + + ZeroMem(DeData, sizeof(DeData)); + + res = EFI_BUFFER_TOO_SMALL; + DeList = MEM_ALLOC(sizeof(*DeList)); + if (DeList == NULL) { + ERR_PRINT(L"Can't alloc DeList\n"); + goto error; + } + + pad512buf = MEM_ALLOC(512); + if (pad512buf == NULL) { + ERR_PRINT(L"No memory\n"); + goto error; + } + + DeList->Signature = DCS_DISK_ENTRY_LIST_HEADER_SIGN; + DeList->HeaderSize = sizeof(*DeList); + DeList->Count = DE_IDX_TOTAL; + Offset = 0; + + DeList_UPDATE_BEGIN(CryptoHeader, DE_Sectors, DE_IDX_CRYPTOHEADER, 512) + DeList->DE[DE_IDX_CRYPTOHEADER].Sectors.Start = 62 * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeList, DE_List, DE_IDX_LIST, 512) + DeList_UPDATE_END + + CopyMem(&DeList->DE[DE_IDX_DISKID], &DeDiskId, sizeof(DeDiskId)); + + DeList_UPDATE_BEGIN(GptMainHdr, DE_Sectors, DE_IDX_MAINGPTHDR, 512) + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start = GptMainHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptMainEntrys, DE_Sectors, DE_IDX_MAINGPTENTRYS, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Start = GptMainHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltHdr, DE_Sectors, DE_IDX_ALTGPTHDR, 512) + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start = GptAltHdr->MyLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(GptAltEntrys, DE_Sectors, DE_IDX_ALTGPTENTRYS, GptAltHdr->NumberOfPartitionEntries * GptAltHdr->SizeOfPartitionEntry) + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Start = GptAltHdr->PartitionEntryLBA * 512; + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeExecParams, DE_ExecParams, DE_IDX_EXEC, sizeof(*DeExecParams)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DePwdCache, DE_PwdCache, DE_IDX_PWDCACHE, sizeof(*DePwdCache)) + DeList_UPDATE_END + + DeList_UPDATE_BEGIN(DeRndSaved, DE_Rnd, DE_IDX_RND, sizeof(*DeRndSaved)) + DeList_UPDATE_END + + DeList->DataSize = Offset; + res = gBS->CalculateCrc32(DeList, 512, &DeList->CRC32); + if (EFI_ERROR(res)) { + ERR_PRINT(L"CRC: %r\n", res); + goto error; + } + { + EFI_FILE* file; + UINTN i; + + FileDelete(NULL, (CHAR16*)DcsDiskEntrysFileName); + res = FileOpen(NULL, (CHAR16*)DcsDiskEntrysFileName, &file, EFI_FILE_MODE_READ | EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE, 0); + if (EFI_ERROR(res)) { + ERR_PRINT(L"File: %r\n", res); + goto error; + } + for (i = 0; i < DeList->Count; ++i) { + if (DeData[i] != 0 && DeList->DE[i].Type != DE_DISKID) { + UINTN len; + UINTN pad; + len = (UINTN)DeList->DE[i].Length; + pad = (((len + 511) >> 9) << 9) - len; + res = FileWrite(file, DeData[i], &len, NULL); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + goto error; + } + if (pad > 0) { + res = FileWrite(file, pad512buf, &pad, NULL); + } + } + } + FileClose(file); + } + +error: + MEM_FREE(DeList); + MEM_FREE(pad512buf); +} + +EFI_STATUS +DeListZero() { + if (DePwdCache != NULL) { + DePwdCache = AskConfirm("Remove passwords cache?", 1) ? NULL : DePwdCache; + } + if (DeExecParams != NULL) { + DeExecParams = AskConfirm("Remove exec?", 1) ? NULL : DeExecParams; + } + if (DeRndSaved != NULL) { + DeRndSaved = AskConfirm("Remove rnd?", 1) ? NULL : DeRndSaved; + } + if (GptMainHdr != NULL) { + if (AskConfirm("Remove GPT?", 1)) { + GptMainHdr = NULL; + GptMainEntrys = NULL; + GptAltHdr = NULL; + GptAltEntrys = NULL; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListParseSaved( + IN UINT8 *DeBuffer + ) +{ + EFI_STATUS res = EFI_SUCCESS; + CryptoHeader = DeBuffer; + DeList = (DCS_DISK_ENTRY_LIST*)(DeBuffer + 512); + CopyMem(&DeDiskId, &DeList->DE[DE_IDX_DISKID], sizeof(DeDiskId)); + + if (DeList->DE[DE_IDX_EXEC].Type == DE_ExecParams) { + DeExecParams = (DCS_DEP_EXEC *)(DeBuffer + DeList->DE[DE_IDX_EXEC].Offset); + } + + if (DeList->DE[DE_IDX_RND].Type == DE_Rnd) { + DeRndSaved = (DCS_RND_SAVED *)(DeBuffer + DeList->DE[DE_IDX_RND].Offset); + if ((UINTN)DeList->DE[DE_IDX_RND].Length != sizeof(*DeRndSaved)) { + return EFI_CRC_ERROR; + } + } + + if (DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) { + UINT32 crc = 0; + UINT32 crcSaved = 0; + DePwdCache = (DCS_DEP_PWD_CACHE*)(DeBuffer + DeList->DE[DE_IDX_PWDCACHE].Offset); + if (DePwdCache->Sign != gDcsDiskEntryPwdCacheID) { + return EFI_CRC_ERROR; + } + crcSaved = DePwdCache->CRC; + DePwdCache->CRC = 0; + res = gBS->CalculateCrc32(DePwdCache, sizeof(*DePwdCache), &crc); + if (crc != crcSaved) { + ERR_PRINT(L"Pwd cache crc\n"); + return EFI_CRC_ERROR; + } + DePwdCache->CRC = crcSaved; + } + + if (DeList->DE[DE_IDX_MAINGPTHDR].Type == DE_Sectors) { + GptMainHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Offset); + if ((GptMainHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptMainHdr->Header) || + (DeList->DE[DE_IDX_MAINGPTHDR].Sectors.Start >> 9) != GptMainHdr->MyLBA || + (GptMainHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Main GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_MAINGPTENTRYS].Type == DE_Sectors) { + GptMainEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_MAINGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main GPT: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTHDR].Type == DE_Sectors) { + GptAltHdr = (EFI_PARTITION_TABLE_HEADER*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Offset); + if ((GptAltHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(512, &GptAltHdr->Header) || + (DeList->DE[DE_IDX_ALTGPTHDR].Sectors.Start >> 9) != GptAltHdr->MyLBA || + (GptAltHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY))) { + res = EFI_CRC_ERROR; + ERR_PRINT(L"Alt GPT header: %r\n", res); + return res; + } + } + + if (DeList->DE[DE_IDX_ALTGPTENTRYS].Type == DE_Sectors) { + GptAltEntrys = (EFI_PARTITION_ENTRY*)(DeBuffer + DeList->DE[DE_IDX_ALTGPTENTRYS].Sectors.Offset); + res = GptCheckEntryArray(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt GPT: %r\n", res); + return res; + } + } + + if (GptMainEntrys != NULL && GptAltEntrys != NULL && GptMainHdr != NULL) { + if (CompareMem(GptMainEntrys, GptAltEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry) != 0) { + ERR_PRINT(L"Alt GPT != Main GPT\n", ); + return EFI_CRC_ERROR; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListLoadFromFile() +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN len; + UINT8 *DeBuffer; + + InitFS(); + res = FileLoad(NULL, (CHAR16*)DcsDiskEntrysFileName, &DeBuffer, &len); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Load: %r\n", res); + return res; + } + return DeListParseSaved(DeBuffer); +} + +EFI_STATUS +DeListApplySectorsToDisk( + IN UINTN diskIdx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + UINT8 *Mbr; + + InitBio(); + InitFS(); + BlockIo = EfiGetBlockIO(gBIOHandles[diskIdx]); + if (BlockIo == NULL) { + ERR_PRINT(L"Can't open device\n"); + return EFI_NOT_FOUND; + } + + // Compare MBR disk ID + Mbr = MEM_ALLOC(512); + if (Mbr == NULL) { + ERR_PRINT(L"Can't load MBR\n"); + return EFI_BUFFER_TOO_SMALL; + } + + res = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, 0, 512, Mbr); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Read MBR: %r\n", res); + MEM_FREE(Mbr); + return res; + } + + if (CompareMem(Mbr + 0x1b8, &DeDiskId.MbrID, sizeof(UINT32)) != 0) { + ERR_PRINT(L"Disk MBR ID %08x != %08x \n", *((UINT32*)(Mbr + 0x1b8)), DeDiskId.MbrID); + MEM_FREE(Mbr); + return res; + } + MEM_FREE(Mbr); + + // Save sectors + for (i = 0; i < DeList->Count; ++i) { + if (DeList->DE[i].Type == DE_Sectors) { + OUT_PRINT(L"%d Write: %lld, %lld\n", i, DeList->DE[i].Sectors.Start, DeList->DE[i].Sectors.Length); + res = BlockIo->WriteBlocks(BlockIo, BlockIo->Media->MediaId, + DeList->DE[i].Sectors.Start >> 9, + (UINTN)DeList->DE[i].Sectors.Length, + CryptoHeader + DeList->DE[i].Sectors.Offset); + } + if (EFI_ERROR(res)) { + ERR_PRINT(L"Write: %r\n", res); + return res; + } + } + return EFI_SUCCESS; +} + + +EFI_STATUS +GptSyncMainAlt() { + EFI_STATUS res = EFI_SUCCESS; + // Duplicate parts array + CopyMem(GptAltEntrys, GptMainEntrys, GptMainHdr->NumberOfPartitionEntries * GptMainHdr->SizeOfPartitionEntry); + + res = GptUpdateCRC(GptMainHdr, GptMainEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Main CRC: %r\n", res); + return res; + } + GptUpdateCRC(GptAltHdr, GptAltEntrys); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Alt CRC: %r\n", res); + return res; + } + return res; +} + +VOID +GptSqueze() { + UINTN i = 0; + UINTN emptyIdx = 0; + UINTN count; + count = GptMainHdr->NumberOfPartitionEntries; + while (i < count) { + if (CompareGuid(&GptMainEntrys[i].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + ++i; + continue; + } + else { + if (emptyIdx != i) { + CopyMem(&GptMainEntrys[emptyIdx], &GptMainEntrys[i], sizeof(*GptMainEntrys) * (count - i)); + SetMem(&GptMainEntrys[i], sizeof(*GptMainEntrys), 0); + } + ++emptyIdx; + i = emptyIdx; + } + } +} + +VOID +GptSort() { + UINTN i = 0; + UINTN j = 0; + UINTN n = 0; + UINTN count; + EFI_PARTITION_ENTRY tmp; + BOOLEAN swapped = TRUE; + count = GptMainHdr->NumberOfPartitionEntries; + + while (n < count) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + break; + } + ++n; + } + + while (swapped) { + swapped = FALSE; + j++; + for (i = 0; i < n - j; ++i) { + if (GptMainEntrys[i].StartingLBA > GptMainEntrys[i + 1].StartingLBA) { + CopyMem(&tmp, &GptMainEntrys[i], sizeof(tmp)); + CopyMem(&GptMainEntrys[i], &GptMainEntrys[i + 1], sizeof(tmp)); + CopyMem(&GptMainEntrys[i + 1], &tmp, sizeof(tmp)); + swapped = TRUE; + } + } + } +} + +// Checks if two regions overlap (borders are parts of regions) +BOOLEAN +IsRegionOverlap(UINT64 start1, UINT64 end1, UINT64 start2, UINT64 end2) { + return (start1 < start2) ? (end1 >= start2) : (start1 <= end2); +} + +VOID +GptHideParts() { + UINTN count; + UINTN n; + BOOLEAN set = FALSE; + count = GptMainHdr->NumberOfPartitionEntries; + + for (n = 0; n < count; ++n) { + if (CompareGuid(&GptMainEntrys[n].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + if (IsRegionOverlap( + GptMainEntrys[n].StartingLBA, GptMainEntrys[n].EndingLBA, + DcsHidePart.StartingLBA, DcsHidePart.EndingLBA)) { + if (set) { + SetMem(&GptMainEntrys[n], sizeof(*GptMainEntrys), 0); + } + else { + set = TRUE; + CopyMem(&GptMainEntrys[n], &DcsHidePart, sizeof(*GptMainEntrys)); + } + } + } + GptSqueze(); + GptSort(); + GptSyncMainAlt(); +} + +BOOLEAN +GptAskGUID( + IN char* prompt, + IN OUT EFI_GUID* guid) +{ + CHAR8 buf[128]; + UINTN len = 0; + EFI_GUID result; + BOOLEAN ok = TRUE; + OUT_PRINT(L"[%g] %a", guid, prompt); + + // (msr, data, oem, efi, del or guid) + GetLine(&len, NULL, buf, sizeof(buf), 1); + if (AsciiStrCmp(buf, "msr") == 0) { + CopyMem(guid, &gEfiPartTypeMsReservedPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "data") == 0) { + CopyMem(guid, &gEfiPartTypeBasicDataPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "wre") == 0) { + CopyMem(guid, &gEfiPartTypeMsRecoveryPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "efi") == 0) { + CopyMem(guid, &gEfiPartTypeSystemPartGuid, sizeof(EFI_GUID)); + } + else if (AsciiStrCmp(buf, "del") == 0) { + CopyMem(guid, &gEfiPartTypeUnusedGuid, sizeof(EFI_GUID)); + } + else if (len == 0) { + ok = TRUE; + } + else { + ok = AsciiStrToGuid(&result, buf); + if (ok) { + CopyMem(guid, &result, sizeof(result)); + } + } + return ok; +} + +EFI_STATUS +DeListExecEdit() +{ + UINTN len; + UINTN i; + CHAR16 execCmd[FIELD_SIZEOF(DCS_DEP_EXEC, ExecCmd)]; + if (DeExecParams == NULL) { + DeExecParams = MEM_ALLOC(sizeof(*DeExecParams)); + } + OUT_PRINT(L"Exec %g, %s\n", &DeExecParams->ExecPartGuid, &DeExecParams->ExecCmd); + if (GptMainHdr != NULL) { + for (i = 0; i < GptMainHdr->NumberOfPartitionEntries; ++i) { + EFI_PARTITION_ENTRY *part; + part = &GptMainEntrys[i]; + if (CompareMem(&gEfiPartTypeSystemPartGuid, &part->PartitionTypeGUID, sizeof(EFI_GUID)) == 0) { + if (CompareMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)) != 0) { + OUT_PRINT(L"EFI partition missmatched, updated"); + CopyMem(&DeExecParams->ExecPartGuid, &part->UniquePartitionGUID, sizeof(EFI_GUID)); + } + break; + } + } + } + while (!GptAskGUID("\n\r:",(EFI_GUID*) &DeExecParams->ExecPartGuid)); + OUT_PRINT(L"[%s]\n\r:", &DeExecParams->ExecCmd); + GetLine(&len, execCmd, NULL, sizeof(execCmd) / 2 - 1, 1); + if (len != 0) { + CopyMem(&DeExecParams->ExecCmd, execCmd, sizeof(execCmd)); + } + return EFI_SUCCESS; +} + +EFI_STATUS +DeListPwdCacheEdit() +{ + UINTN count; + UINTN len; + UINTN i; + UINT32 crc = 0; + Password pwd; + UINTN pim; + EFI_STATUS res; + if (DePwdCache == NULL) { + DePwdCache = MEM_ALLOC(sizeof(*DePwdCache)); + DePwdCache->Sign = DCS_DEP_PWD_CACHE_SIGN; + } + OUT_PRINT(L"PwdCache\n"); + do { + count = (uint32)AskUINTN("Count[0-4]:", DePwdCache->Count); + } while (count > 4); + DePwdCache->Count = (uint32)count; + for (i = 0; i < 4; ++i) { + ZeroMem(&pwd, sizeof(pwd)); + pim = 0; + if (i < DePwdCache->Count) { + OUT_PRINT(L"%H%d%N [%a] [%d]\n:", i, DePwdCache->Pwd[i].Text, DePwdCache->Pim[i]); + GetLine(&len, NULL, pwd.Text, MAX_PASSWORD, 1); + if (len != 0) { + pwd.Length = (uint32)len; + pim = (uint32)AskUINTN("Pim:", DePwdCache->Pim[i]); + } + } + DePwdCache->Pim[i] = (uint32)pim; + CopyMem(&DePwdCache->Pwd[i], &pwd, sizeof(pwd)); + } + ZeroMem(&DePwdCache->pad, sizeof(DePwdCache->pad)); + DePwdCache->CRC = 0; + res =gBS->CalculateCrc32(DePwdCache, 512, &crc); + DePwdCache->CRC = crc; + return res; +} + +EFI_STATUS +DeListRndSave() +{ + EFI_STATUS res; + if (gRnd == NULL) { + DeRndSaved = NULL; + return EFI_SUCCESS; + } + res = RndSave(gRnd,&DeRndSaved); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", DeRndSaved->Type); + return res; +} + +EFI_STATUS +DeListRndLoad() +{ + EFI_STATUS res = EFI_NOT_FOUND; + if (DeRndSaved != NULL) { + res = RndLoad(DeRndSaved,&gRnd); + if (EFI_ERROR(res)) { + ERR_PRINT(L"Random: %r\n", res); + return res; + } + OUT_PRINT(L"Rnd selected:%d\n", gRnd->Type); + } + return res; +} diff --git a/Library/GraphLib/EfiGraph.c b/Library/GraphLib/EfiGraph.c new file mode 100644 index 0000000..b8e8e2e --- /dev/null +++ b/Library/GraphLib/EfiGraph.c @@ -0,0 +1,670 @@ +/** @file +Graph library + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include +#include +#include + +EFI_HANDLE* gGraphHandles = NULL; +UINTN gGraphCount = 0; + +EFI_GRAPHICS_OUTPUT_PROTOCOL* gGraphOut = NULL; + +EFI_STATUS +InitGraph() { + EFI_STATUS res; + res = EfiGetHandles(ByProtocol, &gEfiGraphicsOutputProtocolGuid, 0, &gGraphHandles, &gGraphCount); + if (gGraphCount > 0) { + GraphGetIO(gGraphHandles[gGraphCount - 1], &gGraphOut); + } + return res; +} + +EFI_STATUS +GraphGetIO( + IN EFI_HANDLE Handle, + OUT EFI_GRAPHICS_OUTPUT_PROTOCOL** io + ) { + if (!io) { + return EFI_INVALID_PARAMETER; + } + return gBS->HandleProtocol(Handle, &gEfiGraphicsOutputProtocolGuid, (VOID**)io); +} + +EFI_STATUS +GraphGetModeInfo( + IN UINTN mode, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **info, + OUT UINTN* szInfo + ) { + if (!info || !gGraphOut || mode > gGraphOut->Mode->MaxMode) { + return EFI_INVALID_PARAMETER; + } + return gGraphOut->QueryMode(gGraphOut, (UINT32)mode, szInfo, info); +} + + +////////////////////////////////////////////////////////////////////////// +// Screen +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +ScreenGetSize( + OUT UINTN *Height, + OUT UINTN *Width + ) +{ + if (gGraphOut == NULL) return EFI_INVALID_PARAMETER; + *Height = gGraphOut->Mode->Info->VerticalResolution; + *Width = gGraphOut->Mode->Info->HorizontalResolution; + return EFI_SUCCESS; +} + +EFI_STATUS ScreenFillRect( + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *color, + IN UINTN x, + IN UINTN y, + IN UINTN width, + IN UINTN height + ) +{ + if (gGraphOut == NULL) return EFI_INVALID_PARAMETER; + + return gGraphOut->Blt(gGraphOut, color, EfiBltVideoFill, 0, 0, x, y, width, height, width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +EFI_STATUS ScreenDrawBlt( + IN BLT_HEADER *blt, + IN UINTN x, + IN UINTN y + ) +{ + return gGraphOut->Blt(gGraphOut, blt->Pixels, EfiBltBufferToVideo, 0, 0, x, y, blt->Width, blt->Height, blt->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +EFI_STATUS ScreenUpdateDirty( + IN BLT_HEADER *bltScreen + ) +{ + EFI_STATUS res = EFI_SUCCESS; + if (bltScreen->Dirty.top != bltScreen->Dirty.bottom || bltScreen->Dirty.left != bltScreen->Dirty.right) { + res = gGraphOut->Blt(gGraphOut, bltScreen->Pixels, EfiBltBufferToVideo, + bltScreen->Dirty.top, bltScreen->Dirty.left, // Source x,y + bltScreen->Dirty.top, bltScreen->Dirty.left, // Dest x,y + bltScreen->Dirty.right - bltScreen->Dirty.left + 1, bltScreen->Dirty.bottom - bltScreen->Dirty.top + 1, // width , height + bltScreen->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + SetMem(&bltScreen->Dirty, sizeof(bltScreen->Dirty), 0); + } + return res; +} + +EFI_STATUS +ScreenSaveBlt( + OUT BLT_HEADER **bltScreen + ) +{ + UINTN height; + UINTN width; + EFI_STATUS res; + BLT_HEADER* blt; + if (!bltScreen) return EFI_INVALID_PARAMETER; + res = ScreenGetSize(&height, &width); + if (EFI_ERROR(res)) return res; + blt = (BLT_HEADER*)MEM_ALLOC(sizeof(BLT_HEADER) + height * width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + blt->Height = (UINT32)height; + blt->Width = (UINT32)width; + *bltScreen = blt; + return gGraphOut->Blt(gGraphOut, blt->Pixels, EfiBltVideoToBltBuffer, 0, 0, 0, 0, blt->Width, blt->Height, blt->Width * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); +} + +////////////////////////////////////////////////////////////////////////// +// Colors +////////////////////////////////////////////////////////////////////////// + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlack = { 0,0,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorWhite = { 255,255,255,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorBlue = { 255,0,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGreen = { 0,255,0,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorRed = { 0,0,255,0 }; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL gColorGray = { 128,128,128,0 }; +DRAW_CONTEXT gDrawContext = { { 255, 255, 255, 0 }, DrawOpSet, 0xFFFFFFFF, 128, { 128,128,128, 0}, NULL }; +INT32 gBrush3[5*2] = { -1,0, 1,0, 0,1, 0,-1, 0,0 }; + +////////////////////////////////////////////////////////////////////////// +// Blt +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +BltDrawBlt( + IN OUT BLT_HEADER* canvas, + IN BLT_HEADER* blt, + IN UINTN x, + IN UINTN y + ) { + UINTN row, col; + DRAW_CONTEXT ctx; + ctx.Op = DrawOpSet; + ctx.Brush = NULL; + for (row = 0; row < blt->Height; ++row) { + for (col = 0; col < blt->Width; ++col) { + ctx.Color = blt->Pixels[col + row * blt->Width]; + BltPoint(canvas, &ctx, x + col, y + row); + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +RectMarkDirty( + IN OUT PRECT rect, + IN UINTN x, + IN UINTN y + ) { + if (!rect) return EFI_INVALID_PARAMETER; + if (rect->top > y) rect->top = (UINT32)y; + if (rect->bottom < y) rect->bottom = (UINT32)y; + if (rect->left > x) rect->left = (UINT32)x; + if (rect->right < x) rect->right = (UINT32)x; + return EFI_SUCCESS; +} + + +EFI_STATUS +BltPointSingle( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN UINTN x, + IN UINTN y + ) { + UINTN pos; + if (!blt || x >= blt->Width || y >= blt->Height) return EFI_INVALID_PARAMETER; + RectMarkDirty(&blt->Dirty, x, y); + pos = x + y * blt->Width; + if (!draw) draw = &gDrawContext; + switch (draw->Op) + { + case DrawOpClear: + *(UINT32*)&blt->Pixels[pos] &= ~(*(UINT32*)&draw->Color); + break; + case DrawOpXor: + *(UINT32*)&blt->Pixels[pos] ^= *(UINT32*)&draw->Color; + break; + case DrawOpOr: + *(UINT32*)&blt->Pixels[pos] |= *(UINT32*)&draw->Color; + break; + case DrawOpSet: + blt->Pixels[pos] = draw->Color; + break; + case DrawOpAlpha: + { + UINT8 val; + val = blt->Pixels[pos].Red; + blt->Pixels[pos].Red = (UINT8)(val + (((draw->AlphaColor.Red - val) * draw->Alpha) >> 8)); + + val = blt->Pixels[pos].Green; + blt->Pixels[pos].Green = (UINT8)(val + (((draw->AlphaColor.Green - val) * draw->Alpha) >> 8)); + + val = blt->Pixels[pos].Blue; + blt->Pixels[pos].Blue = (UINT8)(val + (((draw->AlphaColor.Blue - val) * draw->Alpha) >> 8)); + + break; + } + default: + break; + } + return EFI_SUCCESS; +} + +EFI_STATUS +BltPoint( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN UINTN x, + IN UINTN y + ) { + if (draw->Brush == NULL) return BltPointSingle(blt, draw, x, y); + else + { + INT32* offset = draw->Brush; + do { + BltPointSingle(blt, draw, x + offset[0], y + +offset[1]); + offset += 2; + } while (!(offset[0] == 0 && offset[1] == 0)); + return BltPointSingle(blt, draw, x, y); + } +} + +VOID +BltBox( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + BltLine(blt, draw, x0, y0, x1, y0); + BltLine(blt, draw, x0, y0, x0, y1); + BltLine(blt, draw, x0, y1, x1, y1); + BltLine(blt, draw, x1, y0, x1, y1); +} + +VOID +BltFill( + IN BLT_HEADER* blt, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL fill, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + INT32 x; + INT32 y; + DRAW_CONTEXT ctx; + ctx.Op = DrawOpSet; + ctx.Brush = NULL; + ctx.Color = fill; + for (y = y0; y < y1; ++y) { + for (x = x0; x < x1; ++x) { + BltPoint(blt, &ctx, x, y); + } + } +} + +VOID +BltLine( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x0, + IN INT32 y0, + IN INT32 x1, + IN INT32 y1) +{ + int dx = ABS(x1 - x0), sx = x0 < x1 ? 1 : -1; + int dy = -ABS(y1 - y0), sy = y0 < y1 ? 1 : -1; + UINT32 mask, dmask, cmask; + int err = dx + dy, e2; /* error value e_xy */ + mask = draw ? draw->DashLine : gDrawContext.DashLine; + dmask = mask; + cmask = 32; + for (;;) { /* loop */ + // Dash + if ((dmask & 1) == 1) { + BltPoint(blt, draw, x0, y0); + } + dmask >>= 1; + cmask--; + if (cmask == 0) { + dmask = mask; + cmask = 32; + } + // next point + e2 = 2 * err; + if (e2 >= dy) { /* e_xy+e_x > 0 */ + if (x0 == x1) break; + err += dy; x0 += sx; + } + if (e2 <= dx) { /* e_xy+e_y < 0 */ + if (y0 == y1) break; + err += dx; y0 += sy; + } + } +} + + + +VOID +BltCircle( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 xm, + IN INT32 ym, + IN INT32 r, + IN BOOLEAN fill) +{ + int sx = 1; + int x = -r, y = 0, err = 2 - 2 * r; /* bottom left to top right */ + UINT32 mask, dmask, cmask; + mask = draw ? draw->DashLine : gDrawContext.DashLine; + dmask = mask; + cmask = 32; + do { + if (fill) { + if (sx != x) { + int i; + for (i = ym - y; i <= ym + y; i++) { + BltPoint(blt, draw, xm + x, i); + if( x != 0 ) BltPoint(blt, draw, xm - x, i); + } + sx = x; + } + } else { + if ((dmask & 1) == 1) { + BltPoint(blt, draw, xm - x, ym + y); /* I. Quadrant +x +y */ + BltPoint(blt, draw, xm - y, ym - x); /* II. Quadrant -x +y */ + BltPoint(blt, draw, xm + x, ym - y); /* III. Quadrant -x -y */ + BltPoint(blt, draw, xm + y, ym + x); /* IV. Quadrant +x -y */ + } + dmask >>= 1; + cmask--; + } + if (cmask == 0) { + dmask = mask; + cmask = 32; + } + r = err; + if (r <= y) err += ++y * 2 + 1; /* e_xy+e_y < 0 */ + if (r >= x || err > y) /* e_xy+e_x > 0 or no 2nd y-step */ + err += ++x * 2 + 1; /* -> x-step now */ + } while (x <= 0); +} + +extern __int8 gSimplex_ascii_32_126[95][112]; +VOID +BltText( + IN BLT_HEADER* blt, + IN PDRAW_CONTEXT draw, + IN INT32 x, + IN INT32 y, + IN INT32 scale, // 0..256 reduce 256... enlarge + IN CONST CHAR8 *text) +{ + INT32 posX = x; + INT32 posY = y; + const char *c; + for (c = text; *c; ++c) + { + INT8 ch = *c; + if (ch >= 32 && ch <= 126) { + INT8 *it = gSimplex_ascii_32_126[ch - 32]; + INT32 nvtcs = *it++; + INT32 spacing = *it++; + INT32 fromX = -1; + INT32 fromY = -1; + INTN i; + for (i = 0; i < nvtcs; ++i) { + INT32 toX = *it++; + INT32 toY = *it++; + if ((fromX != -1 || fromY != -1) && (toX != -1 || toY != -1)) { + BltLine( + blt, draw, + posX + ((fromX * scale) >> 8), posY + (((25 - fromY) * scale) >> 8), + posX + ((toX * scale) >> 8), posY + (((25 - toY) * scale) >> 8)); + } + fromX = toX; + fromY = toY; + } + posX += (spacing * scale) >> 8; + } + // Next line + if (ch == '\n') { + posX = x; + posY += 30 * scale >> 8; + } + } +} + +////////////////////////////////////////////////////////////////////////// +// Bmp +////////////////////////////////////////////////////////////////////////// + +#pragma pack(1) +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} BMP_COLOR_MAP; + +typedef struct { + CHAR8 CharB; + CHAR8 CharM; + UINT32 Size; + UINT16 Reserved[2]; + UINT32 ImageOffset; + UINT32 HeaderSize; + UINT32 PixelWidth; + UINT32 PixelHeight; + UINT16 Planes; // Must be 1 + UINT16 BitPerPixel; // 1, 4, 8, or 24 + UINT32 CompressionType; + UINT32 ImageSize; // Compressed image size in bytes + UINT32 XPixelsPerMeter; + UINT32 YPixelsPerMeter; + UINT32 NumberOfColors; + UINT32 ImportantColors; +} BMP_IMAGE_HEADER; +#pragma pack() + +EFI_STATUS BmpGetSize( + IN const unsigned char* BmpImage, + IN UINTN BmpImageSize, + OUT UINTN *Height, + OUT UINTN *Width + ) +{ + BMP_IMAGE_HEADER *BmpHeader; + + if (sizeof(BMP_IMAGE_HEADER) > BmpImageSize) { + return EFI_INVALID_PARAMETER; + } + + BmpHeader = (BMP_IMAGE_HEADER *)BmpImage; + + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + // + // Only support BITMAPINFOHEADER format. + // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER + // + if (BmpHeader->HeaderSize != sizeof(BMP_IMAGE_HEADER) - ((UINTN)&(((BMP_IMAGE_HEADER *)0)->HeaderSize))) { + return EFI_UNSUPPORTED; + } + + *Height = BmpHeader->PixelHeight; + *Width = BmpHeader->PixelWidth; + return EFI_SUCCESS; +} + +EFI_STATUS +BmpToBlt( + IN CONST VOID *BmpImage, + IN UINTN BmpImageSize, + OUT BLT_HEADER **blt + ) +{ + UINT8 *Image; + UINT8 *ImageHeader; + BMP_IMAGE_HEADER *BmpHeader; + BMP_COLOR_MAP *BmpColorMap; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt_; + UINT64 BltBufferSize; + UINTN Index; + UINTN Height; + UINTN Width; + UINTN ImageIndex; + UINTN DataSizePerLine; + UINT32 ColorMapNum; + + if (sizeof(BMP_IMAGE_HEADER) > BmpImageSize) { + return EFI_INVALID_PARAMETER; + } + + BmpHeader = (BMP_IMAGE_HEADER *)BmpImage; + + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + // + // Doesn't support compress. + // + if (BmpHeader->CompressionType != 0) { + return EFI_UNSUPPORTED; + } + + // + // Only support BITMAPINFOHEADER format. + // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER + // + if (BmpHeader->HeaderSize != sizeof(BMP_IMAGE_HEADER) - ((UINTN)&(((BMP_IMAGE_HEADER *)0)->HeaderSize))) { + return EFI_UNSUPPORTED; + } + + // + // The data size in each line must be 4 byte alignment. + // + DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3); + BltBufferSize = MultU64x32(DataSizePerLine, BmpHeader->PixelHeight); + if (BltBufferSize > (UINT32)~0) { + return EFI_INVALID_PARAMETER; + } + + if ((BmpHeader->Size != BmpImageSize) || + (BmpHeader->Size < BmpHeader->ImageOffset) || + (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate Color Map offset in the image. + // + Image = (UINT8 *)BmpImage; + BmpColorMap = (BMP_COLOR_MAP *)(Image + sizeof(BMP_IMAGE_HEADER)); + if (BmpHeader->ImageOffset < sizeof(BMP_IMAGE_HEADER)) { + return EFI_INVALID_PARAMETER; + } + + if (BmpHeader->ImageOffset > sizeof(BMP_IMAGE_HEADER)) { + switch (BmpHeader->BitPerPixel) { + case 1: + ColorMapNum = 2; + break; + case 4: + ColorMapNum = 16; + break; + case 8: + ColorMapNum = 256; + break; + default: + ColorMapNum = 0; + break; + } + if (BmpHeader->ImageOffset - sizeof(BMP_IMAGE_HEADER) != sizeof(BMP_COLOR_MAP) * ColorMapNum) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Calculate graphics image data address in the image + // + Image = ((UINT8 *)BmpImage) + BmpHeader->ImageOffset; + ImageHeader = Image; + + BltBufferSize = MultU64x32((UINT64)BmpHeader->PixelWidth, BmpHeader->PixelHeight); + // + // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow + // + if (BltBufferSize > DivU64x32((UINTN)~0, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) { + return EFI_UNSUPPORTED; + } + BltBufferSize = MultU64x32(BltBufferSize, sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); + + *blt = MEM_ALLOC((UINTN)BltBufferSize + sizeof(**blt)); + + (*blt)->Width = BmpHeader->PixelWidth; + (*blt)->Height = BmpHeader->PixelHeight; + + // + // Convert image from BMP to Blt buffer format + // + BltBuffer = (*blt)->Pixels; + for (Height = 0; Height < BmpHeader->PixelHeight; Height++) { + Blt_ = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth]; + for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt_++) { + switch (BmpHeader->BitPerPixel) { + case 1: + // + // Convert 1bit BMP to 24-bit color + // + for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) { + Blt_->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red; + Blt_->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green; + Blt_->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue; + Blt_++; + Width++; + } + + Blt_--; + Width--; + break; + + case 4: + // + // Convert BMP Palette to 24-bit color + // + Index = (*Image) >> 4; + Blt_->Red = BmpColorMap[Index].Red; + Blt_->Green = BmpColorMap[Index].Green; + Blt_->Blue = BmpColorMap[Index].Blue; + if (Width < (BmpHeader->PixelWidth - 1)) { + Blt_++; + Width++; + Index = (*Image) & 0x0f; + Blt_->Red = BmpColorMap[Index].Red; + Blt_->Green = BmpColorMap[Index].Green; + Blt_->Blue = BmpColorMap[Index].Blue; + } + break; + + case 8: + // + // Convert BMP Palette to 24-bit color + // + Blt_->Red = BmpColorMap[*Image].Red; + Blt_->Green = BmpColorMap[*Image].Green; + Blt_->Blue = BmpColorMap[*Image].Blue; + break; + + case 24: + Blt_->Blue = *Image++; + Blt_->Green = *Image++; + Blt_->Red = *Image; + break; + + default: + MEM_FREE(*blt); + *blt = NULL; + return EFI_UNSUPPORTED; + break; + }; + + } + + ImageIndex = (UINTN)(Image - ImageHeader); + if ((ImageIndex % 4) != 0) { + // + // Bmp Image starts each row on a 32-bit boundary! + // + Image = Image + (4 - (ImageIndex % 4)); + } + } + + return EFI_SUCCESS; +} diff --git a/Library/GraphLib/GraphLib.inf b/Library/GraphLib/GraphLib.inf new file mode 100644 index 0000000..8201c82 --- /dev/null +++ b/Library/GraphLib/GraphLib.inf @@ -0,0 +1,43 @@ +## @file +# Graph library +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = GraphLib + MODULE_UNI_FILE = GraphLib.uni + FILE_GUID = 9BD93C5C-7EF7-4B07-A53D-1E84A9F00F2C + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GraphLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + + +[Sources.common] + EfiGraph.c + font.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + +[Protocols] + gEfiGraphicsOutputProtocolGuid diff --git a/Library/GraphLib/font.c b/Library/GraphLib/font.c new file mode 100644 index 0000000..c3ba9b2 --- /dev/null +++ b/Library/GraphLib/font.c @@ -0,0 +1,586 @@ +/** @file +Vector font definition based on Hershey Vector Font + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +__int8 gSimplex_ascii_32_126[95][112] = { + 0,16, /* Ascii 32 */ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,10, /* Ascii 33 */ + 5,21, 5, 7,-1,-1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 34 */ + 4,21, 4,14,-1,-1,12,21,12,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,21, /* Ascii 35 */ + 11,25, 4,-7,-1,-1,17,25,10,-7,-1,-1, 4,12,18,12,-1,-1, 3, 6,17, 6,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 26,20, /* Ascii 36 */ + 8,25, 8,-4,-1,-1,12,25,12,-4,-1,-1,17,18,15,20,12,21, 8,21, 5,20, 3, + 18, 3,16, 4,14, 5,13, 7,12,13,10,15, 9,16, 8,17, 6,17, 3,15, 1,12, 0, + 8, 0, 5, 1, 3, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 31,24, /* Ascii 37 */ + 21,21, 3, 0,-1,-1, 8,21,10,19,10,17, 9,15, 7,14, 5,14, 3,16, 3,18, 4, + 20, 6,21, 8,21,10,20,13,19,16,19,19,20,21,21,-1,-1,17, 7,15, 6,14, 4, + 14, 2,16, 0,18, 0,20, 1,21, 3,21, 5,19, 7,17, 7,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 34,26, /* Ascii 38 */ + 23,12,23,13,22,14,21,14,20,13,19,11,17, 6,15, 3,13, 1,11, 0, 7, 0, 5, + 1, 4, 2, 3, 4, 3, 6, 4, 8, 5, 9,12,13,13,14,14,16,14,18,13,20,11,21, + 9,20, 8,18, 8,16, 9,13,11,10,16, 3,18, 1,20, 0,22, 0,23, 1,23, 2,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 7,10, /* Ascii 39 */ + 5,19, 4,20, 5,21, 6,20, 6,18, 5,16, 4,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,14, /* Ascii 40 */ + 11,25, 9,23, 7,20, 5,16, 4,11, 4, 7, 5, 2, 7,-2, 9,-5,11,-7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,14, /* Ascii 41 */ + 3,25, 5,23, 7,20, 9,16,10,11,10, 7, 9, 2, 7,-2, 5,-5, 3,-7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,16, /* Ascii 42 */ + 8,21, 8, 9,-1,-1, 3,18,13,12,-1,-1,13,18, 3,12,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,26, /* Ascii 43 */ + 13,18,13, 0,-1,-1, 4, 9,22, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,10, /* Ascii 44 */ + 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6,-1, 5,-3, 4,-4,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,26, /* Ascii 45 */ + 4, 9,22, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,10, /* Ascii 46 */ + 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,22, /* Ascii 47 */ + 20,25, 2,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,20, /* Ascii 48 */ + 9,21, 6,20, 4,17, 3,12, 3, 9, 4, 4, 6, 1, 9, 0,11, 0,14, 1,16, 4,17, + 9,17,12,16,17,14,20,11,21, 9,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 4,20, /* Ascii 49 */ + 6,17, 8,18,11,21,11, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,20, /* Ascii 50 */ + 4,16, 4,17, 5,19, 6,20, 8,21,12,21,14,20,15,19,16,17,16,15,15,13,13, + 10, 3, 0,17, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 15,20, /* Ascii 51 */ + 5,21,16,21,10,13,13,13,15,12,16,11,17, 8,17, 6,16, 3,14, 1,11, 0, 8, + 0, 5, 1, 4, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 6,20, /* Ascii 52 */ + 13,21, 3, 7,18, 7,-1,-1,13,21,13, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,20, /* Ascii 53 */ + 15,21, 5,21, 4,12, 5,13, 8,14,11,14,14,13,16,11,17, 8,17, 6,16, 3,14, + 1,11, 0, 8, 0, 5, 1, 4, 2, 3, 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,20, /* Ascii 54 */ + 16,18,15,20,12,21,10,21, 7,20, 5,17, 4,12, 4, 7, 5, 3, 7, 1,10, 0,11, + 0,14, 1,16, 3,17, 6,17, 7,16,10,14,12,11,13,10,13, 7,12, 5,10, 4, 7, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,20, /* Ascii 55 */ + 17,21, 7, 0,-1,-1, 3,21,17,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 29,20, /* Ascii 56 */ + 8,21, 5,20, 4,18, 4,16, 5,14, 7,13,11,12,14,11,16, 9,17, 7,17, 4,16, + 2,15, 1,12, 0, 8, 0, 5, 1, 4, 2, 3, 4, 3, 7, 4, 9, 6,11, 9,12,13,13, + 15,14,16,16,16,18,15,20,12,21, 8,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,20, /* Ascii 57 */ + 16,14,15,11,13, 9,10, 8, 9, 8, 6, 9, 4,11, 3,14, 3,15, 4,18, 6,20, 9, + 21,10,21,13,20,15,18,16,14,16, 9,15, 4,13, 1,10, 0, 8, 0, 5, 1, 4, 3, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,10, /* Ascii 58 */ + 5,14, 4,13, 5,12, 6,13, 5,14,-1,-1, 5, 2, 4, 1, 5, 0, 6, 1, 5, 2,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,10, /* Ascii 59 */ + 5,14, 4,13, 5,12, 6,13, 5,14,-1,-1, 6, 1, 5, 0, 4, 1, 5, 2, 6, 1, 6, + -1, 5,-3, 4,-4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 3,24, /* Ascii 60 */ + 20,18, 4, 9,20, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,26, /* Ascii 61 */ + 4,12,22,12,-1,-1, 4, 6,22, 6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 3,24, /* Ascii 62 */ + 4,18,20, 9, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 20,18, /* Ascii 63 */ + 3,16, 3,17, 4,19, 5,20, 7,21,11,21,13,20,14,19,15,17,15,15,14,13,13, + 12, 9,10, 9, 7,-1,-1, 9, 2, 8, 1, 9, 0,10, 1, 9, 2,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 55,27, /* Ascii 64 */ + 18,13,17,15,15,16,12,16,10,15, 9,14, 8,11, 8, 8, 9, 6,11, 5,14, 5,16, + 6,17, 8,-1,-1,12,16,10,14, 9,11, 9, 8,10, 6,11, 5,-1,-1,18,16,17, 8, + 17, 6,19, 5,21, 5,23, 7,24,10,24,12,23,15,22,17,20,19,18,20,15,21,12, + 21, 9,20, 7,19, 5,17, 4,15, 3,12, 3, 9, 4, 6, 5, 4, 7, 2, 9, 1,12, 0, + 15, 0,18, 1,20, 2,21, 3,-1,-1,19,16,18, 8,18, 6,19, 5, + 8,18, /* Ascii 65 */ + 9,21, 1, 0,-1,-1, 9,21,17, 0,-1,-1, 4, 7,14, 7,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,21, /* Ascii 66 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13, + 11,-1,-1, 4,11,13,11,16,10,17, 9,18, 7,18, 4,17, 2,16, 1,13, 0, 4, 0, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 18,21, /* Ascii 67 */ + 18,16,17,18,15,20,13,21, 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0,13, 0,15, 1,17, 3,18, 5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 15,21, /* Ascii 68 */ + 4,21, 4, 0,-1,-1, 4,21,11,21,14,20,16,18,17,16,18,13,18, 8,17, 5,16, + 3,14, 1,11, 0, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,19, /* Ascii 69 */ + 4,21, 4, 0,-1,-1, 4,21,17,21,-1,-1, 4,11,12,11,-1,-1, 4, 0,17, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,18, /* Ascii 70 */ + 4,21, 4, 0,-1,-1, 4,21,17,21,-1,-1, 4,11,12,11,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 22,21, /* Ascii 71 */ + 18,16,17,18,15,20,13,21, 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, + 3, 7, 1, 9, 0,13, 0,15, 1,17, 3,18, 5,18, 8,-1,-1,13, 8,18, 8,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,22, /* Ascii 72 */ + 4,21, 4, 0,-1,-1,18,21,18, 0,-1,-1, 4,11,18,11,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 73 */ + 4,21, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,16, /* Ascii 74 */ + 12,21,12, 5,11, 2,10, 1, 8, 0, 6, 0, 4, 1, 3, 2, 2, 5, 2, 7,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,21, /* Ascii 75 */ + 4,21, 4, 0,-1,-1,18,21, 4, 7,-1,-1, 9,12,18, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,17, /* Ascii 76 */ + 4,21, 4, 0,-1,-1, 4, 0,16, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,24, /* Ascii 77 */ + 4,21, 4, 0,-1,-1, 4,21,12, 0,-1,-1,20,21,12, 0,-1,-1,20,21,20, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,22, /* Ascii 78 */ + 4,21, 4, 0,-1,-1, 4,21,18, 0,-1,-1,18,21,18, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 21,22, /* Ascii 79 */ + 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0,13, 0,15, + 1,17, 3,18, 5,19, 8,19,13,18,16,17,18,15,20,13,21, 9,21,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 13,21, /* Ascii 80 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,14,17,12,16,11,13, + 10, 4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 24,22, /* Ascii 81 */ + 9,21, 7,20, 5,18, 4,16, 3,13, 3, 8, 4, 5, 5, 3, 7, 1, 9, 0,13, 0,15, + 1,17, 3,18, 5,19, 8,19,13,18,16,17,18,15,20,13,21, 9,21,-1,-1,12, 4, + 18,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 16,21, /* Ascii 82 */ + 4,21, 4, 0,-1,-1, 4,21,13,21,16,20,17,19,18,17,18,15,17,13,16,12,13, + 11, 4,11,-1,-1,11,11,18, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 20,20, /* Ascii 83 */ + 17,18,15,20,12,21, 8,21, 5,20, 3,18, 3,16, 4,14, 5,13, 7,12,13,10,15, + 9,16, 8,17, 6,17, 3,15, 1,12, 0, 8, 0, 5, 1, 3, 3,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 84 */ + 8,21, 8, 0,-1,-1, 1,21,15,21,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,22, /* Ascii 85 */ + 4,21, 4, 6, 5, 3, 7, 1,10, 0,12, 0,15, 1,17, 3,18, 6,18,21,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,18, /* Ascii 86 */ + 1,21, 9, 0,-1,-1,17,21, 9, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,24, /* Ascii 87 */ + 2,21, 7, 0,-1,-1,12,21, 7, 0,-1,-1,12,21,17, 0,-1,-1,22,21,17, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,20, /* Ascii 88 */ + 3,21,17, 0,-1,-1,17,21, 3, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 6,18, /* Ascii 89 */ + 1,21, 9,11, 9, 0,-1,-1,17,21, 9,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,20, /* Ascii 90 */ + 17,21, 3, 0,-1,-1, 3,21,17,21,-1,-1, 3, 0,17, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,14, /* Ascii 91 */ + 4,25, 4,-7,-1,-1, 5,25, 5,-7,-1,-1, 4,25,11,25,-1,-1, 4,-7,11,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,14, /* Ascii 92 */ + 0,21,14,-3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,14, /* Ascii 93 */ + 9,25, 9,-7,-1,-1,10,25,10,-7,-1,-1, 3,25,10,25,-1,-1, 3,-7,10,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,16, /* Ascii 94 */ + 6,15, 8,18,10,15,-1,-1, 3,12, 8,17,13,12,-1,-1, 8,17, 8, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2,16, /* Ascii 95 */ + 0,-2,16,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 7,10, /* Ascii 96 */ + 6,21, 5,20, 4,18, 4,16, 5,15, 6,16, 5,17,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 97 */ + 15,14,15, 0,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 98 */ + 4,21, 4, 0,-1,-1, 4,11, 6,13, 8,14,11,14,13,13,15,11,16, 8,16, 6,15, + 3,13, 1,11, 0, 8, 0, 6, 1, 4, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 14,18, /* Ascii 99 */ + 15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, + 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 100 */ + 15,21,15, 0,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,18, /* Ascii 101 */ + 3, 8,15, 8,15,10,14,12,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,12, /* Ascii 102 */ + 10,21, 8,21, 6,20, 5,17, 5, 0,-1,-1, 2,14, 9,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 22,19, /* Ascii 103 */ + 15,14,15,-2,14,-5,13,-6,11,-7, 8,-7, 6,-6,-1,-1,15,11,13,13,11,14, 8, + 14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 104 */ + 4,21, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8, 8, /* Ascii 105 */ + 3,21, 4,20, 5,21, 4,22, 3,21,-1,-1, 4,14, 4, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,10, /* Ascii 106 */ + 5,21, 6,20, 7,21, 6,22, 5,21,-1,-1, 6,14, 6,-3, 5,-6, 3,-7, 1,-7,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,17, /* Ascii 107 */ + 4,21, 4, 0,-1,-1,14,14, 4, 4,-1,-1, 8, 8,15, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 108 */ + 4,21, 4, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 18,30, /* Ascii 109 */ + 4,14, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,15, + 10,18,13,20,14,23,14,25,13,26,10,26, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 110 */ + 4,14, 4, 0,-1,-1, 4,10, 7,13, 9,14,12,14,14,13,15,10,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 111 */ + 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,16, + 6,16, 8,15,11,13,13,11,14, 8,14,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 112 */ + 4,14, 4,-7,-1,-1, 4,11, 6,13, 8,14,11,14,13,13,15,11,16, 8,16, 6,15, + 3,13, 1,11, 0, 8, 0, 6, 1, 4, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,19, /* Ascii 113 */ + 15,14,15,-7,-1,-1,15,11,13,13,11,14, 8,14, 6,13, 4,11, 3, 8, 3, 6, 4, + 3, 6, 1, 8, 0,11, 0,13, 1,15, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,13, /* Ascii 114 */ + 4,14, 4, 0,-1,-1, 4, 8, 5,11, 7,13, 9,14,12,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 17,17, /* Ascii 115 */ + 14,11,13,13,10,14, 7,14, 4,13, 3,11, 4, 9, 6, 8,11, 7,13, 6,14, 4,14, + 3,13, 1,10, 0, 7, 0, 4, 1, 3, 3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,12, /* Ascii 116 */ + 5,21, 5, 4, 6, 1, 8, 0,10, 0,-1,-1, 2,14, 9,14,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 10,19, /* Ascii 117 */ + 4,14, 4, 4, 5, 1, 7, 0,10, 0,12, 1,15, 4,-1,-1,15,14,15, 0,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,16, /* Ascii 118 */ + 2,14, 8, 0,-1,-1,14,14, 8, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 11,22, /* Ascii 119 */ + 3,14, 7, 0,-1,-1,11,14, 7, 0,-1,-1,11,14,15, 0,-1,-1,19,14,15, 0,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 5,17, /* Ascii 120 */ + 3,14,14, 0,-1,-1,14,14, 3, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 9,16, /* Ascii 121 */ + 2,14, 8, 0,-1,-1,14,14, 8, 0, 6,-4, 4,-6, 2,-7, 1,-7,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 8,17, /* Ascii 122 */ + 14,14, 3, 0,-1,-1, 3,14,14,14,-1,-1, 3, 0,14, 0,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 39,14, /* Ascii 123 */ + 9,25, 7,24, 6,23, 5,21, 5,19, 6,17, 7,16, 8,14, 8,12, 6,10,-1,-1, 7, + 24, 6,22, 6,20, 7,18, 8,17, 9,15, 9,13, 8,11, 4, 9, 8, 7, 9, 5, 9, 3, + 8, 1, 7, 0, 6,-2, 6,-4, 7,-6,-1,-1, 6, 8, 8, 6, 8, 4, 7, 2, 6, 1, 5, + -1, 5,-3, 6,-5, 7,-6, 9,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 2, 8, /* Ascii 124 */ + 4,25, 4,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 39,14, /* Ascii 125 */ + 5,25, 7,24, 8,23, 9,21, 9,19, 8,17, 7,16, 6,14, 6,12, 8,10,-1,-1, 7, + 24, 8,22, 8,20, 7,18, 6,17, 5,15, 5,13, 6,11,10, 9, 6, 7, 5, 5, 5, 3, + 6, 1, 7, 0, 8,-2, 8,-4, 7,-6,-1,-1, 8, 8, 6, 6, 6, 4, 7, 2, 8, 1, 9, + -1, 9,-3, 8,-5, 7,-6, 5,-7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 23,24, /* Ascii 126 */ + 3, 6, 3, 8, 4,11, 6,12, 8,12,10,11,14, 8,16, 7,18, 7,20, 8,21,10,-1, + -1, 3, 8, 4,10, 6,11, 8,11,10,10,14, 7,16, 6,18, 6,20, 7,21,10,21,12, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; \ No newline at end of file diff --git a/Library/PasswordLib/ConsolePassword.c b/Library/PasswordLib/ConsolePassword.c new file mode 100644 index 0000000..c195b48 --- /dev/null +++ b/Library/PasswordLib/ConsolePassword.c @@ -0,0 +1,128 @@ +/** @file +Ask password from console + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include "Library/CommonLib.h" +#include "Library/PasswordLib.h" +#include + +VOID +AskConsolePwdInt( + OUT UINT32 *length, + OUT CHAR8 *asciiLine, + OUT INT32 *retCode, + IN UINTN line_max, + IN UINT8 show + ) +{ + EFI_INPUT_KEY key; + UINT32 count = 0; + UINTN i; + + gST->ConOut->EnableCursor(gST->ConOut, TRUE); + + do { + key = GetKey(); + // Remove dirty chars 0.1s + FlushInputDelay(100000); + + if (key.ScanCode == SCAN_ESC) { + *retCode = AskPwdRetCancel; + break; + } + + if (key.ScanCode == SCAN_F2) { + *retCode = AskPwdRetChange; + break; + } + + if (key.ScanCode == SCAN_F5) { + show = show ? 0 : 1; + if (show) { + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b"); + } + OUT_PRINT(L"%a", asciiLine); + } + else { + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b"); + } + for (i = 0; i < count; i++) { + OUT_PRINT(L"*"); + } + } + } + + if (key.ScanCode == SCAN_F7) { + gPlatformLocked = gPlatformLocked ? 0 : 1; + ConsoleShowTip(gPlatformLocked ? L" Platform locked!" : L" Platform unlocked!", 10000000); + } + + if (key.ScanCode == SCAN_F8) { + gTPMLocked = gTPMLocked ? 0 : 1; + ConsoleShowTip(gTPMLocked ? L" TPM locked!" : L" TPM unlocked!", 10000000); + } + + + if (key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + *retCode = AskPwdRetLogin; + break; + } + + if ((count >= line_max && + key.UnicodeChar != CHAR_BACKSPACE) || + key.UnicodeChar == CHAR_NULL || + key.UnicodeChar == CHAR_TAB || + key.UnicodeChar == CHAR_LINEFEED || + key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + continue; + } + + if (count == 0 && key.UnicodeChar == CHAR_BACKSPACE) { + continue; + } + else if (key.UnicodeChar == CHAR_BACKSPACE) { + OUT_PRINT(L"\b \b"); + if (asciiLine != NULL) asciiLine[--count] = '\0'; + continue; + } + + // check size of line + if (count < line_max - 1) { + if (show) { + OUT_PRINT(L"%c", key.UnicodeChar); + } + else { + OUT_PRINT(L"*"); + } + // save char + if (asciiLine != NULL) { + asciiLine[count++] = (CHAR8)key.UnicodeChar; + asciiLine[count] = 0; + } + } + } while (key.UnicodeChar != CHAR_CARRIAGE_RETURN); + + if (length != NULL) *length = count; + // Set end of line + if (asciiLine != NULL) { + asciiLine[count] = '\0'; + for (i = 0; i < count; i++) { + OUT_PRINT(L"\b \b"); + } + OUT_PRINT(L"*"); + } + OUT_PRINT(L"\n"); +} diff --git a/Library/PasswordLib/PasswordLib.inf b/Library/PasswordLib/PasswordLib.inf new file mode 100644 index 0000000..6b30c0c --- /dev/null +++ b/Library/PasswordLib/PasswordLib.inf @@ -0,0 +1,46 @@ +## @file +# Password library +# +# Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +# Copyright (c) 2016. VeraCrypt, Mounir IDRASSI +# +# This program and the accompanying materials are licensed and made available +# under the terms and conditions of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). +# +# The full text of the license may be found at +# https://opensource.org/licenses/LGPL-3.0 +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = GraphLib + MODULE_UNI_FILE = GraphLib.uni + FILE_GUID = A73BC841-498A-41E5-87B1-A0CED9933756 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = GraphLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + PicturePassword.c + ConsolePassword.c + PlatformID.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + +[Protocols] + gEfiGraphicsOutputProtocolGuid + +[Guids] + gEfiSmbiosTableGuid diff --git a/Library/PasswordLib/PicturePassword.c b/Library/PasswordLib/PicturePassword.c new file mode 100644 index 0000000..f917899 --- /dev/null +++ b/Library/PasswordLib/PicturePassword.c @@ -0,0 +1,629 @@ +/** @file +Picture password + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include + +#include +#include +#include + +CHAR16* gPasswordPictureFileName = NULL; + +CHAR8* gPasswordPictureChars = NULL; +CHAR8* gPasswordPictureCharsDefault = "MN/[aQ-eyPr}GT: |V^UqiI_gbdA9YwZ%f8t6S@D\"7uXl\\30R#+zH*,W4J?=&BLFv]hx~E;$<.o'sp1`(>C)O{!5j2nmkcK"; +//CHAR8* gPicturePasswordCharsDefault = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"; +UINTN gPasswordPictureCharsLen = 95; + +UINT8 gPasswordVisible = 0; +int gPasswordShowMark = 1; + +int gPlatformLocked = 0; +int gTPMLocked = 0; +int gSCLocked = 0; + + +////////////////////////////////////////////////////////////////////////// +// Picture password +////////////////////////////////////////////////////////////////////////// +CONST CHAR16* BmpName = L"Test.bmp"; +VOID* Bmp = NULL; +UINTN BmpSize = 0; +BLT_HEADER* bltPwd = NULL; +UINTN posPictX, posPictY; +BLT_HEADER* bltScrn = NULL; +UINTN* cellSelected = NULL; +UINTN picPwdIdx = 0; +UINTN sHeight; +UINTN sWidth; +UINTN step; + +DRAW_CONTEXT ctxCursor; +DRAW_CONTEXT ctxCell; +DRAW_CONTEXT ctxMark; +DRAW_CONTEXT ctxSet; + +VOID +CellUpdate( + IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y, + IN BOOLEAN selected) { + if (selected && gPasswordShowMark) { + BltCircle(blt, &ctxMark, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), TRUE); + BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 9), TRUE); + } + else { + CHAR8 ch[2] = { 0,0 }; + BltCircle(blt, &ctxCell, (INT32)(x * step + step / 2), (INT32)(y * step + step / 2), (INT32)(step / 3), FALSE); + if (gPasswordVisible) { + ch[0] = gPasswordPictureChars[(x + blt->Width / step * y) % gPasswordPictureCharsLen]; + BltText(blt, &ctxCell, (INT32)(x * step + step / 2 - 12), (INT32)(y * step + step / 2 - 12), 256, ch); + } + } +} + +BOOLEAN +CellGetSelected( + IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y, + OUT UINTN* cellX, + OUT UINTN* cellY) { + RECT reg; + UINTN sen; + if (x > blt->Width || y > blt->Height) return FALSE; + *cellX = x / step; + *cellY = y / step; + sen = step / 5; // zone sensible + reg.left = (UINT32)(*cellX * step + step / 2 - sen); + reg.right = (UINT32)(*cellX * step + step / 2 + sen); + reg.top = (UINT32)(*cellY * step + step / 2 - sen); + reg.bottom = (UINT32)(*cellY * step + step / 2 + sen); + return (x > reg.left && x < reg.right && y > reg.top && y < reg.bottom); +} + +VOID +DrawCursor(IN OUT BLT_HEADER* blt, + IN UINTN x, + IN UINTN y + ) { + BltLine(blt, &ctxCursor, (INT32)(x - 10), (INT32)y, (INT32)(x + 10), (INT32)y); + BltLine(blt, &ctxCursor, (INT32)x, (INT32)(y - 10), (INT32)x, (INT32)(y + 10)); +} + +typedef struct _TOUCH_ZONE { + UINTN Zone; + CHAR8* Message; + UINTN RetCode; + INT32 TextScale; +} TOUCH_ZONE, *PTOUCH_ZONE; + +enum TouchZoneIds { + tznLogin = 1, + tznBeep, + tznShow, + tznChange +}; + +CHAR8* msgLogin = "LOGIN"; +CHAR8* msgBeepOn = "Beep\non"; +CHAR8* msgBeepOff = "Beep\noff"; +CHAR8* msgChg = "Change\npwd"; +CHAR8* msgShowPwd = "Show\npwd"; +CHAR8* msgHidePwd = "Hide\npwd"; +CHAR8* msgNewPwd = "New\npwd"; +CHAR8* msgConfirmPwd = "Confirm\npwd"; +CHAR8* msgPlatformLocked = "PLT\nlkd"; +CHAR8* msgPlatformUnLocked = "PLT\nunlkd"; +CHAR8* msgTpmLocked = "TPM\nlkd"; +CHAR8* msgTpmUnLocked = "TPM\nunlkd"; + +TOUCH_ZONE TZN_Login = { 0, NULL, tznLogin, 128 }; +TOUCH_ZONE TZN_Speaker = { 2, NULL, tznBeep, 64 }; +TOUCH_ZONE TZN_Show = { 3, NULL, tznShow, 64 }; +TOUCH_ZONE TZN_Change = { 5, NULL, tznChange, 32 }; +TOUCH_ZONE TZN_Platform = { 6, NULL, 0, 32 }; +TOUCH_ZONE TZN_Tpm = { 7, NULL, 0, 32 }; + +VOID +DrawTouchZone( + IN PTOUCH_ZONE zone + ) { + BltFill(bltScrn, gColorBlack, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step)); + BltBox(bltScrn, &ctxCell, (INT32)(sWidth - step), (INT32)(2 + zone->Zone * step), (INT32)(INT32)(sWidth - 2), (INT32)(step + zone->Zone * step)); + BltText(bltScrn, &ctxCell, (INT32)(sWidth - step * 3 / 4), (INT32)(step * 1 / 3 + zone->Zone * step), 128, zone->Message); +} + +BOOLEAN +IsTouchZone( + IN PTOUCH_ZONE zone, + IN UINTN x, + IN UINTN y + ) { + if (x > sWidth - step && + (y > (zone->Zone * step)) && + (y < (step + zone->Zone * step))) { + return TRUE; + } + return FALSE; +} + +VOID +DrawPwdZone( + IN CHAR8* pwd, + IN UINT32 pwdMax) +{ + INT32 pwdGrphMaxLen = (INT32)(sWidth - 2 * step); + BltFill(bltScrn, gColorBlack, 0, 0, (INT32)(sWidth - 2 * step), (INT32)(posPictY)); + if (gPasswordVisible) { + BltText(bltScrn, &ctxCell, 0, 0, 256, pwd); + } + else { + INT32 pwdGrphLen = (INT32)(pwdGrphMaxLen * picPwdIdx / pwdMax); + INT32 pwdGrphHeight = (INT32)(posPictY) / 2; + INT32 pwdGrphTop = (INT32)(posPictY) / 4; + BltFill(bltScrn, gColorGreen, 0, pwdGrphTop, pwdGrphLen, pwdGrphHeight + pwdGrphTop); + BltFill(bltScrn, gColorBlack, pwdGrphLen, pwdGrphTop, pwdGrphMaxLen, pwdGrphHeight + pwdGrphTop); + } +} + +EFI_STATUS +DrawPwdPicture() +{ + EFI_STATUS res; + UINTN idx; + UINTN cellX, cellY; + + if (bltPwd != NULL) MEM_FREE(bltPwd); + + res = BmpToBlt(Bmp, BmpSize, &bltPwd); + if (EFI_ERROR(res)) { + return res; + } + cellY = 0; + do { + cellX = 0; + do { + CellUpdate(bltPwd, cellX, cellY, FALSE); + cellX++; + } while ((cellX + 1) * step <= (bltPwd->Width)); + cellY++; + } while ((cellY + 1)* step <= (bltPwd->Height)); + + // Update selected + for (idx = 0; idx < picPwdIdx; ++idx) { + if (cellSelected[idx * 2] != MAX_INTN) { + CellUpdate(bltPwd, cellSelected[idx * 2], cellSelected[idx * 2 + 1], TRUE); + } + } + return EFI_SUCCESS; +} + +VOID +CreateDraws() { + // Set + ctxSet.Color = gColorGray; + ctxSet.DashLine = 0xFFFFFFFF; + ctxSet.Op = DrawOpSet; + ctxSet.Brush = NULL; + + // Cursor + ctxCursor.Color = gColorWhite; + ctxCursor.DashLine = 0xFFFFFFFF; + ctxCursor.Op = DrawOpXor; + ctxCursor.Brush = NULL; + + // Cell + ctxCell.Color = gColorGreen; + ctxCell.DashLine = 0xFFFFFFFF; + ctxCell.Op = DrawOpSet; + ctxCell.Brush = gBrush3; + + // Shade (close to black) + ctxMark.AlphaColor = gColorWhite; + ctxMark.Alpha = 128; + ctxMark.Op = DrawOpAlpha; + ctxMark.Brush = NULL; +} + +enum PictPwdAction { + PwdActNone = 0, + PwdActLogin, + PwdActCancel, + PwdActChange, + PwdActShow, + PwdActBeep, + PwdActNewChar, + PwdActUpdateZones, +}; + +VOID +AskPictPwdInt( + IN UINTN pwdType, + IN UINTN pwdMax, + OUT CHAR8* pwd, + OUT UINT32* pwdLen, + OUT INT32* retCode + ) { + EFI_STATUS res; + UINTN cellX, cellY; + UINTN cellPrevX, cellPrevY; + UINTN curX, curY; + UINTN curPrevX, curPrevY; + EFI_INPUT_KEY key; + EFI_EVENT UpdateEvent; + EFI_EVENT BeepOffEvent; + EFI_EVENT InputEvents[3]; + UINTN EventIndex = 0; + UINTN eventsCount = 2; + EFI_ABSOLUTE_POINTER_STATE aps = {0}; + BOOLEAN showCursor = FALSE; + BOOLEAN beepOn = FALSE; + UINTN pwdAction = PwdActNone; + CHAR8 pwdNewChar = 0; + + InitConsoleControl(); + if (gBeepEnabled) { + InitSpeaker(); + } + + if (Bmp == NULL) { + if (gPasswordPictureFileName != NULL) { + res = FileLoad(NULL, (CHAR16*)gPasswordPictureFileName, &Bmp, &BmpSize); + if (EFI_ERROR(res)) { + ERR_PRINT(L"File load - %r\n", res); + return; + } + } else { + ERR_PRINT(L"Picture file name undefined\n"); + return; + } + } + // Init draws + CreateDraws(); + + // Init screen + if (bltScrn != NULL) MEM_FREE(bltScrn); + ScreenSaveBlt(&bltScrn); + sWidth = bltScrn->Width; + sHeight = bltScrn->Height; + step = sWidth >> 4; + + // Init picture password + picPwdIdx = 0; + res = DrawPwdPicture(); + if (EFI_ERROR(res)) { + MEM_FREE(bltScrn); + ERR_PRINT(L"BmpToBlt - %r", res); + return; + } + + // Touch zones + switch (pwdType) { + case AskPwdConfirm: + TZN_Login.Message = msgConfirmPwd; + break; + case AskPwdNew: + TZN_Login.Message = msgNewPwd; + break; + case AskPwdLogin: + default: + TZN_Login.Message = msgLogin; + } + DrawTouchZone(&TZN_Login); + + if (pwdType == AskPwdLogin) { + TZN_Change.Message = msgChg; + DrawTouchZone(&TZN_Change); + } + + if (gBeepControlEnabled) { + TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn; + DrawTouchZone(&TZN_Speaker); + } + + TZN_Platform.Message = gPlatformLocked? msgPlatformLocked : msgPlatformUnLocked; + DrawTouchZone(&TZN_Platform); + + TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked; + DrawTouchZone(&TZN_Tpm); + + TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd; + DrawTouchZone(&TZN_Show); + cellSelected = MEM_ALLOC(sizeof(UINTN) * 2 * (pwdMax + 1)); + + ScreenUpdateDirty(bltScrn); + + // Prepare cursors + posPictX = (sWidth - bltPwd->Width) >> 1; + posPictY = (sHeight - bltPwd->Height) >> 1; + cellPrevX = MAX_INTN; + cellPrevY = MAX_INTN; + curX = sWidth / 2; + curY = posPictY / 2; + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + + // Prepare events + InputEvents[0] = gST->ConIn->WaitForKey; + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &InputEvents[1]); + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &BeepOffEvent); + gBS->CreateEvent(EVT_TIMER, 0, (EFI_EVENT_NOTIFY)NULL, NULL, &UpdateEvent); + gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update + gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10); + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + + if (gTouchPointer != NULL) { + eventsCount = 3; + InputEvents[2] = gTouchPointer->WaitForInput; + while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) { + gTouchPointer->GetState(gTouchPointer, &aps); + } + } + while (gBS->CheckEvent(InputEvents[0]) == EFI_SUCCESS) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + } + do + { + curPrevX = curX; + curPrevY = curY; + res = gBS->WaitForEvent(eventsCount, InputEvents, &EventIndex); + // OUT_PRINT(L" \r%05d %05d", (UINT32)curX, (UINT32)curY, ); + // recharge timeout event and stop beep + if (gBeepControlEnabled && gBeepEnabled && beepOn) { + if (gBS->CheckEvent(BeepOffEvent) == EFI_SUCCESS) { + beepOn = FALSE; + SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0); + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + } + } + else { + gBS->SetTimer(InputEvents[1], TimerRelative, 5000000); + } + + // hide cursor + if (showCursor && EventIndex != 1) { + DrawCursor(bltScrn, curX, curY); + showCursor = FALSE; + } + + // Blink cursor + if (EventIndex == 1) { + DrawCursor(bltScrn, curX, curY); + showCursor = !showCursor; + } + + if (EventIndex == 0) { + gST->ConIn->ReadKeyStroke(gST->ConIn, &key); + // OUT_PRINT(L" %04x, %04x\r", key.ScanCode, key.UnicodeChar); + + // Remove dirty chars 0.1s + FlushInputDelay(100000); + switch (key.ScanCode) + { + case SCAN_HOME: + curX -= gTouchSimulateStep; + curY -= gTouchSimulateStep; + break; + case SCAN_LEFT: + curX -= gTouchSimulateStep; + break; + case SCAN_END: + curX -= gTouchSimulateStep; + curY += gTouchSimulateStep; + break; + case SCAN_DOWN: + curY += gTouchSimulateStep; + break; + case SCAN_PAGE_DOWN: + curX += gTouchSimulateStep; + curY += gTouchSimulateStep; + break; + case SCAN_RIGHT: + curX += gTouchSimulateStep; + break; + case SCAN_PAGE_UP: + curX += gTouchSimulateStep; + curY -= gTouchSimulateStep; + break; + case SCAN_UP: + curY -= gTouchSimulateStep; + break; + case SCAN_F11: + if (gTouchSimulateStep > 1) + gTouchSimulateStep--; + break; + case SCAN_F12: + gTouchSimulateStep++; + break; + case SCAN_ESC: + pwdAction = PwdActCancel; + break; + case SCAN_F2: + if (pwdType == AskPwdLogin) { + pwdAction = PwdActChange; + } + break; + case SCAN_F4: + if (gBeepControlEnabled) { + pwdAction = PwdActBeep; + } + break; + case SCAN_F5: + pwdAction = PwdActShow; + break; + case SCAN_F7: + gPlatformLocked = gPlatformLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + break; + case SCAN_F8: + gTPMLocked = gTPMLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + break; + default: + ; + } + + if (key.UnicodeChar != 0) { + if (key.UnicodeChar == 0x0d) { + pwdAction = PwdActLogin; + } + else { + pwdNewChar = (CHAR8)key.UnicodeChar; + pwdAction = PwdActNewChar; + cellSelected[picPwdIdx * 2] = MAX_INTN; + } + } + + } + + if (EventIndex == 2) { + res = gTouchPointer->GetState(gTouchPointer, &aps); + if (!EFI_ERROR(res)) { + curX = (UINTN)(aps.CurrentX * sWidth / (gTouchPointer->Mode->AbsoluteMaxX - gTouchPointer->Mode->AbsoluteMinX)); + curY = (UINTN)(aps.CurrentY * sHeight / (gTouchPointer->Mode->AbsoluteMaxY - gTouchPointer->Mode->AbsoluteMinY)); + } + } + + if (curX > sWidth) curX = sWidth; + if (curY > sHeight) curY = sHeight; + + // Cell check + if (CellGetSelected(bltPwd, curX - posPictX, curY - posPictY, &cellX, &cellY) && picPwdIdx < pwdMax) { + if (cellPrevX != cellX || cellPrevY != cellY) { + cellPrevX = cellX; + cellPrevY = cellY; + cellSelected[picPwdIdx * 2] = cellX; + cellSelected[picPwdIdx * 2 + 1] = cellY; + CellUpdate(bltPwd, cellX, cellY, TRUE); + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + pwdAction = PwdActNewChar; + pwdNewChar = gPasswordPictureChars[(cellX + bltPwd->Width / step * cellY) % gPasswordPictureCharsLen]; + } + else if (EventIndex == 2 && aps.ActiveButtons == 0) { + cellPrevX = MAX_INTN; + cellPrevY = MAX_INTN; + curX = posPictX + cellX * step; + curY = posPictY + cellY * step; + while (gBS->CheckEvent(InputEvents[2]) == EFI_SUCCESS) { + gTouchPointer->GetState(gTouchPointer, &aps); + } + } + } + + if (pwdAction == PwdActNone) { + if (IsTouchZone(&TZN_Login, curX, curY)) { + pwdAction = PwdActLogin; + } + + if (pwdType == AskPwdLogin && IsTouchZone(&TZN_Change, curX, curY)) { + pwdAction = PwdActChange; + } + + if (curPrevX != curX || curPrevY != curY) { + if (gSpeakerCount > 0 && IsTouchZone(&TZN_Speaker, curX, curY)) { + pwdAction = PwdActBeep; + } + if (IsTouchZone(&TZN_Show, curX, curY)) { + pwdAction = PwdActShow; + } + if (IsTouchZone(&TZN_Tpm, curX, curY)) { + gTPMLocked = gTPMLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + } + if (IsTouchZone(&TZN_Platform, curX, curY)) { + gPlatformLocked = gPlatformLocked ? 0 : 1; + pwdAction = PwdActUpdateZones; + } + } + } + + if (PwdActNewChar == pwdAction) { + BOOLEAN bUpdPwdZone = FALSE; + if (pwdNewChar == '\b' && picPwdIdx > 0) { + picPwdIdx--; + pwd[picPwdIdx] = 0; + bUpdPwdZone = TRUE; + } else if ((picPwdIdx < pwdMax - 1) && (pwdNewChar >= 32)) { + pwd[picPwdIdx++] = pwdNewChar; + pwd[picPwdIdx] = 0; + bUpdPwdZone = TRUE; + } + if(bUpdPwdZone) { + *pwdLen = (int)picPwdIdx; + DrawPwdZone(pwd, (INT32)pwdMax); + if (gBeepControlEnabled && gBeepEnabled) { + SpeakerBeep((UINT16)gBeepToneDefault, gBeepNumberDefault, 0, 0); + gBS->SetTimer(BeepOffEvent, TimerRelative, gBeepDurationDefault * 10); + gBS->SetTimer(InputEvents[1], TimerRelative, gBeepDurationDefault * 10); + beepOn = TRUE; + } + } + } + else if (PwdActBeep == pwdAction && gBeepControlEnabled) { + if (gBeepEnabled && beepOn) { + beepOn = FALSE; + SpeakerBeep((UINT16)gBeepToneDefault, 0, 0, 0); + } + gBeepEnabled = gBeepEnabled ? 0 : 1; + TZN_Speaker.Message = gBeepEnabled ? msgBeepOff : msgBeepOn; + DrawTouchZone(&TZN_Speaker); + } + else if (PwdActShow == pwdAction) { + gPasswordVisible = gPasswordVisible ? 0 : 1; + DrawPwdZone(pwd, (INT32)pwdMax); + DrawPwdPicture(); + BltDrawBlt(bltScrn, bltPwd, posPictX, posPictY); + TZN_Show.Message = gPasswordVisible ? msgHidePwd : msgShowPwd; + DrawTouchZone(&TZN_Show); + } + else if (PwdActLogin == pwdAction) { + *retCode = AskPwdRetLogin; + break; + } + else if (pwdType == AskPwdLogin && PwdActChange == pwdAction) { + *retCode = AskPwdRetChange; + break; + } + else if (PwdActCancel == pwdAction){ + *retCode = AskPwdRetCancel; + break; + } + else if (PwdActUpdateZones == pwdAction) { + TZN_Platform.Message = gPlatformLocked ? msgPlatformLocked : msgPlatformUnLocked; + DrawTouchZone(&TZN_Platform); + + TZN_Tpm.Message = gTPMLocked ? msgTpmLocked : msgTpmUnLocked; + DrawTouchZone(&TZN_Tpm); + } + + if (curPrevX != curX || curPrevY != curY) { + DrawCursor(bltScrn, curX, curY); + showCursor = TRUE; + } + // Time to update screen? + if (gBS->CheckEvent(UpdateEvent) == EFI_SUCCESS) { + ScreenUpdateDirty(bltScrn); + gBS->SetTimer(UpdateEvent, TimerRelative, 500000); // 20 times per second to update + } + + pwdAction = PwdActNone; + } while (TRUE); + gBS->CloseEvent(InputEvents[1]); + gBS->CloseEvent(UpdateEvent); + gBS->CloseEvent(BeepOffEvent); + ScreenFillRect(&gColorBlack, 0, 0, sWidth, sHeight); + gBS->Stall(500000); +} diff --git a/Library/PasswordLib/PlatformID.c b/Library/PasswordLib/PlatformID.c new file mode 100644 index 0000000..351503e --- /dev/null +++ b/Library/PasswordLib/PlatformID.c @@ -0,0 +1,266 @@ +/** @file +Platform Id based on SMBIOS structures + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +#include "Library/CommonLib.h" + +SMBIOS_TABLE_ENTRY_POINT* gSmbTable = NULL; +EFI_GUID* gSmbSystemUUID = NULL; // Universal unique ID +CHAR8* gSmbSystemSerial = NULL; // System serial +CHAR8* gSmbSystemSKU = NULL; // SKU number +CHAR8* gSmbBaseBoardSerial = NULL; // Base board serial +UINT64* gSmbProcessorID = NULL; // Processor ID + +UINTN gBioIndexAuth = 0; +typedef struct _DCS_AUTH_DATA_MARK { + UINT32 HeaderCrc; + UINT32 PlatformCrc; + UINT32 AuthDataSize; + UINT32 Reserved; +} DCS_AUTH_DATA_MARK; + +CHAR8* SMBIOSGetString(UINTN StringNumber, SMBIOS_STRUCTURE* smbtbl, CHAR8* lastAddr) { + CHAR8* String; + UINTN Index; + String = ((UINT8*)smbtbl) + smbtbl->Length; + for (Index = 1; Index <= StringNumber; Index++) { + if (StringNumber == Index) { + return String; + } + // + // Skip string + // + while (*String != 0) { + String++; + if (String > lastAddr) { + return NULL; + } + } + String++; +// if (*String == 0) { +// return NULL; +// } + } + return NULL; +} + +/** +* Get SMBIOS serial data +*/ +EFI_STATUS +SMBIOSGetSerials() +{ + EFI_STATUS res; + SMBIOS_STRUCTURE_POINTER pSMBIOS; + CHAR8* pos = NULL; + CHAR8* endOfTable; + + // Get SMBIOS tables pointer from System Configure table + res = EfiGetSystemConfigurationTable(&gEfiSmbiosTableGuid, (VOID**)&gSmbTable); + if (EFI_ERROR(res)) { + return res; + } + pSMBIOS.Raw = (UINT8 *)(UINTN)(gSmbTable->TableAddress); + pos = pSMBIOS.Raw; + endOfTable = pSMBIOS.Raw + gSmbTable->TableLength; + do { + SMBIOS_STRUCTURE* smbtbl = (SMBIOS_STRUCTURE*)pos; + // System info + if (smbtbl->Type == 1) { + gSmbSystemUUID = (EFI_GUID*)&pos[8]; + gSmbSystemSerial = SMBIOSGetString(4, smbtbl, endOfTable); + gSmbSystemSKU = SMBIOSGetString(5, smbtbl, endOfTable); + } + // Base board + if (smbtbl->Type == 2) { + gSmbBaseBoardSerial = SMBIOSGetString(4, smbtbl, endOfTable); + } + // Processor + if (smbtbl->Type == 4) { + gSmbProcessorID = (UINT64*)&pos[8]; + } + pos += smbtbl->Length; + while (((pos[0] != 0) || (pos[1] != 0)) && (pos < endOfTable)) pos++; + pos += 2; + } while (pos < endOfTable); + + return EFI_SUCCESS; +} + +EFI_STATUS +PlatformGetID( + IN EFI_HANDLE handle, + OUT CHAR8 **id, + OUT UINTN *idlength + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN idLen = 0; + CHAR8* idBuf = NULL; + CHAR8* handleSerial = NULL; + + UsbGetId(handle, &handleSerial); + if (gSmbSystemUUID == NULL) SMBIOSGetSerials(); + idLen += (gSmbSystemUUID == NULL) ? 0 : sizeof(*gSmbSystemUUID); + idLen += (gSmbSystemSerial == NULL) ? 0 : AsciiStrLen((char*)gSmbSystemSerial) + 1; + idLen += (gSmbSystemSKU == NULL) ? 0 : AsciiStrLen((char*)gSmbSystemSKU) + 1; + idLen += (gSmbBaseBoardSerial == NULL) ? 0 : AsciiStrLen((char*)gSmbBaseBoardSerial) + 1; + idLen += (gSmbProcessorID == NULL) ? 0 : sizeof(*gSmbProcessorID); + idLen += (handleSerial == NULL) ? 0 : AsciiStrLen((char*)handleSerial) + 1; + + idBuf = MEM_ALLOC(idLen); + if (idBuf == NULL) { + res = EFI_BUFFER_TOO_SMALL; + goto error; + } + + *id = idBuf; + *idlength = idLen; + + if (gSmbSystemUUID != NULL) { + CopyMem(idBuf, gSmbSystemUUID, sizeof(*gSmbSystemUUID)); + idBuf += sizeof(*gSmbSystemUUID); + } + + if (gSmbSystemSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbSystemSerial) + 1; + CopyMem(idBuf, gSmbSystemSerial, ssz); + idBuf += ssz; + } + + if (gSmbSystemSKU != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbSystemSKU) + 1; + CopyMem(idBuf, gSmbSystemSKU, ssz); + idBuf += ssz; + } + + if (gSmbBaseBoardSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)gSmbBaseBoardSerial) + 1; + CopyMem(idBuf, gSmbBaseBoardSerial, ssz); + idBuf += ssz; + } + + if (gSmbProcessorID != NULL) { + CopyMem(idBuf, gSmbProcessorID, sizeof(*gSmbProcessorID)); + idBuf += sizeof(*gSmbProcessorID); + } + + if (handleSerial != NULL) { + UINTN ssz; + ssz = AsciiStrLen((char*)handleSerial) + 1; + CopyMem(idBuf, handleSerial, ssz); + idBuf += ssz; + MEM_FREE(handleSerial); + } + + return res; + +error: + MEM_FREE(handleSerial); + MEM_FREE(idBuf); + return res; +} + + +EFI_STATUS +PlatformGetIDCRC( + IN EFI_HANDLE handle, + OUT UINT32 *crc32 + ) +{ + EFI_STATUS res; + UINTN crcLen; + CHAR8* crcBuf = NULL; + res = PlatformGetID(handle, &crcBuf, &crcLen); + if (EFI_ERROR(res)) { + return res; + } + res = gBS->CalculateCrc32(crcBuf, crcLen, crc32); + MEM_FREE(crcBuf); + return res; +} + +EFI_STATUS +PlatformGetAuthDataByType( + OUT UINT8 **data, + OUT UINTN *len, + OUT EFI_HANDLE *secRegionHandle, + IN BOOLEAN RemovableMedia) +{ + EFI_STATUS res; + UINT32 crc; + CHAR8* buf = NULL; + EFI_BLOCK_IO_PROTOCOL* bio; + DCS_AUTH_DATA_MARK* mark = NULL; + mark = (DCS_AUTH_DATA_MARK*)MEM_ALLOC(512); + for (; gBioIndexAuth < gBIOCount; ++gBioIndexAuth) { + bio = EfiGetBlockIO(gBIOHandles[gBioIndexAuth]); + if (bio == NULL) continue; + if(bio->Media->RemovableMedia != RemovableMedia) continue; + res = bio->ReadBlocks(bio, bio->Media->MediaId, 61, 512, mark); + if (EFI_ERROR(res)) continue; + + res = gBS->CalculateCrc32(&mark->PlatformCrc, sizeof(*mark) - 4, &crc); + if (EFI_ERROR(res)) continue; + if( crc != mark->HeaderCrc) continue; + + res = PlatformGetIDCRC(gBIOHandles[gBioIndexAuth], &crc); + if (EFI_ERROR(res)) continue; + if (crc != mark->PlatformCrc) continue; + + buf = MEM_ALLOC(mark->AuthDataSize * 1024 * 128); + if (buf == NULL) continue; + + res = bio->ReadBlocks(bio, bio->Media->MediaId, 62, mark->AuthDataSize * 1024 * 128, buf); + if (EFI_ERROR(res)) { + MEM_FREE(buf); + continue; + } + *data = buf; + *len = mark->AuthDataSize * 1024 * 128; + *secRegionHandle = gBIOHandles[gBioIndexAuth]; + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +BOOLEAN gBioIndexAuthOnRemovable = TRUE; + +EFI_STATUS +PlatformGetAuthData( + OUT UINT8 **data, + OUT UINTN *len, + OUT EFI_HANDLE *secRegionHandle + ) +{ + EFI_STATUS res; + res = PlatformGetAuthDataByType(data, len, secRegionHandle, gBioIndexAuthOnRemovable); + if (EFI_ERROR(res)) { + if (gBioIndexAuthOnRemovable) { + gBioIndexAuthOnRemovable = FALSE; + gBioIndexAuth = 0; + res = PlatformGetAuthDataByType(data, len, secRegionHandle, FALSE); + } + } + return res; +} + diff --git a/Library/VeraCryptLib/DcsVeraCrypt.c b/Library/VeraCryptLib/DcsVeraCrypt.c new file mode 100644 index 0000000..9cf57ce --- /dev/null +++ b/Library/VeraCryptLib/DcsVeraCrypt.c @@ -0,0 +1,391 @@ +/** @file +Interface for DCS + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the Apache License, Version 2.0. + +The full text of the license may be found at +https://opensource.org/licenses/Apache-2.0 +**/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include "common/Crypto.h" +#include "common/Xml.h" +#include "common/Crc.h" +#include "BootCommon.h" + +////////////////////////////////////////////////////////////////////////// +// Config +////////////////////////////////////////////////////////////////////////// +char *ConfigBuffer = NULL; +UINTN ConfigBufferSize = 0; + +BOOL ConfigRead(char *configKey, char *configValue, int maxValueSize) +{ + char *xml; + + if (ConfigBuffer == NULL) + FileLoad(NULL, L"\\EFI\\VeraCrypt\\DcsProp", &ConfigBuffer, &ConfigBufferSize); + + xml = ConfigBuffer; + if (xml != NULL) + { + xml = XmlFindElementByAttributeValue(xml, "config", "key", configKey); + if (xml != NULL) + { + XmlGetNodeText(xml, configValue, maxValueSize); + return TRUE; + } + } + + return FALSE; +} + +int ConfigReadInt(char *configKey, int defaultValue) +{ + char s[32]; + if (ConfigRead(configKey, s, sizeof(s))) { + if (*s == '-') { + return (-1) * (int)AsciiStrDecimalToUintn(&s[1]); + } + return (int)AsciiStrDecimalToUintn(s); + } + else + return defaultValue; +} + + +char *ConfigReadString(char *configKey, char *defaultValue, char *str, int maxLen) +{ + if (!ConfigRead(configKey, str, maxLen)) { + AsciiStrCpyS(str, maxLen, defaultValue); + } + return str; +} + + +/////////////////////////////////////////////////////////////////////////// +// Globals +////////////////////////////////////////////////////////////////////////// +#define MAX_MSG 256 +int gAuthPasswordType = 0; +char* gAuthPasswordMsg = NULL; +Password gAuthPassword; + +char* gAuthPimMsg = NULL; +int gAuthPimRqt = 1; +int gAuthPim = 0; + +int gAuthTcRqt = 0; +int gAuthTc = 0; + +char *gAuthHashMsg = NULL; +int gAuthHashRqt = 1; +int gAuthHash = 0; + +int gAuthBootRqt = 0; +int gAuthBoot = 1; + +int gAuthRetry = 10; +int gAuthPwdCode = 1; + +INT32 gRUD = 0; + +int gAuthSecRegionSearch = 0; + +CHAR8* gPlatformKeyFile = NULL; +UINTN gPlatformKeyFileSize = 0; + +EFI_GUID *gPartitionGuidOS = NULL; + +int gDcsBootForce = 1; + +CHAR8* gOnExitFailed = NULL; +CHAR8* gOnExitSuccess = NULL; +CHAR8* gOnExitNotFound = NULL; + +////////////////////////////////////////////////////////////////////////// +// Authorize +///////////////////////////////////////////////////////////////////////// + +VOID +VCAuthLoadConfig() +{ + int tmp; + + if (gAuthPasswordMsg != NULL) return; // Already loaded + + SetMem(&gAuthPassword, sizeof(gAuthPassword), 0); + { + char* passwordPictureAscii = NULL; + passwordPictureAscii = MEM_ALLOC(MAX_MSG); + gPasswordPictureFileName = MEM_ALLOC(MAX_MSG * 2); + ConfigReadString("PasswordPicture", "\\EFI\\VeraCrypt\\login.bmp", passwordPictureAscii, MAX_MSG); + AsciiStrToUnicodeStr(passwordPictureAscii, gPasswordPictureFileName); + MEM_FREE(passwordPictureAscii); + } + SetMem(&gAuthPassword, sizeof(gAuthPassword), 0); + + // + gAuthSecRegionSearch = ConfigReadInt("SecRegionSearch", 0); + gPlatformLocked = ConfigReadInt("PlatformLocked", 0); + gTPMLocked = ConfigReadInt("TPMLocked", 0); + gSCLocked = ConfigReadInt("SCLocked", 0); + gDcsBootForce = ConfigReadInt("DcsBootForce", 1); + + // Actions for DcsInt + gOnExitSuccess = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionSuccess", "Exit", gOnExitSuccess, MAX_MSG); + gOnExitNotFound = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionNotFound", "Exit", gOnExitNotFound, MAX_MSG); + gOnExitFailed = MEM_ALLOC(MAX_MSG); + ConfigReadString("ActionFailed", "Exit", gOnExitFailed, MAX_MSG); + + { + char* strTemp = NULL; + strTemp = MEM_ALLOC(MAX_MSG); + ConfigReadString("PartitionGuidOS", "", strTemp, MAX_MSG); + if (strTemp[0] != 0) { + EFI_GUID g; + if (AsciiStrToGuid(&g, strTemp)) { + gPartitionGuidOS = MEM_ALLOC(sizeof(EFI_GUID)); + if (gPartitionGuidOS != NULL) { + memcpy(gPartitionGuidOS, &g, sizeof(g)); + } + } + } + MEM_FREE(strTemp); + } + + gPasswordPictureChars = MEM_ALLOC(MAX_MSG); + ConfigReadString("PictureChars", gPasswordPictureCharsDefault, gPasswordPictureChars, MAX_MSG); + gPasswordPictureCharsLen = strlen(gPasswordPictureChars); + + gAuthPasswordType = ConfigReadInt("PasswordType", 0); + gAuthPasswordMsg = MEM_ALLOC(MAX_MSG); + ConfigReadString("PasswordMsg", "Password:", gAuthPasswordMsg, MAX_MSG); + + gAuthPimMsg = MEM_ALLOC(MAX_MSG); + gAuthPimRqt = ConfigReadInt("PimRqt", 1); + gAuthPim = ConfigReadInt("Pim", 0); + ConfigReadString("PimMsg", "Pim:", gAuthPimMsg, MAX_MSG); + + gAuthHashMsg = MEM_ALLOC(MAX_MSG); + gAuthHashRqt = ConfigReadInt("HashRqt", 1); + gAuthHash = ConfigReadInt("Hash", 0); + ConfigReadString("HashMsg", "(0) TEST ALL (1) SHA512 (2) WHIRLPOOL (3) SHA256 (4) RIPEMD160\n\rHash:", gAuthHashMsg, MAX_MSG); + + gPasswordVisible = (UINT8)ConfigReadInt("AuthorizeVisible", 0); + gPasswordShowMark = ConfigReadInt("AuthorizeMarkTouch", 1); + gAuthBootRqt = ConfigReadInt("BootRqt", 0); + gAuthTcRqt = ConfigReadInt("TcRqt", 0); + gRUD = ConfigReadInt("RUD", 0); + gAuthRetry = ConfigReadInt("AuthorizeRetry", 10); + + // touch + tmp = ConfigReadInt("TouchDevice", -1); + if (tmp == -1) InitTouch(); + if (tmp >= 0) { + if (gTouchCount == 0) InitTouch(); + if (tmp < (int)gTouchCount) { + TouchGetIO(gTouchHandles[tmp], &gTouchPointer); + } + } + gTouchSimulate = ConfigReadInt("TouchSimulate", 0); + + // Graph + tmp = ConfigReadInt("GraphDevice", -1); + if (tmp == -1) InitGraph(); + if (tmp >= 0) { + if (gGraphCount == 0) InitGraph(); + if (tmp < (int)gGraphCount) { + GraphGetIO(gGraphHandles[tmp], &gGraphOut); + } + } + if (gGraphOut != NULL) { + tmp = ConfigReadInt("GraphMode", -1); + if (tmp >= 0 && tmp <= (int)gGraphOut->Mode->MaxMode) { + gGraphOut->SetMode(gGraphOut, tmp); + } + } + + // Beep + gBeepEnabled = ConfigReadInt("Beep", 0); + if (gBeepEnabled) { + gBeepNumberDefault = ConfigReadInt("BeepNumber", 1); + gBeepDurationDefault = ConfigReadInt("BeepDuration", 100); + gBeepIntervalDefault = ConfigReadInt("BeepInterval", 0); + gBeepToneDefault = ConfigReadInt("BeepTone", 0x500); + gBeepControlEnabled = ConfigReadInt("BeepControl", 1) != 0; + + tmp = ConfigReadInt("BeepDevice", -1); + if (tmp == -1) InitSpeaker(); + if (tmp >= 0) { + if (gSpeakerCount == 0) InitSpeaker(); + if (tmp < (int)gSpeakerCount) { + SpeakerSelect(tmp); + } + } + } + +} + + +VOID +VCAskPwd( + IN UINTN pwdType, + OUT Password* vcPwd) { + if (gAuthPasswordMsg == NULL) VCAuthLoadConfig(); + if (gAuthPasswordType == 1 && + gGraphOut != NULL && + ((gTouchPointer != NULL) || (gTouchSimulate != 0))) { + AskPictPwdInt(pwdType, sizeof(vcPwd->Text), vcPwd->Text, &vcPwd->Length, &gAuthPwdCode); + } else { + switch (pwdType) { + case AskPwdNew: + OUT_PRINT(L"New password:"); + break; + case AskPwdConfirm: + OUT_PRINT(L"Confirm password:"); + break; + case AskPwdLogin: + default: + OUT_PRINT(L"%a", gAuthPasswordMsg); + break; + } + AskConsolePwdInt(&vcPwd->Length, vcPwd->Text, &gAuthPwdCode, sizeof(vcPwd->Text), gPasswordVisible); + } + + if (gAuthPwdCode == AskPwdRetCancel) { + return; + } + + if (gPlatformLocked) { + if (gPlatformKeyFile == NULL) { + ERR_PRINT(L"Platform key file absent\n"); + } else { + ApplyKeyFile(vcPwd, gPlatformKeyFile, gPlatformKeyFileSize); + } + } + + if (gTPMLocked) { + // TO DO + ERR_PRINT(L"TPM lock is not implemented\n"); + } +} + +VOID +VCAuthAsk() +{ + VCAskPwd(AskPwdLogin, &gAuthPassword); + + if (gAuthPwdCode == AskPwdRetCancel) { + return; + } + + if (gAuthPimRqt) { + gAuthPim = AskInt(gAuthPimMsg, gPasswordVisible); + } + if (gAuthTcRqt) { + gAuthTc = AskConfirm("True crypt mode [N]?", gPasswordVisible); + } + + if (gAuthBootRqt) { + gAuthBoot = AskConfirm("Boot mount mode [N]?", gPasswordVisible); + } + + if (gAuthHashRqt) { + do { + gAuthHash = AskInt(gAuthHashMsg, gPasswordVisible); + } while (gAuthHash < 0 || gAuthHash > 4); + } +} + + +////////////////////////////////////////////////////////////////////////// +// VeraCrypt helpers +////////////////////////////////////////////////////////////////////////// +void* VeraCryptMemAlloc(IN UINTN size) { + return MEM_ALLOC(size); +} + +void VeraCryptMemFree(IN VOID* ptr) { + MEM_FREE(ptr); +} +void ThrowFatalException(int line) { + ERR_PRINT(L"Fatal %d\n", line); +} + +////////////////////////////////////////////////////////////////////////// +// Random data +////////////////////////////////////////////////////////////////////////// +BOOL +RandgetBytes(unsigned char *buf, int len, BOOL forceSlowPoll) { + EFI_STATUS res; + res = RndGetBytes(buf, len); + return !EFI_ERROR(res); +} + +////////////////////////////////////////////////////////////////////////// +// Key file +////////////////////////////////////////////////////////////////////////// + +#define KEYFILE_POOL_SIZE 64 +#define KEYFILE_MAX_READ_LEN (1024*1024) + +VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ) +{ + unsigned __int32 crc = 0xffffffff; + int writePos = 0; + size_t totalRead = 0; + size_t i; + CHAR8 keyPool[KEYFILE_POOL_SIZE]; + + ZeroMem(keyPool, sizeof(keyPool)); + + for (i = 0; i < keyfileDataSize; i++) + { + crc = UPDC32(keyfileData[i], crc); + + keyPool[writePos++] += (unsigned __int8)(crc >> 24); + keyPool[writePos++] += (unsigned __int8)(crc >> 16); + keyPool[writePos++] += (unsigned __int8)(crc >> 8); + keyPool[writePos++] += (unsigned __int8)crc; + + if (writePos >= KEYFILE_POOL_SIZE) + writePos = 0; + + if (++totalRead >= KEYFILE_MAX_READ_LEN) + break; + } + + for (i = 0; i < sizeof(keyPool); i++) + { + if (i < password->Length) + password->Text[i] += keyPool[i]; + else + password->Text[i] = keyPool[i]; + } + + if (password->Length < (int)sizeof(keyPool)) + password->Length = sizeof(keyPool); + +} \ No newline at end of file diff --git a/Library/VeraCryptLib/DcsVeraCrypt.h b/Library/VeraCryptLib/DcsVeraCrypt.h new file mode 100644 index 0000000..aae0152 --- /dev/null +++ b/Library/VeraCryptLib/DcsVeraCrypt.h @@ -0,0 +1,84 @@ +/** @file +Interface for DCS services + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov +Copyright (c) 2016. VeraCrypt, Mounir IDRASSI + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the Apache License, Version 2.0. + +The full text of the license may be found at +https://opensource.org/licenses/Apache-2.0 +**/ + +#ifndef __DCSVERACRYPT_H__ +#define __DCSVERACRYPT_H__ + +#include +#include +#include + +////////////////////////////////////////////////////////////////////////// +// Auth +////////////////////////////////////////////////////////////////////////// +extern int gAuthPasswordType; +extern CHAR16* gPasswordPictureFileName; +extern char* gAuthPasswordMsg; +extern Password gAuthPassword; + +extern char* gAuthPimMsg; +extern int gAuthPimRqt; +extern int gAuthPim; + +extern int gAuthTcRqt; +extern int gAuthTc; + +extern char *gAuthHashMsg; +extern int gAuthHashRqt; +extern int gAuthHash; + +extern int gAuthBootRqt; +extern int gAuthBoot; + +extern int gAuthRetry; +extern INT32 gRUD; + +extern int gAuthSecRegionSearch; + +extern int gPlatformLocked; +extern int gTPMLocked; +extern int gSCLocked; + +extern int gAuthPwdCode; + +extern CHAR8* gPlatformKeyFile; +extern UINTN gPlatformKeyFileSize; + +extern EFI_GUID *gPartitionGuidOS; +extern int gDcsBootForce; + +extern CHAR8* gOnExitFailed; +extern CHAR8* gOnExitSuccess; +extern CHAR8* gOnExitNotFound; + +void +VCAuthAsk(); + +VOID +VCAskPwd( + IN UINTN pwdType, + OUT Password* vcPwd); + +VOID +VCAuthLoadConfig(); + +VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ); + +#endif + diff --git a/Library/VeraCryptLib/VeraCryptLib.inf b/Library/VeraCryptLib/VeraCryptLib.inf new file mode 100644 index 0000000..a4f257b --- /dev/null +++ b/Library/VeraCryptLib/VeraCryptLib.inf @@ -0,0 +1,120 @@ +## @file +# Library used for DCS +# +## + +[Defines] + INF_VERSION = 0x00010006 + BASE_NAME = VeraCryptLib + MODULE_UNI_FILE = VeraCryptLib.uni + FILE_GUID = 6E5F01BD-D550-40AC-AC63-167DE971E3A1 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = VeraCryptLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] +common\Crc.c +common\Crc.h +common\Crypto.c +common\Crypto.h +common\Endian.c +common\Endian.h +common\GfMul.h +common\Password.h +common\Pkcs5.c +common\Pkcs5.h +common\Tcdefs.h +common\Volumes.c +common\Volumes.h +common\Xts.c +common\Xts.h +common\Xml.c +common\Xml.h +crypto\Aes.h +crypto\Aeskey.c +crypto\Aesopt.h +crypto\Aestab.c +crypto\Aestab.h +crypto\Aes_hw_cpu.nasm +crypto\Aes_hw_cpu.h +crypto\config.h +crypto\Rmd160.c +crypto\Rmd160.h +crypto\Serpent.c +crypto\Serpent.h +crypto\Sha2.c +crypto\Sha2.h +crypto\Twofish.c +crypto\Twofish.h +crypto\Whirlpool.c +crypto\Whirlpool.h +crypto\GostCipher.c +crypto\GostCipher.h +crypto\Streebog.c +crypto\Streebog.h +crypto\kuznyechik.c +crypto\kuznyechik.h +crypto\Camellia.c +crypto\Camellia.h +crypto\cpu.c +crypto\cpu.h +DcsVeraCrypt.c +DcsVeraCrypt.h + +[Sources.X64] +crypto\Aes_x64.nasm +crypto\Gost89_x64.nasm + +[Sources.IA32] +llmath.c +crypto\Aes_x86.nasm + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + RngLib + +[Protocols] + + +[BuildOptions.IA32] +DEBUG_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2010x86_IA32_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +DEBUG_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /FAcs /D_UEFI +RELEASE_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /FAcs /D_UEFI +NOOPT_VS2015x86_IA32_CC_FLAGS == /arch:IA32 /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od /FAcs /D_UEFI + +RELEASE_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2010x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +RELEASE_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +DEBUG_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 +NOOPT_VS2015x86_IA32_NASM_FLAGS = -Xvc --prefix _ -d_UEFI=1 + +[BuildOptions.X64] +DEBUG_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2010x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +DEBUG_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /D_UEFI +RELEASE_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /D_UEFI +NOOPT_VS2015x86_X64_CC_FLAGS == /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /Gy /FIAutoGen.h /EHs-c- /GR- /GF /Zi /Gm /Od /D_UEFI + +RELEASE_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2010x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 + +RELEASE_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +DEBUG_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 +NOOPT_VS2015x86_X64_NASM_FLAGS = -Xvc -d_UEFI=1 diff --git a/Library/VeraCryptLib/llmath.c b/Library/VeraCryptLib/llmath.c new file mode 100644 index 0000000..6b4360c --- /dev/null +++ b/Library/VeraCryptLib/llmath.c @@ -0,0 +1,383 @@ +#include +void __cdecl atexit() {} + +int __cdecl _purecall() { return 0; } + +#if defined(_M_IX86) +////////////////////////////////////////////////////////////////////////// +// _allmul +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _allmul(void) +{ + _asm { + mov ebx, [esp + 4] ; ebx <- M1[0..31] + mov edx, [esp + 12] ; edx <- M2[0..31] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 16] ; ebx <- M1[0..31] * M2[32..63] + imul edx, [esp + 8] ; edx <- M1[32..63] * M2[0..31] + add ebx, edx ; carries are abandoned + mul ecx ; edx:eax <- M1[0..31] * M2[0..31] + add edx, ebx ; carries are abandoned + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _aullmul +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aullmul() +{ + _asm { + mov ebx, [esp + 4] ; ebx <- M1[0..31] + mov edx, [esp + 12] ; edx <- M2[0..31] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 16] ; ebx <- M1[0..31] * M2[32..63] + imul edx, [esp + 8] ; edx <- M1[32..63] * M2[0..31] + add ebx, edx ; carries are abandoned + mul ecx ; edx:eax <- M1[0..31] * M2[0..31] + add edx, ebx ; carries are abandoned + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _alldiv +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _alldiv() +{ + _asm { + ; Check sign of res + mov ebx, [esp + 8] ; dividend msdw + mov ecx, [esp + 16] ; divisor msdw + xor ebx, ecx + shr ebx, 31 + jz _PosRes ; if Result is positive + push 1 ; if is negative + jmp _Preparing + _PosRes: + push 0 + + ; Preparing operands + ; Dividend + _Preparing: + mov ecx, [esp + 12] + shr ecx, 31 + jz _ChkDvsr ; Divident is positive + mov eax, [esp + 12] ; is negative + mov ecx, [esp + 8] + xor eax, 0xFFFFFFFF + xor ecx, 0xFFFFFFFF + add ecx, 1 + jnc _DvntOK + adc eax, 0 + _DvntOK: + mov [esp + 12], eax + mov [esp + 8], ecx + + ; Divisor + _ChkDvsr: + mov ecx, [esp + 20] + shr ecx, 31 + jz _Divide ; Divisor is positive + mov eax, [esp + 20] ; is negative + mov ecx, [esp + 16] + xor eax, 0xFFFFFFFF + xor ecx, 0xFFFFFFFF + add ecx, 1 + jnc _DvsrOK + adc eax, 0 + _DvsrOK: + mov [esp + 20], eax + mov [esp + 16], ecx + + _Divide: + mov ecx, [esp + 20] ; ecx <- divisor[32..63] + test ecx, ecx + jnz __DivRemU64x64 ; call __DivRemU64x64 if Divisor > 2^32 + mov ecx, [esp + 16] ; ecx <- divisor + mov eax, [esp + 12] ; eax <- dividend[32..63] + xor edx, edx + div ecx ; eax <- quotient[32..63], edx <- remainder + push eax + mov eax, [esp + 12] ; eax <- dividend[0..31] + div ecx ; eax <- quotient[0..31] + pop edx ; edx <- quotient[32..63] - edx:eax + jmp _GetSign + + __DivRemU64x64: + mov edx, dword ptr [esp + 12] + mov eax, dword ptr [esp + 8] ; edx:eax <- dividend + mov edi, edx + mov esi, eax ; edi:esi <- dividend + mov ebx, dword ptr [esp + 16] ; ecx:ebx <- divisor + _B: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz _B + div ebx + mov ebx, eax ; ebx <- quotient + mov ecx, [esp + 20] ; ecx <- high dword of divisor + mul dword ptr [esp + 16] ; edx:eax <- quotient * divisor[0..31] + imul ecx, ebx ; ecx <- quotient * divisor[32..63] + add edx, ecx ; edx <- (quotient * divisor)[32..63] + ;mov ecx, dword ptr [esp + 32] ; ecx <- addr for Remainder + jc _TooLarge ; product > 2^64 + cmp edi, edx ; compare high 32 bits + ja _Correct + jb _TooLarge ; product > dividend + cmp esi, eax + jae _Correct ; product <= dividend + _TooLarge: + dec ebx ; adjust quotient by -1 + jecxz _Return ; return if Remainder == NULL + sub eax, dword ptr [esp + 16] + sbb edx, dword ptr [esp + 20] ; edx:eax <- (quotient - 1) * divisor + _Correct: + jecxz _Return + sub esi, eax + sbb edi, edx ; edi:esi <- remainder + ;mov [ecx], esi + ;mov [ecx + 4], edi + _Return: + mov eax, ebx ; eax <- quotient + xor edx, edx ; quotient is 32 bits long + + ; Get sign of result + _GetSign: + pop ecx ; Sign of res + jecxz _Rtrn ; Result is positive + xor eax, 0xFFFFFFFF + xor edx, 0xFFFFFFFF + add eax, 1 ; edx:eax + jnc _Rtrn + adc edx, 0 + + _Rtrn: + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// _aulldiv +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aulldiv() +{ + _asm { + mov ecx, [esp + 16] ; ecx <- divisor[32..63] + test ecx, ecx + jnz __DivRemU64x64 ; call __DivRemU64x64 if Divisor > 2^32 + mov ecx, [esp + 12] ; ecx <- divisor + mov eax, [esp + 8] ; eax <- dividend[32..63] + xor edx, edx + div ecx ; eax <- quotient[32..63], edx <- remainder + push eax + mov eax, [esp + 8] ; eax <- dividend[0..31] + div ecx ; eax <- quotient[0..31] + pop edx ; edx <- quotient[32..63] + ret 16 + + __DivRemU64x64: + mov edx, dword ptr [esp + 8] + mov eax, dword ptr [esp + 4] ; edx:eax <- dividend + mov edi, edx + mov esi, eax ; edi:esi <- dividend + mov ebx, dword ptr [esp + 12] ; ecx:ebx <- divisor + _B: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz _B + div ebx + mov ebx, eax ; ebx <- quotient + mov ecx, [esp + 16] ; ecx <- high dword of divisor + mul dword ptr [esp + 12] ; edx:eax <- quotient * divisor[0..31] + imul ecx, ebx ; ecx <- quotient * divisor[32..63] + add edx, ecx ; edx <- (quotient * divisor)[32..63] + ;mov ecx, dword ptr [esp + 32] ; ecx <- addr for Remainder + jc _TooLarge ; product > 2^64 + cmp edi, edx ; compare high 32 bits + ja _Correct + jb _TooLarge ; product > dividend + cmp esi, eax + jae _Correct ; product <= dividend + _TooLarge: + dec ebx ; adjust quotient by -1 + jecxz _Return ; return if Remainder == NULL + sub eax, dword ptr [esp + 12] + sbb edx, dword ptr [esp + 16] ; edx:eax <- (quotient - 1) * divisor + _Correct: + jecxz _Return + sub esi, eax + sbb edi, edx ; edi:esi <- remainder + ;mov [ecx], esi + ;mov [ecx + 4], edi + _Return: + mov eax, ebx ; eax <- quotient + xor edx, edx ; quotient is 32 bits long + + ret 16 + } +} + +////////////////////////////////////////////////////////////////////////// +// Shifts +////////////////////////////////////////////////////////////////////////// +__declspec(naked) void __cdecl _aullshr() { + _asm { + ; + ; Checking: Only handle 64bit shifting or more + ; + cmp cl, 64 + jae _Exit + + ; + ; Handle shifting between 0 and 31 bits + ; + cmp cl, 32 + jae More32 + shrd eax, edx, cl + shr edx, cl + ret + + ; + ; Handle shifting of 32-63 bits + ; +More32: + mov eax, edx + xor edx, edx + and cl, 31 + shr eax, cl + ret + + ; + ; Invalid number (less then 32bits), return 0 + ; +_Exit: + xor eax, eax + xor edx, edx + ret + } +} + +__declspec(naked) void __cdecl _allshl() { + _asm { + ; + ; Handle shifting of 64 or more bits (return 0) + ; + cmp cl, 64 + jae short ReturnZero + + ; + ; Handle shifting of between 0 and 31 bits + ; + cmp cl, 32 + jae short More32 + shld edx, eax, cl + shl eax, cl + ret + + ; + ; Handle shifting of between 32 and 63 bits + ; +More32: + mov edx, eax + xor eax, eax + and cl, 31 + shl edx, cl + ret + +ReturnZero: + xor eax,eax + xor edx,edx + ret + } +} + +UINT64 +EFIAPI +DivU64x64Remainder( +IN UINT64 Dividend, +IN UINT64 Divisor, +OUT UINT64 *Remainder OPTIONAL +); +/* + * Divides a 64-bit unsigned value by another 64-bit unsigned value and returns + * the 64-bit unsigned remainder. + */ +__declspec(naked) void __cdecl _aullrem(void) +{ + // + // Wrapper Implementation over EDKII DivU64x64Remainder() routine + // UINT64 + // EFIAPI + // DivU64x64Remainder ( + // IN UINT64 Dividend, + // IN UINT64 Divisor, + // OUT UINT64 *Remainder OPTIONAL + // ) + // + _asm { + ; Original local stack when calling _aullrem + ; ----------------- + ; | | + ; |---------------| + ; | | + ; |-- Divisor --| + ; | | + ; |---------------| + ; | | + ; |-- Dividend --| + ; | | + ; |---------------| + ; | ReturnAddr** | + ; ESP---->|---------------| + ; + + ; + ; Set up the local stack for Reminder pointer + ; + sub esp, 8 + push esp + + ; + ; Set up the local stack for Divisor parameter + ; + mov eax, [esp + 28] + push eax + mov eax, [esp + 28] + push eax + + ; + ; Set up the local stack for Dividend parameter + ; + mov eax, [esp + 28] + push eax + mov eax, [esp + 28] + push eax + + ; + ; Call native DivU64x64Remainder of BaseLib + ; + call DivU64x64Remainder + + ; + ; Put the Reminder in EDX:EAX as return value + ; + mov eax, [esp + 20] + mov edx, [esp + 24] + + ; + ; Adjust stack + ; + add esp, 28 + + ret 16 + } +} + +#endif diff --git a/Library/VeraCryptLib/mklinks_src.bat b/Library/VeraCryptLib/mklinks_src.bat new file mode 100644 index 0000000..aad3094 --- /dev/null +++ b/Library/VeraCryptLib/mklinks_src.bat @@ -0,0 +1,112 @@ +@echo off +pushd %~dp0 + +call :select_path "%veracrypt_src%" "Select VeraCrypt directory:" +set veracrypt_src=%select_path_result% + +set /P YesNo=Create links[Y/N]? +if /I ["%YesNo%"]==["Y"] goto :check_links +goto :end + +:check_links +if NOT EXIST common goto :create_links +set /P create_links_del_ren=Old links detected [D]elete or [R]ename? + +:create_links +if NOT EXIST common mkdir common +call :create_link common\Crc.c +call :create_link common\Crc.h +call :create_link common\Crypto.c +call :create_link common\Crypto.h +call :create_link common\Endian.c +call :create_link common\Endian.h +call :create_link common\GfMul.h +call :create_link common\Password.h +call :create_link common\Pkcs5.c +call :create_link common\Pkcs5.h +call :create_link common\Tcdefs.h +call :create_link common\Volumes.c +call :create_link common\Volumes.h +call :create_link common\Xml.c +call :create_link common\Xml.h +call :create_link common\Xts.c +call :create_link common\Xts.h + +if NOT EXIST crypto mkdir crypto +call :create_link crypto\GostCipher.c +call :create_link crypto\GostCipher.h +call :create_link crypto\Gost89_x64.asm Gost89_x64.nasm +call :create_link crypto\Streebog.c +call :create_link crypto\Streebog.h +call :create_link crypto\kuznyechik.c +call :create_link crypto\kuznyechik.h +call :create_link crypto\Aes.h +call :create_link crypto\Aeskey.c +call :create_link crypto\Aesopt.h +call :create_link crypto\Aestab.c +call :create_link crypto\Aestab.h +call :create_link crypto\Aes_hw_cpu.h +call :create_link crypto\Aes_hw_cpu.asm Aes_hw_cpu.nasm +call :create_link crypto\Aes_x64.asm Aes_x64.nasm +call :create_link crypto\Aes_x86.asm Aes_x86.nasm +call :create_link crypto\cpu.h +call :create_link crypto\cpu.c +call :create_link crypto\config.h +call :create_link crypto\misc.h +call :create_link crypto\Rmd160.c +call :create_link crypto\Rmd160.h +call :create_link crypto\Serpent.c +call :create_link crypto\Serpent.h +call :create_link crypto\Sha2.c +call :create_link crypto\Sha2.h +call :create_link crypto\Twofish.c +call :create_link crypto\Twofish.h +call :create_link crypto\Whirlpool.c +call :create_link crypto\Whirlpool.h +call :create_link crypto\Camellia.c +call :create_link crypto\Camellia.h + +set create_link_skip_pushd=Y +call :create_link Boot\Windows\BootCommon.h +call :create_link Boot\Windows\BootDefs.h +set create_link_skip_pushd=N + +goto :end + +:create_link +if /I NOT ["%create_link_skip_pushd%"]==["Y"] pushd %~dp1 +set fn=%~n1%~x1 +if NOT ["%2"]==[""] set fn=%2 +call :get_bak_name %fn% +if /I ["%create_links_del_ren%"]==["R"] ren %fn% %name_bak% +if EXIST "%fn%" del %fn% +@echo on +mklink /H %fn% %veracrypt_src%\%1 +@echo off +if /I NOT ["%create_link_skip_pushd%"]==["Y"] popd +goto :eof + +:get_bak_name +set name_bak=%1 +:get_bak_name_retry +if NOT EXIST %name_bak% goto :eof +set name_bak=%name_bak%.sv +goto :get_bak_name_retry + +rem call select path +:select_path +set select_path_default=%1 +if not exist "%select_path_default%" echo not found %select_path_default% +set select_path_msg=%2 +set select_path_msg=%select_path_msg:~1,-1% + +:select_path_retry +set select_path_result= +set /p select_path_result=[%select_path_default:~1,-1%] %select_path_msg% +if ["%select_path_result%"]==[""] set select_path_result=%select_path_default:~1,-1% +if exist %select_path_result% goto :eof +echo can not find %select_path_result% +goto :select_path_retry + +:end +popd \ No newline at end of file diff --git a/SecureBoot/certs/DCS_key_exchange.crt b/SecureBoot/certs/DCS_key_exchange.crt new file mode 100644 index 0000000..80bc7ca Binary files /dev/null and b/SecureBoot/certs/DCS_key_exchange.crt differ diff --git a/SecureBoot/certs/DCS_platform.crt b/SecureBoot/certs/DCS_platform.crt new file mode 100644 index 0000000..a7cf8ce Binary files /dev/null and b/SecureBoot/certs/DCS_platform.crt differ diff --git a/SecureBoot/certs/DCS_sign.crt b/SecureBoot/certs/DCS_sign.crt new file mode 100644 index 0000000..f0538db Binary files /dev/null and b/SecureBoot/certs/DCS_sign.crt differ diff --git a/SecureBoot/certs/MicCorUEFCA2011_2011-06-27.crt b/SecureBoot/certs/MicCorUEFCA2011_2011-06-27.crt new file mode 100644 index 0000000..9aa6ac6 Binary files /dev/null and b/SecureBoot/certs/MicCorUEFCA2011_2011-06-27.crt differ diff --git a/SecureBoot/certs/MicWinProPCA2011_2011-10-19.crt b/SecureBoot/certs/MicWinProPCA2011_2011-10-19.crt new file mode 100644 index 0000000..a6d001c Binary files /dev/null and b/SecureBoot/certs/MicWinProPCA2011_2011-10-19.crt differ diff --git a/SecureBoot/certs/readme.txt b/SecureBoot/certs/readme.txt new file mode 100644 index 0000000..29bed3c --- /dev/null +++ b/SecureBoot/certs/readme.txt @@ -0,0 +1,3 @@ +There are two public DB entries - one for Windows and one for the UEFI Certificate Authority (CA). +Windows DB: http://www.microsoft.com/pkiops/certs/MicWinProPCA2011_2011-10-19.crt +UEFI DB: http://www.microsoft.com/pkiops/certs/MicCorUEFCA2011_2011-06-27.crt diff --git a/SecureBoot/efi_sign.bat b/SecureBoot/efi_sign.bat new file mode 100644 index 0000000..4b4b764 --- /dev/null +++ b/SecureBoot/efi_sign.bat @@ -0,0 +1 @@ +signtool sign /ac %3 /f %2 /fd sha256 %1 \ No newline at end of file diff --git a/SecureBoot/readme.txt b/SecureBoot/readme.txt new file mode 100644 index 0000000..6e2dc43 --- /dev/null +++ b/SecureBoot/readme.txt @@ -0,0 +1,13 @@ +To update secure boot configuration +1. Enter BIOS configuration +2. Switch Secure boot to setup mode (or custom mode). It deletes PK (platform certificate) and allows to load DCS platform key. +3. Boot Windows +4. execute from admin command prompt + powershell -File sb_set_siglists.ps1 +It sets in PK (platform key) - DCS_platform +It sets in KEK (key exchange key) - DCS_key_exchange +It sets in db - DCS_sign MicWinProPCA2011_2011-10-19 MicCorUEFCA2011_2011-06-27 + +All DCS modules are protected by DCS_sign. +All Windows modules are protected by MicWinProPCA2011_2011-10-19 +All SHIM(linux) modules are protected by MicCorUEFCA2011_2011-06-27 \ No newline at end of file diff --git a/SecureBoot/sb_set_siglists.ps1 b/SecureBoot/sb_set_siglists.ps1 new file mode 100644 index 0000000..ae53ca8 --- /dev/null +++ b/SecureBoot/sb_set_siglists.ps1 @@ -0,0 +1,22 @@ +Set-ExecutionPolicy Bypass -Force +Import-Module secureboot + +Set-SecureBootUEFI -Name PK -Time 2015-09-11 -Content $null +Set-SecureBootUEFI -Name KEK -Time 2015-09-11 -Content $null +Set-SecureBootUEFI -Name db -Time 2015-09-11 -Content $null +Set-SecureBootUEFI -Name dbx -Time 2015-09-11 -Content $null + +Write-Host "Setting self-signed PK..." +Set-SecureBootUEFI -Time 2016-08-08T00:00:00Z -ContentFilePath siglists\DCS_platform_SigList.bin -SignedFilePath siglists\DCS_platform_SigList_Serialization.bin.p7 -Name PK + +Write-Host "Setting PK-signed KEK..." +Set-SecureBootUEFI -Time 2016-08-08T00:00:00Z -ContentFilePath siglists\DCS_key_exchange_SigList.bin -SignedFilePath siglists\DCS_key_exchange_SigList_Serialization.bin.p7 -Name KEK + +Write-Host "Setting KEK-signed DCS cert in db..." +Set-SecureBootUEFI -Time 2016-08-08T00:00:00Z -ContentFilePath siglists\DCS_sign_SigList.bin -SignedFilePath siglists\DCS_sign_SigList_Serialization.bin.p7 -Name db + +Write-Host "Setting KEK-signed MS cert in db..." +Set-SecureBootUEFI -Time 2016-08-08T00:00:00Z -ContentFilePath siglists\MicWinProPCA2011_2011-10-19_SigList.bin -SignedFilePath siglists\MicWinProPCA2011_2011-10-19_SigList_Serialization.bin.p7 -Name db -AppendWrite:$true + +Write-Host "Setting KEK-signed MS UEFI cert in db..." +Set-SecureBootUEFI -Time 2016-08-08T00:00:00Z -ContentFilePath siglists\MicCorUEFCA2011_2011-06-27_SigList.bin -SignedFilePath siglists\MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin.p7 -Name db -AppendWrite:$true diff --git a/SecureBoot/siglists/DCS_key_exchange_SigList.bin b/SecureBoot/siglists/DCS_key_exchange_SigList.bin new file mode 100644 index 0000000..62f5cc6 Binary files /dev/null and b/SecureBoot/siglists/DCS_key_exchange_SigList.bin differ diff --git a/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin b/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin new file mode 100644 index 0000000..1cffcf0 Binary files /dev/null and b/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin differ diff --git a/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin.p7 b/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin.p7 new file mode 100644 index 0000000..1e9d29a Binary files /dev/null and b/SecureBoot/siglists/DCS_key_exchange_SigList_Serialization.bin.p7 differ diff --git a/SecureBoot/siglists/DCS_platform_SigList.bin b/SecureBoot/siglists/DCS_platform_SigList.bin new file mode 100644 index 0000000..0b6d7e1 Binary files /dev/null and b/SecureBoot/siglists/DCS_platform_SigList.bin differ diff --git a/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin b/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin new file mode 100644 index 0000000..e8fbf79 Binary files /dev/null and b/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin differ diff --git a/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin.p7 b/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin.p7 new file mode 100644 index 0000000..19cb86d Binary files /dev/null and b/SecureBoot/siglists/DCS_platform_SigList_Serialization.bin.p7 differ diff --git a/SecureBoot/siglists/DCS_sign_SigList.bin b/SecureBoot/siglists/DCS_sign_SigList.bin new file mode 100644 index 0000000..9a3f568 Binary files /dev/null and b/SecureBoot/siglists/DCS_sign_SigList.bin differ diff --git a/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin b/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin new file mode 100644 index 0000000..de58d77 Binary files /dev/null and b/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin differ diff --git a/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin.p7 b/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin.p7 new file mode 100644 index 0000000..01753a8 Binary files /dev/null and b/SecureBoot/siglists/DCS_sign_SigList_Serialization.bin.p7 differ diff --git a/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList.bin b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList.bin new file mode 100644 index 0000000..413ccab Binary files /dev/null and b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList.bin differ diff --git a/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin new file mode 100644 index 0000000..735d962 Binary files /dev/null and b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin differ diff --git a/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin.p7 b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin.p7 new file mode 100644 index 0000000..ed8cefd Binary files /dev/null and b/SecureBoot/siglists/MicCorUEFCA2011_2011-06-27_SigList_Serialization.bin.p7 differ diff --git a/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList.bin b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList.bin new file mode 100644 index 0000000..ac542ca Binary files /dev/null and b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList.bin differ diff --git a/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin new file mode 100644 index 0000000..9138dae Binary files /dev/null and b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin differ diff --git a/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin.p7 b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin.p7 new file mode 100644 index 0000000..b08c60a Binary files /dev/null and b/SecureBoot/siglists/MicWinProPCA2011_2011-10-19_SigList_Serialization.bin.p7 differ diff --git a/bld.bat b/bld.bat new file mode 100644 index 0000000..75859a4 --- /dev/null +++ b/bld.bat @@ -0,0 +1,7 @@ +if not defined WORKSPACE ( + echo WORKSPACE not defined + goto :eof +) +pushd %WORKSPACE% +build %* +popd \ No newline at end of file diff --git a/setenv.bat b/setenv.bat new file mode 100644 index 0000000..82a963a --- /dev/null +++ b/setenv.bat @@ -0,0 +1,46 @@ +@echo off +pushd "%~dp0" + +if not defined PYTHONHOME ( + echo PYTHONHOME not found! + goto :end +) + +if defined VS100COMNTOOLS ( + call "%VS100COMNTOOLS%\vsvars32.bat" + goto :initialize +) else ( + echo MSVS2010 not found! + goto :end +) + +:initialize + +if not defined NASM_PREFIX set NASM_PREFIX=c:\Tools\nasm\ +if not defined EDK_PREFIX set EDK_PREFIX=c:\Tools\edk2 + +call :updatepath "%PYTHONHOME%" +call :updatepath "%NASM_PREFIX%" + +if not defined EDK_TOOLS_BIN ( + pushd "%EDK_PREFIX%" + call edksetup.bat + popd +) + +goto :end + +:updatepath +set appendpath=%~1 +for %%A in ("%path:;=";"%") do ( + if /I "%~1"=="%%~A" ( + echo %1 in path found + set appendpath= + ) +rem echo %%~A +) +if defined appendpath set path=%path%;%appendpath% +goto :eof + +:end +popd \ No newline at end of file -- cgit v1.2.3