?? drivefilter.c
字號:
/*
Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
Governed by the TrueCrypt License 2.5 the full text of which is contained
in the file License.txt included in TrueCrypt binary and source code
distribution packages.
*/
#include "TCdefs.h"
#include <ntddk.h>
#include <ntddvol.h>
#include "Crc.h"
#include "Crypto.h"
#include "Apidrvr.h"
#include "EncryptedIoQueue.h"
#include "Endian.h"
#include "Ntdriver.h"
#include "Ntvol.h"
#include "Volumes.h"
#include "VolumeFilter.h"
#include "Wipe.h"
#include "DriveFilter.h"
#include "Boot/Windows/BootCommon.h"
static BOOL DeviceFilterActive = FALSE;
BOOL BootArgsValid = FALSE;
BootArguments BootArgs;
static BOOL BootDriveFound = FALSE;
static DriveFilterExtension *BootDriveFilterExtension = NULL;
static LARGE_INTEGER BootDriveLength;
static BOOL HibernationDriverFilterActive = FALSE;
static byte *HibernationWriteBuffer = NULL;
static MDL *HibernationWriteBufferMdl = NULL;
static uint32 HibernationPreventionCount = 0;
static BootEncryptionSetupRequest SetupRequest;
static volatile BOOL SetupInProgress = FALSE;
static PKTHREAD EncryptionSetupThread;
static volatile BOOL EncryptionSetupThreadAbortRequested;
static KSPIN_LOCK SetupStatusSpinLock;
static int64 SetupStatusEncryptedAreaEnd;
static BOOL TransformWaitingForIdle;
static NTSTATUS SetupResult;
NTSTATUS LoadBootArguments ()
{
NTSTATUS status = STATUS_UNSUCCESSFUL;
PHYSICAL_ADDRESS bootArgsAddr;
byte *mappedBootArgs;
bootArgsAddr.QuadPart = (TC_BOOT_LOADER_SEGMENT << 4) + TC_BOOT_LOADER_ARGS_OFFSET;
mappedBootArgs = MmMapIoSpace (bootArgsAddr, sizeof (BootArguments), MmCached);
if (!mappedBootArgs)
return STATUS_INSUFFICIENT_RESOURCES;
DumpMem (mappedBootArgs, sizeof (BootArguments));
if (TC_IS_BOOT_ARGUMENTS_SIGNATURE (mappedBootArgs))
{
BootArguments *bootArguments = (BootArguments *) mappedBootArgs;
Dump ("BootArguments at 0x%x\n", bootArgsAddr.LowPart);
if (bootArguments->BootLoaderVersion == VERSION_NUM
&& bootArguments->BootArgumentsCrc32 != GetCrc32 ((byte *) bootArguments, (int) ((byte *) &bootArguments->BootArgumentsCrc32 - (byte *) bootArguments)))
{
Dump ("BootArguments CRC incorrect\n");
TC_BUG_CHECK (STATUS_CRC_ERROR);
}
BootArgs = *bootArguments;
BootArgsValid = TRUE;
memset (bootArguments, 0, sizeof (*bootArguments));
if (BootArgs.BootLoaderVersion < 0x600)
{
BootArgs.HiddenSystemPartitionStart = 0;
BootArgs.DecoySystemPartitionStart = 0;
}
Dump ("BootLoaderVersion = %x\n", (int) BootArgs.BootLoaderVersion);
Dump ("HeaderSaltCrc32 = %x\n", (int) BootArgs.HeaderSaltCrc32);
Dump ("CryptoInfoOffset = %x\n", (int) BootArgs.CryptoInfoOffset);
Dump ("CryptoInfoLength = %d\n", (int) BootArgs.CryptoInfoLength);
Dump ("HiddenSystemPartitionStart = %I64u\n", BootArgs.HiddenSystemPartitionStart);
Dump ("DecoySystemPartitionStart = %I64u\n", BootArgs.DecoySystemPartitionStart);
Dump ("BootArgumentsCrc32 = %x\n", BootArgs.BootArgumentsCrc32);
status = STATUS_SUCCESS;
}
MmUnmapIoSpace (mappedBootArgs, sizeof (BootArguments));
return status;
}
NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
{
DriveFilterExtension *Extension;
NTSTATUS status;
PDEVICE_OBJECT filterDeviceObject = NULL;
Dump ("DriveFilterAddDevice pdo=%p\n", pdo);
DriverMutexWait();
status = IoCreateDevice (driverObject, sizeof (DriveFilterExtension), NULL, FILE_DEVICE_DISK, 0, FALSE, &filterDeviceObject); // Using pdo->DeviceType instead of FILE_DEVICE_DISK induces a bug in Disk Management console on Vista
DriverMutexRelease();
if (!NT_SUCCESS (status))
{
filterDeviceObject = NULL;
goto err;
}
Extension = (DriveFilterExtension *) filterDeviceObject->DeviceExtension;
memset (Extension, 0, sizeof (DriveFilterExtension));
Extension->LowerDeviceObject = IoAttachDeviceToDeviceStack (filterDeviceObject, pdo); // IoAttachDeviceToDeviceStackSafe() is not required in AddDevice routine and is also unavailable on Windows 2000 SP4
if (!Extension->LowerDeviceObject)
{
status = STATUS_DEVICE_REMOVED;
goto err;
}
Extension->IsDriveFilterDevice = Extension->Queue.IsFilterDevice = TRUE;
Extension->DeviceObject = Extension->Queue.DeviceObject = filterDeviceObject;
Extension->Pdo = pdo;
Extension->Queue.LowerDeviceObject = Extension->LowerDeviceObject;
IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0);
Extension->ConfiguredEncryptedAreaStart = -1;
Extension->ConfiguredEncryptedAreaEnd = -1;
Extension->Queue.EncryptedAreaStart = -1;
Extension->Queue.EncryptedAreaEnd = -1;
if (!BootDriveFound)
{
status = EncryptedIoQueueStart (&Extension->Queue, NULL);
if (!NT_SUCCESS (status))
goto err;
Extension->QueueStarted = TRUE;
}
filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
DeviceFilterActive = TRUE;
return status;
err:
if (filterDeviceObject)
{
if (Extension->LowerDeviceObject)
IoDetachDevice (Extension->LowerDeviceObject);
DriverMutexWait();
IoDeleteDevice (filterDeviceObject);
DriverMutexRelease();
}
return status;
}
static void DismountDrive (DriveFilterExtension *Extension)
{
Dump ("Dismounting drive\n");
ASSERT (Extension->DriveMounted);
crypto_close (Extension->Queue.CryptoInfo);
Extension->Queue.CryptoInfo = NULL;
crypto_close (Extension->HeaderCryptoInfo);
Extension->HeaderCryptoInfo = NULL;
Extension->DriveMounted = FALSE;
}
static NTSTATUS MountDrive (DriveFilterExtension *Extension, Password *password, uint32 *headerSaltCrc32)
{
BOOL hiddenVolume = (BootArgs.HiddenSystemPartitionStart != 0);
int64 hiddenHeaderOffset = BootArgs.HiddenSystemPartitionStart + TC_HIDDEN_VOLUME_HEADER_OFFSET;
NTSTATUS status;
LARGE_INTEGER offset;
char *header;
Dump ("MountDrive pdo=%p\n", Extension->Pdo);
ASSERT (KeGetCurrentIrql() == PASSIVE_LEVEL);
header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!header)
return STATUS_INSUFFICIENT_RESOURCES;
offset.QuadPart = hiddenVolume ? hiddenHeaderOffset : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
Dump ("Reading volume header at %I64u\n", offset.QuadPart);
status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!NT_SUCCESS (status))
{
Dump ("TCReadDevice error %x\n", status);
goto ret;
}
if (headerSaltCrc32)
{
uint32 saltCrc = GetCrc32 (header, PKCS5_SALT_SIZE);
if (saltCrc != *headerSaltCrc32)
{
status = STATUS_UNSUCCESSFUL;
goto ret;
}
Extension->VolumeHeaderSaltCrc32 = saltCrc;
}
Extension->HeaderCryptoInfo = crypto_open();
if (!Extension->HeaderCryptoInfo)
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto ret;
}
if (VolumeReadHeader (!hiddenVolume, header, password, &Extension->Queue.CryptoInfo, Extension->HeaderCryptoInfo) == 0)
{
// Header decrypted
status = STATUS_SUCCESS;
Dump ("Header decrypted\n");
if (Extension->Queue.CryptoInfo->hiddenVolume)
{
int64 hiddenPartitionOffset = BootArgs.HiddenSystemPartitionStart;
Dump ("Hidden volume start offset = %I64d\n", Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + hiddenPartitionOffset);
Extension->HiddenSystem = TRUE;
Extension->Queue.RemapEncryptedArea = TRUE;
Extension->Queue.RemappedAreaOffset = hiddenPartitionOffset + Extension->Queue.CryptoInfo->EncryptedAreaStart.Value - BootArgs.DecoySystemPartitionStart;
Extension->Queue.RemappedAreaDataUnitOffset = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value / ENCRYPTION_DATA_UNIT_SIZE - BootArgs.DecoySystemPartitionStart / ENCRYPTION_DATA_UNIT_SIZE;
Extension->Queue.CryptoInfo->EncryptedAreaStart.Value = BootArgs.DecoySystemPartitionStart;
if (Extension->Queue.CryptoInfo->VolumeSize.Value > hiddenPartitionOffset - BootArgs.DecoySystemPartitionStart)
TC_THROW_FATAL_EXCEPTION;
Dump ("RemappedAreaOffset = %I64d\n", Extension->Queue.RemappedAreaOffset);
Dump ("RemappedAreaDataUnitOffset = %I64d\n", Extension->Queue.RemappedAreaDataUnitOffset);
}
else
{
Extension->HiddenSystem = FALSE;
Extension->Queue.RemapEncryptedArea = FALSE;
}
Extension->ConfiguredEncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value;
Extension->ConfiguredEncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->VolumeSize.Value - 1;
Extension->Queue.EncryptedAreaStart = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value;
Extension->Queue.EncryptedAreaEnd = Extension->Queue.CryptoInfo->EncryptedAreaStart.Value + Extension->Queue.CryptoInfo->EncryptedAreaLength.Value - 1;
if (Extension->Queue.CryptoInfo->EncryptedAreaLength.Value == 0)
{
Extension->Queue.EncryptedAreaStart = -1;
Extension->Queue.EncryptedAreaEnd = -1;
}
Dump ("Loaded: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd);
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);
// Erase boot loader scheduled keys
if (BootArgs.CryptoInfoLength > 0)
{
PHYSICAL_ADDRESS cryptoInfoAddress;
byte *mappedCryptoInfo;
cryptoInfoAddress.QuadPart = (TC_BOOT_LOADER_SEGMENT << 4) + BootArgs.CryptoInfoOffset;
mappedCryptoInfo = MmMapIoSpace (cryptoInfoAddress, BootArgs.CryptoInfoLength, MmCached);
if (mappedCryptoInfo)
{
Dump ("Wiping memory %x %d\n", cryptoInfoAddress.LowPart, BootArgs.CryptoInfoLength);
memset (mappedCryptoInfo, 0, BootArgs.CryptoInfoLength);
MmUnmapIoSpace (mappedCryptoInfo, BootArgs.CryptoInfoLength);
}
}
BootDriveFilterExtension = Extension;
BootDriveFound = Extension->BootDrive = Extension->DriveMounted = Extension->VolumeHeaderPresent = TRUE;
burn (&BootArgs.BootPassword, sizeof (BootArgs.BootPassword));
// Get drive length
status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &BootDriveLength, sizeof (BootDriveLength));
if (!NT_SUCCESS (status))
{
Dump ("Failed to get drive length - error %x\n", status);
BootDriveLength.QuadPart = 0;
}
if (!HibernationDriverFilterActive)
StartHibernationDriverFilter();
}
else
{
Dump ("Header not decrypted\n");
crypto_close (Extension->HeaderCryptoInfo);
Extension->HeaderCryptoInfo = NULL;
status = STATUS_UNSUCCESSFUL;
}
ret:
TCfree (header);
return status;
}
static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension)
{
NTSTATUS status = STATUS_SUCCESS;
LARGE_INTEGER offset;
byte *header;
header = TCalloc (TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!header)
return STATUS_INSUFFICIENT_RESOURCES;
offset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
status = TCReadDevice (Extension->LowerDeviceObject, header, offset, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
if (!NT_SUCCESS (status))
{
Dump ("TCReadDevice error %x", status);
goto ret;
}
Dump ("Saving: ConfiguredEncryptedAreaStart=%I64d (%I64d) ConfiguredEncryptedAreaEnd=%I64d (%I64d)\n", Extension->ConfiguredEncryptedAreaStart / 1024 / 1024, Extension->ConfiguredEncryptedAreaStart, Extension->ConfiguredEncryptedAreaEnd / 1024 / 1024, Extension->ConfiguredEncryptedAreaEnd);
Dump ("Saving: EncryptedAreaStart=%I64d (%I64d) EncryptedAreaEnd=%I64d (%I64d)\n", Extension->Queue.EncryptedAreaStart / 1024 / 1024, Extension->Queue.EncryptedAreaStart, Extension->Queue.EncryptedAreaEnd / 1024 / 1024, Extension->Queue.EncryptedAreaEnd);
if (Extension->Queue.EncryptedAreaStart == -1 || Extension->Queue.EncryptedAreaEnd == -1
|| Extension->Queue.EncryptedAreaEnd <= Extension->Queue.EncryptedAreaStart)
{
if (SetupRequest.SetupMode == SetupDecryption)
{
memset (header, 0, TC_BOOT_ENCRYPTION_VOLUME_HEADER_SIZE);
Extension->VolumeHeaderPresent = FALSE;
}
}
else
{
uint32 headerCrc32;
uint64 encryptedAreaLength = Extension->Queue.EncryptedAreaEnd + 1 - Extension->Queue.EncryptedAreaStart;
byte *fieldPos = header + TC_HEADER_OFFSET_ENCRYPTED_AREA_LENGTH;
DecryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo);
if (GetHeaderField32 (header, TC_HEADER_OFFSET_MAGIC) != 0x54525545)
{
Dump ("Header not decrypted");
status = STATUS_UNSUCCESSFUL;
goto ret;
}
mputInt64 (fieldPos, encryptedAreaLength);
headerCrc32 = GetCrc32 (header + TC_HEADER_OFFSET_MAGIC, TC_HEADER_OFFSET_HEADER_CRC - TC_HEADER_OFFSET_MAGIC);
fieldPos = header + TC_HEADER_OFFSET_HEADER_CRC;
mputLong (fieldPos, headerCrc32);
EncryptBuffer (header + HEADER_ENCRYPTED_DATA_OFFSET, HEADER_ENCRYPTED_DATA_SIZE, Extension->HeaderCryptoInfo);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -