"Fossies" - the Fresh Open Source Software Archive

Member "src/Driver/DumpFilter.c" (10 Oct 2018, 8450 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "DumpFilter.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.20_Source_vs_1.21_Source.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "DumpFilter.h"
   14 #include "DriveFilter.h"
   15 #include "Ntdriver.h"
   16 #include "Tests.h"
   17 #include "cpu.h"
   18 
   19 static DriveFilterExtension *BootDriveFilterExtension = NULL;
   20 static LARGE_INTEGER DumpPartitionOffset;
   21 static byte *WriteFilterBuffer = NULL;
   22 static SIZE_T WriteFilterBufferSize;
   23 
   24 
   25 NTSTATUS DumpFilterEntry (PFILTER_EXTENSION filterExtension, PFILTER_INITIALIZATION_DATA filterInitData)
   26 {
   27     GetSystemDriveDumpConfigRequest dumpConfig;
   28     PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
   29     STORAGE_DEVICE_NUMBER storageDeviceNumber;
   30     PARTITION_INFORMATION partitionInfo;
   31     LONG version;
   32     NTSTATUS status;
   33 
   34     Dump ("DumpFilterEntry type=%d\n", filterExtension->DumpType);
   35 
   36     filterInitData->MajorVersion = DUMP_FILTER_MAJOR_VERSION;
   37     filterInitData->MinorVersion = DUMP_FILTER_MINOR_VERSION;
   38     filterInitData->Flags |= DUMP_FILTER_CRITICAL;
   39 
   40     // Check driver version of the main device
   41     status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version));
   42     if (!NT_SUCCESS (status))
   43         goto err;
   44 
   45     if (version != VERSION_NUM)
   46     {
   47         status = STATUS_INVALID_PARAMETER;
   48         goto err;
   49     }
   50 
   51     // Get dump configuration from the main device
   52     status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG, NULL, 0, &dumpConfig, sizeof (dumpConfig));
   53     if (!NT_SUCCESS (status))
   54         goto err;
   55 
   56     BootDriveFilterExtension = dumpConfig.BootDriveFilterExtension;
   57 
   58     if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
   59     {
   60         status = STATUS_CRC_ERROR;
   61         goto err;
   62     }
   63 
   64     // KeSaveFloatingPointState() may generate a bug check during crash dump
   65 #if !defined (_WIN64)
   66     if (filterExtension->DumpType == DumpTypeCrashdump)
   67     {
   68         dumpConfig.HwEncryptionEnabled = FALSE;
   69         // disable also CPU extended features used in optimizations
   70         DisableCPUExtendedFeatures ();
   71     }
   72 #endif
   73 
   74     EnableHwEncryption (dumpConfig.HwEncryptionEnabled);
   75 
   76     if (!AutoTestAlgorithms())
   77     {
   78         status = STATUS_INVALID_PARAMETER;
   79         goto err;
   80     }
   81 
   82     // Check dump volume is located on the system drive
   83     status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
   84     if (!NT_SUCCESS (status))
   85         goto err;
   86 
   87     if (!BootDriveFilterExtension->SystemStorageDeviceNumberValid)
   88     {
   89         status = STATUS_INVALID_PARAMETER;
   90         goto err;
   91     }
   92 
   93     if (storageDeviceNumber.DeviceNumber != BootDriveFilterExtension->SystemStorageDeviceNumber)
   94     {
   95         status = STATUS_ACCESS_DENIED;
   96         goto err;
   97     }
   98 
   99     // Check dump volume is located within the scope of system encryption
  100     status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &partitionInfo, sizeof (partitionInfo));
  101     if (!NT_SUCCESS (status))
  102     {
  103         PARTITION_INFORMATION_EX partitionInfoEx;
  104         status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partitionInfoEx, sizeof (partitionInfoEx));
  105         if (!NT_SUCCESS (status))
  106         {
  107             goto err;
  108         }
  109 
  110         // we only need starting offset
  111         partitionInfo.StartingOffset = partitionInfoEx.StartingOffset;
  112     }
  113 
  114     DumpPartitionOffset = partitionInfo.StartingOffset;
  115 
  116     if (DumpPartitionOffset.QuadPart < BootDriveFilterExtension->ConfiguredEncryptedAreaStart
  117         || DumpPartitionOffset.QuadPart > BootDriveFilterExtension->ConfiguredEncryptedAreaEnd)
  118     {
  119         status = STATUS_ACCESS_DENIED;
  120         goto err;
  121     }
  122 
  123     // Allocate buffer for encryption
  124     if (filterInitData->MaxPagesPerWrite == 0)
  125     {
  126         status = STATUS_INVALID_PARAMETER;
  127         goto err;
  128     }
  129 
  130     WriteFilterBufferSize = filterInitData->MaxPagesPerWrite * PAGE_SIZE;
  131 
  132 #ifdef _WIN64
  133     highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFLL;
  134 #else
  135     highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFLL;
  136 #endif
  137 
  138     WriteFilterBuffer = MmAllocateContiguousMemory (WriteFilterBufferSize, highestAcceptableWriteBufferAddr);
  139     if (!WriteFilterBuffer)
  140     {
  141         status = STATUS_INSUFFICIENT_RESOURCES;
  142         goto err;
  143     }
  144 
  145     filterInitData->DumpStart = DumpFilterStart;
  146     filterInitData->DumpWrite = DumpFilterWrite;
  147     filterInitData->DumpFinish = DumpFilterFinish;
  148     filterInitData->DumpUnload = DumpFilterUnload;
  149 
  150     Dump ("Dump filter loaded type=%d\n", filterExtension->DumpType);
  151     return STATUS_SUCCESS;
  152 
  153 err:
  154     Dump ("DumpFilterEntry error %x\n", status);
  155     return status;
  156 }
  157 
  158 
  159 static NTSTATUS DumpFilterStart (PFILTER_EXTENSION filterExtension)
  160 {
  161     Dump ("DumpFilterStart type=%d\n", filterExtension->DumpType);
  162 
  163     if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
  164         TC_BUG_CHECK (STATUS_CRC_ERROR);
  165 
  166     return BootDriveFilterExtension->DriveMounted ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  167 }
  168 
  169 
  170 static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEGER diskWriteOffset, PMDL writeMdl)
  171 {
  172     ULONG dataLength = MmGetMdlByteCount (writeMdl);
  173     uint64 offset = DumpPartitionOffset.QuadPart + diskWriteOffset->QuadPart;
  174     uint64 intersectStart;
  175     uint32 intersectLength;
  176     PVOID writeBuffer;
  177     CSHORT origMdlFlags;
  178 
  179     if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
  180         TC_BUG_CHECK (STATUS_CRC_ERROR);
  181 
  182     if (BootDriveFilterExtension->Queue.EncryptedAreaEndUpdatePending)  // Hibernation should always abort the setup thread
  183         TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
  184 
  185     if (BootDriveFilterExtension->Queue.EncryptedAreaStart == -1 || BootDriveFilterExtension->Queue.EncryptedAreaEnd == -1)
  186         return STATUS_SUCCESS;
  187 
  188     if (dataLength > WriteFilterBufferSize)
  189         TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW);  // Bug check is required as returning an error does not prevent data from being written to disk
  190 
  191     if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
  192         TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
  193 
  194     if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
  195         TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
  196 
  197     writeBuffer = MmGetSystemAddressForMdlSafe (writeMdl, (HighPagePriority | ExDefaultMdlProtection));
  198     if (!writeBuffer)
  199         TC_BUG_CHECK (STATUS_INSUFFICIENT_RESOURCES);
  200 
  201     memcpy (WriteFilterBuffer, writeBuffer, dataLength);
  202 
  203     GetIntersection (offset,
  204         dataLength,
  205         BootDriveFilterExtension->Queue.EncryptedAreaStart,
  206         BootDriveFilterExtension->Queue.EncryptedAreaEnd,
  207         &intersectStart,
  208         &intersectLength);
  209 
  210     if (intersectLength > 0)
  211     {
  212         UINT64_STRUCT dataUnit;
  213         dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
  214 
  215         if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
  216         {
  217             diskWriteOffset->QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset;
  218             dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset;
  219         }
  220 
  221         EncryptDataUnitsCurrentThread (WriteFilterBuffer + (intersectStart - offset),
  222             &dataUnit,
  223             intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
  224             BootDriveFilterExtension->Queue.CryptoInfo);
  225     }
  226 
  227     origMdlFlags = writeMdl->MdlFlags;
  228 
  229     MmInitializeMdl (writeMdl, WriteFilterBuffer, dataLength);
  230     MmBuildMdlForNonPagedPool (writeMdl);
  231 
  232     // Instead of using MmGetSystemAddressForMdlSafe(), some buggy custom storage drivers may directly test MDL_MAPPED_TO_SYSTEM_VA flag,
  233     // 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).
  234     // Therefore, to work around this issue, the original flags will be restored even if they do not match the new MDL.
  235     // MS BitLocker also uses this hack/workaround (it should be safe to use until the MDL structure is changed).
  236 
  237     writeMdl->MdlFlags = origMdlFlags;
  238 
  239     return STATUS_SUCCESS;
  240 }
  241 
  242 
  243 static NTSTATUS DumpFilterFinish (PFILTER_EXTENSION filterExtension)
  244 {
  245     Dump ("DumpFilterFinish type=%d\n", filterExtension->DumpType);
  246 
  247     return STATUS_SUCCESS;
  248 }
  249 
  250 
  251 static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension)
  252 {
  253     Dump ("DumpFilterUnload type=%d\n", filterExtension->DumpType);
  254 
  255     if (WriteFilterBuffer)
  256     {
  257         memset (WriteFilterBuffer, 0, WriteFilterBufferSize);
  258         MmFreeContiguousMemory (WriteFilterBuffer);
  259         WriteFilterBuffer = NULL;
  260     }
  261 
  262     return STATUS_SUCCESS;
  263 }