"Fossies" - the Fresh Open Source Software Archive

Member "src/Driver/DriveFilter.c" (10 Oct 2018, 75765 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 "DriveFilter.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.21_Source_vs_1.22_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 "TCdefs.h"
   14 #include <ntddk.h>
   15 #include <ntddvol.h>
   16 #include <Ntstrsafe.h>
   17 #include "Cache.h"
   18 #include "Crc.h"
   19 #include "Crypto.h"
   20 #include "Apidrvr.h"
   21 #include "EncryptedIoQueue.h"
   22 #include "Common/Endian.h"
   23 #include "Ntdriver.h"
   24 #include "Ntvol.h"
   25 #include "Volumes.h"
   26 #include "VolumeFilter.h"
   27 #include "Wipe.h"
   28 #include "DriveFilter.h"
   29 #include "Boot/Windows/BootCommon.h"
   30 #include "cpu.h"
   31 
   32 static BOOL DeviceFilterActive = FALSE;
   33 
   34 BOOL BootArgsValid = FALSE;
   35 BootArguments BootArgs;
   36 byte*  BootSecRegionData = NULL;
   37 uint32 BootSecRegionSize = 0;
   38 uint32 BootPkcs5 = 0;
   39 
   40 static uint64 BootLoaderArgsPtr;
   41 static BOOL BootDriveSignatureValid = FALSE;
   42 
   43 static KMUTEX MountMutex;
   44 
   45 static volatile BOOL BootDriveFound = FALSE;
   46 static DriveFilterExtension *BootDriveFilterExtension = NULL;
   47 static LARGE_INTEGER BootDriveLength;
   48 static byte BootLoaderFingerprint[WHIRLPOOL_DIGESTSIZE + SHA512_DIGESTSIZE];
   49 
   50 static BOOL CrashDumpEnabled = FALSE;
   51 static BOOL HibernationEnabled = FALSE;
   52 
   53 static BOOL LegacyHibernationDriverFilterActive = FALSE;
   54 static byte *HibernationWriteBuffer = NULL;
   55 static MDL *HibernationWriteBufferMdl = NULL;
   56 
   57 static uint32 HibernationPreventionCount = 0;
   58 
   59 static BootEncryptionSetupRequest SetupRequest;
   60 static volatile BOOL SetupInProgress = FALSE;
   61 PKTHREAD EncryptionSetupThread = NULL;
   62 static volatile BOOL EncryptionSetupThreadAbortRequested;
   63 static KSPIN_LOCK SetupStatusSpinLock;
   64 static int64 SetupStatusEncryptedAreaEnd;
   65 static BOOL TransformWaitingForIdle;
   66 static NTSTATUS SetupResult;
   67 
   68 static WipeDecoySystemRequest WipeDecoyRequest;
   69 static volatile BOOL DecoySystemWipeInProgress = FALSE;
   70 static volatile BOOL DecoySystemWipeThreadAbortRequested;
   71 static KSPIN_LOCK DecoySystemWipeStatusSpinLock;
   72 static int64 DecoySystemWipedAreaEnd;
   73 PKTHREAD DecoySystemWipeThread = NULL;
   74 static NTSTATUS DecoySystemWipeResult;
   75 
   76 uint64 BootArgsRegions[] = { EFI_BOOTARGS_REGIONS };
   77 
   78 NTSTATUS LoadBootArguments ()
   79 {
   80     NTSTATUS status = STATUS_UNSUCCESSFUL;
   81     PHYSICAL_ADDRESS bootArgsAddr;
   82     byte *mappedBootArgs;
   83     byte *mappedCryptoInfo = NULL;
   84     uint16 bootLoaderArgsIndex;
   85 
   86     KeInitializeMutex (&MountMutex, 0);
   87 //  __debugbreak();
   88     for (bootLoaderArgsIndex = 0;
   89         bootLoaderArgsIndex < sizeof(BootArgsRegions)/ sizeof(BootArgsRegions[1]) && status != STATUS_SUCCESS;
   90         ++bootLoaderArgsIndex)
   91     {
   92         bootArgsAddr.QuadPart = BootArgsRegions[bootLoaderArgsIndex] + TC_BOOT_LOADER_ARGS_OFFSET;
   93         Dump ("Checking BootArguments at 0x%x\n", bootArgsAddr.LowPart);
   94 
   95         mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof (BootArguments), MmCached);
   96         if (!mappedBootArgs)
   97             return STATUS_INSUFFICIENT_RESOURCES;
   98 
   99         if (TC_IS_BOOT_ARGUMENTS_SIGNATURE (mappedBootArgs))
  100         {
  101             BootArguments *bootArguments = (BootArguments *) mappedBootArgs;
  102             Dump ("BootArguments found at 0x%x\n", bootArgsAddr.LowPart);
  103 
  104             DumpMem (mappedBootArgs, sizeof (BootArguments));
  105 
  106             if (bootArguments->BootLoaderVersion == VERSION_NUM
  107                 && bootArguments->BootArgumentsCrc32 != GetCrc32 ((byte *) bootArguments, (int) ((byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments)))
  108             {
  109                 Dump ("BootArguments CRC incorrect\n");
  110                 burn (mappedBootArgs, sizeof (BootArguments));
  111                 MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments));
  112                 mappedBootArgs = NULL;
  113                 TC_BUG_CHECK (STATUS_CRC_ERROR);
  114             }
  115 
  116             // Sanity check: for valid boot argument, the password is less than 64 bytes long
  117             if (bootArguments->BootPassword.Length <= MAX_PASSWORD)
  118             {
  119                 BootLoaderArgsPtr = BootArgsRegions[bootLoaderArgsIndex];
  120 
  121                 BootArgs = *bootArguments;
  122                 BootArgsValid = TRUE;
  123                 burn (bootArguments, sizeof (*bootArguments));
  124 
  125                 BootDriveSignatureValid = TRUE;
  126 
  127                 Dump ("BootLoaderVersion = %x\n", (int) BootArgs.BootLoaderVersion);
  128                 Dump ("HeaderSaltCrc32 = %x\n", (int) BootArgs.HeaderSaltCrc32);
  129                 Dump ("CryptoInfoOffset = %x\n", (int) BootArgs.CryptoInfoOffset);
  130                 Dump ("CryptoInfoLength = %d\n", (int) BootArgs.CryptoInfoLength);
  131                 Dump ("HiddenSystemPartitionStart = %I64u\n", BootArgs.HiddenSystemPartitionStart);
  132                 Dump ("DecoySystemPartitionStart = %I64u\n", BootArgs.DecoySystemPartitionStart);
  133                 Dump ("Flags = %x\n", BootArgs.Flags);
  134                 Dump ("BootDriveSignature = %x\n", BootArgs.BootDriveSignature);
  135                 Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32);
  136 
  137                 // clear fingerprint
  138                 burn (BootLoaderFingerprint, sizeof (BootLoaderFingerprint));
  139                 MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments));
  140                 mappedBootArgs = NULL;
  141 
  142                 // Extra parameters? (pkcs5, hash)
  143                 if (BootArgs.CryptoInfoLength > 0)
  144                 {
  145                     PHYSICAL_ADDRESS cryptoInfoAddress;
  146                     cryptoInfoAddress.QuadPart = BootLoaderArgsPtr + BootArgs.CryptoInfoOffset;
  147                     Dump ("CryptoInfo memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength);
  148 
  149                     mappedCryptoInfo = MmMapIoSpace (cryptoInfoAddress, BootArgs.CryptoInfoLength, MmCached);
  150                     if (mappedCryptoInfo)
  151                     {
  152                         /* Get the parameters used for booting to speed up driver startup and avoid testing irrelevant PRFs */
  153                         BOOT_CRYPTO_HEADER* pBootCryptoInfo = (BOOT_CRYPTO_HEADER*) mappedCryptoInfo;
  154                         BootPkcs5 = pBootCryptoInfo->pkcs5; // save hash to speed up boot.
  155 
  156                         BootSecRegionData = NULL;
  157                         BootSecRegionSize = 0;
  158 
  159                         // SecRegion data?
  160                         if(BootArgs.CryptoInfoLength > (sizeof(BOOT_CRYPTO_HEADER) + sizeof(SECREGION_BOOT_PARAMS)) ) {
  161                             uint32   crc;
  162                             PHYSICAL_ADDRESS SecRegionAddress;
  163                             SECREGION_BOOT_PARAMS* SecRegionParams = (SECREGION_BOOT_PARAMS*) (mappedCryptoInfo + sizeof(BOOT_CRYPTO_HEADER) + 2);
  164                             byte *secRegionData = NULL;
  165 
  166                             SecRegionAddress.QuadPart = SecRegionParams->Ptr;
  167                             Dump ("SecRegion memory 0x%x %d\n", SecRegionAddress.LowPart, SecRegionParams->Size);
  168                             // SecRegion correct?
  169                             if( (SecRegionParams->Ptr != 0) && (SecRegionParams->Size > 0)) {
  170                                 crc = GetCrc32((byte*)SecRegionParams, 12);
  171                                 if(crc == SecRegionParams->Crc) {
  172                                     Dump ("SecRegion crc ok\n");
  173                                     secRegionData = MmMapIoSpace (SecRegionAddress, SecRegionParams->Size, MmCached);
  174                                     if(secRegionData) {
  175                                         BootSecRegionData = TCalloc (SecRegionParams->Size);
  176                                         if(BootSecRegionData != NULL) {
  177                                             BootSecRegionSize = SecRegionParams->Size;
  178                                             memcpy(BootSecRegionData, secRegionData, SecRegionParams->Size);
  179                                         }
  180                                         burn (secRegionData, SecRegionParams->Size);
  181                                         MmUnmapIoSpace (secRegionData,  SecRegionParams->Size);
  182                                     }
  183                                 }
  184                             }
  185                         }
  186                         // Erase boot loader scheduled keys
  187                         burn (mappedCryptoInfo, BootArgs.CryptoInfoLength);
  188                         MmUnmapIoSpace (mappedCryptoInfo, BootArgs.CryptoInfoLength);
  189                         BootArgs.CryptoInfoLength = 0;
  190                     }
  191                     else
  192                     {
  193                         BootArgs.CryptoInfoLength = 0;
  194                     }
  195                 }
  196                 status = STATUS_SUCCESS;
  197             }
  198             else
  199             {
  200                 Dump ("BootArguments contains a password larger than maximum limit\n");
  201                 burn (mappedBootArgs, sizeof (BootArguments));
  202                 MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments));
  203                 mappedBootArgs = NULL;
  204                 TC_BUG_CHECK (STATUS_FAIL_CHECK);
  205             }
  206         }
  207         
  208         if (mappedBootArgs) {
  209             MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments));
  210         }
  211     }
  212     return status;
  213 }
  214 
  215 
  216 NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
  217 {
  218     DriveFilterExtension *Extension;
  219     NTSTATUS status;
  220     PDEVICE_OBJECT filterDeviceObject = NULL;
  221     PDEVICE_OBJECT attachedDeviceObject;
  222 
  223     Dump ("DriveFilterAddDevice pdo=%p\n", pdo);
  224 
  225     attachedDeviceObject = IoGetAttachedDeviceReference (pdo);
  226     status = IoCreateDevice (driverObject, sizeof (DriveFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject);
  227 
  228     ObDereferenceObject (attachedDeviceObject);
  229 
  230     if (!NT_SUCCESS (status))
  231     {
  232         filterDeviceObject = NULL;
  233         goto err;
  234     }
  235 
  236     Extension = (DriveFilterExtension *) filterDeviceObject->DeviceExtension;
  237     memset (Extension, 0, sizeof (DriveFilterExtension));
  238 
  239     status = IoAttachDeviceToDeviceStackSafe (filterDeviceObject, pdo, &(Extension->LowerDeviceObject)); 
  240     if (!NT_SUCCESS (status))
  241     {
  242         goto err;
  243     }
  244 
  245     if (!Extension->LowerDeviceObject)
  246     {
  247         status = STATUS_DEVICE_REMOVED;
  248         goto err;
  249     }
  250 
  251     Extension->IsDriveFilterDevice = Extension->Queue.IsFilterDevice = TRUE;
  252     Extension->DeviceObject = Extension->Queue.DeviceObject = filterDeviceObject;
  253     Extension->Pdo = pdo;
  254     
  255     Extension->Queue.LowerDeviceObject = Extension->LowerDeviceObject;
  256     IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCV', 0, 0);
  257 
  258     Extension->ConfiguredEncryptedAreaStart = -1;
  259     Extension->ConfiguredEncryptedAreaEnd = -1;
  260     Extension->Queue.EncryptedAreaStart = -1;
  261     Extension->Queue.EncryptedAreaEnd = -1;
  262     Extension->Queue.EncryptedAreaEndUpdatePending = FALSE;
  263 
  264     filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
  265     filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  266 
  267     DeviceFilterActive = TRUE;
  268     return status;
  269 
  270 err:
  271     if (filterDeviceObject)
  272     {
  273         if (Extension->LowerDeviceObject)
  274             IoDetachDevice (Extension->LowerDeviceObject);
  275 
  276         IoDeleteDevice (filterDeviceObject);
  277     }
  278 
  279     return status;
  280 }
  281 
  282 
  283 static void DismountDrive (DriveFilterExtension *Extension, BOOL stopIoQueue)
  284 {
  285     Dump ("Dismounting drive\n");
  286     ASSERT (Extension->DriveMounted);
  287     
  288     if (stopIoQueue && EncryptedIoQueueIsRunning (&Extension->Queue))
  289         EncryptedIoQueueStop (&Extension->Queue);
  290 
  291     crypto_close (Extension->Queue.CryptoInfo);
  292     Extension->Queue.CryptoInfo = NULL;
  293 
  294     crypto_close (Extension->HeaderCryptoInfo);
  295     Extension->HeaderCryptoInfo = NULL;
  296 
  297     Extension->DriveMounted = FALSE;
  298 }
  299 
  300 static void ComputeBootLoaderFingerprint(PDEVICE_OBJECT LowerDeviceObject, byte* ioBuffer /* ioBuffer must be at least 512 bytes long */)
  301 {
  302     NTSTATUS status;
  303     LARGE_INTEGER offset;
  304     WHIRLPOOL_CTX whirlpool;
  305     sha512_ctx sha2;
  306     ULONG bytesToRead, remainingBytes, bootloaderTotalSize = TC_BOOT_LOADER_AREA_SIZE - TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE;
  307 
  308     // clear fingerprint
  309     burn (BootLoaderFingerprint, sizeof (BootLoaderFingerprint));
  310 
  311     // compute Whirlpool+SHA512 fingerprint of bootloader including MBR
  312     // we skip user configuration fields:
  313     // TC_BOOT_SECTOR_PIM_VALUE_OFFSET = 400
  314     // TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_OFFSET = 402
  315     //  => TC_BOOT_SECTOR_OUTER_VOLUME_BAK_HEADER_CRC_SIZE = 4
  316     // TC_BOOT_SECTOR_USER_MESSAGE_OFFSET     = 406
  317     //  => TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH = 24
  318     // TC_BOOT_SECTOR_USER_CONFIG_OFFSET      = 438
  319     //
  320     // 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
  321     
  322     WHIRLPOOL_init (&whirlpool);
  323     sha512_begin (&sha2);
  324     // read the first 512 bytes
  325     offset.QuadPart = 0;
  326 
  327     status = TCReadDevice (LowerDeviceObject, ioBuffer, offset, TC_SECTOR_SIZE_BIOS);
  328     if (NT_SUCCESS (status))
  329     {
  330         NTSTATUS saveStatus = STATUS_INVALID_PARAMETER;
  331 #ifdef _WIN64
  332         XSTATE_SAVE SaveState;
  333         if (g_isIntel && HasSAVX())
  334             saveStatus = KeSaveExtendedProcessorState(XSTATE_MASK_GSSE, &SaveState);
  335 #else
  336         KFLOATING_SAVE floatingPointState;      
  337         if (HasISSE() || (HasSSSE3() && HasMMX()))
  338             saveStatus = KeSaveFloatingPointState (&floatingPointState);
  339 #endif
  340         WHIRLPOOL_add (ioBuffer, TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &whirlpool);
  341         WHIRLPOOL_add (ioBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)), &whirlpool);
  342 
  343         sha512_hash (ioBuffer, TC_BOOT_SECTOR_PIM_VALUE_OFFSET, &sha2);
  344         sha512_hash (ioBuffer + TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH, (TC_BOOT_SECTOR_USER_CONFIG_OFFSET - (TC_BOOT_SECTOR_USER_MESSAGE_OFFSET + TC_BOOT_SECTOR_USER_MESSAGE_MAX_LENGTH)), &sha2);
  345 
  346         // we has the reste of the bootloader, 512 bytes at a time
  347         offset.QuadPart = TC_SECTOR_SIZE_BIOS;
  348         remainingBytes = bootloaderTotalSize - TC_SECTOR_SIZE_BIOS;
  349 
  350         while (NT_SUCCESS (status) && (remainingBytes > 0))
  351         {
  352             bytesToRead = (remainingBytes >= TC_SECTOR_SIZE_BIOS)? TC_SECTOR_SIZE_BIOS : remainingBytes;
  353             status = TCReadDevice (LowerDeviceObject, ioBuffer, offset, bytesToRead);
  354             if (NT_SUCCESS (status))
  355             {
  356                 remainingBytes -= bytesToRead;
  357                 offset.QuadPart += bytesToRead;
  358                 WHIRLPOOL_add (ioBuffer, bytesToRead, &whirlpool);
  359                 sha512_hash (ioBuffer, bytesToRead, &sha2);
  360             }
  361             else
  362             {
  363                 Dump ("TCReadDevice error %x during ComputeBootLoaderFingerprint call\n", status);
  364                 break;
  365             }
  366         }
  367 
  368         if (NT_SUCCESS (status))
  369         {
  370             WHIRLPOOL_finalize (&whirlpool, BootLoaderFingerprint);
  371             sha512_end (&BootLoaderFingerprint [WHIRLPOOL_DIGESTSIZE], &sha2);
  372         }
  373 
  374         if (NT_SUCCESS (saveStatus))
  375 #ifdef _WIN64
  376             KeRestoreExtendedProcessorState(&SaveState);
  377 #else
  378             KeRestoreFloatingPointState (&floatingPointState);
  379 #endif
  380     }
  381     else
  382     {
  383         Dump ("TCReadDevice error %x during ComputeBootLoaderFingerprint call\n", status);
  384     }
  385 }
  386 
  387 
  388 static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, uint32 *headerSaltCrc32)
  389 {
  390     BOOL hiddenVolume = (BootArgs.HiddenSystemPartitionStart != 0);
  391     int64 hiddenHeaderOffset = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
  392     NTSTATUS status;
  393     LARGE_INTEGER offset;
  394     char *header;
  395     int pkcs5_prf = 0, pim = 0;
  396     PARTITION_INFORMATION_EX pi;
  397     BOOL bIsGPT = FALSE;
  398 
  399     Dump ("MountDrive pdo=%p\n", Extension->Pdo);
  400     ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
  401 
  402     // Check disk MBR id and GPT ID if BootSecRegion is available to detect boot drive
  403     if (BootSecRegionData != NULL && BootSecRegionSize >= 1024) {
  404         byte mbr[TC_SECTOR_SIZE_BIOS];
  405         DCS_DISK_ENTRY_LIST* DeList = (DCS_DISK_ENTRY_LIST*)(BootSecRegionData + 512);
  406         offset.QuadPart = 0;
  407         status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS);
  408 
  409         if (NT_SUCCESS (status) && DeList->DE[DE_IDX_DISKID].DiskId.MbrID != *(uint32 *) (mbr + 0x1b8))
  410             return STATUS_UNSUCCESSFUL;
  411 
  412         offset.QuadPart = 512;
  413         status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS);
  414         if (NT_SUCCESS (status) && memcmp(&DeList->DE[DE_IDX_DISKID].DiskId.GptID, mbr + 0x38, sizeof(DCS_GUID)) != 0)
  415             return STATUS_UNSUCCESSFUL;
  416 
  417         header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  418         if (!header)
  419             return STATUS_INSUFFICIENT_RESOURCES;
  420         // Copy header from SecRegion instead of read from disk
  421         memcpy(header, BootSecRegionData, 512);
  422 
  423         // Set SecRegion data for the disk (sectors to substitute to hide GPT table)
  424         Extension->Queue.SecRegionData = BootSecRegionData;
  425         Extension->Queue.SecRegionSize = BootSecRegionSize;
  426     } else {
  427         // Check boot drive signature first (header CRC search could fail if a user restored the header to a non-boot drive)
  428         if (BootDriveSignatureValid)
  429         {
  430             byte mbr[TC_SECTOR_SIZE_BIOS];
  431 
  432             offset.QuadPart = 0;
  433             status = TCReadDevice (Extension->LowerDeviceObject, mbr, offset, TC_SECTOR_SIZE_BIOS);
  434 
  435             if (NT_SUCCESS (status) && BootArgs.BootDriveSignature != *(uint32 *) (mbr + 0x1b8))
  436                 return STATUS_UNSUCCESSFUL;
  437         }
  438 
  439         header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  440         if (!header)
  441             return STATUS_INSUFFICIENT_RESOURCES;
  442 
  443         offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
  444         Dump ("Reading volume header at %I64u\n", offset.QuadPart);
  445 
  446         status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  447         if (!NT_SUCCESS (status))
  448         {
  449             Dump ("TCReadDevice error %x\n", status);
  450             goto ret;
  451         }
  452         Extension->Queue.SecRegionData = NULL;
  453         Extension->Queue.SecRegionSize = 0;
  454     }
  455 
  456     if (headerSaltCrc32)
  457     {
  458         uint32 saltCrc = GetCrc32 (header, PKCS5_SALT_SIZE);
  459 
  460         if (saltCrc != *headerSaltCrc32)
  461         {
  462             status = STATUS_UNSUCCESSFUL;
  463             goto ret;
  464         }
  465 
  466         Extension->VolumeHeaderSaltCrc32 = saltCrc;
  467     }
  468 
  469     Extension->HeaderCryptoInfo = crypto_open();
  470     if (!Extension->HeaderCryptoInfo)
  471     {
  472         status = STATUS_INSUFFICIENT_RESOURCES;
  473         goto ret;
  474     }
  475 
  476     if (NT_SUCCESS(SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &pi, sizeof (pi))))
  477     {
  478         bIsGPT = (pi.PartitionStyle == PARTITION_STYLE_GPT)? TRUE : FALSE;
  479     }
  480 
  481     if (BootPkcs5 > 0)
  482     {
  483         /* Get the parameters used for booting to speed up driver startup and avoid testing irrelevant PRFs */
  484         Hash* pHash = HashGet(BootPkcs5);
  485         if (pHash && (bIsGPT || pHash->SystemEncryption))
  486             pkcs5_prf = BootPkcs5;
  487     }
  488 
  489     pim = (int) (BootArgs.Flags >> 16);
  490 
  491     if (ReadVolumeHeader (!hiddenVolume, header, password, pkcs5_prf, pim, FALSE, &Extension->Queue.CryptoInfo, Extension->HeaderCryptoInfo) == 0)
  492     {
  493         // Header decrypted
  494         status = STATUS_SUCCESS;
  495         Dump ("Header decrypted\n");
  496 
  497         // calculate Fingerprint
  498         ComputeBootLoaderFingerprint (Extension->LowerDeviceObject, header);
  499             
  500         if (Extension->Queue.CryptoInfo->hiddenVolume)
  501         {
  502             int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart;
  503             Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset);
  504             
  505             Extension->HiddenSystem = TRUE;
  506 
  507             Extension->Queue.RemapEncryptedArea = TRUE;
  508             Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart;
  509             Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE;
  510             
  511             Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart;
  512             
  513             if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart)
  514             {
  515                 // we have already erased boot loader scheduled keys
  516                 TC_THROW_FATAL_EXCEPTION;
  517             }
  518 
  519             Dump ("RemappedAreaOffset = %I64d\n", Extension->Queue.RemappedAreaOffset);
  520             Dump ("RemappedAreaDataUnitOffset = %I64d\n", Extension->Queue.RemappedAreaDataUnitOffset);
  521         }
  522         else
  523         {
  524             Extension->HiddenSystem = FALSE;
  525             Extension->Queue.RemapEncryptedArea = FALSE;
  526         }
  527 
  528         Extension->ConfiguredEncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value;
  529         Extension->ConfiguredEncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->VolumeSize.Value - 1;
  530 
  531         Extension->Queue.EncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value;
  532         Extension->Queue.EncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->EncryptedAreaLength.Value - 1;
  533 
  534         if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0)
  535         {
  536             Extension->Queue.EncryptedAreaStart = -1;
  537             Extension->Queue.EncryptedAreaEnd = -1;
  538         }
  539 
  540         Dump ("Loaded: ConfiguredEncryptedAreaStart=%I64d (%I64d)  ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd);
  541         Dump ("Loaded: EncryptedAreaStart=%I64d (%I64d)  EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd);
  542 
  543         // at this stage, we have already erased boot loader scheduled keys
  544 
  545         BootDriveFilterExtension = Extension;
  546         BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE;
  547         BootDriveFilterExtension->MagicNumber = TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER;
  548 
  549         // Try to load password cached if saved in SecRegion
  550         if (BootSecRegionData != NULL && BootSecRegionSize > 1024) {
  551             DCS_DISK_ENTRY_LIST* DeList = (DCS_DISK_ENTRY_LIST*)(BootSecRegionData + 512);
  552             uint32 crc;
  553             uint32 crcSaved;
  554             crcSaved = DeList->CRC32;
  555             DeList->CRC32 = 0;
  556             crc = GetCrc32((byte*)DeList, 512);
  557             if(crc == crcSaved){
  558                 if(DeList->DE[DE_IDX_PWDCACHE].Type == DE_PwdCache) {
  559                     uint64 sector = 0;
  560                     DCS_DEP_PWD_CACHE* pwdCache = (DCS_DEP_PWD_CACHE*)(BootSecRegionData + DeList->DE[DE_IDX_PWDCACHE].Sectors.Offset);
  561                     DecryptDataUnits((unsigned char*)pwdCache, (UINT64_STRUCT*)&sector, 1, Extension->Queue.CryptoInfo);
  562                     crcSaved = pwdCache->CRC;
  563                     pwdCache->CRC = 0;
  564                     crc = GetCrc32((unsigned char*)pwdCache, 512);
  565                     if(crcSaved == crc && pwdCache->Count < CACHE_SIZE){
  566                         uint32 i;
  567                         for(i = 0; i<pwdCache->Count; ++i){
  568                             if (CacheBootPassword && pwdCache->Pwd[i].Length > 0)   {
  569                                 int cachedPim = CacheBootPim? (int) (pwdCache->Pim[i]) : 0;
  570                                 AddPasswordToCache (&pwdCache->Pwd[i], cachedPim);
  571                             }
  572                         }
  573                         burn(pwdCache, sizeof(*pwdCache));
  574                     }
  575                 }
  576             }
  577         }
  578 
  579         if (CacheBootPassword && BootArgs.BootPassword.Length > 0)
  580         {
  581             int cachedPim = CacheBootPim? pim : 0;
  582             AddPasswordToCache (&BootArgs.BootPassword, cachedPim);
  583         }
  584 
  585         burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword));
  586 
  587         {
  588             STORAGE_DEVICE_NUMBER storageDeviceNumber;
  589             status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
  590 
  591             if (!NT_SUCCESS (status))
  592             {
  593                 Dump ("Failed to get drive number - error %x\n", status);
  594                 Extension->SystemStorageDeviceNumberValid = FALSE;
  595             }
  596             else
  597             {
  598                 Extension->SystemStorageDeviceNumber = storageDeviceNumber.DeviceNumber;
  599                 Extension->SystemStorageDeviceNumberValid = TRUE;
  600             }
  601         }
  602 
  603         status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &BootDriveLength, sizeof (BootDriveLength));
  604         
  605         if (!NT_SUCCESS (status))
  606         {
  607             Dump ("Failed to get drive length - error %x\n", status);
  608             BootDriveLength.QuadPart = 0;
  609             Extension->Queue.MaxReadAheadOffset.QuadPart = 0;
  610         }
  611         else
  612             Extension->Queue.MaxReadAheadOffset = BootDriveLength;
  613         
  614         status = EncryptedIoQueueStart (&Extension->Queue);
  615         if (!NT_SUCCESS (status))
  616             TC_BUG_CHECK (status);
  617 
  618         if (IsOSAtLeast (WIN_VISTA))
  619         {
  620             CrashDumpEnabled = TRUE;
  621             HibernationEnabled = TRUE;
  622         }
  623         else if (!LegacyHibernationDriverFilterActive)
  624             StartLegacyHibernationDriverFilter();
  625 
  626         // Hidden system hibernation is not supported if an extra boot partition is present as the system is not allowed to update the boot partition
  627         if (IsHiddenSystemRunning() && (BootArgs.Flags & TC_BOOT_ARGS_FLAG_EXTRA_BOOT_PARTITION))
  628         {
  629             CrashDumpEnabled = FALSE;
  630             HibernationEnabled = FALSE;
  631         }
  632     }
  633     else
  634     {
  635         Dump ("Header not decrypted\n");
  636         crypto_close (Extension->HeaderCryptoInfo);
  637         Extension->HeaderCryptoInfo = NULL;
  638 
  639         status = STATUS_UNSUCCESSFUL;
  640     }
  641 
  642 ret:
  643     TCfree (header);
  644     return status;
  645 }
  646 
  647 
  648 static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension)
  649 {
  650     NTSTATUS status = STATUS_SUCCESS;
  651     LARGE_INTEGER offset;
  652     byte *header;
  653 
  654     header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  655     if (!header)
  656         return STATUS_INSUFFICIENT_RESOURCES;
  657 
  658     offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
  659 
  660     status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  661     if (!NT_SUCCESS (status))
  662     {
  663         Dump ("TCReadDevice error %x", status);
  664         goto ret;
  665     }
  666 
  667     Dump ("Saving: ConfiguredEncryptedAreaStart=%I64d (%I64d)  ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd);
  668     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);
  669     
  670     if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1
  671         || Extension->Queue.EncryptedAreaEnd <= Extension->Queue.EncryptedAreaStart)
  672     {
  673         if (SetupRequest.SetupMode == SetupDecryption)
  674         {
  675             memset (header, 0, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  676             Extension->VolumeHeaderPresent = FALSE;
  677         }
  678     }
  679     else
  680     {
  681         uint32 headerCrc32;
  682         uint64 encryptedAreaLength = Extension->Queue.EncryptedAreaEnd + 1 - Extension->Queue.EncryptedAreaStart;
  683         byte *fieldPos = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
  684 
  685         DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo);
  686 
  687         if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x56455241)
  688         {
  689             Dump ("Header not decrypted");
  690             status = STATUS_UNKNOWN_REVISION;
  691             goto ret;
  692         }
  693 
  694         mputInt64 (fieldPos, encryptedAreaLength);
  695 
  696         headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
  697         fieldPos = header + TC_HEADER_OFFSET_HEADER_CRC;
  698         mputLong (fieldPos, headerCrc32);
  699 
  700         EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo);
  701     }
  702 
  703     status = TCWriteDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
  704     if (!NT_SUCCESS (status))
  705     {
  706         Dump ("TCWriteDevice error %x", status);
  707         goto ret;
  708     }
  709 
  710 ret:
  711     TCfree (header);
  712     return status;
  713 }
  714 
  715 
  716 static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp)
  717 {
  718     IoSkipCurrentIrpStackLocation (irp);
  719     return IoCallDriver (deviceObject, irp);
  720 }
  721 
  722 
  723 static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg)
  724 {
  725     IoCopyCurrentIrpStackLocationToNext (irp);
  726 
  727     if (completionRoutine)
  728         IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE);
  729 
  730     return IoCallDriver (deviceObject, irp);
  731 }
  732 
  733 
  734 static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension)
  735 {
  736     if (Irp->PendingReturned)
  737         IoMarkIrpPending (Irp);
  738 
  739     if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
  740         filterDeviceObject->Flags &= ~DO_POWER_PAGABLE;
  741 
  742     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  743     return STATUS_CONTINUE_COMPLETION;
  744 }
  745 
  746 
  747 static BOOL IsVolumeDevice (PDEVICE_OBJECT deviceObject)
  748 {
  749     VOLUME_NUMBER volNumber;
  750     VOLUME_DISK_EXTENTS extents[2];
  751     NTSTATUS extentStatus = SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, extents, sizeof (extents));
  752 
  753     return NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_SUPPORTS_ONLINE_OFFLINE, NULL, 0,  NULL, 0))
  754         || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_OFFLINE, NULL, 0,  NULL, 0))
  755         || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_IO_CAPABLE, NULL, 0,  NULL, 0))
  756         || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_IS_PARTITION, NULL, 0,  NULL, 0))
  757         || NT_SUCCESS (SendDeviceIoControlRequest (deviceObject, IOCTL_VOLUME_QUERY_VOLUME_NUMBER, NULL, 0, &volNumber, sizeof (volNumber)))
  758         || NT_SUCCESS (extentStatus) || extentStatus == STATUS_BUFFER_OVERFLOW || extentStatus == STATUS_BUFFER_TOO_SMALL;
  759 }
  760 
  761 
  762 static void CheckDeviceTypeAndMount (DriveFilterExtension *filterExtension)
  763 {
  764     if (BootArgsValid)
  765     {
  766         // Windows sometimes merges a removable drive PDO and its volume PDO to a single PDO having no volume interface (GUID_DEVINTERFACE_VOLUME).
  767         // Therefore, we need to test whether the device supports volume IOCTLs.
  768         if (VolumeClassFilterRegistered
  769             && BootArgs.HiddenSystemPartitionStart != 0
  770             && IsVolumeDevice (filterExtension->LowerDeviceObject))
  771         {
  772             Dump ("Drive and volume merged pdo=%p", filterExtension->Pdo);
  773 
  774             filterExtension->IsVolumeFilterDevice = TRUE;
  775             filterExtension->IsDriveFilterDevice = FALSE;
  776         }
  777         else
  778         {
  779             NTSTATUS status = KeWaitForMutexObject (&MountMutex, Executive, KernelMode, FALSE, NULL);
  780             if (!NT_SUCCESS (status))
  781                 TC_BUG_CHECK (status);
  782 
  783             if (!BootDriveFound)
  784                 MountDrive (filterExtension, &BootArgs.BootPassword, &BootArgs.HeaderSaltCrc32);
  785 
  786             KeReleaseMutex (&MountMutex, FALSE);
  787         }
  788     }
  789 }
  790 
  791 
  792 static VOID MountDriveWorkItemRoutine (PDEVICE_OBJECT deviceObject, DriveFilterExtension *filterExtension)
  793 {
  794     CheckDeviceTypeAndMount (filterExtension);
  795     KeSetEvent (&filterExtension->MountWorkItemCompletedEvent, IO_NO_INCREMENT, FALSE);
  796 }
  797 
  798 
  799 static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, DriveFilterExtension *Extension)
  800 {
  801     if (Irp->PendingReturned)
  802         IoMarkIrpPending (Irp);
  803 
  804     if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
  805         filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
  806 
  807     if (KeGetCurrentIrql() == PASSIVE_LEVEL)
  808     {
  809         CheckDeviceTypeAndMount (Extension);
  810     }
  811     else
  812     {
  813         PIO_WORKITEM workItem = IoAllocateWorkItem (filterDeviceObject);
  814         if (!workItem)
  815         {
  816             IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  817             return STATUS_INSUFFICIENT_RESOURCES;
  818         }
  819 
  820         KeInitializeEvent (&Extension->MountWorkItemCompletedEvent, SynchronizationEvent, FALSE);
  821         IoQueueWorkItem (workItem, MountDriveWorkItemRoutine, DelayedWorkQueue, Extension); 
  822 
  823         KeWaitForSingleObject (&Extension->MountWorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL);
  824         IoFreeWorkItem (workItem);
  825     }
  826 
  827     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  828     return STATUS_CONTINUE_COMPLETION;
  829 }
  830 
  831 
  832 static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  833 {
  834     NTSTATUS status;
  835 
  836     status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  837     if (!NT_SUCCESS (status))
  838         return TCCompleteIrp (Irp, status, 0);
  839 
  840     switch (irpSp->MinorFunction)
  841     {
  842     case IRP_MN_START_DEVICE:
  843         Dump ("IRP_MN_START_DEVICE pdo=%p\n", Extension->Pdo);
  844         return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension);
  845 
  846 
  847     case IRP_MN_DEVICE_USAGE_NOTIFICATION:
  848         Dump ("IRP_MN_DEVICE_USAGE_NOTIFICATION type=%d\n", (int) irpSp->Parameters.UsageNotification.Type);
  849 
  850         {
  851             PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject);
  852 
  853             if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE))
  854                 DeviceObject->Flags |= DO_POWER_PAGABLE;
  855 
  856             ObDereferenceObject (attachedDevice);
  857         }
  858 
  859         // Prevent creation of hibernation and crash dump files if required
  860         if (irpSp->Parameters.UsageNotification.InPath
  861             && (
  862                 (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeDumpFile && !CrashDumpEnabled)
  863                 || (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation && !HibernationEnabled)
  864                 )
  865             )
  866         {
  867             IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  868 
  869             if (irpSp->Parameters.UsageNotification.Type == DeviceUsageTypeHibernation)
  870                 ++HibernationPreventionCount;
  871 
  872             Dump ("Preventing dump type=%d\n", (int) irpSp->Parameters.UsageNotification.Type);
  873             return TCCompleteIrp (Irp, STATUS_UNSUCCESSFUL, 0);
  874         }
  875 
  876         return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension);
  877 
  878 
  879     case IRP_MN_REMOVE_DEVICE:
  880         Dump ("IRP_MN_REMOVE_DEVICE pdo=%p\n", Extension->Pdo);
  881 
  882         IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp);
  883         status = PassIrp (Extension->LowerDeviceObject, Irp);
  884 
  885         IoDetachDevice (Extension->LowerDeviceObject);
  886 
  887         if (Extension->DriveMounted)
  888             DismountDrive (Extension, TRUE);
  889 
  890         if (Extension->BootDrive)
  891         {
  892             BootDriveFound = FALSE;
  893             BootDriveFilterExtension = NULL;
  894         }
  895 
  896         IoDeleteDevice (DeviceObject);
  897         return status;
  898 
  899 
  900     default:
  901         status = PassIrp (Extension->LowerDeviceObject, Irp);
  902         IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  903     }
  904     return status;
  905 }
  906 
  907 
  908 static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  909 {
  910     NTSTATUS status;
  911     Dump ("IRP_MJ_POWER minor=%d type=%d shutdown=%d\n", (int) irpSp->MinorFunction, (int) irpSp->Parameters.Power.Type, (int) irpSp->Parameters.Power.ShutdownType);
  912 
  913     if (SetupInProgress
  914         && irpSp->MinorFunction == IRP_MN_SET_POWER
  915         && irpSp->Parameters.Power.ShutdownType == PowerActionHibernate)
  916     {
  917         while (SendDeviceIoControlRequest (RootDeviceObject, TC_IOCTL_ABORT_BOOT_ENCRYPTION_SETUP, NULL, 0, NULL, 0) == STATUS_INSUFFICIENT_RESOURCES);
  918     }
  919 
  920 #if 0   // Dismount of the system drive is disabled until there is a way to do it without causing system errors (see the documentation for more info)
  921     if (DriverShuttingDown
  922         && Extension->BootDrive
  923         && Extension->DriveMounted
  924         && irpSp->MinorFunction == IRP_MN_SET_POWER
  925         && irpSp->Parameters.Power.Type == DevicePowerState)
  926     {
  927         DismountDrive (Extension, TRUE);
  928     }
  929 #endif // 0
  930 
  931     PoStartNextPowerIrp (Irp);
  932 
  933     status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  934     if (!NT_SUCCESS (status))
  935         return TCCompleteIrp (Irp, status, 0);
  936 
  937     IoSkipCurrentIrpStackLocation (Irp);
  938     status = PoCallDriver (Extension->LowerDeviceObject, Irp);
  939 
  940     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  941     return status;
  942 }
  943 
  944 static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRP Irp, DriveFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
  945 {
  946     BOOL bBlockTrim = BlockSystemTrimCommand || IsHiddenSystemRunning();
  947     NTSTATUS status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
  948     if (!NT_SUCCESS (status))
  949         return TCCompleteIrp (Irp, status, 0);
  950 
  951     switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
  952     {
  953         case IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES:
  954             Dump ("DriverFilter-DispatchControl: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES\n");
  955             if (bBlockTrim)
  956             {
  957                 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  958                 DWORD inputLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
  959                 if (inputLength >= sizeof (DEVICE_MANAGE_DATA_SET_ATTRIBUTES))
  960                 {
  961                     PDEVICE_MANAGE_DATA_SET_ATTRIBUTES pInputAttrs = (PDEVICE_MANAGE_DATA_SET_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer;
  962                     DEVICE_DATA_MANAGEMENT_SET_ACTION action = pInputAttrs->Action;
  963                     if (action == DeviceDsmAction_Trim)
  964                     {
  965                         Dump ("DriverFilter-DispatchControl: IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES - DeviceDsmAction_Trim.\n");
  966 
  967                         if (bBlockTrim)
  968                         {
  969                             Dump ("DriverFilter-DispatchControl:: TRIM command blocked.\n");
  970                             IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  971                             return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
  972                         }
  973                     }
  974                 }
  975             }
  976             break;
  977     }
  978 
  979     status = PassIrp (Extension->LowerDeviceObject, Irp);
  980     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
  981     return status;
  982 }
  983 
  984 
  985 NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp)
  986 {
  987     DriveFilterExtension *Extension = (DriveFilterExtension *) DeviceObject->DeviceExtension;
  988     PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
  989     NTSTATUS status;
  990 
  991     ASSERT (!Extension->bRootDevice && Extension->IsDriveFilterDevice);
  992 
  993     switch (irpSp->MajorFunction)
  994     {
  995     case IRP_MJ_READ:
  996     case IRP_MJ_WRITE:
  997         if (Extension->BootDrive)
  998         {
  999             status = EncryptedIoQueueAddIrp (&Extension->Queue, Irp);
 1000             
 1001             if (status != STATUS_PENDING)
 1002                 TCCompleteDiskIrp (Irp, status, 0);
 1003 
 1004             return status;
 1005         }
 1006         break;
 1007 
 1008     case IRP_MJ_PNP:
 1009         return DispatchPnp (DeviceObject, Irp, Extension, irpSp);
 1010 
 1011     case IRP_MJ_POWER:
 1012         return DispatchPower (DeviceObject, Irp, Extension, irpSp);
 1013 
 1014     case IRP_MJ_DEVICE_CONTROL:
 1015         return DispatchControl (DeviceObject, Irp, Extension, irpSp);
 1016     }
 1017 
 1018     status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
 1019     if (!NT_SUCCESS (status))
 1020         return TCCompleteIrp (Irp, status, 0);
 1021 
 1022     status = PassIrp (Extension->LowerDeviceObject, Irp);
 1023 
 1024     IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
 1025     return status;
 1026 }
 1027 
 1028 
 1029 void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp)
 1030 {
 1031     LARGE_INTEGER offset;
 1032     char *header;
 1033     ReopenBootVolumeHeaderRequest *request = (ReopenBootVolumeHeaderRequest *) irp->AssociatedIrp.SystemBuffer;
 1034 
 1035     irp->IoStatus.Information = 0;
 1036 
 1037     if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice())
 1038     {
 1039         irp->IoStatus.Status = STATUS_ACCESS_DENIED;
 1040         return;
 1041     }
 1042 
 1043     if (!ValidateIOBufferSize (irp, sizeof (ReopenBootVolumeHeaderRequest), ValidateInput))
 1044         return;
 1045 
 1046     if (!BootDriveFound || !BootDriveFilterExtension || !BootDriveFilterExtension->DriveMounted || !BootDriveFilterExtension->HeaderCryptoInfo
 1047         || request->VolumePassword.Length > MAX_PASSWORD
 1048         || request->pkcs5_prf < 0
 1049         || request->pkcs5_prf > LAST_PRF_ID
 1050         || request->pim < 0
 1051         || request->pim > 65535
 1052         )
 1053     {
 1054         irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 1055         goto wipe;
 1056     }
 1057 
 1058     header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 1059     if (!header)
 1060     {
 1061         irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
 1062         goto wipe;
 1063     }
 1064 
 1065     if (BootDriveFilterExtension->HiddenSystem)
 1066         offset.QuadPart = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
 1067     else
 1068         offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
 1069 
 1070     irp->IoStatus.Status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 1071     if (!NT_SUCCESS (irp->IoStatus.Status))
 1072     {
 1073         Dump ("TCReadDevice error %x\n", irp->IoStatus.Status);
 1074         goto ret;
 1075     }
 1076 
 1077     if (ReadVolumeHeader (!BootDriveFilterExtension->HiddenSystem, header, &request->VolumePassword, request->pkcs5_prf, request->pim, FALSE, NULL, BootDriveFilterExtension->HeaderCryptoInfo) == 0)
 1078     {
 1079         Dump ("Header reopened\n");
 1080         ComputeBootLoaderFingerprint (BootDriveFilterExtension->LowerDeviceObject, header);
 1081         
 1082         BootDriveFilterExtension->Queue.CryptoInfo->header_creation_time = BootDriveFilterExtension->HeaderCryptoInfo->header_creation_time;
 1083         BootDriveFilterExtension->Queue.CryptoInfo->pkcs5 = BootDriveFilterExtension->HeaderCryptoInfo->pkcs5;
 1084         BootDriveFilterExtension->Queue.CryptoInfo->noIterations = BootDriveFilterExtension->HeaderCryptoInfo->noIterations;
 1085         BootDriveFilterExtension->Queue.CryptoInfo->volumePim = BootDriveFilterExtension->HeaderCryptoInfo->volumePim;
 1086 
 1087         irp->IoStatus.Status = STATUS_SUCCESS;
 1088     }
 1089     else
 1090     {
 1091         crypto_close (BootDriveFilterExtension->HeaderCryptoInfo);
 1092         BootDriveFilterExtension->HeaderCryptoInfo = NULL;
 1093 
 1094         Dump ("Header not reopened\n");
 1095         irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 1096     }
 1097 
 1098 ret:
 1099     TCfree (header);
 1100 wipe:
 1101     burn (request, sizeof (*request));
 1102 }
 1103 
 1104 
 1105 // Legacy Windows XP/2003 hibernation dump filter
 1106 
 1107 typedef NTSTATUS (*HiberDriverWriteFunctionA) (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3);
 1108 typedef NTSTATUS (*HiberDriverWriteFunctionB) (PLARGE_INTEGER writeOffset, PMDL dataMdl);
 1109 
 1110 typedef struct
 1111 {
 1112 #ifdef _WIN64
 1113     byte FieldPad1[64];
 1114     HiberDriverWriteFunctionB WriteFunctionB;
 1115     byte FieldPad2[56];
 1116 #else
 1117     byte FieldPad1[48];
 1118     HiberDriverWriteFunctionB WriteFunctionB;
 1119     byte FieldPad2[32];
 1120 #endif
 1121     HiberDriverWriteFunctionA WriteFunctionA;
 1122     byte FieldPad3[24];
 1123     LARGE_INTEGER PartitionStartOffset;
 1124 } HiberDriverContext;
 1125 
 1126 typedef NTSTATUS (*HiberDriverEntry) (PVOID arg0, HiberDriverContext *hiberDriverContext);
 1127 
 1128 typedef struct
 1129 {
 1130     LIST_ENTRY ModuleList;
 1131 #ifdef _WIN64
 1132     byte FieldPad1[32];
 1133 #else
 1134     byte FieldPad1[16];
 1135 #endif
 1136     PVOID ModuleBaseAddress;
 1137     HiberDriverEntry ModuleEntryAddress;
 1138 #ifdef _WIN64
 1139     byte FieldPad2[24];
 1140 #else
 1141     byte FieldPad2[12];
 1142 #endif
 1143     UNICODE_STRING ModuleName;
 1144 } ModuleTableItem;
 1145 
 1146 
 1147 #define TC_MAX_HIBER_FILTER_COUNT 3
 1148 static int LastHiberFilterNumber = 0;
 1149 
 1150 static HiberDriverEntry OriginalHiberDriverEntries[TC_MAX_HIBER_FILTER_COUNT];
 1151 static HiberDriverWriteFunctionA OriginalHiberDriverWriteFunctionsA[TC_MAX_HIBER_FILTER_COUNT];
 1152 static HiberDriverWriteFunctionB OriginalHiberDriverWriteFunctionsB[TC_MAX_HIBER_FILTER_COUNT];
 1153 
 1154 static LARGE_INTEGER HiberPartitionOffset;
 1155 
 1156 
 1157 static NTSTATUS HiberDriverWriteFunctionFilter (int filterNumber, PLARGE_INTEGER writeOffset, PMDL dataMdl, BOOL writeB, ULONG arg0WriteA, PVOID arg3WriteA)
 1158 {
 1159     MDL *encryptedDataMdl = dataMdl;
 1160 
 1161     if (writeOffset && dataMdl && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted)
 1162     {
 1163         ULONG dataLength = MmGetMdlByteCount (dataMdl);
 1164 
 1165         if (dataMdl->MappedSystemVa && dataLength > 0)
 1166         {
 1167             uint64 offset = HiberPartitionOffset.QuadPart + writeOffset->QuadPart;
 1168             uint64 intersectStart;
 1169             uint32 intersectLength;
 1170 
 1171             if (dataLength > TC_HIBERNATION_WRITE_BUFFER_SIZE)
 1172                 TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW);
 1173 
 1174             if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
 1175                 TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
 1176 
 1177             if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
 1178                 TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
 1179 
 1180             GetIntersection (offset,
 1181                 dataLength,
 1182                 BootDriveFilterExtension->Queue.EncryptedAreaStart,
 1183                 BootDriveFilterExtension->Queue.EncryptedAreaEnd,
 1184                 &intersectStart,
 1185                 &intersectLength);
 1186 
 1187             if (intersectLength > 0)
 1188             {
 1189                 UINT64_STRUCT dataUnit;
 1190                 dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
 1191 
 1192                 memcpy (HibernationWriteBuffer, dataMdl->MappedSystemVa, dataLength);
 1193 
 1194                 if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
 1195                     dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset;
 1196 
 1197                 EncryptDataUnitsCurrentThread (HibernationWriteBuffer + (intersectStart - offset),
 1198                     &dataUnit,
 1199                     intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
 1200                     BootDriveFilterExtension->Queue.CryptoInfo);
 1201 
 1202                 encryptedDataMdl = HibernationWriteBufferMdl;
 1203                 MmInitializeMdl (encryptedDataMdl, HibernationWriteBuffer, dataLength);
 1204                 encryptedDataMdl->MdlFlags = dataMdl->MdlFlags;
 1205             }
 1206         }
 1207     }
 1208 
 1209     if (writeB)
 1210         return (*OriginalHiberDriverWriteFunctionsB[filterNumber]) (writeOffset, encryptedDataMdl);
 1211     
 1212     return (*OriginalHiberDriverWriteFunctionsA[filterNumber]) (arg0WriteA, writeOffset, encryptedDataMdl, arg3WriteA);
 1213 }
 1214 
 1215 
 1216 static NTSTATUS HiberDriverWriteFunctionAFilter0 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
 1217 {
 1218     return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, FALSE, arg0, arg3);
 1219 }
 1220 
 1221 static NTSTATUS HiberDriverWriteFunctionAFilter1 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
 1222 {
 1223     return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, FALSE, arg0, arg3);
 1224 }
 1225 
 1226 static NTSTATUS HiberDriverWriteFunctionAFilter2 (ULONG arg0, PLARGE_INTEGER writeOffset, PMDL dataMdl, PVOID arg3)
 1227 {
 1228     return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, FALSE, arg0, arg3);
 1229 }
 1230 
 1231 
 1232 static NTSTATUS HiberDriverWriteFunctionBFilter0 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
 1233 {
 1234     return HiberDriverWriteFunctionFilter (0, writeOffset, dataMdl, TRUE, 0, NULL);
 1235 }
 1236 
 1237 static NTSTATUS HiberDriverWriteFunctionBFilter1 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
 1238 {
 1239     return HiberDriverWriteFunctionFilter (1, writeOffset, dataMdl, TRUE, 0, NULL);
 1240 }
 1241 
 1242 static NTSTATUS HiberDriverWriteFunctionBFilter2 (PLARGE_INTEGER writeOffset, PMDL dataMdl)
 1243 {
 1244     return HiberDriverWriteFunctionFilter (2, writeOffset, dataMdl, TRUE, 0, NULL);
 1245 }
 1246 
 1247 
 1248 static NTSTATUS HiberDriverEntryFilter (int filterNumber, PVOID arg0, HiberDriverContext *hiberDriverContext)
 1249 {
 1250     BOOL filterInstalled = FALSE;
 1251     NTSTATUS status;
 1252 
 1253     if (!OriginalHiberDriverEntries[filterNumber])
 1254         return STATUS_UNSUCCESSFUL;
 1255 
 1256     status = (*OriginalHiberDriverEntries[filterNumber]) (arg0, hiberDriverContext);
 1257 
 1258     if (!NT_SUCCESS (status) || !hiberDriverContext)
 1259         return status;
 1260 
 1261     if (SetupInProgress)
 1262         TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
 1263 
 1264     if (hiberDriverContext->WriteFunctionA)
 1265     {
 1266         Dump ("Filtering WriteFunctionA %d\n", filterNumber);
 1267         OriginalHiberDriverWriteFunctionsA[filterNumber] = hiberDriverContext->WriteFunctionA;
 1268 
 1269         switch (filterNumber)
 1270         {
 1271         case 0: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter0; break;
 1272         case 1: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter1; break;
 1273         case 2: hiberDriverContext->WriteFunctionA = HiberDriverWriteFunctionAFilter2; break;
 1274         default: TC_THROW_FATAL_EXCEPTION;
 1275         }
 1276 
 1277         filterInstalled = TRUE;
 1278     }
 1279 
 1280     if (hiberDriverContext->WriteFunctionB)
 1281     {
 1282         Dump ("Filtering WriteFunctionB %d\n", filterNumber);
 1283         OriginalHiberDriverWriteFunctionsB[filterNumber] = hiberDriverContext->WriteFunctionB;
 1284 
 1285         switch (filterNumber)
 1286         {
 1287         case 0: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter0; break;
 1288         case 1: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter1; break;
 1289         case 2: hiberDriverContext->WriteFunctionB = HiberDriverWriteFunctionBFilter2; break;
 1290         default: TC_THROW_FATAL_EXCEPTION;
 1291         }
 1292 
 1293         filterInstalled = TRUE;
 1294     }
 1295 
 1296     if (filterInstalled && hiberDriverContext->PartitionStartOffset.QuadPart != 0)
 1297     {
 1298         HiberPartitionOffset = hiberDriverContext->PartitionStartOffset;
 1299 
 1300         if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
 1301             hiberDriverContext->PartitionStartOffset.QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset;
 1302     }
 1303 
 1304     return STATUS_SUCCESS;
 1305 }
 1306 
 1307 
 1308 static NTSTATUS HiberDriverEntryFilter0 (PVOID arg0, HiberDriverContext *hiberDriverContext)
 1309 {
 1310     return HiberDriverEntryFilter (0, arg0, hiberDriverContext);
 1311 }
 1312 
 1313 
 1314 static NTSTATUS HiberDriverEntryFilter1 (PVOID arg0, HiberDriverContext *hiberDriverContext)
 1315 {
 1316     return HiberDriverEntryFilter (1, arg0, hiberDriverContext);
 1317 }
 1318 
 1319 
 1320 static NTSTATUS HiberDriverEntryFilter2 (PVOID arg0, HiberDriverContext *hiberDriverContext)
 1321 {
 1322     return HiberDriverEntryFilter (2, arg0, hiberDriverContext);
 1323 }
 1324 
 1325 
 1326 static VOID LoadImageNotifyRoutine (PUNICODE_STRING fullImageName, HANDLE processId, PIMAGE_INFO imageInfo)
 1327 {
 1328     ModuleTableItem *moduleItem;
 1329     LIST_ENTRY *listEntry;
 1330     KIRQL origIrql;
 1331 
 1332     if (!imageInfo || !imageInfo->SystemModeImage || !imageInfo->ImageBase || !TCDriverObject->DriverSection)
 1333         return;
 1334 
 1335     moduleItem = *(ModuleTableItem **) TCDriverObject->DriverSection;
 1336     if (!moduleItem || !moduleItem->ModuleList.Flink)
 1337         return;
 1338 
 1339     // Search loaded system modules for hibernation driver
 1340     origIrql = KeRaiseIrqlToDpcLevel();
 1341 
 1342     for (listEntry = moduleItem->ModuleList.Flink->Blink;
 1343         listEntry && listEntry != TCDriverObject->DriverSection;
 1344         listEntry = listEntry->Flink)
 1345     {
 1346         moduleItem = CONTAINING_RECORD (listEntry, ModuleTableItem, ModuleList);
 1347 
 1348         if (moduleItem && imageInfo->ImageBase == moduleItem->ModuleBaseAddress)
 1349         {
 1350             if (moduleItem->ModuleName.Buffer && moduleItem->ModuleName.Length >= 5 * sizeof (wchar_t))
 1351             {
 1352                 if (memcmp (moduleItem->ModuleName.Buffer, L"hiber", 5 * sizeof (wchar_t)) == 0
 1353                     || memcmp (moduleItem->ModuleName.Buffer, L"Hiber", 5 * sizeof (wchar_t)) == 0
 1354                     || memcmp (moduleItem->ModuleName.Buffer, L"HIBER", 5 * sizeof (wchar_t)) == 0)
 1355                 {
 1356                     HiberDriverEntry filterEntry;
 1357 
 1358                     switch (LastHiberFilterNumber)
 1359                     {
 1360                     case 0: filterEntry = HiberDriverEntryFilter0; break;
 1361                     case 1: filterEntry = HiberDriverEntryFilter1; break;
 1362                     case 2: filterEntry = HiberDriverEntryFilter2; break;
 1363                     default: TC_THROW_FATAL_EXCEPTION;
 1364                     }
 1365 
 1366                     if (moduleItem->ModuleEntryAddress != filterEntry)
 1367                     {
 1368                         // Install filter
 1369                         OriginalHiberDriverEntries[LastHiberFilterNumber] = moduleItem->ModuleEntryAddress;
 1370                         moduleItem->ModuleEntryAddress = filterEntry;
 1371 
 1372                         if (++LastHiberFilterNumber > TC_MAX_HIBER_FILTER_COUNT - 1)
 1373                             LastHiberFilterNumber = 0;
 1374                     }
 1375                 }
 1376             }
 1377             break;
 1378         }
 1379     }
 1380 
 1381     KeLowerIrql (origIrql);
 1382 }
 1383 
 1384 
 1385 void StartLegacyHibernationDriverFilter ()
 1386 {
 1387     PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
 1388     NTSTATUS status;
 1389 
 1390     ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
 1391     ASSERT (!IsOSAtLeast (WIN_VISTA));
 1392 
 1393     if (!TCDriverObject->DriverSection || !*(ModuleTableItem **) TCDriverObject->DriverSection)
 1394         goto err;
 1395 
 1396     // All buffers required for hibernation must be allocated here
 1397 #ifdef _WIN64
 1398     highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFULL;
 1399 #else
 1400     highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFULL;
 1401 #endif
 1402 
 1403     HibernationWriteBuffer = MmAllocateContiguousMemory (TC_HIBERNATION_WRITE_BUFFER_SIZE, highestAcceptableWriteBufferAddr);
 1404     if (!HibernationWriteBuffer)
 1405         goto err;
 1406 
 1407     HibernationWriteBufferMdl = IoAllocateMdl (HibernationWriteBuffer, TC_HIBERNATION_WRITE_BUFFER_SIZE, FALSE, FALSE, NULL);
 1408     if (!HibernationWriteBufferMdl)
 1409         goto err;
 1410 
 1411     MmBuildMdlForNonPagedPool (HibernationWriteBufferMdl);
 1412 
 1413     status = PsSetLoadImageNotifyRoutine (LoadImageNotifyRoutine);
 1414     if (!NT_SUCCESS (status))
 1415         goto err;
 1416 
 1417     LegacyHibernationDriverFilterActive = TRUE;
 1418     CrashDumpEnabled = FALSE;
 1419     HibernationEnabled = TRUE;
 1420     return;
 1421 
 1422 err:
 1423     LegacyHibernationDriverFilterActive = FALSE;
 1424     CrashDumpEnabled = FALSE;
 1425     HibernationEnabled = FALSE;
 1426 
 1427     if (HibernationWriteBufferMdl)
 1428     {
 1429         IoFreeMdl (HibernationWriteBufferMdl);
 1430         HibernationWriteBufferMdl = NULL;
 1431     }
 1432 
 1433     if (HibernationWriteBuffer)
 1434     {
 1435         MmFreeContiguousMemory (HibernationWriteBuffer);
 1436         HibernationWriteBuffer = NULL;
 1437     }
 1438 }
 1439 
 1440 
 1441 static VOID SetupThreadProc (PVOID threadArg)
 1442 {
 1443     DriveFilterExtension *Extension = BootDriveFilterExtension;
 1444 
 1445     LARGE_INTEGER offset;
 1446     UINT64_STRUCT dataUnit;
 1447     ULONG setupBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE;
 1448     BOOL headerUpdateRequired = FALSE;
 1449     int64 bytesWrittenSinceHeaderUpdate = 0;
 1450 
 1451     byte *buffer = NULL;
 1452     byte *wipeBuffer = NULL;
 1453     byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT];
 1454     byte wipeRandCharsUpdate[TC_WIPE_RAND_CHAR_COUNT];
 1455     
 1456     KIRQL irql;
 1457     NTSTATUS status;
 1458 
 1459     // generate real random values for wipeRandChars and 
 1460     // wipeRandCharsUpdate instead of relying on uninitialized stack memory
 1461     LARGE_INTEGER iSeed;
 1462     KeQuerySystemTime( &iSeed );
 1463     if (KeGetCurrentIrql() < DISPATCH_LEVEL)
 1464     {
 1465         ULONG ulRandom;
 1466         ulRandom = RtlRandomEx( &iSeed.LowPart );
 1467         memcpy (wipeRandChars, &ulRandom, TC_WIPE_RAND_CHAR_COUNT);
 1468         ulRandom = RtlRandomEx( &ulRandom );
 1469         memcpy (wipeRandCharsUpdate, &ulRandom, TC_WIPE_RAND_CHAR_COUNT);
 1470         burn (&ulRandom, sizeof(ulRandom));
 1471     }
 1472     else
 1473     {
 1474         byte digest[SHA512_DIGESTSIZE];
 1475         sha512_ctx tctx;
 1476         sha512_begin (&tctx);
 1477         sha512_hash ((unsigned char *) &(iSeed.QuadPart), sizeof(iSeed.QuadPart), &tctx);
 1478         sha512_end (digest, &tctx);
 1479 
 1480         memcpy (wipeRandChars, digest, TC_WIPE_RAND_CHAR_COUNT);
 1481         memcpy (wipeRandCharsUpdate, &digest[SHA512_DIGESTSIZE - TC_WIPE_RAND_CHAR_COUNT], TC_WIPE_RAND_CHAR_COUNT);
 1482 
 1483         burn (digest, SHA512_DIGESTSIZE);
 1484         burn (&tctx, sizeof (tctx));
 1485     }
 1486     
 1487     burn (&iSeed, sizeof(iSeed));
 1488 
 1489     SetupResult = STATUS_UNSUCCESSFUL;
 1490 
 1491     // Make sure volume header can be updated
 1492     if (Extension->HeaderCryptoInfo == NULL)
 1493     {
 1494         SetupResult = STATUS_INVALID_PARAMETER;
 1495         goto ret;
 1496     }
 1497 
 1498     buffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 1499     if (!buffer)
 1500     {
 1501         SetupResult = STATUS_INSUFFICIENT_RESOURCES;
 1502         goto ret;
 1503     }
 1504 
 1505     if (SetupRequest.SetupMode == SetupEncryption && SetupRequest.WipeAlgorithm != TC_WIPE_NONE)
 1506     {
 1507         wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 1508         if (!wipeBuffer)
 1509         {
 1510             SetupResult = STATUS_INSUFFICIENT_RESOURCES;
 1511             goto ret;
 1512         }
 1513     }
 1514 
 1515     while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 1000)))
 1516     {
 1517         if (EncryptionSetupThreadAbortRequested)
 1518             goto abort;
 1519 
 1520         TransformWaitingForIdle = TRUE;
 1521     }
 1522     TransformWaitingForIdle = FALSE;
 1523 
 1524     switch (SetupRequest.SetupMode)
 1525     {
 1526     case SetupEncryption:
 1527         Dump ("Encrypting...\n");
 1528         if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1)
 1529         {
 1530             // Start encryption
 1531             Extension->Queue.EncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart;
 1532             Extension->Queue.EncryptedAreaEnd = -1;
 1533             offset.QuadPart = Extension->ConfiguredEncryptedAreaStart;
 1534         }
 1535         else
 1536         {
 1537             // Resume aborted encryption
 1538             if (Extension->Queue.EncryptedAreaEnd == Extension->ConfiguredEncryptedAreaEnd)
 1539                 goto err;
 1540 
 1541             offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1;
 1542         }
 1543 
 1544         break;
 1545 
 1546     case SetupDecryption:
 1547         Dump ("Decrypting...\n");
 1548         if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1)
 1549         {
 1550             SetupResult = STATUS_SUCCESS;
 1551             goto abort;
 1552         }
 1553 
 1554         offset.QuadPart = Extension->Queue.EncryptedAreaEnd + 1;
 1555         break;
 1556 
 1557     default:
 1558         goto err;
 1559     }
 1560 
 1561     EncryptedIoQueueResumeFromHold (&Extension->Queue);
 1562         
 1563     Dump ("EncryptedAreaStart=%I64d\n", Extension->Queue.EncryptedAreaStart);
 1564     Dump ("EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaEnd);
 1565     Dump ("ConfiguredEncryptedAreaStart=%I64d\n", Extension->ConfiguredEncryptedAreaStart);
 1566     Dump ("ConfiguredEncryptedAreaEnd=%I64d\n", Extension->ConfiguredEncryptedAreaEnd);
 1567     Dump ("offset=%I64d\n", offset.QuadPart);
 1568     Dump ("EncryptedAreaStart=%I64d (%I64d)  EncryptedAreaEnd=%I64d\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024);
 1569 
 1570     while (!EncryptionSetupThreadAbortRequested)
 1571     {
 1572         if (SetupRequest.SetupMode == SetupEncryption)
 1573         {
 1574             if (offset.QuadPart + setupBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1)
 1575                 setupBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart);
 1576 
 1577             if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd)
 1578                 break;
 1579         }
 1580         else
 1581         {
 1582             if (offset.QuadPart - setupBlockSize < Extension->Queue.EncryptedAreaStart)
 1583                 setupBlockSize = (ULONG) (offset.QuadPart - Extension->Queue.EncryptedAreaStart);
 1584 
 1585             offset.QuadPart -= setupBlockSize;
 1586 
 1587             if (setupBlockSize == 0 || offset.QuadPart < Extension->Queue.EncryptedAreaStart)
 1588                 break;
 1589         }
 1590 
 1591         while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500)))
 1592         {
 1593             if (EncryptionSetupThreadAbortRequested)
 1594                 goto abort;
 1595 
 1596             TransformWaitingForIdle = TRUE;
 1597         }
 1598         TransformWaitingForIdle = FALSE;
 1599 
 1600         status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
 1601         if (!NT_SUCCESS (status))
 1602         {
 1603             Dump ("TCReadDevice error %x  offset=%I64d\n", status, offset.QuadPart);
 1604 
 1605             if (SetupRequest.ZeroUnreadableSectors && SetupRequest.SetupMode == SetupEncryption)
 1606             {
 1607                 // Zero unreadable sectors
 1608                 uint64 zeroedSectorCount;
 1609 
 1610                 status = ZeroUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, offset, setupBlockSize, &zeroedSectorCount);
 1611                 if (!NT_SUCCESS (status))
 1612                 {
 1613                     SetupResult = status;
 1614                     goto err;
 1615                 }
 1616 
 1617                 // Retry read
 1618                 status = TCReadDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
 1619                 if (!NT_SUCCESS (status))
 1620                 {
 1621                     SetupResult = status;
 1622                     goto err;
 1623                 }
 1624             }
 1625             else if (SetupRequest.DiscardUnreadableEncryptedSectors && SetupRequest.SetupMode == SetupDecryption)
 1626             {
 1627                 // Discard unreadable encrypted sectors
 1628                 uint64 badSectorCount;
 1629 
 1630                 status = ReadDeviceSkipUnreadableSectors (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize, &badSectorCount);
 1631                 if (!NT_SUCCESS (status))
 1632                 {
 1633                     SetupResult = status;
 1634                     goto err;
 1635                 }
 1636             }
 1637             else
 1638             {
 1639                 SetupResult = status;
 1640                 goto err;
 1641             }
 1642         }
 1643 
 1644         dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE;
 1645 
 1646         if (SetupRequest.SetupMode == SetupEncryption)
 1647         {
 1648             EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1649 
 1650             if (SetupRequest.WipeAlgorithm != TC_WIPE_NONE)
 1651             {
 1652                 byte wipePass;
 1653                 int wipePassCount = GetWipePassCount (SetupRequest.WipeAlgorithm);
 1654                 if (wipePassCount <= 0)
 1655                 {
 1656                     SetupResult = STATUS_INVALID_PARAMETER;
 1657                     goto err;
 1658                 }
 1659 
 1660                 for (wipePass = 1; wipePass <= wipePassCount; ++wipePass)
 1661                 {
 1662                     if (!WipeBuffer (SetupRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, setupBlockSize))
 1663                     {
 1664                         ULONG i;
 1665                         for (i = 0; i < setupBlockSize; ++i)
 1666                         {
 1667                             wipeBuffer[i] = buffer[i] + wipePass;
 1668                         }
 1669 
 1670                         EncryptDataUnits (wipeBuffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1671                         memcpy (wipeRandCharsUpdate, wipeBuffer, sizeof (wipeRandCharsUpdate)); 
 1672                     }
 1673 
 1674                     status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, setupBlockSize);
 1675                     if (!NT_SUCCESS (status))
 1676                     {
 1677                         // Undo failed write operation
 1678                         DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1679                         TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
 1680 
 1681                         SetupResult = status;
 1682                         goto err;
 1683                     }
 1684                 }
 1685 
 1686                 memcpy (wipeRandChars, wipeRandCharsUpdate, sizeof (wipeRandCharsUpdate)); 
 1687             }
 1688         }
 1689         else
 1690         {
 1691             DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1692         }
 1693 
 1694         status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
 1695         if (!NT_SUCCESS (status))
 1696         {
 1697             Dump ("TCWriteDevice error %x\n", status);
 1698 
 1699             // Undo failed write operation
 1700             if (SetupRequest.SetupMode == SetupEncryption)
 1701                 DecryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1702             else
 1703                 EncryptDataUnits (buffer, &dataUnit, setupBlockSize / ENCRYPTION_DATA_UNIT_SIZE, Extension->Queue.CryptoInfo);
 1704 
 1705             TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, buffer, offset, setupBlockSize);
 1706 
 1707             SetupResult = status;
 1708             goto err;
 1709         }
 1710 
 1711         if (SetupRequest.SetupMode == SetupEncryption)
 1712             offset.QuadPart += setupBlockSize;
 1713 
 1714         Extension->Queue.EncryptedAreaEndUpdatePending = TRUE;
 1715         Extension->Queue.EncryptedAreaEnd = offset.QuadPart - 1;
 1716         Extension->Queue.EncryptedAreaEndUpdatePending = FALSE;
 1717 
 1718         headerUpdateRequired = TRUE;
 1719 
 1720         EncryptedIoQueueResumeFromHold (&Extension->Queue);
 1721 
 1722         KeAcquireSpinLock (&SetupStatusSpinLock, &irql);
 1723         SetupStatusEncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd;
 1724         KeReleaseSpinLock (&SetupStatusSpinLock, irql);
 1725 
 1726         // Update volume header
 1727         bytesWrittenSinceHeaderUpdate += setupBlockSize;
 1728         if (bytesWrittenSinceHeaderUpdate >= TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD)
 1729         {
 1730             status = SaveDriveVolumeHeader (Extension);
 1731             ASSERT (NT_SUCCESS (status));
 1732             if (NT_SUCCESS (status))
 1733             {
 1734                 headerUpdateRequired = FALSE;
 1735                 bytesWrittenSinceHeaderUpdate = 0;
 1736             }
 1737         }
 1738     }
 1739 
 1740 abort:
 1741     SetupResult = STATUS_SUCCESS;
 1742 err:
 1743 
 1744     if (Extension->Queue.EncryptedAreaEnd == -1)
 1745         Extension->Queue.EncryptedAreaStart = -1;
 1746 
 1747     if (EncryptedIoQueueIsSuspended (&Extension->Queue))
 1748         EncryptedIoQueueResumeFromHold (&Extension->Queue);
 1749 
 1750     if (SetupRequest.SetupMode == SetupDecryption && Extension->Queue.EncryptedAreaStart >= Extension->Queue.EncryptedAreaEnd)
 1751     {
 1752         while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 0)));
 1753 
 1754         Extension->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaEnd = -1;
 1755         Extension->Queue.EncryptedAreaStart = Extension->Queue.EncryptedAreaEnd = -1;
 1756 
 1757         EncryptedIoQueueResumeFromHold (&Extension->Queue);
 1758 
 1759         headerUpdateRequired = TRUE;
 1760     }
 1761 
 1762     Dump ("Setup completed:  EncryptedAreaStart=%I64d (%I64d)  EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd);
 1763 
 1764     if (headerUpdateRequired)
 1765     {
 1766         status = SaveDriveVolumeHeader (Extension);
 1767 
 1768         if (!NT_SUCCESS (status) && NT_SUCCESS (SetupResult))
 1769             SetupResult = status;
 1770     }
 1771 
 1772     if (SetupRequest.SetupMode == SetupDecryption && Extension->ConfiguredEncryptedAreaEnd == -1 && Extension->DriveMounted)
 1773     {
 1774         while (!RootDeviceControlMutexAcquireNoWait() && !EncryptionSetupThreadAbortRequested)
 1775         {
 1776             TCSleep (10);
 1777         }
 1778 
 1779         // Disable hibernation (resume would fail due to a change in the system memory map)
 1780         HibernationEnabled = FALSE;
 1781 
 1782         DismountDrive (Extension, FALSE);
 1783 
 1784         if (!EncryptionSetupThreadAbortRequested)
 1785             RootDeviceControlMutexRelease();
 1786     }
 1787 
 1788 ret:
 1789     if (buffer)
 1790     {
 1791         burn (buffer, TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 1792         TCfree (buffer);
 1793     }
 1794     if (wipeBuffer)
 1795     {
 1796         burn (wipeBuffer, TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 1797         TCfree (wipeBuffer);
 1798     }
 1799 
 1800     burn (wipeRandChars, TC_WIPE_RAND_CHAR_COUNT);
 1801     burn (wipeRandCharsUpdate, TC_WIPE_RAND_CHAR_COUNT);
 1802 
 1803     SetupInProgress = FALSE;
 1804     PsTerminateSystemThread (SetupResult);
 1805 }
 1806 
 1807 
 1808 NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp)
 1809 {
 1810     NTSTATUS status;
 1811 
 1812     if (!UserCanAccessDriveDevice())
 1813         return STATUS_ACCESS_DENIED;
 1814 
 1815     if (SetupInProgress || !BootDriveFound || !BootDriveFilterExtension
 1816         || !BootDriveFilterExtension->DriveMounted
 1817         || BootDriveFilterExtension->HiddenSystem
 1818         || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (BootEncryptionSetupRequest))
 1819         return STATUS_INVALID_PARAMETER;
 1820 
 1821     if (EncryptionSetupThread)
 1822         AbortBootEncryptionSetup();
 1823 
 1824     SetupRequest = *(BootEncryptionSetupRequest *) irp->AssociatedIrp.SystemBuffer;
 1825 
 1826     EncryptionSetupThreadAbortRequested = FALSE;
 1827     KeInitializeSpinLock (&SetupStatusSpinLock);
 1828     SetupStatusEncryptedAreaEnd = BootDriveFilterExtension ? BootDriveFilterExtension->Queue.EncryptedAreaEnd : -1;
 1829 
 1830     SetupInProgress = TRUE;
 1831     status = TCStartThread (SetupThreadProc, DeviceObject, &EncryptionSetupThread);
 1832     
 1833     if (!NT_SUCCESS (status))
 1834         SetupInProgress = FALSE;
 1835 
 1836     return status;
 1837 }
 1838 
 1839 
 1840 void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp)
 1841 {
 1842     if (ValidateIOBufferSize (irp, sizeof (VOLUME_PROPERTIES_STRUCT), ValidateOutput))
 1843     {
 1844         DriveFilterExtension *Extension = BootDriveFilterExtension;
 1845         VOLUME_PROPERTIES_STRUCT *prop = (VOLUME_PROPERTIES_STRUCT *) irp->AssociatedIrp.SystemBuffer;
 1846         memset (prop, 0, sizeof (*prop));
 1847 
 1848         if (!BootDriveFound || !Extension || !Extension->DriveMounted)
 1849         {
 1850             irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 1851             irp->IoStatus.Information = 0;
 1852         }
 1853         else
 1854         {
 1855             prop->hiddenVolume = Extension->Queue.CryptoInfo->hiddenVolume;
 1856             prop->diskLength = Extension->ConfiguredEncryptedAreaEnd + 1 - Extension->ConfiguredEncryptedAreaStart;
 1857             prop->ea = Extension->Queue.CryptoInfo->ea;
 1858             prop->mode = Extension->Queue.CryptoInfo->mode;
 1859             prop->pkcs5 = Extension->Queue.CryptoInfo->pkcs5;
 1860             prop->pkcs5Iterations = Extension->Queue.CryptoInfo->noIterations;
 1861             prop->volumePim = Extension->Queue.CryptoInfo->volumePim;
 1862 #if 0
 1863             prop->volumeCreationTime = Extension->Queue.CryptoInfo->volume_creation_time;
 1864             prop->headerCreationTime = Extension->Queue.CryptoInfo->header_creation_time;
 1865 #endif
 1866             prop->volFormatVersion = Extension->Queue.CryptoInfo->LegacyVolume ? TC_VOLUME_FORMAT_VERSION_PRE_6_0 : TC_VOLUME_FORMAT_VERSION;
 1867 
 1868             prop->totalBytesRead = Extension->Queue.TotalBytesRead;
 1869             prop->totalBytesWritten = Extension->Queue.TotalBytesWritten;
 1870 
 1871             irp->IoStatus.Information = sizeof (VOLUME_PROPERTIES_STRUCT);
 1872             irp->IoStatus.Status = STATUS_SUCCESS;
 1873         }
 1874     }
 1875 }
 1876 
 1877 
 1878 void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp)
 1879 {
 1880     /* IMPORTANT: Do NOT add any potentially time-consuming operations to this function. */
 1881 
 1882     if (ValidateIOBufferSize (irp, sizeof (BootEncryptionStatus), ValidateOutput))
 1883     {
 1884         DriveFilterExtension *Extension = BootDriveFilterExtension;
 1885         BootEncryptionStatus *bootEncStatus = (BootEncryptionStatus *) irp->AssociatedIrp.SystemBuffer;
 1886         memset (bootEncStatus, 0, sizeof (*bootEncStatus));
 1887 
 1888         if (BootArgsValid)
 1889             bootEncStatus->BootLoaderVersion = BootArgs.BootLoaderVersion;
 1890 
 1891         bootEncStatus->DeviceFilterActive = DeviceFilterActive;
 1892         bootEncStatus->SetupInProgress = SetupInProgress;
 1893         bootEncStatus->SetupMode = SetupRequest.SetupMode;
 1894         bootEncStatus->TransformWaitingForIdle = TransformWaitingForIdle;
 1895 
 1896         if (!BootDriveFound || !Extension || !Extension->DriveMounted)
 1897         {
 1898             bootEncStatus->DriveEncrypted = FALSE;
 1899             bootEncStatus->DriveMounted = FALSE;
 1900             bootEncStatus->VolumeHeaderPresent = FALSE;
 1901         }
 1902         else
 1903         {
 1904             bootEncStatus->DriveMounted = Extension->DriveMounted;
 1905             bootEncStatus->VolumeHeaderPresent = Extension->VolumeHeaderPresent;
 1906             bootEncStatus->DriveEncrypted = Extension->Queue.EncryptedAreaStart != -1;
 1907             bootEncStatus->BootDriveLength = BootDriveLength;
 1908 
 1909             bootEncStatus->ConfiguredEncryptedAreaStart = Extension->ConfiguredEncryptedAreaStart;
 1910             bootEncStatus->ConfiguredEncryptedAreaEnd = Extension->ConfiguredEncryptedAreaEnd;
 1911             bootEncStatus->EncryptedAreaStart = Extension->Queue.EncryptedAreaStart;
 1912 
 1913             if (SetupInProgress)
 1914             {
 1915                 KIRQL irql;
 1916                 KeAcquireSpinLock (&SetupStatusSpinLock, &irql);
 1917                 bootEncStatus->EncryptedAreaEnd = SetupStatusEncryptedAreaEnd;
 1918                 KeReleaseSpinLock (&SetupStatusSpinLock, irql);
 1919             }
 1920             else
 1921                 bootEncStatus->EncryptedAreaEnd = Extension->Queue.EncryptedAreaEnd;
 1922 
 1923             bootEncStatus->VolumeHeaderSaltCrc32 = Extension->VolumeHeaderSaltCrc32;
 1924             bootEncStatus->HibernationPreventionCount = HibernationPreventionCount;
 1925             bootEncStatus->HiddenSysLeakProtectionCount = HiddenSysLeakProtectionCount;
 1926 
 1927             bootEncStatus->HiddenSystem = Extension->HiddenSystem;
 1928             
 1929             if (Extension->HiddenSystem)
 1930                 bootEncStatus->HiddenSystemPartitionStart = BootArgs.HiddenSystemPartitionStart;
 1931         }
 1932 
 1933         irp->IoStatus.Information = sizeof (BootEncryptionStatus);
 1934         irp->IoStatus.Status = STATUS_SUCCESS;
 1935     }
 1936 }
 1937 
 1938 
 1939 void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp)
 1940 {
 1941     if (ValidateIOBufferSize (irp, sizeof (uint16), ValidateOutput))
 1942     {
 1943         if (BootArgsValid)
 1944         {
 1945             *(uint16 *) irp->AssociatedIrp.SystemBuffer = BootArgs.BootLoaderVersion;
 1946             irp->IoStatus.Information = sizeof (uint16);
 1947             irp->IoStatus.Status = STATUS_SUCCESS;
 1948         }
 1949         else
 1950         {
 1951             irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 1952             irp->IoStatus.Information = 0;
 1953         }
 1954     }
 1955 }
 1956 
 1957 void GetBootLoaderFingerprint (PIRP irp, PIO_STACK_LOCATION irpSp)
 1958 {
 1959     if (ValidateIOBufferSize (irp, sizeof (BootLoaderFingerprintRequest), ValidateOutput))
 1960     {
 1961         irp->IoStatus.Information = 0;
 1962         if (BootArgsValid && BootDriveFound && BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted && BootDriveFilterExtension->HeaderCryptoInfo)
 1963         {
 1964             BootLoaderFingerprintRequest *bootLoaderFingerprint = (BootLoaderFingerprintRequest *) irp->AssociatedIrp.SystemBuffer;         
 1965 
 1966             /* compute the fingerprint again and check if it is the same as the one retrieved during boot */
 1967             char *header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 1968             if (!header)
 1969             {
 1970                 irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
 1971             }
 1972             else
 1973             {
 1974                 memcpy (bootLoaderFingerprint->Fingerprint, BootLoaderFingerprint, sizeof (BootLoaderFingerprint));
 1975                 ComputeBootLoaderFingerprint (BootDriveFilterExtension->LowerDeviceObject, header);
 1976 
 1977                 burn (header, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
 1978                 TCfree (header);
 1979 
 1980                 if (0 == memcmp (bootLoaderFingerprint->Fingerprint, BootLoaderFingerprint, sizeof (BootLoaderFingerprint)))
 1981                 {
 1982                     irp->IoStatus.Information = sizeof (BootLoaderFingerprintRequest);
 1983                     irp->IoStatus.Status = STATUS_SUCCESS;
 1984                 }
 1985                 else
 1986                 {
 1987                     /* fingerprint mismatch.*/
 1988                     irp->IoStatus.Status = STATUS_INVALID_IMAGE_HASH;
 1989                 }
 1990             }
 1991         }
 1992         else
 1993         {
 1994             irp->IoStatus.Status = STATUS_INVALID_PARAMETER;            
 1995         }
 1996     }
 1997 }
 1998 
 1999 void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp)
 2000 {
 2001     if (ValidateIOBufferSize (irp, sizeof (GetBootEncryptionAlgorithmNameRequest), ValidateOutput))
 2002     {
 2003         if (BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted)
 2004         {
 2005             wchar_t BootEncryptionAlgorithmNameW[256];
 2006             wchar_t BootPrfAlgorithmNameW[256];
 2007             GetBootEncryptionAlgorithmNameRequest *request = (GetBootEncryptionAlgorithmNameRequest *) irp->AssociatedIrp.SystemBuffer;
 2008             EAGetName (BootEncryptionAlgorithmNameW, BootDriveFilterExtension->Queue.CryptoInfo->ea, 0);
 2009             HashGetName2 (BootPrfAlgorithmNameW, BootDriveFilterExtension->Queue.CryptoInfo->pkcs5);
 2010 
 2011             RtlStringCbPrintfA (request->BootEncryptionAlgorithmName, sizeof (request->BootEncryptionAlgorithmName), "%S", BootEncryptionAlgorithmNameW);
 2012             RtlStringCbPrintfA (request->BootPrfAlgorithmName, sizeof (request->BootPrfAlgorithmName), "%S", BootPrfAlgorithmNameW);
 2013 
 2014             irp->IoStatus.Information = sizeof (GetBootEncryptionAlgorithmNameRequest);
 2015             irp->IoStatus.Status = STATUS_SUCCESS;
 2016         }
 2017         else
 2018         {
 2019             irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 2020             irp->IoStatus.Information = 0;
 2021         }
 2022     }
 2023 }
 2024 
 2025 
 2026 NTSTATUS GetSetupResult()
 2027 {
 2028     return SetupResult;
 2029 }
 2030 
 2031 
 2032 BOOL IsBootDriveMounted ()
 2033 {
 2034     return BootDriveFilterExtension && BootDriveFilterExtension->DriveMounted;
 2035 }
 2036 
 2037 
 2038 BOOL IsBootEncryptionSetupInProgress ()
 2039 {
 2040     return SetupInProgress;
 2041 }
 2042 
 2043 
 2044 BOOL IsHiddenSystemRunning ()
 2045 {
 2046     return BootDriveFilterExtension && BootDriveFilterExtension->HiddenSystem;
 2047 }
 2048 
 2049 
 2050 DriveFilterExtension *GetBootDriveFilterExtension ()
 2051 {
 2052     return BootDriveFilterExtension;
 2053 }
 2054 
 2055 
 2056 CRYPTO_INFO *GetSystemDriveCryptoInfo ()
 2057 {
 2058     return BootDriveFilterExtension->Queue.CryptoInfo;
 2059 }
 2060 
 2061 
 2062 NTSTATUS AbortBootEncryptionSetup ()
 2063 {
 2064     if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice())
 2065         return STATUS_ACCESS_DENIED;
 2066 
 2067     if (EncryptionSetupThread)
 2068     {
 2069         EncryptionSetupThreadAbortRequested = TRUE;
 2070 
 2071         TCStopThread (EncryptionSetupThread, NULL);
 2072         EncryptionSetupThread = NULL;
 2073     }
 2074 
 2075     return STATUS_SUCCESS;
 2076 }
 2077 
 2078 
 2079 static VOID DecoySystemWipeThreadProc (PVOID threadArg)
 2080 {
 2081     DriveFilterExtension *Extension = BootDriveFilterExtension;
 2082 
 2083     LARGE_INTEGER offset;
 2084     UINT64_STRUCT dataUnit;
 2085     ULONG wipeBlockSize = TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE;
 2086 
 2087     CRYPTO_INFO *wipeCryptoInfo = NULL;
 2088     byte *wipeBuffer = NULL;
 2089     byte *wipeRandBuffer = NULL;
 2090     byte wipeRandChars[TC_WIPE_RAND_CHAR_COUNT];
 2091     int wipePass, wipePassCount;
 2092     int ea = Extension->Queue.CryptoInfo->ea;
 2093 
 2094     KIRQL irql;
 2095     NTSTATUS status;
 2096 
 2097     DecoySystemWipeResult = STATUS_UNSUCCESSFUL;
 2098 
 2099     wipeBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 2100     if (!wipeBuffer)
 2101     {
 2102         DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES;
 2103         goto ret;
 2104     }
 2105     
 2106     wipeRandBuffer = TCalloc (TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE);
 2107     if (!wipeRandBuffer)
 2108     {
 2109         DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES;
 2110         goto ret;
 2111     }
 2112 
 2113     wipeCryptoInfo = crypto_open();
 2114     if (!wipeCryptoInfo)
 2115     {
 2116         DecoySystemWipeResult = STATUS_INSUFFICIENT_RESOURCES;
 2117         goto ret;
 2118     }
 2119 
 2120     wipeCryptoInfo->ea = ea;
 2121     wipeCryptoInfo->mode = Extension->Queue.CryptoInfo->mode;
 2122 
 2123     if (EAInit (ea, WipeDecoyRequest.WipeKey, wipeCryptoInfo->ks) != ERR_SUCCESS)
 2124     {
 2125         DecoySystemWipeResult = STATUS_INVALID_PARAMETER;
 2126         goto ret;
 2127     }
 2128 
 2129     memcpy (wipeCryptoInfo->k2, WipeDecoyRequest.WipeKey + EAGetKeySize (ea), EAGetKeySize (ea));
 2130     
 2131     if (!EAInitMode (wipeCryptoInfo))
 2132     {
 2133         DecoySystemWipeResult = STATUS_INVALID_PARAMETER;
 2134         goto err;
 2135     }
 2136 
 2137     EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo);
 2138     memcpy (wipeRandChars, wipeRandBuffer, sizeof (wipeRandChars));
 2139 
 2140     burn (WipeDecoyRequest.WipeKey, sizeof (WipeDecoyRequest.WipeKey));
 2141 
 2142     offset.QuadPart = Extension->ConfiguredEncryptedAreaStart;
 2143         
 2144     Dump ("Wiping decoy system:  start offset = %I64d\n", offset.QuadPart);
 2145 
 2146     while (!DecoySystemWipeThreadAbortRequested)
 2147     {
 2148         if (offset.QuadPart + wipeBlockSize > Extension->ConfiguredEncryptedAreaEnd + 1)
 2149             wipeBlockSize = (ULONG) (Extension->ConfiguredEncryptedAreaEnd + 1 - offset.QuadPart);
 2150 
 2151         if (offset.QuadPart > Extension->ConfiguredEncryptedAreaEnd)
 2152             break;
 2153 
 2154         wipePassCount = GetWipePassCount (WipeDecoyRequest.WipeAlgorithm);
 2155         if (wipePassCount <= 0)
 2156         {
 2157             DecoySystemWipeResult = STATUS_INVALID_PARAMETER;
 2158             goto err;
 2159         }
 2160 
 2161         for (wipePass = 1; wipePass <= wipePassCount; ++wipePass)
 2162         {
 2163             if (!WipeBuffer (WipeDecoyRequest.WipeAlgorithm, wipeRandChars, wipePass, wipeBuffer, wipeBlockSize))
 2164             {
 2165                 dataUnit.Value = offset.QuadPart / ENCRYPTION_DATA_UNIT_SIZE;
 2166                 EncryptDataUnits (wipeRandBuffer, &dataUnit, wipeBlockSize / ENCRYPTION_DATA_UNIT_SIZE, wipeCryptoInfo);
 2167                 memcpy (wipeBuffer, wipeRandBuffer, wipeBlockSize);
 2168             }
 2169 
 2170             while (!NT_SUCCESS (EncryptedIoQueueHoldWhenIdle (&Extension->Queue, 500)))
 2171             {
 2172                 if (DecoySystemWipeThreadAbortRequested)
 2173                     goto abort;
 2174             }
 2175 
 2176             status = TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, wipeBuffer, offset, wipeBlockSize);
 2177 
 2178             if (!NT_SUCCESS (status))
 2179             {
 2180                 DecoySystemWipeResult = status;
 2181                 goto err;
 2182             }
 2183 
 2184             EncryptedIoQueueResumeFromHold (&Extension->Queue);
 2185         }
 2186 
 2187         offset.QuadPart += wipeBlockSize;
 2188 
 2189         KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql);
 2190         DecoySystemWipedAreaEnd = offset.QuadPart - 1;
 2191         KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql);
 2192     }
 2193 
 2194 abort:
 2195     DecoySystemWipeResult = STATUS_SUCCESS;
 2196 err:
 2197 
 2198     if (EncryptedIoQueueIsSuspended (&Extension->Queue))
 2199         EncryptedIoQueueResumeFromHold (&Extension->Queue);
 2200 
 2201     Dump ("Wipe end: DecoySystemWipedAreaEnd=%I64d (%I64d)\n", DecoySystemWipedAreaEnd, DecoySystemWipedAreaEnd / 1024 / 1024);
 2202 
 2203 ret:
 2204     if (wipeCryptoInfo)
 2205         crypto_close (wipeCryptoInfo);
 2206 
 2207     if (wipeRandBuffer)
 2208         TCfree (wipeRandBuffer);
 2209 
 2210     if (wipeBuffer)
 2211         TCfree (wipeBuffer);
 2212 
 2213     DecoySystemWipeInProgress = FALSE;
 2214     PsTerminateSystemThread (DecoySystemWipeResult);
 2215 }
 2216 
 2217 
 2218 NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp)
 2219 {
 2220     NTSTATUS status;
 2221     WipeDecoySystemRequest *request;
 2222 
 2223     if (!UserCanAccessDriveDevice())
 2224         return STATUS_ACCESS_DENIED;
 2225 
 2226     if (!IsHiddenSystemRunning()
 2227         || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WipeDecoySystemRequest))
 2228         return STATUS_INVALID_PARAMETER;
 2229 
 2230     if (DecoySystemWipeInProgress)
 2231         return STATUS_SUCCESS;
 2232 
 2233     if (DecoySystemWipeThread)
 2234         AbortDecoySystemWipe();
 2235 
 2236     request = (WipeDecoySystemRequest *) irp->AssociatedIrp.SystemBuffer;
 2237     WipeDecoyRequest = *request;
 2238 
 2239     burn (request->WipeKey, sizeof (request->WipeKey));
 2240 
 2241     DecoySystemWipeThreadAbortRequested = FALSE;
 2242     KeInitializeSpinLock (&DecoySystemWipeStatusSpinLock);
 2243     DecoySystemWipedAreaEnd = BootDriveFilterExtension->ConfiguredEncryptedAreaStart;
 2244 
 2245     DecoySystemWipeInProgress = TRUE;
 2246     status = TCStartThread (DecoySystemWipeThreadProc, DeviceObject, &DecoySystemWipeThread);
 2247     
 2248     if (!NT_SUCCESS (status))
 2249         DecoySystemWipeInProgress = FALSE;
 2250 
 2251     return status;
 2252 }
 2253 
 2254 
 2255 BOOL IsDecoySystemWipeInProgress()
 2256 {
 2257     return DecoySystemWipeInProgress;
 2258 }
 2259 
 2260 
 2261 void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp)
 2262 {
 2263     if (ValidateIOBufferSize (irp, sizeof (DecoySystemWipeStatus), ValidateOutput))
 2264     {
 2265         DecoySystemWipeStatus *wipeStatus = (DecoySystemWipeStatus *) irp->AssociatedIrp.SystemBuffer;
 2266 
 2267         if (!IsHiddenSystemRunning())
 2268         {
 2269             irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
 2270             irp->IoStatus.Information = 0;
 2271         }
 2272         else
 2273         {
 2274             wipeStatus->WipeInProgress = DecoySystemWipeInProgress;
 2275             wipeStatus->WipeAlgorithm = WipeDecoyRequest.WipeAlgorithm;
 2276 
 2277             if (DecoySystemWipeInProgress)
 2278             {
 2279                 KIRQL irql;
 2280                 KeAcquireSpinLock (&DecoySystemWipeStatusSpinLock, &irql);
 2281                 wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd;
 2282                 KeReleaseSpinLock (&DecoySystemWipeStatusSpinLock, irql);
 2283             }
 2284             else
 2285                 wipeStatus->WipedAreaEnd = DecoySystemWipedAreaEnd;
 2286             
 2287             irp->IoStatus.Information = sizeof (DecoySystemWipeStatus);
 2288             irp->IoStatus.Status = STATUS_SUCCESS;
 2289         }
 2290     }
 2291 }
 2292 
 2293 
 2294 NTSTATUS GetDecoySystemWipeResult()
 2295 {
 2296     return DecoySystemWipeResult;
 2297 }
 2298 
 2299 
 2300 NTSTATUS AbortDecoySystemWipe ()
 2301 {
 2302     if (!IoIsSystemThread (PsGetCurrentThread()) && !UserCanAccessDriveDevice())
 2303         return STATUS_ACCESS_DENIED;
 2304 
 2305     if (DecoySystemWipeThread)
 2306     {
 2307         DecoySystemWipeThreadAbortRequested = TRUE;
 2308 
 2309         TCStopThread (DecoySystemWipeThread, NULL);
 2310         DecoySystemWipeThread = NULL;
 2311     }
 2312 
 2313     return STATUS_SUCCESS;
 2314 }
 2315 
 2316 
 2317 uint64 GetBootDriveLength ()
 2318 {
 2319     return BootDriveLength.QuadPart;
 2320 }
 2321 
 2322 
 2323 NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp)
 2324 {
 2325     WriteBootDriveSectorRequest *request;
 2326 
 2327     if (!UserCanAccessDriveDevice())
 2328         return STATUS_ACCESS_DENIED;
 2329 
 2330     if (!BootDriveFilterExtension
 2331         || irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof (WriteBootDriveSectorRequest))
 2332         return STATUS_INVALID_PARAMETER;
 2333 
 2334     request = (WriteBootDriveSectorRequest *) irp->AssociatedIrp.SystemBuffer;
 2335     return TCWriteDevice (BootDriveFilterExtension->LowerDeviceObject, request->Data, request->Offset, sizeof (request->Data));
 2336 }