From 0d88d54f987fa0e464177febbc04c93257a17b40 Mon Sep 17 00:00:00 2001 From: kavsrf Date: Sat, 28 Jan 2017 14:12:08 +0300 Subject: full disk encryption support --- DcsBoot/DcsBoot.c | 38 ++++++- DcsBoot/DcsBoot.inf | 1 + DcsCfg/DcsCfgCrypt.c | 6 +- DcsRe/DcsRe.c | 2 +- Include/Library/CommonLib.h | 37 +++++++ Library/CommonLib/CommonLib.inf | 1 + Library/CommonLib/GptRead.c | 215 ++++++++++++++++++++++++++++++++++++++++ Library/DcsCfgLib/GptEdit.c | 202 +------------------------------------ 8 files changed, 297 insertions(+), 205 deletions(-) create mode 100644 Library/CommonLib/GptRead.c diff --git a/DcsBoot/DcsBoot.c b/DcsBoot/DcsBoot.c index 60c8eed..108da0c 100644 --- a/DcsBoot/DcsBoot.c +++ b/DcsBoot/DcsBoot.c @@ -16,7 +16,9 @@ https://opensource.org/licenses/LGPL-3.0 #include #include #include +#include #include "DcsConfig.h" +#include EFI_GUID ImagePartGuid; EFI_GUID *gEfiExecPartGuid = &ImagePartGuid; @@ -43,6 +45,7 @@ DcsBootMain( UINTN len; UINT32 attr; int drvInst; + BOOLEAN searchOnESP = FALSE; InitBio(); res = InitFS(); if (EFI_ERROR(res)) { @@ -51,8 +54,8 @@ DcsBootMain( drvInst = ConfigReadInt("DcsDriver", 0); - if (!FileExist(NULL, L"\\EFI\\VeraCrypt\\PlatformInfo") && - !FileExist(NULL, L"\\EFI\\VeraCrypt\\DcsInfo.dcs")) { + if (EFI_ERROR(FileExist(NULL, L"\\EFI\\VeraCrypt\\PlatformInfo")) && + !EFI_ERROR(FileExist(NULL, L"\\EFI\\VeraCrypt\\DcsInfo.dcs"))) { res = EfiExec(NULL, L"\\EFI\\VeraCrypt\\DcsInfo.dcs"); } // Load all drivers @@ -83,11 +86,40 @@ DcsBootMain( gEfiExecCmd = gEfiExecCmdDefault; } + searchOnESP = CompareGuid(gEfiExecPartGuid, &ImagePartGuid) && + EFI_ERROR(FileExist(NULL, gEfiExecCmd)); + // Find new start partition ConnectAllEfi(); InitBio(); res = InitFS(); -// OUT_PRINT(L"."); + + // Default load of bootmgfw? + if (searchOnESP) { + // gEfiExecCmd is not found on start partition. Try from ESP + EFI_BLOCK_IO_PROTOCOL *bio = NULL; + EFI_PARTITION_TABLE_HEADER *gptHdr = NULL; + EFI_PARTITION_ENTRY *gptEntry = NULL; + HARDDRIVE_DEVICE_PATH hdp; + EFI_HANDLE disk; + if (!EFI_ERROR(res = EfiGetPartDetails(gFileRootHandle, &hdp, &disk))) { + if ((bio = EfiGetBlockIO(disk)) != NULL) { + if (!EFI_ERROR(res = GptReadHeader(bio, 1, &gptHdr)) && + !EFI_ERROR(res = GptReadEntryArray(bio, gptHdr, &gptEntry))) { + UINT32 i; + for (i = 0; i < gptHdr->NumberOfPartitionEntries; ++i) { + if (CompareGuid(&gptEntry[i].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)) { + // select ESP GUID + CopyGuid(gEfiExecPartGuid, &gptEntry[i].UniquePartitionGUID); + break; + } + } + } + } + } + } + + // OUT_PRINT(L"."); res = EfiFindPartByGUID(gEfiExecPartGuid, &gFileRootHandle); if (EFI_ERROR(res)) { ERR_PRINT(L"\nCan't find start partition %g\n", gEfiExecPartGuid); diff --git a/DcsBoot/DcsBoot.inf b/DcsBoot/DcsBoot.inf index 14d8d0d..34c78f3 100644 --- a/DcsBoot/DcsBoot.inf +++ b/DcsBoot/DcsBoot.inf @@ -47,6 +47,7 @@ gEfiGlobalVariableGuid gEfiDcsVariableGuid gEfiFileInfoGuid + gEfiPartTypeSystemPartGuid [Protocols] gEfiBlockIoProtocolGuid diff --git a/DcsCfg/DcsCfgCrypt.c b/DcsCfg/DcsCfgCrypt.c index 0e892dd..45523dd 100644 --- a/DcsCfg/DcsCfgCrypt.c +++ b/DcsCfg/DcsCfgCrypt.c @@ -187,9 +187,9 @@ ChangePassword( if (AskConfirm("Change range of encrypted sectors[N]?", 1)) { modified = TRUE; - cryptoInfo->VolumeSize.Value = AskUINT64("Volume size", cryptoInfo->VolumeSize.Value >> 9) << 9; - cryptoInfo->EncryptedAreaStart.Value = AskUINT64("Encrypted area start", cryptoInfo->EncryptedAreaStart.Value >> 9) << 9; - cryptoInfo->EncryptedAreaLength.Value = AskUINT64("Encrypted area length", cryptoInfo->EncryptedAreaLength.Value >> 9) << 9; + cryptoInfo->VolumeSize.Value = AskUINT64("Volume size:", cryptoInfo->VolumeSize.Value >> 9) << 9; + cryptoInfo->EncryptedAreaStart.Value = AskUINT64("Encrypted area start:", cryptoInfo->EncryptedAreaStart.Value >> 9) << 9; + cryptoInfo->EncryptedAreaLength.Value = AskUINT64("Encrypted area length:", cryptoInfo->EncryptedAreaLength.Value >> 9) << 9; } if (modified) { diff --git a/DcsRe/DcsRe.c b/DcsRe/DcsRe.c index 1f71f11..7f4096f 100644 --- a/DcsRe/DcsRe.c +++ b/DcsRe/DcsRe.c @@ -80,8 +80,8 @@ SelectEfiVolume() else { OUT_PRINT(L"%V [Boot] %N"); } - EfiPrintDevicePath(gFSHandles[i]); } + EfiPrintDevicePath(gFSHandles[i]); OUT_PRINT(L"\n"); } diff --git a/Include/Library/CommonLib.h b/Include/Library/CommonLib.h index 950406f..98e93db 100644 --- a/Include/Library/CommonLib.h +++ b/Include/Library/CommonLib.h @@ -21,6 +21,7 @@ https://opensource.org/licenses/LGPL-3.0 #include #include #include +#include ////////////////////////////////////////////////////////////////////////// // Check error @@ -136,6 +137,42 @@ EfiFindPartByGUID( OUT EFI_HANDLE* h ); +////////////////////////////////////////////////////////////////////////// +// GPT +////////////////////////////////////////////////////////////////////////// + +BOOLEAN +GptHeaderCheckCrc( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +EFI_STATUS +GptCheckEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ); + +EFI_STATUS +GptUpdateCRC( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ); + +EFI_STATUS +GptReadEntryArray( + IN EFI_BLOCK_IO_PROTOCOL* BlockIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + OUT EFI_PARTITION_ENTRY **Entrys + ); + +EFI_STATUS +GptReadHeader( + IN EFI_BLOCK_IO_PROTOCOL* BlockIo, + IN EFI_LBA HeaderLba, + OUT EFI_PARTITION_TABLE_HEADER **PartHeader + ); + ////////////////////////////////////////////////////////////////////////// // Bluetooth ////////////////////////////////////////////////////////////////////////// diff --git a/Library/CommonLib/CommonLib.inf b/Library/CommonLib/CommonLib.inf index b5758f5..dde5c61 100644 --- a/Library/CommonLib/CommonLib.inf +++ b/Library/CommonLib/CommonLib.inf @@ -38,6 +38,7 @@ EfiTouch.c EfiBluetooth.c EfiTpm.c + GptRead.c [Sources.IA32] IA32/EfiCpuHalt.asm diff --git a/Library/CommonLib/GptRead.c b/Library/CommonLib/GptRead.c new file mode 100644 index 0000000..0eab963 --- /dev/null +++ b/Library/CommonLib/GptRead.c @@ -0,0 +1,215 @@ +/** @file +GPT low level actions + +Copyright (c) 2016. Disk Cryptography Services for EFI (DCS), Alex Kolotnikov + +This program and the accompanying materials +are licensed and made available under the terms and conditions +of the GNU Lesser General Public License, version 3.0 (LGPL-3.0). + +The full text of the license may be found at +https://opensource.org/licenses/LGPL-3.0 +**/ + +#include +#include +#include +#include +#include + +#include + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Size The size of the table +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrcAltSize( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + UINT32 Crc; + UINT32 OrgCrc; + EFI_STATUS Status; + + Crc = 0; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + + if ((MaxSize != 0) && (Size > MaxSize)) { + return FALSE; + } + // + // clear old crc from header + // + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc); + if (EFI_ERROR(Status)) { + return FALSE; + } + // + // set results + // + Hdr->CRC32 = OrgCrc; + + return (BOOLEAN)(OrgCrc == Crc); +} + +/** +Checks the CRC32 value in the table header. + +@param MaxSize Max Size limit +@param Hdr Table to check + +@return TRUE CRC Valid +@return FALSE CRC Invalid + +**/ +BOOLEAN +GptHeaderCheckCrc( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +{ + return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr); +} + +EFI_STATUS +GptCheckEntryArray( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = (UINTN)PartHeader->NumberOfPartitionEntries * (UINTN)PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return EFI_CRC_ERROR; + } + Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR; + return Status; +} + +EFI_STATUS +GptUpdateCRC( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *Entrys + ) +{ + EFI_STATUS Status; + UINT32 Crc; + UINTN Size; + + Size = (UINTN)PartHeader->NumberOfPartitionEntries * (UINTN)PartHeader->SizeOfPartitionEntry; + Status = gBS->CalculateCrc32(Entrys, Size, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->PartitionEntryArrayCRC32 = Crc; + PartHeader->Header.CRC32 = 0; + + Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc); + if (EFI_ERROR(Status)) { + return Status; + } + PartHeader->Header.CRC32 = Crc; + return Status; +} + +/** +Read GPT +Check if the CRC field in the Partition table header is valid +for Partition entry array. + +@param[in] BlockIo Disk Io Protocol. +@param[in] PartHeader Partition table header structure + +@retval EFI_SUCCESS the CRC is valid +**/ +EFI_STATUS +GptReadEntryArray( + IN EFI_BLOCK_IO_PROTOCOL* BlockIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + OUT EFI_PARTITION_ENTRY **Entrys + ) +{ + EFI_STATUS Status; + UINT8 *Ptr; + + // + // Read the EFI Partition Entries + // + Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + return EFI_BUFFER_TOO_SMALL; + } + + Status = BlockIo->ReadBlocks( + BlockIo, + BlockIo->Media->MediaId, + PartHeader->PartitionEntryLBA, + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR(Status)) { + MEM_FREE(Ptr); + return Status; + } + + *Entrys = (EFI_PARTITION_ENTRY*)Ptr; + return GptCheckEntryArray(PartHeader, *Entrys); +} + +EFI_STATUS +GptReadHeader( + IN EFI_BLOCK_IO_PROTOCOL* BlockIo, + IN EFI_LBA HeaderLba, + OUT EFI_PARTITION_TABLE_HEADER **PartHeader + ) +{ + EFI_STATUS res = EFI_SUCCESS; + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + UINT32 MediaId; + + BlockSize = BlockIo->Media->BlockSize; + MediaId = BlockIo->Media->MediaId; + PartHdr = MEM_ALLOC(BlockSize); + + res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr); + if (EFI_ERROR(res)) { + MEM_FREE(PartHdr); + return res; + } + + // Check header + if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || + !GptHeaderCheckCrc(BlockSize, &PartHdr->Header) || + PartHdr->MyLBA != HeaderLba || + (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) + ) { + MEM_FREE(PartHdr); + return EFI_CRC_ERROR; + } + *PartHeader = PartHdr; + return EFI_SUCCESS; +} diff --git a/Library/DcsCfgLib/GptEdit.c b/Library/DcsCfgLib/GptEdit.c index ea016f1..e1d6d2a 100644 --- a/Library/DcsCfgLib/GptEdit.c +++ b/Library/DcsCfgLib/GptEdit.c @@ -61,200 +61,6 @@ UINTN MirrorPartIdx; // Partitions ////////////////////////////////////////////////////////////////////////// - -/** -Checks the CRC32 value in the table header. - -@param MaxSize Max Size limit -@param Size The size of the table -@param Hdr Table to check - -@return TRUE CRC Valid -@return FALSE CRC Invalid - -**/ -BOOLEAN -GptHeaderCheckCrcAltSize( - IN UINTN MaxSize, - IN UINTN Size, - IN OUT EFI_TABLE_HEADER *Hdr - ) -{ - UINT32 Crc; - UINT32 OrgCrc; - EFI_STATUS Status; - - Crc = 0; - - if (Size == 0) { - // - // If header size is 0 CRC will pass so return FALSE here - // - return FALSE; - } - - if ((MaxSize != 0) && (Size > MaxSize)) { - return FALSE; - } - // - // clear old crc from header - // - OrgCrc = Hdr->CRC32; - Hdr->CRC32 = 0; - - Status = gBS->CalculateCrc32((UINT8 *)Hdr, Size, &Crc); - if (EFI_ERROR(Status)) { - return FALSE; - } - // - // set results - // - Hdr->CRC32 = OrgCrc; - - return (BOOLEAN)(OrgCrc == Crc); -} - -/** -Checks the CRC32 value in the table header. - -@param MaxSize Max Size limit -@param Hdr Table to check - -@return TRUE CRC Valid -@return FALSE CRC Invalid - -**/ -BOOLEAN -GptHeaderCheckCrc( - IN UINTN MaxSize, - IN OUT EFI_TABLE_HEADER *Hdr - ) -{ - return GptHeaderCheckCrcAltSize(MaxSize, Hdr->HeaderSize, Hdr); -} - -EFI_STATUS -GptCheckEntryArray( - IN EFI_PARTITION_TABLE_HEADER *PartHeader, - IN EFI_PARTITION_ENTRY *Entrys - ) -{ - EFI_STATUS Status; - UINT32 Crc; - UINTN Size; - - Size = (UINTN) PartHeader->NumberOfPartitionEntries * (UINTN) PartHeader->SizeOfPartitionEntry; - Status = gBS->CalculateCrc32(Entrys, Size, &Crc); - if (EFI_ERROR(Status)) { - return EFI_CRC_ERROR; - } - Status = (PartHeader->PartitionEntryArrayCRC32 == Crc) ? EFI_SUCCESS : EFI_CRC_ERROR; - return Status; -} - -EFI_STATUS -GptUpdateCRC( - IN EFI_PARTITION_TABLE_HEADER *PartHeader, - IN EFI_PARTITION_ENTRY *Entrys - ) -{ - EFI_STATUS Status; - UINT32 Crc; - UINTN Size; - - Size = (UINTN) PartHeader->NumberOfPartitionEntries * (UINTN) PartHeader->SizeOfPartitionEntry; - Status = gBS->CalculateCrc32(Entrys, Size, &Crc); - if (EFI_ERROR(Status)) { - return Status; - } - PartHeader->PartitionEntryArrayCRC32 = Crc; - PartHeader->Header.CRC32 = 0; - - Status = gBS->CalculateCrc32((UINT8 *)PartHeader, PartHeader->Header.HeaderSize, &Crc); - if (EFI_ERROR(Status)) { - return Status; - } - PartHeader->Header.CRC32 = Crc; - return Status; -} - -/** -Read GPT -Check if the CRC field in the Partition table header is valid -for Partition entry array. - -@param[in] DiskIo Disk Io Protocol. -@param[in] PartHeader Partition table header structure - -@retval EFI_SUCCESS the CRC is valid -**/ -EFI_STATUS -GptReadEntryArray( - IN EFI_PARTITION_TABLE_HEADER *PartHeader, - OUT EFI_PARTITION_ENTRY **Entrys - ) -{ - EFI_STATUS Status; - UINT8 *Ptr; - - // - // Read the EFI Partition Entries - // - Ptr = MEM_ALLOC(PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); - if (Ptr == NULL) { - return EFI_BUFFER_TOO_SMALL; - } - - Status = BlockIo->ReadBlocks( - BlockIo, - BlockIo->Media->MediaId, - PartHeader->PartitionEntryLBA, - PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, - Ptr - ); - if (EFI_ERROR(Status)) { - MEM_FREE(Ptr); - return Status; - } - - *Entrys = (EFI_PARTITION_ENTRY*)Ptr; - return GptCheckEntryArray(PartHeader, *Entrys); -} - -EFI_STATUS -GptReadHeader( - IN EFI_LBA HeaderLba, - OUT EFI_PARTITION_TABLE_HEADER **PartHeader - ) -{ - EFI_STATUS res = EFI_SUCCESS; - UINT32 BlockSize; - EFI_PARTITION_TABLE_HEADER *PartHdr; - UINT32 MediaId; - - BlockSize = BlockIo->Media->BlockSize; - MediaId = BlockIo->Media->MediaId; - PartHdr = MEM_ALLOC(BlockSize); - - res = BlockIo->ReadBlocks(BlockIo, MediaId, HeaderLba, BlockSize, PartHdr); - if (EFI_ERROR(res)) { - MEM_FREE(PartHdr); - return res; - } - - // Check header - if ((PartHdr->Header.Signature != EFI_PTAB_HEADER_ID) || - !GptHeaderCheckCrc(BlockSize, &PartHdr->Header) || - PartHdr->MyLBA != HeaderLba || - (PartHdr->SizeOfPartitionEntry < sizeof(EFI_PARTITION_ENTRY)) - ) { - MEM_FREE(PartHdr); - return EFI_CRC_ERROR; - } - *PartHeader = PartHdr; - return EFI_SUCCESS; -} - VOID GptPrint( IN EFI_PARTITION_TABLE_HEADER *PartHdr, @@ -298,26 +104,26 @@ GptLoadFromDisk( return EFI_NOT_FOUND; } - res = GptReadHeader(1, &GptMainHdr); + res = GptReadHeader(BlockIo, 1, &GptMainHdr); if (EFI_ERROR(res)) { ERR_PRINT(L"Can't read main GPT header: %r\n", res); goto error; } - res = GptReadHeader(GptMainHdr->AlternateLBA, &GptAltHdr); + res = GptReadHeader(BlockIo, GptMainHdr->AlternateLBA, &GptAltHdr); if (EFI_ERROR(res)) { ERR_PRINT(L"Can't read alt GPT header: %r\n", res); goto error; } - res = GptReadEntryArray(GptMainHdr, &GptMainEntrys); + res = GptReadEntryArray(BlockIo, GptMainHdr, &GptMainEntrys); // Read GPT if (EFI_ERROR(res)) { ERR_PRINT(L"Main GPT error: %r\n", res); goto error; } - res = GptReadEntryArray(GptAltHdr, &GptAltEntrys); + res = GptReadEntryArray(BlockIo, GptAltHdr, &GptAltEntrys); // Read GPT if (EFI_ERROR(res)) { ERR_PRINT(L"Alt GPT error: %r\n", res); -- cgit v1.2.3