From 6701b862aa96775609a7d42662ae4a98e43071bb Mon Sep 17 00:00:00 2001 From: kavsrf Date: Sun, 4 Dec 2016 13:46:48 +0300 Subject: TPM12 support --- DcsCfg/DcsCfg.h | 13 + DcsCfg/DcsCfg.inf | 2 + DcsCfg/DcsCfg.man | 19 +- DcsCfg/DcsCfgMain.c | 128 ++-- DcsCfg/DcsCfgTpm.c | 88 +++ DcsInt/DcsInt.c | 44 +- DcsPkg.dsc | 5 + DcsRe/DcsRe.c | 102 +-- Include/Library/CommonLib.h | 43 +- Include/Library/DcsCfgLib.h | 5 +- Include/Library/DcsTpmLib.h | 106 +++ Library/CommonLib/EfiConsole.c | 67 ++ Library/DcsCfgLib/DcsCfgLib.inf | 3 + Library/DcsCfgLib/DcsRandom.c | 144 +++- Library/DcsTpmLib/DcsTpmLib.inf | 48 ++ Library/DcsTpmLib/Tpm12.c | 1344 +++++++++++++++++++++++++++++++++ Library/VeraCryptLib/DcsVeraCrypt.c | 176 ++++- Library/VeraCryptLib/DcsVeraCrypt.h | 3 + Library/VeraCryptLib/VeraCryptLib.inf | 2 + Library/VeraCryptLib/llmath.c | 4 +- 20 files changed, 2136 insertions(+), 210 deletions(-) create mode 100644 DcsCfg/DcsCfgTpm.c create mode 100644 Include/Library/DcsTpmLib.h create mode 100644 Library/DcsTpmLib/DcsTpmLib.inf create mode 100644 Library/DcsTpmLib/Tpm12.c diff --git a/DcsCfg/DcsCfg.h b/DcsCfg/DcsCfg.h index 2ffd50d..8a9a15a 100644 --- a/DcsCfg/DcsCfg.h +++ b/DcsCfg/DcsCfg.h @@ -161,6 +161,19 @@ TestTouch(); EFI_STATUS DcsInteractiveSetup(); +////////////////////////////////////////////////////////////////////////// +// TPM +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12ListPcrs( + UINT32 sPcr, + UINT32 ePcr + ); +EFI_STATUS +Tpm12NvList(); + +EFI_STATUS +Tpm12DcsConfigure(); #endif // DcsCfg_h__ diff --git a/DcsCfg/DcsCfg.inf b/DcsCfg/DcsCfg.inf index c7218aa..c057b96 100644 --- a/DcsCfg/DcsCfg.inf +++ b/DcsCfg/DcsCfg.inf @@ -34,6 +34,7 @@ DcsCfgGraphics.c DcsCfgBlockio.c DcsCfgTouch.c + DcsCfgTpm.c DcsCfgSetup.c [Packages] @@ -51,6 +52,7 @@ GraphLib PasswordLib DcsCfgLib + DcsTpmLib VeraCryptLib ShellLib diff --git a/DcsCfg/DcsCfg.man b/DcsCfg/DcsCfg.man index bb6fda4..72575dc 100644 --- a/DcsCfg/DcsCfg.man +++ b/DcsCfg/DcsCfg.man @@ -35,16 +35,20 @@ DcsCfg -ds -wipe .SH OPTIONS + -dc - check devices (try to authorize) -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 + -rnd - select rnadom type (0 - none, 1 - file, 2- rdrand, 3 HMAC, 4 OPENSSL 5 TPM) + -rndgen - generate random file + -rndload - load rnd generator state from file + -rndsave - save rnd generator state to file -ul - USB device list -tl - touch device -tt - Test touch device @@ -55,18 +59,29 @@ DcsCfg -ds -wipe -bt - Beep device test -setup - interactive setup -pl - GPT list - -pf - file with GPT + -pf - file with GPT and params -ps - save GPT to file + -pz - delete info from 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 + -pedt - partition number to edit(from -pl) + -pexec - edit executable parameter + -prndsave - save random state to params + -prndload - load random state from params + -pwdcache - edit password cache in params -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] + -osdecrypt - decrypt OS (rescue) + -osrestorekey - restore key (rescue) + -tpmpcrs - print PCRs + -tpmnvlist - List NV regions in TPM + -tpmcfg - Configure TPM .SH DESCRIPTION diff --git a/DcsCfg/DcsCfgMain.c b/DcsCfg/DcsCfgMain.c index 59ff730..6e4c863 100644 --- a/DcsCfg/DcsCfgMain.c +++ b/DcsCfg/DcsCfgMain.c @@ -34,51 +34,53 @@ https://opensource.org/licenses/LGPL-3.0 ////////////////////////////////////////////////////////////////////////// // 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_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" - +#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" +#define OPT_TPM_PCRS L"-tpmpcrs" +#define OPT_TPM_NVLIST L"-tpmnvlist" +#define OPT_TPM_CFG L"-tpmcfg" STATIC CONST SHELL_PARAM_ITEM ParamList[] = { { OPT_DISK_LIST, TypeValue }, { OPT_DISK_CHECK, TypeFlag }, @@ -124,6 +126,9 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = { { OPT_WIPE, TypeDoubleValue }, { OPT_OS_DECRYPT, TypeFlag }, { OPT_OS_RESTORE_KEY, TypeFlag }, + { OPT_TPM_PCRS, TypeDoubleValue }, + { OPT_TPM_NVLIST, TypeFlag }, + { OPT_TPM_CFG, TypeFlag }, { NULL, TypeMax } }; @@ -257,6 +262,30 @@ DcsCfgMain( TestTouch(); } + // TPM + if (ShellCommandLineGetFlag(Package, OPT_TPM_PCRS)) { + CONST CHAR16* opt1 = NULL; + CONST CHAR16* opt2 = NULL; + UINT32 sPcr; + UINT32 ePcr; + opt1 = ShellCommandLineGetValue(Package, OPT_TPM_PCRS); + sPcr = (UINT32)StrDecimalToUintn(opt1); + opt2 = StrStr(opt1, L" "); + if (opt2 != NULL) { + opt2++; + } + ePcr = (UINT32)StrDecimalToUintn(opt2); + Tpm12ListPcrs(sPcr, ePcr); + } + + if (ShellCommandLineGetFlag(Package, OPT_TPM_NVLIST)) { + Tpm12NvList(); + } + + if (ShellCommandLineGetFlag(Package, OPT_TPM_CFG)) { + Tpm12DcsConfigure(); + } + // Graph if (ShellCommandLineGetFlag(Package, OPT_GRAPH_DEVICE)) { CONST CHAR16* opt = NULL; @@ -294,15 +323,20 @@ DcsCfgMain( // Create random if (ShellCommandLineGetFlag(Package, OPT_RND)) { CONST CHAR16* opt = NULL; - CONST CHAR16* context = NULL; + CHAR16* context = NULL; UINTN rndType; + UINTN contextSize = 0; opt = ShellCommandLineGetValue(Package, OPT_RND); rndType = StrDecimalToUintn(opt); - context = StrStr(opt, L" "); + context = (CHAR16*)StrStr(opt, L" "); if (context != NULL) { context++; + contextSize = StrLen(context) * 2; + if (!EFI_ERROR(FileExist(NULL, context))) { + FileLoad(NULL, context, &context, &contextSize); + } } - res = RndInit(rndType, (CHAR16*)context, &gRnd); + res = RndInit(rndType, context, contextSize, &gRnd); if (EFI_ERROR(res)) { ERR_PRINT(L"Random: %r\n", res); } diff --git a/DcsCfg/DcsCfgTpm.c b/DcsCfg/DcsCfgTpm.c new file mode 100644 index 0000000..5003132 --- /dev/null +++ b/DcsCfg/DcsCfgTpm.c @@ -0,0 +1,88 @@ +/** @file +This is DCS configuration, TPM + +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 "DcsVeraCrypt.h" + +EFI_STATUS +Tpm12ListPcrs( + UINT32 sPcr, + UINT32 ePcr + ) { + EFI_STATUS res; + res = InitTpm12(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + return res; + } + return Tpm12DumpPcrs(sPcr, ePcr); +} + +EFI_STATUS +Tpm12NvList( + ) { + EFI_STATUS res; + UINT32 count; + UINT32 i; + UINT32 nv[256]; + res = InitTpm12(); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + return res; + } + count = sizeof(nv); + res = Tpm12GetNvList(&count, nv); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + return res; + } + count = count >> 2; + for (i = 0; i < count; ++i) { + UINT32 index = SwapBytes32(nv[i]); + UINT32 attr = 0; + UINT32 dataSz = 0; + UINT32 pcrR = 0; + UINT32 pcrW = 0; + OUT_PRINT(L"%H%08x%N ", index); + res = Tpm12NvDetails(index, &attr, &dataSz, &pcrR, &pcrW); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + continue; + } + + OUT_PRINT(L"Attr[%08x] PcrR[%08x] PcrW[%08x] [%d] ", attr, pcrR, pcrW, dataSz); + OUT_PRINT(L"\n"); + } + return res; +} + +EFI_STATUS +Tpm12DcsConfigure( + ) { + EFI_STATUS res; + Password pwd; + ZeroMem(&pwd, sizeof(pwd)); + CE(GetTpm()); + CE(RndInit(RndTypeTpm, NULL, 0, &gRnd)); + CE(gTpm->Configure(gTpm)); + CE(gTpm->Apply(gTpm, &pwd)); + return res; + +err: + ERR_PRINT(L"%r, line %d", res, gCELine); + return res; +} diff --git a/DcsInt/DcsInt.c b/DcsInt/DcsInt.c index 6d008cc..af2391b 100644 --- a/DcsInt/DcsInt.c +++ b/DcsInt/DcsInt.c @@ -23,6 +23,7 @@ https://opensource.org/licenses/LGPL-3.0 #include #include #include +#include #include "common/Tcdefs.h" #include "common/Crypto.h" @@ -262,7 +263,7 @@ IntBlockIO_Write( writeCrypted = MEM_ALLOC(BufferSize); if (writeCrypted == NULL) { Status = EFI_BAD_BUFFER_SIZE; - return Status; + return Status; } CopyMem(writeCrypted, Buffer, BufferSize); // Print(L"*"); @@ -354,7 +355,7 @@ IntBlockIo_Hook( DcsIntBlockIo->Controller = DeviceHandle; DcsIntBlockIo->BlockIo = BlockIo; DcsIntBlockIo->IsReinstalled = 0; -// Block +// Block // Tpl = gBS->RaiseTPL(TPL_NOTIFY); // Install new routines DcsIntBlockIo->CryptInfo = SecRegionCryptInfo; @@ -570,28 +571,28 @@ SecRegionChangePwd() { if (vcres != 0) { ERR_PRINT(L"header create error(%x)\n", vcres); - Status = EFI_INVALID_PARAMETER; - goto ret; + Status = EFI_INVALID_PARAMETER; + goto ret; } // get BlockIo protocol bio = EfiGetBlockIO(SecRegionHandle); if (bio == NULL) { ERR_PRINT(L"Block io not supported\n,"); - Status = EFI_NOT_FOUND; - goto ret; + Status = EFI_NOT_FOUND; + goto ret; } Status = bio->WriteBlocks(bio, bio->Media->MediaId, SecRegionSector, 512, Header); if (EFI_ERROR(Status)) { ERR_PRINT(L"Write: %r\n", Status); - goto ret; + goto ret; } CopyMem(&gAuthPassword, &newPassword, sizeof(gAuthPassword)); CopyMem(SecRegionData + SecRegionOffset, Header, 512); ERR_PRINT(L"Update (%r)\n", Status); - -ret: + +ret: MEM_BURN(&newPassword, sizeof(newPassword)); MEM_BURN(&confirmPassword, sizeof(confirmPassword)); return Status; @@ -644,7 +645,7 @@ SecRegionTryDecrypt() } 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); + OUT_PRINT(L"Start %d %lld len %lld\n", SecRegionOffset / (1024*128), SecRegionCryptInfo->EncryptedAreaStart.Value, SecRegionCryptInfo->EncryptedAreaLength.Value); break; } else { ERR_PRINT(L"Authorization failed. Wrong password, PIM or hash. Decrypt error(%x)\n\r", vcres); @@ -963,6 +964,7 @@ UefiMain( if (key.UnicodeChar != 0) { GetKey(); } + OUT_PRINT(L"\n"); } } else if (gRUD != 0) { // RUD defined @@ -1020,12 +1022,26 @@ UefiMain( return res; } + res = GetTpm(); // Try to get TPM + if (!EFI_ERROR(res)) { + if (gConfigBuffer != NULL) { + TpmMeasure(gConfigBuffer, gConfigBufferSize); // Measure configuration + } + RndInit(RndTypeTpm, NULL, 0, &gRnd); + if (gTpm->IsConfigured(gTpm) && !gTpm->IsOpen(gTpm)) { + ERR_PRINT(L"TPM is configured but locked. Probably boot chain is modified!\n"); + KeyWait(L"%1d\r", 9, 0, 0); + } + } + DetectX86Features(); res = SecRegionTryDecrypt(); - - // Reset Console buffer - gST->ConIn->Reset(gST->ConIn, FALSE); - + if (gTpm != NULL) { + gTpm->Lock(gTpm); + } + // Reset Console buffer + gST->ConIn->Reset(gST->ConIn, FALSE); + if (EFI_ERROR(res)) { return OnExit(gOnExitFailed, OnExitAuthFaild, res); } diff --git a/DcsPkg.dsc b/DcsPkg.dsc index e3e4963..8b1004f 100644 --- a/DcsPkg.dsc +++ b/DcsPkg.dsc @@ -44,6 +44,10 @@ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf @@ -61,6 +65,7 @@ PasswordLib|DcsPkg/Library/PasswordLib/PasswordLib.inf RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf DcsCfgLib|DcsPkg/Library/DcsCfgLib/DcsCfgLib.inf + DcsTpmLib|DcsPkg/Library/DcsTpmLib/DcsTpmLib.inf VeraCryptLib|DcsPkg/Library/VeraCryptLib/VeraCryptLib.inf [LibraryClasses.common.UEFI_APPLICATION] diff --git a/DcsRe/DcsRe.c b/DcsRe/DcsRe.c index 1278eea..1d86e50 100644 --- a/DcsRe/DcsRe.c +++ b/DcsRe/DcsRe.c @@ -23,61 +23,11 @@ https://opensource.org/licenses/LGPL-3.0 ////////////////////////////////////////////////////////////////////////// // 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; - StrCatS(item->Text, sizeof (item->Text) / sizeof (CHAR16), 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 ////////////////////////////////////////////////////////////////////////// @@ -144,7 +94,7 @@ SelectEfiVolume() // Actions ////////////////////////////////////////////////////////////////////////// EFI_STATUS -ActionBootWinPE() { +ActionBootWinPE(IN VOID* ctx) { #ifdef _M_X64 return EfiExec(NULL, L"EFI\\Boot\\WinPE_bootx64.efi"); #else @@ -153,12 +103,12 @@ ActionBootWinPE() { } EFI_STATUS -ActionShell() { +ActionShell(IN VOID* ctx) { return EfiExec(NULL, L"EFI\\Shell\\Shell.efi"); } EFI_STATUS -ActionDcsBoot() { +ActionDcsBoot(IN VOID* ctx) { SelectEfiVolume(); if (EfiBootVolume == NULL) return EFI_NOT_READY; return EfiExec(gFSHandles[EfiBootVolumeIndex], L"EFI\\VeraCrypt\\DcsBoot.efi"); @@ -176,7 +126,7 @@ CHAR16* DcsBootBins[] = { Copy DCS binaries from rescue disk to EFI boot volume */ EFI_STATUS -ActionRestoreDcsLoader() { +ActionRestoreDcsLoader(IN VOID* ctx) { EFI_STATUS res = EFI_NOT_READY; UINTN i; SelectEfiVolume(); @@ -194,7 +144,7 @@ CHAR16* sDcsBootEfiDesc = L"VeraCrypt(DCS) loader"; Update boot menu */ EFI_STATUS -ActionRestoreDcsBootMenu() +ActionRestoreDcsBootMenu(IN VOID* ctx) { EFI_STATUS res = EFI_NOT_READY; SelectEfiVolume(); @@ -207,7 +157,7 @@ ActionRestoreDcsBootMenu() } EFI_STATUS -ActionRemoveDcsBootMenu() +ActionRemoveDcsBootMenu(IN VOID* ctx) { EFI_STATUS res = EFI_NOT_READY; BootMenuItemRemove(L"BootDC5B"); @@ -219,7 +169,7 @@ ActionRemoveDcsBootMenu() Copy DcsProp from rescue disk to EFI boot volume */ EFI_STATUS -ActionRestoreDcsProp() { +ActionRestoreDcsProp(IN VOID* ctx) { SelectEfiVolume(); if (EfiBootVolume == NULL) return EFI_NOT_READY; return FileCopy(NULL, L"EFI\\VeraCrypt\\DcsProp", EfiBootVolume, L"EFI\\VeraCrypt\\DcsProp", 1024*1024); @@ -233,27 +183,27 @@ CHAR16* sOSRestoreKey = OPT_OS_RESTORE_KEY; CHAR16* sDcsCfg = L"EFI\\VeraCrypt\\DcsCfg.dcs"; EFI_STATUS -ActionRestoreHeader() { +ActionRestoreHeader(IN VOID* ctx) { 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() { +ActionDecryptOS(IN VOID* ctx) { 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() { +ActionExit(IN VOID* ctx) { gContiniue = FALSE; return EFI_SUCCESS; } EFI_STATUS -ActionHelp() { +ActionHelp(IN VOID* ctx) { OUT_PRINT(L"\ %HRescue disk for VeraCrypt OS encryption%N\n\r\ Help message to be defined\n\r\ @@ -288,42 +238,38 @@ DcsReMain( return res; } - item = AppendMenu(NULL, L"Decrypt OS", 'd', ActionDecryptOS); + item = DcsMenuAppend(NULL, L"Decrypt OS", 'd', ActionDecryptOS, NULL); 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); + item = DcsMenuAppend(item, L"Restore VeraCrypt loader to boot menu", 'm', ActionRestoreDcsBootMenu, NULL); + item = DcsMenuAppend(item, L"Remove VeraCrypt loader from boot menu", 'z' , ActionRemoveDcsBootMenu, NULL); if (!EFI_ERROR(FileExist(NULL, L"EFI\\VeraCrypt\\DcsProp"))) { - item = AppendMenu(item, L"Restore VeraCrypt loader configuration to system disk", 'c', ActionRestoreDcsProp); + item = DcsMenuAppend(item, L"Restore VeraCrypt loader configuration to system disk", 'c', ActionRestoreDcsProp, NULL); } if (!EFI_ERROR(FileExist(NULL, L"EFI\\VeraCrypt\\svh_bak"))) { - item = AppendMenu(item, L"Restore OS header keys", 'k', ActionRestoreHeader); + item = DcsMenuAppend(item, L"Restore OS header keys", 'k', ActionRestoreHeader, NULL); } 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); + item = DcsMenuAppend(item, L"Restore VeraCrypt loader binaries to system disk", 'r', ActionRestoreDcsLoader, NULL); + item = DcsMenuAppend(item, L"Boot VeraCrypt loader from rescue disk", 'v', ActionDcsBoot, NULL); } -#ifdef _M_X64 if (!EFI_ERROR(FileExist(NULL, L"EFI\\Boot\\WinPE_bootx64.efi"))) { -#else - if (!EFI_ERROR(FileExist(NULL, L"EFI\\Boot\\WinPE_bootia32.efi"))) { -#endif - item = AppendMenu(item, L"Boot Windows PE from rescue disk", 'w', ActionBootWinPE); + item = DcsMenuAppend(item, L"Boot Windows PE from rescue disk", 'w', ActionBootWinPE, NULL); } if (!EFI_ERROR(FileExist(NULL, L"EFI\\Shell\\Shell.efi"))) { - item = AppendMenu(item, L"Boot Shell.efi from rescue disk", 's', ActionShell); + item = DcsMenuAppend(item, L"Boot Shell.efi from rescue disk", 's', ActionShell, NULL); } - item = AppendMenu(item, L"Help", 'h', ActionHelp); - item = AppendMenu(item, L"Exit", 'e', ActionExit); + item = DcsMenuAppend(item, L"Help", 'h', ActionHelp, NULL); + item = DcsMenuAppend(item, L"Exit", 'e', ActionExit, NULL); OUT_PRINT(L"%V%a rescue disk %a%N\n", TC_APP_NAME, VERSION_STRING); gBS->SetWatchdogTimer(0, 0, 0, NULL); do { - PrintMenu(gMenu); + DcsMenuPrint(gMenu); item = NULL; key.UnicodeChar = 0; while (item == NULL) { @@ -335,7 +281,7 @@ DcsReMain( } } OUT_PRINT(L"%c\n",key.UnicodeChar); - res = item->Action(); + res = item->Action(item->Context); if (EFI_ERROR(res)) { ERR_PRINT(L"%r\n", res); } diff --git a/Include/Library/CommonLib.h b/Include/Library/CommonLib.h index e1e30b0..5f96bba 100644 --- a/Include/Library/CommonLib.h +++ b/Include/Library/CommonLib.h @@ -22,6 +22,15 @@ https://opensource.org/licenses/LGPL-3.0 #include #include +////////////////////////////////////////////////////////////////////////// +// Check error +////////////////////////////////////////////////////////////////////////// +extern UINTN gCELine; +#define CE(ex) gCELine = __LINE__; if(EFI_ERROR(res = ex)) goto err + +////////////////////////////////////////////////////////////////////////// +// defines +////////////////////////////////////////////////////////////////////////// #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f)) #define FIELD_OFFSET(t, f) ((UINTN)(&((t*)0)->f)) @@ -32,7 +41,7 @@ https://opensource.org/licenses/LGPL-3.0 #define MEM_ALLOC MemAlloc #define MEM_FREE MemFree #define MEM_REALLOC MemRealloc -#define MEM_BURN(ptr,count) do { volatile char *burnPtr = (volatile char *)(ptr); UINT64 burnCount = (UINT64) count; while (burnCount--) *burnPtr++ = 0; } while (0) +#define MEM_BURN(ptr,count) do { volatile char *burnPtr = (volatile char *)(ptr); UINTN burnCount = (UINTN) count; while (burnCount--) *burnPtr++ = 0; } while (0) VOID* MemAlloc( @@ -182,6 +191,11 @@ TouchGetIO( #define OUT_PRINT(format, ...) AttrPrintEx(-1,-1, format, ##__VA_ARGS__) #define ERR_PRINT(format, ...) AttrPrintEx(-1,-1, L"%E" format L"%N" , ##__VA_ARGS__) +VOID +PrintBytes( + IN UINT8* Data, + IN UINT32 Size); + EFI_STATUS ConsoleGetOutput( IN EFI_HANDLE handle, @@ -270,6 +284,33 @@ AsciiStrToGuid( IN CHAR8 *str ); +////////////////////////////////////////////////////////////////////////// +// Menu +////////////////////////////////////////////////////////////////////////// +typedef EFI_STATUS(*MENU_ACTION)(IN VOID *ctx); + +typedef struct _MENU_ITEM MENU_ITEM; +typedef struct _MENU_ITEM { + CHAR16 Text[128]; + CHAR16 Select; + MENU_ACTION Action; + VOID* Context; + MENU_ITEM *Next; +} MENU_ITEM, *PMENU_ITEM; + +PMENU_ITEM +DcsMenuAppend( + IN PMENU_ITEM menu, + IN CHAR16 *text, + IN CHAR16 select, + IN MENU_ACTION action, + IN VOID* actionContext + ); + +VOID +DcsMenuPrint( + IN PMENU_ITEM head + ); ////////////////////////////////////////////////////////////////////////// // Attribute print diff --git a/Include/Library/DcsCfgLib.h b/Include/Library/DcsCfgLib.h index 6d74729..322aaa1 100644 --- a/Include/Library/DcsCfgLib.h +++ b/Include/Library/DcsCfgLib.h @@ -118,7 +118,9 @@ enum RndGeneratorTypes { RndTypeNone = 0, RndTypeFile, RndTypeRDRand, - RndTypeDtrmHmacSha512 + RndTypeDtrmHmacSha512, + RndTypeOpenSSL, + RndTypeTpm }; #define RND_HEADER_SIGN SIGNATURE_64('D','C','S','_','R','A','N','D') @@ -186,6 +188,7 @@ EFI_STATUS RndInit( IN UINTN rndType, IN VOID* Context, + IN UINTN ContextSize, OUT DCS_RND **rnd); // Serialize rnd with state to/from memory diff --git a/Include/Library/DcsTpmLib.h b/Include/Library/DcsTpmLib.h new file mode 100644 index 0000000..a8f015e --- /dev/null +++ b/Include/Library/DcsTpmLib.h @@ -0,0 +1,106 @@ +/** @file +Dcs TPM 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 __DCSTPMLIB_H__ +#define __DCSTPMLIB_H__ + +#include + +EFI_STATUS +InitTpm12(); + +EFI_STATUS +Tpm12PcrRead( + IN UINT32 PcrIndex, + OUT void *PcrValue + ); + +EFI_STATUS +Tpm12DumpPcrs( + IN UINT32 sPcr, + IN UINT32 ePcr); + +EFI_STATUS +Tpm12GetNvList( + OUT UINT32 *respSize, + OUT UINT32 *resp + ); + +EFI_STATUS +Tpm12NvDetails( + IN UINT32 index, + OUT UINT32 *attr, + OUT UINT32 *dataSz, + OUT UINT32 *pcrR, + OUT UINT32 *pcrW + ); + +EFI_STATUS +Tpm12GetRandom( + IN OUT UINT32 *DataSize, + OUT UINT8 *Data + ); + +////////////////////////////////////////////////////////////////////////// +// DCS TPM protocol +////////////////////////////////////////////////////////////////////////// +/* +Lock - Try lock TPM secret +Apply - Apply secret to password +Configure - Create TPM secret and configure PCRs +IsConfigured - TPM secret is set? +IsOpen - Can apply secret? +*/ +typedef struct _DCS_TPM_PROTOCOL DCS_TPM_PROTOCOL; + +extern DCS_TPM_PROTOCOL* gTpm; + +typedef EFI_STATUS(*DCS_TPM_LOCK)( + IN DCS_TPM_PROTOCOL *tpm + ); + +typedef EFI_STATUS(*DCS_TPM_APPLY)( + IN DCS_TPM_PROTOCOL *tpm, + OUT VOID* pwd + ); + +typedef EFI_STATUS(*DCS_TPM_CONFIGURE)( + IN DCS_TPM_PROTOCOL *tpm + ); + +typedef BOOLEAN(*DCS_TPM_IS_OPEN)( + IN DCS_TPM_PROTOCOL *tpm + ); + +typedef BOOLEAN(*DCS_TPM_IS_CONFIGURED)( + IN DCS_TPM_PROTOCOL *tpm + ); + +typedef struct _DCS_TPM_PROTOCOL { + DCS_TPM_LOCK Lock; + DCS_TPM_APPLY Apply; + DCS_TPM_CONFIGURE Configure; + DCS_TPM_IS_OPEN IsOpen; + DCS_TPM_IS_CONFIGURED IsConfigured; +} DCS_TPM_PROTOCOL; + +EFI_STATUS +GetTpm(); + +EFI_STATUS +TpmMeasure( + IN VOID* data, + IN UINTN dataSz + ); + +#endif \ No newline at end of file diff --git a/Library/CommonLib/EfiConsole.c b/Library/CommonLib/EfiConsole.c index f03f3f8..63b32ae 100644 --- a/Library/CommonLib/EfiConsole.c +++ b/Library/CommonLib/EfiConsole.c @@ -19,10 +19,27 @@ https://opensource.org/licenses/LGPL-3.0 #include #include +UINTN gCELine = 0; + ////////////////////////////////////////////////////////////////////////// // Print ////////////////////////////////////////////////////////////////////////// +VOID +PrintBytes( + IN UINT8* Data, + IN UINT32 Size) +{ + UINT32 i; + for (i = 0; i < Size; ++i) { + UINT32 val = Data[i]; + OUT_PRINT(L"%02X", val); + } +} + +////////////////////////////////////////////////////////////////////////// +// Input +////////////////////////////////////////////////////////////////////////// VOID FlushInputDelay( IN UINTN delay @@ -327,6 +344,56 @@ AsciiStrToGuid( return res; } +////////////////////////////////////////////////////////////////////////// +// Console menu +////////////////////////////////////////////////////////////////////////// + +PMENU_ITEM +DcsMenuAppend( + IN PMENU_ITEM menu, + IN CHAR16 *text, + IN CHAR16 select, + IN MENU_ACTION action, + IN VOID* actionContext + ) { + PMENU_ITEM item; + item = (PMENU_ITEM)MEM_ALLOC(sizeof(MENU_ITEM)); + if (item == NULL) return item; + item->Action = action; + item->Context = actionContext; + StrCat(item->Text, text); + item->Select = select; + if (menu != NULL) { + menu->Next = item; + } + return item; +} + +VOID +DcsMenuPrint( + IN 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"]:"); +} ////////////////////////////////////////////////////////////////////////// diff --git a/Library/DcsCfgLib/DcsCfgLib.inf b/Library/DcsCfgLib/DcsCfgLib.inf index 8607cb4..d199bb1 100644 --- a/Library/DcsCfgLib/DcsCfgLib.inf +++ b/Library/DcsCfgLib/DcsCfgLib.inf @@ -36,11 +36,14 @@ DcsRandom.c [Packages] MdePkg/MdePkg.dec DcsPkg/DcsPkg.dec + CryptoPkg/CryptoPkg.dec [LibraryClasses] MemoryAllocationLib UefiLib RngLib + BaseCryptLib + DcsTpmLib [Protocols] diff --git a/Library/DcsCfgLib/DcsRandom.c b/Library/DcsCfgLib/DcsRandom.c index a269a46..084a8cf 100644 --- a/Library/DcsCfgLib/DcsRandom.c +++ b/Library/DcsCfgLib/DcsRandom.c @@ -18,9 +18,11 @@ https://opensource.org/licenses/LGPL-3.0 #include #include #include +#include #include #include +#include "../../Include/Library/DcsTpmLib.h" DCS_RND* gRnd = NULL; @@ -61,7 +63,8 @@ RndFileGetBytes( EFI_STATUS RndFileInit( IN DCS_RND* rnd, - IN VOID* Context + IN VOID* Context, + IN UINTN ContextSize ) { EFI_STATUS res = EFI_NOT_FOUND; @@ -70,10 +73,8 @@ RndFileInit( 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); - } + rnd->State.File.Data = Context; + rnd->State.File.Size = ContextSize; } return res; } @@ -121,7 +122,8 @@ RndRDRandGetBytes( EFI_STATUS RndRDRandInit( IN DCS_RND* rnd, - IN VOID* Context + IN VOID* Context, + IN UINTN ContextSize ) { ZeroMem(rnd, sizeof(DCS_RND)); @@ -321,8 +323,8 @@ RndDtrmHmacSha512GetBytes( EFI_STATUS RndDtrmHmacSha512Init( IN DCS_RND* rnd, - IN VOID* Context - ) + IN VOID* Context, + IN UINTN ContextSize) { EFI_STATUS res = EFI_SUCCESS; ZeroMem(rnd, sizeof(DCS_RND)); @@ -331,24 +333,107 @@ RndDtrmHmacSha512Init( 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; - } + res = RndDtrmHmacSha512Update(&rnd->State.HMacSha512, (UINT8*)Context, ContextSize, 0); + if (EFI_ERROR(res)) { + rnd->Type = RndTypeNone; } } return rnd->Prepare(rnd); } +////////////////////////////////////////////////////////////////////////// +// OpenSSL random +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndOpenSSLPrepare( + IN DCS_RND* rnd + ) +{ + UINT64 rndTmp; + if (rnd != NULL && rnd->Type == RndTypeOpenSSL) { + if (RandomBytes((UINT8*)&rndTmp, 8)) { + return EFI_SUCCESS; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndOpenSSLGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + if (rnd != NULL && rnd->Type == RndTypeOpenSSL) { + if (RandomBytes(buf, len)) { + return EFI_SUCCESS; + } + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndOpenSSLInit( + IN DCS_RND* rnd, + IN VOID* Context, + IN UINTN ContextSize + ) +{ + int res; + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeOpenSSL; + rnd->GetBytes = RndOpenSSLGetBytes; + rnd->Prepare = RndOpenSSLPrepare; + res = RandomSeed(Context, ContextSize); + if (!res) { + return EFI_NOT_READY; + } + return rnd->Prepare(rnd); +} + +////////////////////////////////////////////////////////////////////////// +// TPM random +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +RndTpmPrepare( + IN DCS_RND* rnd + ) +{ + UINT64 rndTmp; + UINT32 sz = sizeof(rndTmp); + if (rnd != NULL && rnd->Type == RndTypeTpm) { + return Tpm12GetRandom(&sz, (UINT8*)&rndTmp); + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndTpmGetBytes( + IN DCS_RND *rnd, + OUT UINT8 *buf, + IN UINTN len) +{ + UINT32 sz = (UINT32)len; + if (rnd != NULL && rnd->Type == RndTypeTpm) { + return Tpm12GetRandom(&sz, buf); + } + return EFI_NOT_READY; +} + +EFI_STATUS +RndTpmInit( + IN DCS_RND* rnd, + IN VOID* Context, + IN UINTN ContextSize + ) +{ + ZeroMem(rnd, sizeof(DCS_RND)); + rnd->Type = RndTypeTpm; + rnd->GetBytes = RndTpmGetBytes; + rnd->Prepare = RndTpmPrepare; + return rnd->Prepare(rnd); +} + ////////////////////////////////////////////////////////////////////////// // Random API ////////////////////////////////////////////////////////////////////////// @@ -356,6 +441,7 @@ EFI_STATUS RndInit( IN UINTN rndType, IN VOID* Context, + IN UINTN ContextSize, OUT DCS_RND **rnd) { if (rnd != NULL) { @@ -366,13 +452,19 @@ RndInit( rndTemp->Type = (UINT32)rndType; switch (rndType) { case RndTypeFile: - res = RndFileInit(rndTemp, Context); + res = RndFileInit(rndTemp, Context, ContextSize); break; case RndTypeRDRand: - res = RndRDRandInit(rndTemp, Context); + res = RndRDRandInit(rndTemp, Context, ContextSize); break; case RndTypeDtrmHmacSha512: - res = RndDtrmHmacSha512Init(rndTemp, Context); + res = RndDtrmHmacSha512Init(rndTemp, Context, ContextSize); + break; + case RndTypeOpenSSL: + res = RndOpenSSLInit(rndTemp, Context, ContextSize); + break; + case RndTypeTpm: + res = RndTpmInit(rndTemp, Context, ContextSize); break; } if (EFI_ERROR(res)) { @@ -417,7 +509,7 @@ RndSave( EFI_STATUS res = EFI_NOT_READY; DCS_RND_SAVED *RndSaved; UINT32 crc; - if (rnd != NULL && rndSaved != NULL && rnd->Type != RndTypeFile) { + if (rnd != NULL && rndSaved != NULL && rnd->Type != RndTypeFile && rnd->Type != RndTypeOpenSSL) { RndSaved = MEM_ALLOC(sizeof(DCS_RND_SAVED)); if (RndSaved != NULL) { RndSaved->Size = sizeof(DCS_RND_SAVED); @@ -452,7 +544,7 @@ RndLoad( if (EFI_ERROR(res) || crc != crcSaved || rndSaved->Sign != gRndHeaderSign) { return EFI_CRC_ERROR; } - res = RndInit(rndSaved->Type, NULL, rndOut); + res = RndInit(rndSaved->Type, NULL, 0, rndOut); if (!EFI_ERROR(res)) { CopyMem(&((*rndOut)->State), &rndSaved->State, sizeof(DCS_RND_STATE)); } diff --git a/Library/DcsTpmLib/DcsTpmLib.inf b/Library/DcsTpmLib/DcsTpmLib.inf new file mode 100644 index 0000000..79ea0f7 --- /dev/null +++ b/Library/DcsTpmLib/DcsTpmLib.inf @@ -0,0 +1,48 @@ +## @file +# TPM 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 = DcsTpmLib + MODULE_UNI_FILE = DcsTpmLib.uni + FILE_GUID = D920E43F-730D-4C48-9BF6-5FA81C5F7697 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = DcsTpmLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources.common] + Tpm12.c + +[Packages] + MdePkg/MdePkg.dec + DcsPkg/DcsPkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + MemoryAllocationLib + UefiLib + PrintLib + Tpm12DeviceLib + BaseCryptLib + +[Protocols] + gEfiTcgProtocolGuid + +# [Guids] + diff --git a/Library/DcsTpmLib/Tpm12.c b/Library/DcsTpmLib/Tpm12.c new file mode 100644 index 0000000..502677b --- /dev/null +++ b/Library/DcsTpmLib/Tpm12.c @@ -0,0 +1,1344 @@ +/** @file +EFI TPM12 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 +#include +#include +#include +#include "Library/DcsCfgLib.h" + + +#define TPM_PREPARE Tpm12RequestUseTpm +#define TPM_TRANSMIT Tpm12SubmitCommand + +//#pragma warning(disable: 4706) + +extern EFI_TCG_PROTOCOL *mTcgProtocol; + +EFI_STATUS +InitTpm12() { + EFI_STATUS res = EFI_SUCCESS; + if (mTcgProtocol == NULL) { + return TPM_PREPARE(); + } + return res; +} + +typedef struct { + UINT8 *Cmd; + UINTN CmdPos; + UINTN CmdSize; + UINT8 *Resp; + UINTN RespPos; + UINTN RespSize; + UINT8 *Hash; +} DCS_TPM12IO; + +EFI_STATUS +Sha1Hash( + IN VOID *data, + IN UINTN dataSize, + OUT UINT8 *hash + ) +{ + UINTN ctxSize; + VOID *ctx; + ctxSize = Sha1GetContextSize(); + ctx = MEM_ALLOC(ctxSize); + if (ctx == NULL) return EFI_BUFFER_TOO_SMALL; + Sha1Init(ctx); + Sha1Update(ctx, data, dataSize); + if (!Sha1Final(ctx, hash)) return EFI_DEVICE_ERROR; + return EFI_SUCCESS; +} + +////////////////////////////////////////////////////////////////////////// +// TPM IO Create/ Free +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12IOCreate( + DCS_TPM12IO **tpmio, + UINTN cmdSize, + UINTN respSize) +{ + DCS_TPM12IO *io; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + io = *tpmio; + if (io == NULL) { + io = MEM_ALLOC(sizeof(*io)); + if (io == NULL) return EFI_BUFFER_TOO_SMALL; + } + if (io->CmdSize < cmdSize) { + MEM_FREE(io->Cmd); + io->Cmd = MEM_ALLOC(cmdSize); + if (io->Cmd == NULL) goto err; + } + io->CmdPos = 0; + io->CmdSize = cmdSize; + if (io->RespSize < respSize) { + MEM_FREE(io->Resp); + io->Resp = MEM_ALLOC(respSize); + if (io->Resp == NULL) goto err; + } + io->RespPos = 0; + io->RespSize = respSize; + if (io->Hash == NULL) { + UINTN sha1ctxsize; + sha1ctxsize = Sha1GetContextSize(); + io->Hash = MEM_ALLOC(sha1ctxsize); + if (io->Hash == NULL) goto err; + } + if(!Sha1Init(io->Hash)) goto err; + *tpmio = io; + return EFI_SUCCESS; +err: + MEM_FREE(io->Cmd); + MEM_FREE(io->Resp); + MEM_FREE(io->Hash); + MEM_FREE(io); + *tpmio = NULL; + return EFI_BUFFER_TOO_SMALL; +} + +VOID +Tpm12IOFree( + DCS_TPM12IO **tpmio) +{ + DCS_TPM12IO *io; + if (tpmio == NULL) return; + io = *tpmio; + if (io == NULL) return; + MEM_FREE(io->Cmd); + MEM_FREE(io->Resp); + MEM_FREE(io->Hash); + MEM_FREE(io); + *tpmio = NULL; +} + +////////////////////////////////////////////////////////////////////////// +// Cmd init and write +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12IOUpdateCmdSize( + DCS_TPM12IO *tpmio) +{ + UINT32 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + data = (UINT32*)&tpmio->Cmd[2]; + *data = SwapBytes32((UINT32)tpmio->CmdPos); + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12IOWrite16( + DCS_TPM12IO *tpmio, + UINT16 prm, + BOOLEAN hashIt) +{ + UINT16 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + 2 >= tpmio->CmdSize) { + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = (UINT16*)&tpmio->Cmd[tpmio->CmdPos]; + *data = SwapBytes16(prm); + if(hashIt) { + Sha1Update(tpmio->Hash, data, 2); + } + tpmio->CmdPos += 2; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWrite32( + DCS_TPM12IO *tpmio, + UINT32 prm, + BOOLEAN hashIt) +{ + UINT32 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + 4 >= tpmio->CmdSize){ + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = (UINT32*)&tpmio->Cmd[tpmio->CmdPos]; + *data = SwapBytes32(prm); + if (hashIt) { + Sha1Update(tpmio->Hash, data, 4); + } + tpmio->CmdPos += 4; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWriteBytes( + DCS_TPM12IO *tpmio, + VOID *prm, + UINTN prmSize, + BOOLEAN hashIt) +{ + UINT8 *data; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos + prmSize >= tpmio->CmdSize) { + tpmio->CmdPos = tpmio->CmdSize; + return EFI_BUFFER_TOO_SMALL; + } + data = &tpmio->Cmd[tpmio->CmdPos]; + CopyMem(data, prm, prmSize); + if (hashIt) { + Sha1Update(tpmio->Hash, data, prmSize); + } + tpmio->CmdPos += prmSize; + return Tpm12IOUpdateCmdSize(tpmio); +} + +EFI_STATUS +Tpm12IOWrite8( + DCS_TPM12IO *tpmio, + UINT8 prm, + BOOLEAN hashIt) +{ + return Tpm12IOWriteBytes(tpmio, &prm, 1, hashIt); +} + +EFI_STATUS +Tpm12IOInit( + DCS_TPM12IO *tpmio, + UINT16 tag, + UINT32 ord) +{ + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + tpmio->CmdPos = 0; + ZeroMem(tpmio->Cmd, tpmio->CmdSize); + tpmio->RespPos = 0; + ZeroMem(tpmio->Resp, tpmio->RespSize); + Sha1Init(tpmio->Hash); + Tpm12IOWrite16(tpmio, tag, FALSE); + Tpm12IOWrite32(tpmio, 0, FALSE); + return Tpm12IOWrite32(tpmio, ord, TRUE); +} + + +////////////////////////////////////////////////////////////////////////// +// Read / Parse responces +////////////////////////////////////////////////////////////////////////// +UINT16 +Tpm12RespTag( + DCS_TPM12IO *tpmio) +{ + UINT16 *tag; + if (tpmio == NULL) return 0; + tag = (UINT16*)tpmio->Resp; + return SwapBytes16(*tag); +} + +UINT32 +Tpm12RespCode( + IN DCS_TPM12IO *tpmio + ) +{ + UINT32 *code; + if (tpmio == NULL) return 0; + code = (UINT32*)&tpmio->Resp[6]; + return SwapBytes32(*code); +} + +UINT32 +Tpm12RespSize( + IN DCS_TPM12IO *tpmio + ) +{ + UINT32 *size; + if (tpmio == NULL) return 0; + size = (UINT32*)&tpmio->Resp[2]; + return SwapBytes32(*size); +} + +UINT8* +Tpm12RespData( + IN DCS_TPM12IO *tpmio + ) +{ + if (tpmio == NULL) return NULL; + return &tpmio->Resp[10]; +} + +EFI_STATUS +Tpm12RespRead16( + IN DCS_TPM12IO *tpmio, + OUT UINT16 *data, + IN BOOLEAN hashIt + ) +{ + UINT16 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if(tpmio->RespPos + 2 > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = (UINT16 *)&tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + *data = SwapBytes16(*tmp); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, 2); + } + tpmio->RespPos += 2; + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12RespRead32( + IN DCS_TPM12IO *tpmio, + OUT UINT32 *data, + IN BOOLEAN hashIt + ) +{ + UINT32 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->RespPos + 4 > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = (UINT32 *)&tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + *data = SwapBytes32(*tmp); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, 4); + } + tpmio->RespPos += 4; + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12RespReadBytes( + IN DCS_TPM12IO *tpmio, + OUT VOID *data, + IN UINT32 dataSize, + IN BOOLEAN hashIt + ) +{ + UINT8 *tmp; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->RespPos + dataSize > tpmio->RespSize) return EFI_BUFFER_TOO_SMALL; + tmp = &tpmio->Resp[tpmio->RespPos]; + if (data != NULL) { + CopyMem(data, tmp, dataSize); + } + if (hashIt) { + Sha1Update(tpmio->Hash, tmp, dataSize); + } + tpmio->RespPos += dataSize; + return EFI_SUCCESS; +} + +VOID +Tpm12Parse16(UINT8** pos, UINT16 *data) { + if (data == NULL) { + data = (UINT16*)(*pos); + } + *data = SwapBytes16(*((UINT16*)(*pos))); + (*pos) += 2; +} + +VOID +Tpm12Parse32(UINT8** pos, UINT32 *data) { + if (data == NULL) { + data = (UINT32*)(*pos); + } + *data = SwapBytes32(*((UINT32*)(*pos))); + (*pos) += 4; +} + +VOID +Tpm12ParsePcrInfoShort(UINT8** pos, TPM_PCR_INFO_SHORT*data) { + if (data == NULL) { + data = (TPM_PCR_INFO_SHORT*)(*pos); + } + data->pcrSelection.sizeOfSelect = SwapBytes16(*((UINT16*)(*pos))); + (*pos) += data->pcrSelection.sizeOfSelect + 2 + 1 + 20; +} + +////////////////////////////////////////////////////////////////////////// +// Transmit command +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Transmit( + DCS_TPM12IO *tpmio) +{ + UINT32 TpmRecvSize; + EFI_STATUS res; + if (tpmio == NULL) return EFI_INVALID_PARAMETER; + if (tpmio->CmdPos >= tpmio->CmdSize) return EFI_BUFFER_TOO_SMALL; + TpmRecvSize = (UINT32)tpmio->RespSize; + res = TPM_TRANSMIT((UINT32)tpmio->CmdPos, tpmio->Cmd, &TpmRecvSize, tpmio->Resp); + if (EFI_ERROR(res)) { + return res; + } + if (Tpm12RespCode(tpmio) != TPM_SUCCESS) { + return EFI_DEVICE_ERROR; + } + Sha1Init(tpmio->Hash); // Init hash + tpmio->RespPos = 6; // Skip tag and size + Tpm12RespRead32(tpmio, NULL, TRUE); // Hash return code + Sha1Update(tpmio->Hash, tpmio->Cmd + 2, 4); // Hash ordinal + return res; +} + +////////////////////////////////////////////////////////////////////////// +// Global TPM12 I/O +////////////////////////////////////////////////////////////////////////// +DCS_TPM12IO *gTpm12Io = NULL; +EFI_STATUS +GetTpm12Io() +{ + EFI_STATUS res = EFI_SUCCESS; + if (gTpm12Io == NULL) { + res = Tpm12IOCreate(&gTpm12Io, 1024, 1024); + } + if (mTcgProtocol == NULL) { + return EFI_NOT_READY; + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// PCRs +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_PcrRead( + DCS_TPM12IO *tpmio, + IN UINT32 PcrIndex + ) +{ + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_PcrRead); + return Tpm12IOWrite32(tpmio, PcrIndex, TRUE); +} + +/** +Send PCR Read command to TPM1.2. + +@param PcrIndex The index of the PCR to read. +@param PcrValue The PCR value. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12PcrRead( + IN UINT32 PcrIndex, + OUT void *PcrValue + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_PcrRead(gTpm12Io, PcrIndex); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + Tpm12RespReadBytes(gTpm12Io, PcrValue, sizeof(TPM_PCRVALUE), TRUE); + return res; +} + +EFI_STATUS +Tpm12Cmd_PcrExtend( + DCS_TPM12IO *tpmio, + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + TPM_DIGEST digest; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_Extend); + Sha1Hash(data, dataSz, (UINT8*)&digest); + Tpm12IOWrite32(tpmio, PcrIndex, TRUE); + return Tpm12IOWriteBytes(tpmio, &digest, sizeof(digest), TRUE); +} + +/** +Send PCR Extend command to TPM1.2. + +@param PcrIndex The index of the PCR to read. +@param dataSz size of data +@param data data. Extend PCR with Sha1(data) + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12PcrExtend( + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_PcrExtend(gTpm12Io, PcrIndex, dataSz, data); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +EFI_STATUS +Tpm12PcrExtendAndLog( + IN UINT32 PcrIndex, + IN UINTN dataSz, + IN VOID *data + ) +{ + EFI_STATUS res = EFI_NOT_FOUND; + + /*TCG_PCR_EVENT_HDR TcgEvent; + TcgEvent->PCRIndex = PcrIndex; + TcgEvent->EventType = EventType; + TcgEvent->EventSize = LogLen; + CopyMem(&TcgEvent->Event[0], EventLog, LogLen); + EventNumber = 1; + Status = TcgProtocol->HashLogExtendEvent( + TcgProtocol, + (EFI_PHYSICAL_ADDRESS)(UINTN)HashData, + HashDataLen, + TPM_ALG_SHA, + TcgEvent, + &EventNumber, + &EventLogLastEntry + ); +// TcgEvent.PCRIndex = PcrIndex; +// TcgEvent.EventType = EV_EFI_VARIABLE_DRIVER_CONFIG; +// res = TpmMeasureAndLogData(PcrIndex, EV_EFI_VARIABLE_DRIVER_CONFIG, &TcgEvent, sizeof(TcgEvent), data, dataSz); +*/ + + return res; +} + +EFI_STATUS +Tpm12PcrsSave( + IN UINTN sPcr, + IN UINTN ePcr, + TPM_DIGEST *Pcrs + ) { + UINT32 i; + EFI_STATUS Status = EFI_SUCCESS; + for (i = (UINT32)sPcr; i <= (UINT32)ePcr; ++i) { + Status = Tpm12PcrRead(i, &Pcrs[i].digest); + if (EFI_ERROR(Status)) { + return Status; + } + } + return Status; +} + +EFI_STATUS +Tpm12PrintPCR( + IN UINT32 PcrIndex) +{ + TPM_PCRVALUE PcrValue; + EFI_STATUS Status; + OUT_PRINT(L"%HPCR%02d%N ", PcrIndex); + Status = Tpm12PcrRead(PcrIndex, &PcrValue); + if (EFI_ERROR(Status)) { + ERR_PRINT(L"%r(%x)\n", Status, Tpm12RespCode(gTpm12Io)); + return Status; + } + PrintBytes(PcrValue.digest, sizeof(PcrValue)); + OUT_PRINT(L"\n"); + return EFI_SUCCESS; +} + +EFI_STATUS +Tpm12DumpPcrs( + IN UINT32 sPcr, + IN UINT32 ePcr) +{ + UINT32 i; + EFI_STATUS Status = EFI_SUCCESS; + for (i = sPcr; i <= ePcr; ++i) { + Status = Tpm12PrintPCR(i); + if (EFI_ERROR(Status)) { + return Status; + } + } + return Status; +} + +////////////////////////////////////////////////////////////////////////// +// Get Capability +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_GetCapability( + DCS_TPM12IO *tpmio, + IN UINT32 capArea, + IN UINT32 subCapSize, + IN UINT8 *subCap + ) +{ + EFI_STATUS res; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_GetCapability); + Tpm12IOWrite32(tpmio, capArea, TRUE); + res = Tpm12IOWrite32(tpmio, subCapSize, TRUE); + if (subCapSize > 0) { + res = Tpm12IOWriteBytes(tpmio, subCap, subCapSize, TRUE); + } + return res; +} + +/** +Send GetCapability command to TPM1.2. + +@param capArea The index of the Capability +@param subCapSize The size of details. +@param subCap Details + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm12GetCapability( + IN UINT32 capArea, + IN UINT32 subCapSize, + IN UINT8 *subCap, + OUT UINT32 *respSize, + OUT UINT8 *resp + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_GetCapability(gTpm12Io, capArea, subCapSize, subCap); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, respSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, resp, *respSize, TRUE); + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// NV +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12GetNvList( + OUT UINT32 *respSize, + OUT UINT32 *resp + ) { + return Tpm12GetCapability(TPM_CAP_NV_LIST, 0, NULL, respSize, (UINT8*)resp); +} + +EFI_STATUS +Tpm12PcrsDigest( + IN UINT16 sizeOfSelect, + IN UINT8 *pcrSelect, + IN TPM_DIGEST *Pcrs, + OUT TPM_DIGEST *digest + ) +{ + UINTN Sha1CtxSize; + UINTN i; + UINTN j; + UINTN k; + VOID* Sha1Ctx; + UINT16 tmp16; + UINT32 tmp32; + + k = 0; + for (i = 0; i < sizeOfSelect; ++i) { + UINT8 tmp = pcrSelect[i]; + for (j = 0; j < 8; ++j) { + if ((tmp & 1) == 1) { + k++; + } + tmp >>= 1; + } + } + if (k == 0) return EFI_SUCCESS; + Sha1CtxSize = Sha1GetContextSize(); + Sha1Ctx = MEM_ALLOC(Sha1CtxSize); + if (Sha1Ctx == NULL) return EFI_BUFFER_TOO_SMALL; + Sha1Init(Sha1Ctx); + tmp16 = SwapBytes16(sizeOfSelect); + Sha1Update(Sha1Ctx, &tmp16, sizeof(tmp16)); + Sha1Update(Sha1Ctx, pcrSelect, sizeOfSelect); + + tmp32 = SwapBytes32((UINT32)(k * sizeof(TPM_DIGEST))); + Sha1Update(Sha1Ctx, &tmp32, sizeof(tmp32)); + k = 0; + for (i = 0; i < sizeOfSelect; ++i) { + UINT8 tmp = pcrSelect[i]; + for (j = 0; j < 8; ++j) { + if ((tmp & 1) == 1) { + Sha1Update(Sha1Ctx, &Pcrs[k], sizeof(TPM_DIGEST)); + } + tmp >>= 1; + k++; + } + } + if (Sha1Final(Sha1Ctx, digest->digest)) return EFI_SUCCESS; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +Tpm12NvDetails( + IN UINT32 index, + OUT UINT32 *attr, + OUT UINT32 *dataSz, + OUT UINT32 *pcrR, + OUT UINT32 *pcrW + ) +{ + EFI_STATUS res; + TPM_PCR_INFO_SHORT* pcrRead; + TPM_PCR_INFO_SHORT* pcrWrite; + UINT8 nvdata[sizeof(TPM_NV_DATA_PUBLIC) + 256]; + UINT8* pos = nvdata; + UINT32 sz = sizeof(nvdata); + UINT32 swapindex = SwapBytes32(index); + res = Tpm12GetCapability(TPM_CAP_NV_INDEX, 4, (UINT8*)&swapindex, &sz, nvdata); + if(EFI_ERROR(res)) return res; + Tpm12Parse16(&pos, NULL); + Tpm12Parse32(&pos, &index); + pcrRead = (TPM_PCR_INFO_SHORT*)pos; + Tpm12ParsePcrInfoShort(&pos, NULL); + pcrWrite = (TPM_PCR_INFO_SHORT*)pos; + Tpm12ParsePcrInfoShort(&pos, NULL); + Tpm12Parse16(&pos, NULL); + Tpm12Parse32(&pos, attr); + pos += 3; + Tpm12Parse32(&pos, dataSz); + if (pcrR != NULL) { + *pcrR = pcrRead->pcrSelection.pcrSelect[0]; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 1 ? pcrRead->pcrSelection.pcrSelect[1] << 8 : 0; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 2 ? pcrRead->pcrSelection.pcrSelect[2] << 16 : 0; + *pcrR |= pcrRead->pcrSelection.sizeOfSelect > 3 ? pcrRead->pcrSelection.pcrSelect[3] << 24 : 0; + } + if (pcrW != NULL) { + *pcrW = pcrWrite->pcrSelection.pcrSelect[0]; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 1 ? pcrWrite->pcrSelection.pcrSelect[1] << 8 : 0; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 2 ? pcrWrite->pcrSelection.pcrSelect[2] << 16 : 0; + *pcrW |= pcrWrite->pcrSelection.sizeOfSelect > 3 ? pcrWrite->pcrSelection.pcrSelect[3] << 24 : 0; + } + return res; +} + +////////////////////////////////////////////////////////////////////////// +// OSAP +////////////////////////////////////////////////////////////////////////// +#pragma pack(1) +typedef struct { + TPM_NONCE nonceOdd; + TPM_NONCE nonceOddOSAP; + TPM_NONCE nonceEven; + TPM_NONCE nonceEvenOSAP; + TPM_DIGEST SharedSecret; + TPM_AUTHHANDLE authHandle; +} TPM12_OSAP; +#pragma pack() + +EFI_STATUS +Tpm12Cmd_OSAP( + IN DCS_TPM12IO *tpmio, + IN TPM12_OSAP *osap, + IN UINT16 entityType, + IN UINT32 entityValue + ) +{ + EFI_STATUS res; + Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_OSAP); + res = Tpm12IOWrite16(tpmio, entityType, TRUE); + res = Tpm12IOWrite32(tpmio, entityValue, TRUE); + res = Tpm12IOWriteBytes(tpmio, &osap->nonceOddOSAP, sizeof(osap->nonceOddOSAP), TRUE); + return res; +} + +TPM12_OSAP *gTpm12Osap; + +EFI_STATUS +Tpm12OSAPStart( + IN UINT16 entityType, + IN UINT32 entityValue, + IN CHAR16 *ownerPass + ) +{ + EFI_STATUS res; + TPM_DIGEST ownerKey; + UINTN CtxSize; + VOID* HmacCtx; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + if (gTpm12Osap == NULL) { + gTpm12Osap = MEM_ALLOC(sizeof(TPM12_OSAP)); + } + res = Tpm12Cmd_OSAP(gTpm12Io, gTpm12Osap, entityType, entityValue); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + Tpm12RespRead32(gTpm12Io, &gTpm12Osap->authHandle, FALSE); + Tpm12RespReadBytes(gTpm12Io, &gTpm12Osap->nonceEven, sizeof(TPM_NONCE), FALSE); + res = Tpm12RespReadBytes(gTpm12Io, &gTpm12Osap->nonceEvenOSAP, sizeof(TPM_NONCE), FALSE); + if (EFI_ERROR(res)) return res; + Sha1Hash(ownerPass, StrLen(ownerPass) * 2, (UINT8*)&ownerKey); + CtxSize = HmacSha1GetContextSize(); + HmacCtx = MEM_ALLOC(CtxSize); + HmacSha1Init(HmacCtx, (UINT8*)&ownerKey, sizeof(ownerKey)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceEvenOSAP, sizeof(gTpm12Osap->nonceEvenOSAP)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceOddOSAP, sizeof(gTpm12Osap->nonceOddOSAP)); + HmacSha1Final(HmacCtx, (UINT8*)&gTpm12Osap->SharedSecret); + MEM_FREE(HmacCtx); + return res; +} + +EFI_STATUS +Tpm12OSAPAppend( + IN UINT8 continueSession + ) +{ + EFI_STATUS res; + UINTN CtxSize; + VOID* HmacCtx; + TPM_DIGEST hashCmd; + TPM_DIGEST auth; + + Tpm12IOWrite32(gTpm12Io, gTpm12Osap->authHandle, FALSE); + Tpm12IOWriteBytes(gTpm12Io, &gTpm12Osap->nonceOdd, sizeof(gTpm12Osap->nonceOdd), FALSE); + res = Tpm12IOWrite8(gTpm12Io, continueSession, FALSE); + *((UINT16*)gTpm12Io->Cmd) = SwapBytes16(TPM_TAG_RQU_AUTH1_COMMAND); // Update Tag + Sha1Final(gTpm12Io->Hash, (UINT8*)&hashCmd); + CtxSize = HmacSha1GetContextSize(); + HmacCtx = MEM_ALLOC(CtxSize); + if (HmacCtx == NULL) return EFI_BUFFER_TOO_SMALL; + HmacSha1Init(HmacCtx, (UINT8*)&gTpm12Osap->SharedSecret, sizeof(gTpm12Osap->SharedSecret)); + HmacSha1Update(HmacCtx, &hashCmd, sizeof(hashCmd)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceEven, sizeof(gTpm12Osap->nonceEven)); + HmacSha1Update(HmacCtx, &gTpm12Osap->nonceOdd, sizeof(gTpm12Osap->nonceOdd)); + HmacSha1Update(HmacCtx, &continueSession, sizeof(continueSession)); + HmacSha1Final(HmacCtx, (UINT8*)&auth); + MEM_FREE(HmacCtx); + res = Tpm12IOWriteBytes(gTpm12Io, &auth, sizeof(auth), FALSE); + return res; +} + +////////////////////////////////////////////////////////////////////////// +// NV +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12WritePcrInfo( + IN DCS_TPM12IO *tpmio, + IN UINT16 sizeOfSelect, + IN UINT8 *pcrSelect, + IN UINT8 localityAtRelease, + IN TPM_DIGEST* pcrs) +{ + TPM_DIGEST digestAtRelease; + ZeroMem(&digestAtRelease, sizeof(digestAtRelease)); + Tpm12IOWrite16 (tpmio, sizeOfSelect, TRUE); + Tpm12IOWriteBytes(tpmio, pcrSelect, sizeOfSelect, TRUE); + Tpm12IOWrite8(tpmio, localityAtRelease, TRUE); + Tpm12PcrsDigest(sizeOfSelect, pcrSelect, pcrs, &digestAtRelease); + return Tpm12IOWriteBytes(tpmio, &digestAtRelease, sizeof(TPM_DIGEST), TRUE); +} + +TPM_DIGEST gTpm12Pcrs[24]; +TPM_DIGEST gTpm12OwnerPass; + +VOID +PcrUpdateMask( + UINT32 mask, + UINT8 *pcr) +{ + pcr[0] = (UINT8)(mask & 0xFF); + pcr[1] = (UINT8)((mask >> 8) & 0xFF); + pcr[2] = (UINT8)((mask >> 16) & 0xFF); +} + +EFI_STATUS +Tpm12NvSpace( + IN UINT32 index, + IN UINT32 size, + IN CHAR16 *ownerPass, + TPM_DIGEST *pcrs, + IN UINT32 pcrReadMask, + IN UINT32 pcrWriteMask, + IN UINT32 Attributes, + IN UINT8 bReadSTClear, + IN UINT8 bWriteSTClear, + IN UINT8 bWriteDefine + ) { + EFI_STATUS res; + TPM_DIGEST encAuth; + UINT8 pcrRead[3]; + UINT8 pcrWrite[3]; + + PcrUpdateMask(pcrReadMask, pcrRead); + PcrUpdateMask(pcrWriteMask, pcrWrite); + SetMem(&encAuth, sizeof(encAuth), 0xEA); // No Auth + + res = Tpm12OSAPStart(TPM_ET_OWNER, TPM_KH_OWNER, ownerPass); + if (EFI_ERROR(res)) { + return res; + } + Tpm12IOInit(gTpm12Io, TPM_TAG_RQU_AUTH1_COMMAND, TPM_ORD_NV_DefineSpace); + // NV_DATA_PUBLIC + Tpm12IOWrite16(gTpm12Io, TPM_TAG_NV_DATA_PUBLIC, TRUE); + Tpm12IOWrite32(gTpm12Io, index, TRUE); + Tpm12WritePcrInfo(gTpm12Io, sizeof(pcrRead) , pcrRead, 0x1F, pcrs); + Tpm12WritePcrInfo(gTpm12Io, sizeof(pcrWrite), pcrWrite, 0x1F, pcrs); + Tpm12IOWrite16(gTpm12Io, TPM_TAG_NV_ATTRIBUTES, TRUE); + Tpm12IOWrite32(gTpm12Io, Attributes, TRUE); + Tpm12IOWrite8(gTpm12Io, bReadSTClear, TRUE); + Tpm12IOWrite8(gTpm12Io, bWriteSTClear, TRUE); + Tpm12IOWrite8(gTpm12Io, bWriteDefine, TRUE); + Tpm12IOWrite32(gTpm12Io, size, TRUE); + // + Tpm12IOWriteBytes(gTpm12Io, &encAuth, sizeof(encAuth), TRUE); + // OSAP + Tpm12OSAPAppend(0); + + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +EFI_STATUS +Tpm12Cmd_NvRead( + IN DCS_TPM12IO *tpmio, + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_NV_ReadValue)); + CE(Tpm12IOWrite32(tpmio, NvIndex, TRUE)); + CE(Tpm12IOWrite32(tpmio, Offset, TRUE)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); +err: + return res; +} + +/** +Send NV ReadValue command to TPM1.2. + +@param NvIndex The index of the area to set. +@param Offset The offset into the area. +@param DataSize The size of the data area. +@param Data The data to set the area to. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +Tpm12NvRead( + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN OUT UINT32 *DataSize, + OUT UINT8 *Data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_NvRead(gTpm12Io, NvIndex,Offset,*DataSize); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, DataSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, Data, *DataSize, TRUE); + } + return res; +} + +EFI_STATUS +Tpm12Cmd_NvWrite( + IN DCS_TPM12IO *tpmio, + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize, + IN UINT8 *Data + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_NV_WriteValue)); + CE(Tpm12IOWrite32(tpmio, NvIndex, TRUE)); + CE(Tpm12IOWrite32(tpmio, Offset, TRUE)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); + CE(Tpm12IOWriteBytes(tpmio, Data, DataSize, TRUE)); +err: + return res; +} + +/** +Send NV WriteValue command to TPM1.2. + +@param NvIndex The index of the area to set. +@param Offset The offset into the NV Area. +@param DataSize The size of the data parameter. +@param Data The data to set the area to. + +@retval EFI_SUCCESS Operation completed successfully. +@retval EFI_DEVICE_ERROR Unexpected device behavior. +**/ +EFI_STATUS +EFIAPI +Tpm12NvWrite( + IN TPM_NV_INDEX NvIndex, + IN UINT32 Offset, + IN UINT32 DataSize, + IN UINT8 *Data, + CHAR16 *ownerPass + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12OSAPStart(TPM_ET_OWNER, TPM_KH_OWNER, ownerPass); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12Cmd_NvWrite(gTpm12Io, NvIndex, Offset, DataSize, Data); + if (EFI_ERROR(res)) return res; + // OSAP + Tpm12OSAPAppend(0); + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + return res; +} + +/* +EFI_STATUS +Tpm12NvDefine( + IN UINT32 index, + IN UINT32 size, + IN CHAR16 *ownerPass) { + EFI_STATUS res; +// UINT32 sz = 20; +// UINT8 data[20]; +// UINT8 dataR[20]; +// SetMem(data, 20, 1); +// +// CE(Tpm12PcrsSave(0, 23, gTpm12Pcrs)); +// CE(Tpm12NvSpace(index, size, ownerPass, gTpm12Pcrs, 0x100, 0, 0x2, 0, 0, 0)); +// CE(Tpm12NvWrite(index,0,size, data, ownerPass)); +// CE(Tpm12NvRead(index, 0, &sz, dataR)); + CE(GetTpm()); + if (gRnd == NULL) { + RndInit() + } + return res; +err: + ERR_PRINT(L"%r(%x),line %d\n", res, Tpm12RespCode(gTpm12Io), gCELine); + return res; +}*/ + +////////////////////////////////////////////////////////////////////////// +// Random +////////////////////////////////////////////////////////////////////////// +EFI_STATUS +Tpm12Cmd_GetRandom( + IN DCS_TPM12IO *tpmio, + IN UINT32 DataSize + ) +{ + EFI_STATUS res; + CE(Tpm12IOInit(tpmio, TPM_TAG_RQU_COMMAND, TPM_ORD_GetRandom)); + CE(Tpm12IOWrite32(tpmio, DataSize, TRUE)); +err: + return res; +} + +EFI_STATUS +Tpm12GetRandom( + IN OUT UINT32 *DataSize, + OUT UINT8 *Data + ) +{ + EFI_STATUS res; + res = GetTpm12Io(); + if (EFI_ERROR(res)) return res; + res = Tpm12Cmd_GetRandom(gTpm12Io, *DataSize); + if (EFI_ERROR(res)) return res; + res = Tpm12Transmit(gTpm12Io); + if (EFI_ERROR(res)) { + return res; + } + res = Tpm12RespRead32(gTpm12Io, DataSize, TRUE); + if (!EFI_ERROR(res)) { + res = Tpm12RespReadBytes(gTpm12Io, Data, *DataSize, TRUE); + } + return res; +} +////////////////////////////////////////////////////////////////////////// +// Protocol +////////////////////////////////////////////////////////////////////////// +#define DCS_TPM_NV_INDEX 0x0DC5B +#define DCS_TPM_NV_SIZE 128 +#define DCS_TPM_PCR_LOCK 8 + +typedef struct _Password Password; + +extern VOID +ApplyKeyFile( + IN OUT Password* password, + IN CHAR8* keyfileData, + IN UINTN keyfileDataSize + ); + +EFI_STATUS +DcsTpm12Lock( + DCS_TPM_PROTOCOL *tpm + ) +{ + UINT32 lock = 1; + return Tpm12PcrExtend(DCS_TPM_PCR_LOCK, sizeof(lock), &lock); +} + +EFI_STATUS +DcsTpm12Apply( + DCS_TPM_PROTOCOL *tpm, + OUT VOID* pwd + ) +{ + EFI_STATUS res; + UINT32 sz = DCS_TPM_NV_SIZE; + CHAR8 data[DCS_TPM_NV_SIZE]; + res = Tpm12NvRead(DCS_TPM_NV_INDEX, 0, &sz, data); + if (EFI_ERROR(res)) return res; + ApplyKeyFile(pwd, data, DCS_TPM_NV_SIZE); + ZeroMem(data, DCS_TPM_NV_SIZE); + return EFI_SUCCESS; +} + +BOOLEAN +DcsTpm12IsOpen( + DCS_TPM_PROTOCOL *tpm + ) +{ + EFI_STATUS res; + UINT32 sz = DCS_TPM_NV_SIZE; + UINT8 data[DCS_TPM_NV_SIZE]; + res = Tpm12NvRead(DCS_TPM_NV_INDEX, 0, &sz, data); + if (EFI_ERROR(res)) return FALSE; + ZeroMem(data, DCS_TPM_NV_SIZE); + return TRUE; +} + +BOOLEAN +DcsTpm12IsConfigured( + DCS_TPM_PROTOCOL *tpm + ) +{ + EFI_STATUS res; + UINT32 dataSz; + UINT32 attr; + UINT32 pcrR; + UINT32 pcrW; + res = Tpm12NvDetails(DCS_TPM_NV_INDEX, &attr, &dataSz, &pcrR, &pcrW); + if (EFI_ERROR(res)) return FALSE; + if (dataSz != DCS_TPM_NV_SIZE) return FALSE; + return TRUE; +} + +#define TPM_OWNER_PWD_MAX 64 +VOID +AskTpmOwnerPwd( + OUT CHAR16* ownerPass + ) { + UINTN ownerPassLen; + OUT_PRINT(L"TPM owner password:"); + ZeroMem(ownerPass, TPM_OWNER_PWD_MAX * 2); + GetLine(&ownerPassLen, ownerPass, NULL, TPM_OWNER_PWD_MAX - 1, FALSE); +} + +UINT32 +AskPcrsMask( + IN UINT32 def + ) +{ + OUT_PRINT(L"PCR selection bits(hex):\n\ + 1 BIOS 2 BIOS data 4 EFI drivers\n\ + 8 EFI variables 10 EFI boot loader 20 EFI boot loader data\n\ +40 Boot event 80 Manufacture 100 DcsProp\n"); + return (UINT32)AskHexUINT64("PCRs mask:", def); +} + +EFI_STATUS +ActionTpm12Update( + IN VOID *ctx + ) +{ + EFI_STATUS res; + CHAR16 ownerPass[TPM_OWNER_PWD_MAX]; + UINT32 pcrMask; + UINT8 data[DCS_TPM_NV_SIZE]; + ZeroMem(data, DCS_TPM_NV_SIZE); + CE(Tpm12PcrsSave(0, 23, gTpm12Pcrs)); + AskTpmOwnerPwd(ownerPass); + pcrMask = AskPcrsMask(0x137); + CE(Tpm12NvSpace(DCS_TPM_NV_INDEX, DCS_TPM_NV_SIZE, ownerPass, gTpm12Pcrs, pcrMask, 0, 0x2, 0, 0, 0)); + CE(gRnd == NULL ? EFI_NOT_READY : EFI_SUCCESS); + CE(gRnd->GetBytes(gRnd, data, sizeof(data))); + CE(Tpm12NvWrite(DCS_TPM_NV_INDEX, 0, DCS_TPM_NV_SIZE, data, ownerPass)); +err: + return res; +} + +EFI_STATUS +ActionTpm12Clean( + IN VOID *ctx + ) +{ + EFI_STATUS res; + CHAR16 ownerPass[TPM_OWNER_PWD_MAX]; + AskTpmOwnerPwd(ownerPass); + CE(Tpm12NvSpace(DCS_TPM_NV_INDEX, 0, ownerPass, gTpm12Pcrs, 0, 0, 0x2, 0, 0, 0)); +err: + return res; +} + +EFI_STATUS +ActionTpm12PrintPcrs( + IN VOID *ctx + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINTN i; + UINT32 pcrMask = 0x1FF; + UINT32 tmp; + Tpm12NvDetails(DCS_TPM_NV_INDEX, NULL, NULL, &pcrMask, NULL); + pcrMask = AskPcrsMask(pcrMask); + tmp = pcrMask; + for (i = 0; i < 32; ++i) { + if ((tmp & 1) == 1) { + Tpm12PrintPCR((UINT32)i); + } + tmp >>= 1; + } + return res; +} + +PMENU_ITEM gTpmMenu = NULL; +BOOLEAN gTpmMenuContinue = TRUE; + +EFI_STATUS +ActionTpmExit( + IN VOID *ctx + ) +{ + gTpmMenuContinue = FALSE; + return EFI_SUCCESS; +} + + +EFI_STATUS +DcsTpm12Configure( + IN DCS_TPM_PROTOCOL* tpm + ) { + PMENU_ITEM item = NULL; + EFI_STATUS res; + item = DcsMenuAppend(item, L"Update TPM secret", 'u', ActionTpm12Update, NULL); + gTpmMenu = item; + item = DcsMenuAppend(item, L"Delete TPM secret", 'd', ActionTpm12Clean, NULL); + item = DcsMenuAppend(item, L"Print PCRs", 'p', ActionTpm12PrintPcrs, NULL); + item = DcsMenuAppend(item, L"Exit", 'e', ActionTpmExit, NULL); + do { + EFI_INPUT_KEY key; + OUT_PRINT(L"TPM "); + if (tpm->IsConfigured(tpm)) { + OUT_PRINT(L"%Vconfigured%N, "); + if (tpm->IsOpen(tpm)) { + OUT_PRINT(L"%Vopen%N"); + } + else { + ERR_PRINT(L"locked"); + } + } + else { + ERR_PRINT(L"not configured"); + } + OUT_PRINT(L"\n"); + DcsMenuPrint(gTpmMenu); + item = NULL; + key.UnicodeChar = 0; + while (item == NULL) { + item = gTpmMenu; + key = GetKey(); + while (item != NULL) { + if (item->Select == key.UnicodeChar) break; + item = item->Next; + } + } + OUT_PRINT(L"%c\n", key.UnicodeChar); + res = item->Action(item->Context); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r(%x),line %d\n", res, Tpm12RespCode(gTpm12Io), gCELine); + } + } while (gTpmMenuContinue); + return EFI_SUCCESS; +} + +DCS_TPM_PROTOCOL* gTpm = (DCS_TPM_PROTOCOL*)NULL; + +EFI_STATUS +GetTpm() { + EFI_STATUS res; + res = InitTpm12(); + if (EFI_ERROR(res)) { + return res; + } + gTpm = (DCS_TPM_PROTOCOL*)MEM_ALLOC(sizeof(DCS_TPM_PROTOCOL)); + if (gTpm == NULL) return EFI_BUFFER_TOO_SMALL; + gTpm->IsConfigured = DcsTpm12IsConfigured; + gTpm->IsOpen = DcsTpm12IsOpen; + gTpm->Configure = DcsTpm12Configure; + gTpm->Apply = DcsTpm12Apply; + gTpm->Lock = DcsTpm12Lock; + return EFI_SUCCESS; +} + +EFI_STATUS +TpmMeasure( + IN VOID* data, + IN UINTN dataSz + ) { + EFI_STATUS res; + TPM_DIGEST hash; + CE(Sha1Hash(data, dataSz, (UINT8*)&hash)); + CE(Tpm12PcrExtend(DCS_TPM_PCR_LOCK, sizeof(hash), &hash)); + +err: + return res; +} diff --git a/Library/VeraCryptLib/DcsVeraCrypt.c b/Library/VeraCryptLib/DcsVeraCrypt.c index 1b6cd35..02128df 100644 --- a/Library/VeraCryptLib/DcsVeraCrypt.c +++ b/Library/VeraCryptLib/DcsVeraCrypt.c @@ -26,24 +26,25 @@ https://opensource.org/licenses/Apache-2.0 #include "common/Xml.h" #include "common/Crc.h" #include "BootCommon.h" +#include "Library/DcsTpmLib.h" ////////////////////////////////////////////////////////////////////////// // Config ////////////////////////////////////////////////////////////////////////// -char *ConfigBuffer = NULL; -UINTN ConfigBufferSize = 0; +char *gConfigBuffer = NULL; +UINTN gConfigBufferSize = 0; BOOL ConfigRead(char *configKey, char *configValue, int maxValueSize) { char *xml; - if (ConfigBuffer == NULL) { - if (FileLoad(NULL, L"\\EFI\\VeraCrypt\\DcsProp", &ConfigBuffer, &ConfigBufferSize) != EFI_SUCCESS) { - return FALSE; - } - } + if (gConfigBuffer == NULL) { + if (FileLoad(NULL, L"\\EFI\\VeraCrypt\\DcsProp", &gConfigBuffer, &gConfigBufferSize) != EFI_SUCCESS) { + return FALSE; + } + } - xml = ConfigBuffer; + xml = gConfigBuffer; if (xml != NULL) { xml = XmlFindElementByAttributeValue(xml, "config", "key", configKey); @@ -246,48 +247,145 @@ VCAuthLoadConfig() } +////////////////////////////////////////////////////////////////////////// +// Configuration menu +////////////////////////////////////////////////////////////////////////// +PMENU_ITEM gCfgMenu = NULL; +BOOLEAN gCfgMenuContinue = TRUE; + +EFI_STATUS +ActionCfgReboot(IN VOID *ctx) { + gST->RuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +ActionCfgTpm(IN VOID *ctx) { + return gTpm->Configure(gTpm); +} + +EFI_STATUS +ActionBoot(IN VOID *ctx) { + gCfgMenuContinue = FALSE; + gAuthPwdCode = AskPwdRetCancel; + return EFI_SUCCESS; +} + +EFI_STATUS +ActionNewPassword(IN VOID *ctx) { + gCfgMenuContinue = FALSE; + gAuthPwdCode = AskPwdRetLogin; + return EFI_SUCCESS; +} + +VOID +CfgMenuCreate() { + PMENU_ITEM item = NULL; + item = DcsMenuAppend(item, L"Boot", 'b', ActionBoot, NULL); + gCfgMenu = item; + item = DcsMenuAppend(item, L"Hard reset", 'r', ActionCfgReboot, NULL); + item = DcsMenuAppend(item, L"New password", 'n', ActionNewPassword, NULL); + if (gTpm != NULL) { + item = DcsMenuAppend(item, L"Configure TPM", 't', ActionCfgTpm, NULL); + } +} + VOID VCAskPwd( IN UINTN pwdType, OUT Password* vcPwd) { + BOOL pwdReady; 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; + do { + pwdReady = TRUE; + if (pwdType == AskPwdNew) { + EFI_INPUT_KEY key; + key = KeyWait(L"Press 'c' to configure, others to skip %1d\r", 9, 0, 0); + if (key.UnicodeChar == 'c') { + PMENU_ITEM item = NULL; + EFI_STATUS res; + OUT_PRINT(L"\n%V%a %a configuration%N\n", TC_APP_NAME, VERSION_STRING); + if (gCfgMenu == NULL) CfgMenuCreate(); + do { + DcsMenuPrint(gCfgMenu); + item = NULL; + key.UnicodeChar = 0; + while (item == NULL) { + item = gCfgMenu; + key = GetKey(); + while (item != NULL) { + if (item->Select == key.UnicodeChar) break; + item = item->Next; + } + } + OUT_PRINT(L"%c\n", key.UnicodeChar); + res = item->Action(item->Context); + if (EFI_ERROR(res)) { + ERR_PRINT(L"%r\n", res); + } + } while (gCfgMenuContinue); + if (gAuthPwdCode == AskPwdRetCancel) { + return; + } + } } - AskConsolePwdInt(&vcPwd->Length, vcPwd->Text, &gAuthPwdCode, sizeof(vcPwd->Text), gPasswordVisible); - } - if (gAuthPwdCode == AskPwdRetCancel) { - return; - } + 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 (gPlatformLocked) { - if (gPlatformKeyFile == NULL) { - ERR_PRINT(L"Platform key file absent\n"); - } else { - ApplyKeyFile(vcPwd, gPlatformKeyFile, gPlatformKeyFileSize); + if (gAuthPwdCode == AskPwdRetCancel) { + return; } - } - if (gTPMLocked) { - // TO DO - ERR_PRINT(L"TPM lock is not implemented\n"); - } + if (gSCLocked) { + ERR_PRINT(L"Smart card is not configured\n"); + } + + if (gPlatformLocked) { + if (gPlatformKeyFile == NULL) { + ERR_PRINT(L"Platform key file is absent\n"); + } + else { + ApplyKeyFile(vcPwd, gPlatformKeyFile, gPlatformKeyFileSize); + } + } + + if (gTPMLocked) { + if (gTpm != NULL) { + pwdReady = !EFI_ERROR(gTpm->Apply(gTpm, vcPwd)); + if (!pwdReady) { + ERR_PRINT(L"TPM error: DCS configuration "); + if (!gTpm->IsConfigured(gTpm)) { + ERR_PRINT(L"absent\n"); + } + else { + ERR_PRINT(L"locked\n"); + } + } + } else { + ERR_PRINT(L"No TPM found\n"); + } + } + } while (!pwdReady); } VOID diff --git a/Library/VeraCryptLib/DcsVeraCrypt.h b/Library/VeraCryptLib/DcsVeraCrypt.h index aae0152..fffe67c 100644 --- a/Library/VeraCryptLib/DcsVeraCrypt.h +++ b/Library/VeraCryptLib/DcsVeraCrypt.h @@ -19,6 +19,9 @@ https://opensource.org/licenses/Apache-2.0 #include #include +extern char *gConfigBuffer; +extern UINTN gConfigBufferSize; + ////////////////////////////////////////////////////////////////////////// // Auth ////////////////////////////////////////////////////////////////////////// diff --git a/Library/VeraCryptLib/VeraCryptLib.inf b/Library/VeraCryptLib/VeraCryptLib.inf index 04eedf5..529043f 100644 --- a/Library/VeraCryptLib/VeraCryptLib.inf +++ b/Library/VeraCryptLib/VeraCryptLib.inf @@ -79,11 +79,13 @@ LIB|Twofish_x64.obj|* [Packages] MdePkg/MdePkg.dec DcsPkg/DcsPkg.dec + CryptoPkg/CryptoPkg.dec [LibraryClasses] MemoryAllocationLib UefiLib RngLib + BaseCryptLib [Protocols] diff --git a/Library/VeraCryptLib/llmath.c b/Library/VeraCryptLib/llmath.c index 6b4360c..7d79657 100644 --- a/Library/VeraCryptLib/llmath.c +++ b/Library/VeraCryptLib/llmath.c @@ -227,7 +227,7 @@ __declspec(naked) void __cdecl _aulldiv() ////////////////////////////////////////////////////////////////////////// // Shifts ////////////////////////////////////////////////////////////////////////// -__declspec(naked) void __cdecl _aullshr() { +__declspec(naked) void __cdecl _aullshr1() { _asm { ; ; Checking: Only handle 64bit shifting or more @@ -264,7 +264,7 @@ _Exit: } } -__declspec(naked) void __cdecl _allshl() { +__declspec(naked) void __cdecl _allshl1() { _asm { ; ; Handle shifting of 64 or more bits (return 0) -- cgit v1.2.3