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. --- 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 ++++ 10 files changed, 2671 insertions(+) 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 (limited to 'DcsCfg') 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); + } +} + -- cgit v1.2.3