diff options
Diffstat (limited to 'src/Driver/DumpFilter.c')
-rw-r--r-- | src/Driver/DumpFilter.c | 496 |
1 files changed, 248 insertions, 248 deletions
diff --git a/src/Driver/DumpFilter.c b/src/Driver/DumpFilter.c index 16d1d37c..d67b1654 100644 --- a/src/Driver/DumpFilter.c +++ b/src/Driver/DumpFilter.c @@ -1,248 +1,248 @@ -/*
- Derived from source code of TrueCrypt 7.1a, which is
- 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)
- 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
- code distribution packages.
-*/
-
-#include "DumpFilter.h"
-#include "DriveFilter.h"
-#include "Ntdriver.h"
-#include "Tests.h"
-
-static DriveFilterExtension *BootDriveFilterExtension = NULL;
-static LARGE_INTEGER DumpPartitionOffset;
-static byte *WriteFilterBuffer = NULL;
-static SIZE_T WriteFilterBufferSize;
-
-
-NTSTATUS DumpFilterEntry (PFILTER_EXTENSION filterExtension, PFILTER_INITIALIZATION_DATA filterInitData)
-{
- GetSystemDriveDumpConfigRequest dumpConfig;
- PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
- STORAGE_DEVICE_NUMBER storageDeviceNumber;
- PARTITION_INFORMATION partitionInfo;
- LONG version;
- NTSTATUS status;
-
- Dump ("DumpFilterEntry type=%d\n", filterExtension->DumpType);
-
- filterInitData->MajorVersion = DUMP_FILTER_MAJOR_VERSION;
- filterInitData->MinorVersion = DUMP_FILTER_MINOR_VERSION;
- filterInitData->Flags |= DUMP_FILTER_CRITICAL;
-
- // Check driver version of the main device
- status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version));
- if (!NT_SUCCESS (status))
- goto err;
-
- if (version != VERSION_NUM)
- {
- status = STATUS_INVALID_PARAMETER;
- goto err;
- }
-
- // Get dump configuration from the main device
- status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG, NULL, 0, &dumpConfig, sizeof (dumpConfig));
- if (!NT_SUCCESS (status))
- goto err;
-
- BootDriveFilterExtension = dumpConfig.BootDriveFilterExtension;
-
- if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
- {
- status = STATUS_CRC_ERROR;
- goto err;
- }
-
- // KeSaveFloatingPointState() may generate a bug check during crash dump
-#if !defined (_WIN64)
- if (filterExtension->DumpType == DumpTypeCrashdump)
- dumpConfig.HwEncryptionEnabled = FALSE;
-#endif
-
- EnableHwEncryption (dumpConfig.HwEncryptionEnabled);
-
- if (!AutoTestAlgorithms())
- {
- status = STATUS_INVALID_PARAMETER;
- goto err;
- }
-
- // Check dump volume is located on the system drive
- status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
- if (!NT_SUCCESS (status))
- goto err;
-
- if (!BootDriveFilterExtension->SystemStorageDeviceNumberValid)
- {
- status = STATUS_INVALID_PARAMETER;
- goto err;
- }
-
- if (storageDeviceNumber.DeviceNumber != BootDriveFilterExtension->SystemStorageDeviceNumber)
- {
- status = STATUS_ACCESS_DENIED;
- goto err;
- }
-
- // Check dump volume is located within the scope of system encryption
- status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &partitionInfo, sizeof (partitionInfo));
- if (!NT_SUCCESS (status))
- goto err;
-
- DumpPartitionOffset = partitionInfo.StartingOffset;
-
- if (DumpPartitionOffset.QuadPart < BootDriveFilterExtension->ConfiguredEncryptedAreaStart
- || DumpPartitionOffset.QuadPart > BootDriveFilterExtension->ConfiguredEncryptedAreaEnd)
- {
- status = STATUS_ACCESS_DENIED;
- goto err;
- }
-
- // Allocate buffer for encryption
- if (filterInitData->MaxPagesPerWrite == 0)
- {
- status = STATUS_INVALID_PARAMETER;
- goto err;
- }
-
- WriteFilterBufferSize = filterInitData->MaxPagesPerWrite * PAGE_SIZE;
-
-#ifdef _WIN64
- highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFLL;
-#else
- highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFLL;
-#endif
-
- WriteFilterBuffer = MmAllocateContiguousMemory (WriteFilterBufferSize, highestAcceptableWriteBufferAddr);
- if (!WriteFilterBuffer)
- {
- status = STATUS_INSUFFICIENT_RESOURCES;
- goto err;
- }
-
- filterInitData->DumpStart = DumpFilterStart;
- filterInitData->DumpWrite = DumpFilterWrite;
- filterInitData->DumpFinish = DumpFilterFinish;
- filterInitData->DumpUnload = DumpFilterUnload;
-
- Dump ("Dump filter loaded type=%d\n", filterExtension->DumpType);
- return STATUS_SUCCESS;
-
-err:
- Dump ("DumpFilterEntry error %x\n", status);
- return status;
-}
-
-
-static NTSTATUS DumpFilterStart (PFILTER_EXTENSION filterExtension)
-{
- Dump ("DumpFilterStart type=%d\n", filterExtension->DumpType);
-
- if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
- TC_BUG_CHECK (STATUS_CRC_ERROR);
-
- return BootDriveFilterExtension->DriveMounted ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
-}
-
-
-static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEGER diskWriteOffset, PMDL writeMdl)
-{
- ULONG dataLength = MmGetMdlByteCount (writeMdl);
- uint64 offset = DumpPartitionOffset.QuadPart + diskWriteOffset->QuadPart;
- uint64 intersectStart;
- uint32 intersectLength;
- PVOID writeBuffer;
- CSHORT origMdlFlags;
-
- if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
- TC_BUG_CHECK (STATUS_CRC_ERROR);
-
- if (BootDriveFilterExtension->Queue.EncryptedAreaEndUpdatePending) // Hibernation should always abort the setup thread
- TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
-
- if (BootDriveFilterExtension->Queue.EncryptedAreaStart == -1 || BootDriveFilterExtension->Queue.EncryptedAreaEnd == -1)
- return STATUS_SUCCESS;
-
- if (dataLength > WriteFilterBufferSize)
- TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW); // Bug check is required as returning an error does not prevent data from being written to disk
-
- if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
- TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
-
- if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
- TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
-
- writeBuffer = MmGetSystemAddressForMdlSafe (writeMdl, HighPagePriority);
- if (!writeBuffer)
- TC_BUG_CHECK (STATUS_INSUFFICIENT_RESOURCES);
-
- memcpy (WriteFilterBuffer, writeBuffer, dataLength);
-
- GetIntersection (offset,
- dataLength,
- BootDriveFilterExtension->Queue.EncryptedAreaStart,
- BootDriveFilterExtension->Queue.EncryptedAreaEnd,
- &intersectStart,
- &intersectLength);
-
- if (intersectLength > 0)
- {
- UINT64_STRUCT dataUnit;
- dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
-
- if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
- {
- diskWriteOffset->QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset;
- dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset;
- }
-
- EncryptDataUnitsCurrentThread (WriteFilterBuffer + (intersectStart - offset),
- &dataUnit,
- intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
- BootDriveFilterExtension->Queue.CryptoInfo);
- }
-
- origMdlFlags = writeMdl->MdlFlags;
-
- MmInitializeMdl (writeMdl, WriteFilterBuffer, dataLength);
- MmBuildMdlForNonPagedPool (writeMdl);
-
- // Instead of using MmGetSystemAddressForMdlSafe(), some buggy custom storage drivers may directly test MDL_MAPPED_TO_SYSTEM_VA flag,
- // disregarding the fact that other MDL flags may be set by the system or a dump filter (e.g. MDL_SOURCE_IS_NONPAGED_POOL flag only).
- // Therefore, to work around this issue, the original flags will be restored even if they do not match the new MDL.
- // MS BitLocker also uses this hack/workaround (it should be safe to use until the MDL structure is changed).
-
- writeMdl->MdlFlags = origMdlFlags;
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS DumpFilterFinish (PFILTER_EXTENSION filterExtension)
-{
- Dump ("DumpFilterFinish type=%d\n", filterExtension->DumpType);
-
- return STATUS_SUCCESS;
-}
-
-
-static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension)
-{
- Dump ("DumpFilterUnload type=%d\n", filterExtension->DumpType);
-
- if (WriteFilterBuffer)
- {
- memset (WriteFilterBuffer, 0, WriteFilterBufferSize);
- MmFreeContiguousMemory (WriteFilterBuffer);
- WriteFilterBuffer = NULL;
- }
-
- return STATUS_SUCCESS;
-}
+/* + Derived from source code of TrueCrypt 7.1a, which is + 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) + 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 + code distribution packages. +*/ + +#include "DumpFilter.h" +#include "DriveFilter.h" +#include "Ntdriver.h" +#include "Tests.h" + +static DriveFilterExtension *BootDriveFilterExtension = NULL; +static LARGE_INTEGER DumpPartitionOffset; +static byte *WriteFilterBuffer = NULL; +static SIZE_T WriteFilterBufferSize; + + +NTSTATUS DumpFilterEntry (PFILTER_EXTENSION filterExtension, PFILTER_INITIALIZATION_DATA filterInitData) +{ + GetSystemDriveDumpConfigRequest dumpConfig; + PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr; + STORAGE_DEVICE_NUMBER storageDeviceNumber; + PARTITION_INFORMATION partitionInfo; + LONG version; + NTSTATUS status; + + Dump ("DumpFilterEntry type=%d\n", filterExtension->DumpType); + + filterInitData->MajorVersion = DUMP_FILTER_MAJOR_VERSION; + filterInitData->MinorVersion = DUMP_FILTER_MINOR_VERSION; + filterInitData->Flags |= DUMP_FILTER_CRITICAL; + + // Check driver version of the main device + status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version)); + if (!NT_SUCCESS (status)) + goto err; + + if (version != VERSION_NUM) + { + status = STATUS_INVALID_PARAMETER; + goto err; + } + + // Get dump configuration from the main device + status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG, NULL, 0, &dumpConfig, sizeof (dumpConfig)); + if (!NT_SUCCESS (status)) + goto err; + + BootDriveFilterExtension = dumpConfig.BootDriveFilterExtension; + + if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER) + { + status = STATUS_CRC_ERROR; + goto err; + } + + // KeSaveFloatingPointState() may generate a bug check during crash dump +#if !defined (_WIN64) + if (filterExtension->DumpType == DumpTypeCrashdump) + dumpConfig.HwEncryptionEnabled = FALSE; +#endif + + EnableHwEncryption (dumpConfig.HwEncryptionEnabled); + + if (!AutoTestAlgorithms()) + { + status = STATUS_INVALID_PARAMETER; + goto err; + } + + // Check dump volume is located on the system drive + status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber)); + if (!NT_SUCCESS (status)) + goto err; + + if (!BootDriveFilterExtension->SystemStorageDeviceNumberValid) + { + status = STATUS_INVALID_PARAMETER; + goto err; + } + + if (storageDeviceNumber.DeviceNumber != BootDriveFilterExtension->SystemStorageDeviceNumber) + { + status = STATUS_ACCESS_DENIED; + goto err; + } + + // Check dump volume is located within the scope of system encryption + status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &partitionInfo, sizeof (partitionInfo)); + if (!NT_SUCCESS (status)) + goto err; + + DumpPartitionOffset = partitionInfo.StartingOffset; + + if (DumpPartitionOffset.QuadPart < BootDriveFilterExtension->ConfiguredEncryptedAreaStart + || DumpPartitionOffset.QuadPart > BootDriveFilterExtension->ConfiguredEncryptedAreaEnd) + { + status = STATUS_ACCESS_DENIED; + goto err; + } + + // Allocate buffer for encryption + if (filterInitData->MaxPagesPerWrite == 0) + { + status = STATUS_INVALID_PARAMETER; + goto err; + } + + WriteFilterBufferSize = filterInitData->MaxPagesPerWrite * PAGE_SIZE; + +#ifdef _WIN64 + highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFLL; +#else + highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFLL; +#endif + + WriteFilterBuffer = MmAllocateContiguousMemory (WriteFilterBufferSize, highestAcceptableWriteBufferAddr); + if (!WriteFilterBuffer) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto err; + } + + filterInitData->DumpStart = DumpFilterStart; + filterInitData->DumpWrite = DumpFilterWrite; + filterInitData->DumpFinish = DumpFilterFinish; + filterInitData->DumpUnload = DumpFilterUnload; + + Dump ("Dump filter loaded type=%d\n", filterExtension->DumpType); + return STATUS_SUCCESS; + +err: + Dump ("DumpFilterEntry error %x\n", status); + return status; +} + + +static NTSTATUS DumpFilterStart (PFILTER_EXTENSION filterExtension) +{ + Dump ("DumpFilterStart type=%d\n", filterExtension->DumpType); + + if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER) + TC_BUG_CHECK (STATUS_CRC_ERROR); + + return BootDriveFilterExtension->DriveMounted ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEGER diskWriteOffset, PMDL writeMdl) +{ + ULONG dataLength = MmGetMdlByteCount (writeMdl); + uint64 offset = DumpPartitionOffset.QuadPart + diskWriteOffset->QuadPart; + uint64 intersectStart; + uint32 intersectLength; + PVOID writeBuffer; + CSHORT origMdlFlags; + + if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER) + TC_BUG_CHECK (STATUS_CRC_ERROR); + + if (BootDriveFilterExtension->Queue.EncryptedAreaEndUpdatePending) // Hibernation should always abort the setup thread + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + if (BootDriveFilterExtension->Queue.EncryptedAreaStart == -1 || BootDriveFilterExtension->Queue.EncryptedAreaEnd == -1) + return STATUS_SUCCESS; + + if (dataLength > WriteFilterBufferSize) + TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW); // Bug check is required as returning an error does not prevent data from being written to disk + + if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0) + TC_BUG_CHECK (STATUS_INVALID_PARAMETER); + + writeBuffer = MmGetSystemAddressForMdlSafe (writeMdl, HighPagePriority); + if (!writeBuffer) + TC_BUG_CHECK (STATUS_INSUFFICIENT_RESOURCES); + + memcpy (WriteFilterBuffer, writeBuffer, dataLength); + + GetIntersection (offset, + dataLength, + BootDriveFilterExtension->Queue.EncryptedAreaStart, + BootDriveFilterExtension->Queue.EncryptedAreaEnd, + &intersectStart, + &intersectLength); + + if (intersectLength > 0) + { + UINT64_STRUCT dataUnit; + dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE; + + if (BootDriveFilterExtension->Queue.RemapEncryptedArea) + { + diskWriteOffset->QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset; + dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset; + } + + EncryptDataUnitsCurrentThread (WriteFilterBuffer + (intersectStart - offset), + &dataUnit, + intersectLength / ENCRYPTION_DATA_UNIT_SIZE, + BootDriveFilterExtension->Queue.CryptoInfo); + } + + origMdlFlags = writeMdl->MdlFlags; + + MmInitializeMdl (writeMdl, WriteFilterBuffer, dataLength); + MmBuildMdlForNonPagedPool (writeMdl); + + // Instead of using MmGetSystemAddressForMdlSafe(), some buggy custom storage drivers may directly test MDL_MAPPED_TO_SYSTEM_VA flag, + // disregarding the fact that other MDL flags may be set by the system or a dump filter (e.g. MDL_SOURCE_IS_NONPAGED_POOL flag only). + // Therefore, to work around this issue, the original flags will be restored even if they do not match the new MDL. + // MS BitLocker also uses this hack/workaround (it should be safe to use until the MDL structure is changed). + + writeMdl->MdlFlags = origMdlFlags; + + return STATUS_SUCCESS; +} + + +static NTSTATUS DumpFilterFinish (PFILTER_EXTENSION filterExtension) +{ + Dump ("DumpFilterFinish type=%d\n", filterExtension->DumpType); + + return STATUS_SUCCESS; +} + + +static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension) +{ + Dump ("DumpFilterUnload type=%d\n", filterExtension->DumpType); + + if (WriteFilterBuffer) + { + memset (WriteFilterBuffer, 0, WriteFilterBufferSize); + MmFreeContiguousMemory (WriteFilterBuffer); + WriteFilterBuffer = NULL; + } + + return STATUS_SUCCESS; +} |