From 246233c40262c5be2edfa916cf841dd4bce6598e Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Aug 2016 22:08:47 +0200 Subject: Windows EFI Bootloader: modifications to prepare EFI system encryption support (common files with DcsBoot) --- src/Driver/DriveFilter.c | 92 ++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 42 deletions(-) (limited to 'src/Driver/DriveFilter.c') diff --git a/src/Driver/DriveFilter.c b/src/Driver/DriveFilter.c index 492c467a..a3d76b3a 100644 --- a/src/Driver/DriveFilter.c +++ b/src/Driver/DriveFilter.c @@ -3,7 +3,7 @@ Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. - Modifications and additions to the original source code (contained in this file) + Modifications and additions to the original source code (contained in this file) and all other portions of this file are Copyright (c) 2013-2016 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source @@ -33,7 +33,7 @@ static BOOL DeviceFilterActive = FALSE; BOOL BootArgsValid = FALSE; BootArguments BootArgs; -static uint16 BootLoaderSegment; +static uint64 BootLoaderArgsPtr; static BOOL BootDriveSignatureValid = FALSE; static KMUTEX MountMutex; @@ -69,21 +69,22 @@ static int64 DecoySystemWipedAreaEnd; PKTHREAD DecoySystemWipeThread = NULL; static NTSTATUS DecoySystemWipeResult; +uint64 BootArgsRegions[] = { EFI_BOOTARGS_REGIONS }; NTSTATUS LoadBootArguments () { NTSTATUS status = STATUS_UNSUCCESSFUL; PHYSICAL_ADDRESS bootArgsAddr; byte *mappedBootArgs; - uint16 bootLoaderSegment; + uint16 bootLoaderArgsIndex; KeInitializeMutex (&MountMutex, 0); - for (bootLoaderSegment = TC_BOOT_LOADER_SEGMENT; - bootLoaderSegment >= TC_BOOT_LOADER_SEGMENT - 64 * 1024 / 16 && status != STATUS_SUCCESS; - bootLoaderSegment -= 32 * 1024 / 16) + for (bootLoaderArgsIndex = 0; + bootLoaderArgsIndex < sizeof(BootArgsRegions)/ sizeof(BootArgsRegions[1]) && status != STATUS_SUCCESS; + ++bootLoaderArgsIndex) { - bootArgsAddr.QuadPart = (bootLoaderSegment << 4) + TC_BOOT_LOADER_ARGS_OFFSET; + bootArgsAddr.QuadPart = BootArgsRegions[bootLoaderArgsIndex] + TC_BOOT_LOADER_ARGS_OFFSET; Dump ("Checking BootArguments at 0x%x\n", bootArgsAddr.LowPart); mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof (BootArguments), MmCached); @@ -107,7 +108,7 @@ NTSTATUS LoadBootArguments () // Sanity check: for valid boot argument, the password is less than 64 bytes long if (bootArguments->BootPassword.Length <= MAX_PASSWORD) { - BootLoaderSegment = bootLoaderSegment; + BootLoaderArgsPtr = BootArgsRegions[bootLoaderArgsIndex]; BootArgs = *bootArguments; BootArgsValid = TRUE; @@ -168,7 +169,7 @@ NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) Extension = (DriveFilterExtension *) filterDeviceObject->DeviceExtension; memset (Extension, 0, sizeof (DriveFilterExtension)); - status = IoAttachDeviceToDeviceStackSafe (filterDeviceObject, pdo, &(Extension->LowerDeviceObject)); + status = IoAttachDeviceToDeviceStackSafe (filterDeviceObject, pdo, &(Extension->LowerDeviceObject)); if (!NT_SUCCESS (status)) { goto err; @@ -183,7 +184,7 @@ NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo) Extension->IsDriveFilterDevice = Extension->Queue.IsFilterDevice = TRUE; Extension->DeviceObject = Extension->Queue.DeviceObject = filterDeviceObject; Extension->Pdo = pdo; - + Extension->Queue.LowerDeviceObject = Extension->LowerDeviceObject; IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCV', 0, 0); @@ -216,7 +217,7 @@ static void DismountDrive (DriveFilterExtension *Extension, BOOL stopIoQueue) { Dump ("Dismounting drive\n"); ASSERT (Extension->DriveMounted); - + if (stopIoQueue && EncryptedIoQueueIsRunning (&Extension->Queue)) EncryptedIoQueueStop (&Extension->Queue); @@ -250,7 +251,7 @@ static void ComputeBootLoaderFingerprint(PDEVICE_OBJECT LowerDeviceObject, byte* // TC_BOOT_SECTOR_USER_CONFIG_OFFSET = 438 // // we have: TC_BOOT_SECTOR_USER_MESSAGE_OFFSET = TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET + TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE - + WHIRLPOOL_init (&whirlpool); sha512_begin (&sha2); // read the first 512 bytes @@ -322,6 +323,8 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, char *header; int pkcs5_prf = 0, pim = 0; byte *mappedCryptoInfo = NULL; + PARTITION_INFORMATION_EX pi; + BOOL bIsGPT = FALSE; Dump ("MountDrive pdo=%p\n", Extension->Pdo); ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL); @@ -372,11 +375,16 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, goto ret; } - if (BootArgs.CryptoInfoLength > 0) + if (NT_SUCCESS(SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof (pi)))) { - PHYSICAL_ADDRESS cryptoInfoAddress; + bIsGPT = (pi.PartitionStyle == PARTITION_STYLE_GPT)? TRUE : FALSE; + } - cryptoInfoAddress.QuadPart = (BootLoaderSegment << 4) + BootArgs.CryptoInfoOffset; + if (BootArgs.CryptoInfoLength > 0) + { + PHYSICAL_ADDRESS cryptoInfoAddress; + + cryptoInfoAddress.QuadPart = BootLoaderArgsPtr + BootArgs.CryptoInfoOffset; #ifdef DEBUG Dump ("Wiping memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength); #endif @@ -386,7 +394,7 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, /* Get the parameters used for booting to speed up driver startup and avoid testing irrelevant PRFs */ BOOT_CRYPTO_HEADER* pBootCryptoInfo = (BOOT_CRYPTO_HEADER*) mappedCryptoInfo; Hash* pHash = HashGet(pBootCryptoInfo->pkcs5); - if (pHash && pHash->SystemEncryption) + if (pHash && (bIsGPT || pHash->SystemEncryption)) pkcs5_prf = pBootCryptoInfo->pkcs5; } } @@ -401,20 +409,20 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, // calculate Fingerprint ComputeBootLoaderFingerprint (Extension->LowerDeviceObject, header); - + if (Extension->Queue.CryptoInfo->hiddenVolume) { int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart; Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset); - + Extension->HiddenSystem = TRUE; Extension->Queue.RemapEncryptedArea = TRUE; Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart; Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE; - + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart; - + if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart) TC_THROW_FATAL_EXCEPTION; @@ -473,7 +481,7 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, } status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &BootDriveLength, sizeof (BootDriveLength)); - + if (!NT_SUCCESS (status)) { Dump ("Failed to get drive length - error %x\n", status); @@ -482,7 +490,7 @@ static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, } else Extension->Queue.MaxReadAheadOffset = BootDriveLength; - + status = EncryptedIoQueueStart (&Extension->Queue); if (!NT_SUCCESS (status)) TC_BUG_CHECK (status); @@ -538,7 +546,7 @@ static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension) Dump ("Saving: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd); Dump ("Saving: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd); - + if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1 || Extension->Queue.EncryptedAreaEnd <= Extension->Queue.EncryptedAreaStart) { @@ -690,7 +698,7 @@ static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP } KeInitializeEvent (&Extension->MountWorkItemCompletedEvent, SynchronizationEvent, FALSE); - IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension); + IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension); KeWaitForSingleObject (&Extension->MountWorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL); IoFreeWorkItem (workItem); @@ -829,7 +837,7 @@ NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp) if (Extension->BootDrive) { status = EncryptedIoQueueAddIrp (&Extension->Queue, Irp); - + if (status != STATUS_PENDING) TCCompleteDiskIrp (Irp, status, 0); @@ -907,7 +915,7 @@ void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp) { Dump ("Header reopened\n"); ComputeBootLoaderFingerprint (BootDriveFilterExtension->LowerDeviceObject, header); - + BootDriveFilterExtension->Queue.CryptoInfo->header_creation_time = BootDriveFilterExtension->HeaderCryptoInfo->header_creation_time; BootDriveFilterExtension->Queue.CryptoInfo->pkcs5 = BootDriveFilterExtension->HeaderCryptoInfo->pkcs5; BootDriveFilterExtension->Queue.CryptoInfo->noIterations = BootDriveFilterExtension->HeaderCryptoInfo->noIterations; @@ -1037,7 +1045,7 @@ static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER if (writeB) return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl); - + return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA); } @@ -1281,11 +1289,11 @@ static VOID SetupThreadProc (PVOID threadArg) byte *wipeBuffer = NULL; byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT]; byte wipeRandCharsUpdate[TC_WIPE_RAND_CHAR_COUNT]; - + KIRQL irql; NTSTATUS status; - // generate real random values for wipeRandChars and + // generate real random values for wipeRandChars and // wipeRandCharsUpdate instead of relying on uninitialized stack memory LARGE_INTEGER iSeed; KeQuerySystemTime( &iSeed ); @@ -1312,7 +1320,7 @@ static VOID SetupThreadProc (PVOID threadArg) burn (digest, SHA512_DIGESTSIZE); burn (&tctx, sizeof (tctx)); } - + burn (&iSeed, sizeof(iSeed)); SetupResult = STATUS_UNSUCCESSFUL; @@ -1388,7 +1396,7 @@ static VOID SetupThreadProc (PVOID threadArg) } EncryptedIoQueueResumeFromHold (&Extension->Queue); - + Dump ("EncryptedAreaStart=%I64d\n", Extension->Queue.EncryptedAreaStart); Dump ("EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaEnd); Dump ("ConfiguredEncryptedAreaStart=%I64d\n", Extension->ConfiguredEncryptedAreaStart); @@ -1497,7 +1505,7 @@ static VOID SetupThreadProc (PVOID threadArg) } EncryptDataUnits (wipeBuffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo); - memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); + memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); } status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, setupBlockSize); @@ -1512,7 +1520,7 @@ static VOID SetupThreadProc (PVOID threadArg) } } - memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); + memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); } } else @@ -1658,7 +1666,7 @@ NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_ST SetupInProgress = TRUE; status = TCStartThread (SetupThreadProc, DeviceObject, &EncryptionSetupThread); - + if (!NT_SUCCESS (status)) SetupInProgress = FALSE; @@ -1754,7 +1762,7 @@ void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp) bootEncStatus->HiddenSysLeakProtectionCount = HiddenSysLeakProtectionCount; bootEncStatus->HiddenSystem = Extension->HiddenSystem; - + if (Extension->HiddenSystem) bootEncStatus->HiddenSystemPartitionStart = BootArgs.HiddenSystemPartitionStart; } @@ -1790,7 +1798,7 @@ void GetBootLoaderFingerprint (PIRP irp, PIO_STACK_LOCATION irpSp) irp->IoStatus.Information = 0; if (BootArgsValid && BootDriveFound && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted && BootDriveFilterExtension->HeaderCryptoInfo) { - BootLoaderFingerprintRequest *bootLoaderFingerprint = (BootLoaderFingerprintRequest *) irp->AssociatedIrp.SystemBuffer; + BootLoaderFingerprintRequest *bootLoaderFingerprint = (BootLoaderFingerprintRequest *) irp->AssociatedIrp.SystemBuffer; /* compute the fingerprint again and check if it is the same as the one retrieved during boot */ char *header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE); @@ -1820,7 +1828,7 @@ void GetBootLoaderFingerprint (PIRP irp, PIO_STACK_LOCATION irpSp) } else { - irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + irp->IoStatus.Status = STATUS_INVALID_PARAMETER; } } } @@ -1931,7 +1939,7 @@ static VOID DecoySystemWipeThreadProc (PVOID threadArg) DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES; goto ret; } - + wipeRandBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE); if (!wipeRandBuffer) { @@ -1956,7 +1964,7 @@ static VOID DecoySystemWipeThreadProc (PVOID threadArg) } memcpy (wipeCryptoInfo->k2, WipeDecoyRequest.WipeKey + EAGetKeySize (ea), EAGetKeySize (ea)); - + if (!EAInitMode (wipeCryptoInfo)) { DecoySystemWipeResult = STATUS_INVALID_PARAMETER; @@ -1969,7 +1977,7 @@ static VOID DecoySystemWipeThreadProc (PVOID threadArg) burn (WipeDecoyRequest.WipeKey, sizeof (WipeDecoyRequest.WipeKey)); offset.QuadPart = Extension->ConfiguredEncryptedAreaStart; - + Dump ("Wiping decoy system: start offset = %I64d\n", offset.QuadPart); while (!DecoySystemWipeThreadAbortRequested) @@ -2073,7 +2081,7 @@ NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_ DecoySystemWipeInProgress = TRUE; status = TCStartThread (DecoySystemWipeThreadProc, DeviceObject, &DecoySystemWipeThread); - + if (!NT_SUCCESS (status)) DecoySystemWipeInProgress = FALSE; @@ -2112,7 +2120,7 @@ void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp) } else wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd; - + irp->IoStatus.Information = sizeof (DecoySystemWipeStatus); irp->IoStatus.Status = STATUS_SUCCESS; } -- cgit v1.2.3