mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2025-11-12 19:38:26 -06:00
Add original TrueCrypt 7.1a sources
This commit is contained in:
162
src/Driver/BuildDriver.cmd
Normal file
162
src/Driver/BuildDriver.cmd
Normal file
@@ -0,0 +1,162 @@
|
||||
::
|
||||
:: Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
::
|
||||
:: Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
:: the file License.txt included in TrueCrypt binary and source code distribution
|
||||
:: packages.
|
||||
::
|
||||
|
||||
:: Usage: BuildDriver <-build|-rebuild|-clean> <-release|-debug> <-x86|-x64> <dir1> [dir2] ...
|
||||
|
||||
@echo off
|
||||
set TC_ARG_CMD=%~1
|
||||
shift
|
||||
set TC_ARG_TYPE=%~1
|
||||
shift
|
||||
set TC_ARG_ARCH=%~1
|
||||
shift
|
||||
|
||||
|
||||
:: Windows Driver Kit build number
|
||||
|
||||
set TC_WINDDK_BUILD=7600.16385.1
|
||||
|
||||
|
||||
:: Check for spaces in the current directory path
|
||||
|
||||
cd | find " " >NUL:
|
||||
|
||||
if %ERRORLEVEL% == 0 (
|
||||
echo BuildDriver.cmd: error: MS Build does not support building of projects stored in a path containing spaces. >&2
|
||||
exit /B 1
|
||||
)
|
||||
|
||||
|
||||
:: Build options
|
||||
|
||||
set TC_C_DEFINES=-D_WIN32 -DTC_WINDOWS_DRIVER
|
||||
set TC_C_FLAGS=-nologo -I..
|
||||
set TC_C_WARNING_LEVEL=-W4
|
||||
set TC_C_DISABLED_WARNINGS=-wd4057 -wd4100 -wd4127 -wd4152 -wd4201 -wd4701 -wd4702 -wd4706
|
||||
set TC_LIBRARIAN_FLAGS=-nologo
|
||||
set TC_LINKER_FLAGS=-nologo
|
||||
set TC_TEST_SIGN=0
|
||||
|
||||
|
||||
:: Windows Driver Kit root
|
||||
|
||||
set TC_WINDDK_ROOT=%SYSTEMDRIVE%\WinDDK\%TC_WINDDK_BUILD%
|
||||
if exist "%TC_WINDDK_ROOT%\bin\setenv.bat" goto ddk_found
|
||||
|
||||
set TC_WINDDK_ROOT=%WINDDK_ROOT%\%TC_WINDDK_BUILD%
|
||||
if exist "%TC_WINDDK_ROOT%\bin\setenv.bat" goto ddk_found
|
||||
|
||||
set TC_WINDDK_ROOT=%WINDDK_ROOT%
|
||||
if exist "%TC_WINDDK_ROOT%\bin\setenv.bat" goto ddk_found
|
||||
|
||||
echo BuildDriver.cmd: error: Windows Driver Development Kit not found in the default directory. Set WINDDK_ROOT environment variable to point to your Windows DDK installation directory. >&2
|
||||
exit /B 1
|
||||
|
||||
:ddk_found
|
||||
|
||||
|
||||
:: CPU architecture
|
||||
|
||||
if "%TC_ARG_ARCH%"=="-x64" (
|
||||
set TC_BUILD_ARCH=x64 WNET
|
||||
set TC_BUILD_ARCH_DIR=amd64
|
||||
set TC_ARCH=x64
|
||||
set TC_ARCH_SUFFIX=-x64
|
||||
set TC_C_DISABLED_WARNINGS=%TC_C_DISABLED_WARNINGS% -wd4328 -wd4366
|
||||
set TC_LINKER_FLAGS=%TC_LINKER_FLAGS% -LTCG
|
||||
if defined TC_KERNEL_TEST_CERTIFICATE_NAME set TC_TEST_SIGN=1
|
||||
) else (
|
||||
set TC_BUILD_ARCH=WXP
|
||||
set TC_BUILD_ARCH_DIR=i386
|
||||
set TC_ARCH=x86
|
||||
set TC_ARCH_SUFFIX=
|
||||
)
|
||||
|
||||
|
||||
:: Build type
|
||||
|
||||
if "%TC_ARG_TYPE%"=="-debug" (
|
||||
set TC_BUILD_TYPE=chk
|
||||
set TC_C_DEFINES=%TC_C_DEFINES% -DDEBUG -D_DEBUG
|
||||
set TC_BUILD_ALT_DIR=_driver_debug
|
||||
set TC_COPY_DIR="..\Debug"
|
||||
) else (
|
||||
set TC_BUILD_TYPE=fre
|
||||
set TC_BUILD_ALT_DIR=_driver_release
|
||||
set TC_COPY_DIR="..\Release"
|
||||
set TC_TEST_SIGN=0
|
||||
)
|
||||
|
||||
|
||||
:: WDK environment
|
||||
|
||||
pushd .
|
||||
call %TC_WINDDK_ROOT%\bin\setenv %TC_WINDDK_ROOT% %TC_BUILD_TYPE% %TC_BUILD_ARCH% no_oacr || exit /B %errorlevel%
|
||||
popd
|
||||
|
||||
|
||||
:: Build
|
||||
|
||||
if "%TC_ARG_CMD%"=="-rebuild" (set TC_BUILD_OPTS=-c -Z)
|
||||
|
||||
pushd .
|
||||
:build_dirs
|
||||
|
||||
if "%~1"=="" goto done
|
||||
cd /D "%~1" || exit /B %errorlevel%
|
||||
|
||||
if "%TC_ARG_CMD%"=="-clean" (
|
||||
rd /s /q obj%TC_BUILD_ALT_DIR%\%TC_BUILD_ARCH_DIR% 2>NUL:
|
||||
rd /q obj%TC_BUILD_ALT_DIR% 2>NUL:
|
||||
) else (
|
||||
|
||||
set USER_C_FLAGS=%TC_C_FLAGS% %TC_C_DISABLED_WARNINGS% -FAcs -Fa%~1\obj%TC_BUILD_ALT_DIR%\%TC_BUILD_ARCH_DIR%\
|
||||
set MSC_WARNING_LEVEL=%TC_C_WARNING_LEVEL%
|
||||
set C_DEFINES=%TC_C_DEFINES%
|
||||
set RCOPTIONS=/I %MFC_INC_PATH%
|
||||
set LIBRARIAN_FLAGS=%TC_LIBRARIAN_FLAGS%
|
||||
set LINKER_FLAGS=%TC_LINKER_FLAGS%
|
||||
set BUILD_ALT_DIR=%TC_BUILD_ALT_DIR%
|
||||
|
||||
build %TC_BUILD_OPTS% -w -nmake /S -nmake /C 2>build_errors.log 1>&2
|
||||
|
||||
if errorlevel 1 (
|
||||
type build_errors.log
|
||||
type build_errors_asm.log 2>NUL:
|
||||
exit /B 1
|
||||
)
|
||||
del /q build_errors.log build_errors_asm.log build%BUILD_ALT_DIR%.* 2>NUL:
|
||||
)
|
||||
|
||||
shift
|
||||
|
||||
goto build_dirs
|
||||
:done
|
||||
popd
|
||||
|
||||
|
||||
if "%TC_ARG_CMD%"=="-clean" exit /B 0
|
||||
|
||||
md "%TC_COPY_DIR%\Setup Files" >NUL: 2>NUL:
|
||||
copy /B /Y obj%TC_BUILD_ALT_DIR%\%TC_BUILD_ARCH_DIR%\truecrypt.sys "%TC_COPY_DIR%\Setup Files\truecrypt%TC_ARCH_SUFFIX%.sys" >NUL:
|
||||
|
||||
if errorlevel 1 (
|
||||
echo BuildDriver.cmd: error: Cannot copy target. >&2
|
||||
exit /B 1
|
||||
)
|
||||
|
||||
if %TC_TEST_SIGN% equ 1 (
|
||||
signtool sign /s "%TC_KERNEL_TEST_CERTIFICATE_STORE%" /n "%TC_KERNEL_TEST_CERTIFICATE_NAME%" "%TC_COPY_DIR%\Setup Files\truecrypt%TC_ARCH_SUFFIX%.sys" >NUL:
|
||||
|
||||
if errorlevel 1 (
|
||||
echo BuildDriver.cmd: error: Cannot test-sign target. >&2
|
||||
exit /B 1
|
||||
)
|
||||
)
|
||||
|
||||
exit /B 0
|
||||
1942
src/Driver/DriveFilter.c
Normal file
1942
src/Driver/DriveFilter.c
Normal file
File diff suppressed because it is too large
Load Diff
85
src/Driver/DriveFilter.h
Normal file
85
src/Driver/DriveFilter.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2008-2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_DRIVER_DRIVE_FILTER
|
||||
#define TC_HEADER_DRIVER_DRIVE_FILTER
|
||||
|
||||
#include "TCdefs.h"
|
||||
#include "Boot/Windows/BootCommon.h"
|
||||
#include "EncryptedIoQueue.h"
|
||||
|
||||
typedef struct _DriveFilterExtension
|
||||
{
|
||||
BOOL bRootDevice;
|
||||
BOOL IsVolumeDevice;
|
||||
BOOL IsDriveFilterDevice;
|
||||
BOOL IsVolumeFilterDevice;
|
||||
uint64 MagicNumber;
|
||||
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDEVICE_OBJECT LowerDeviceObject;
|
||||
PDEVICE_OBJECT Pdo;
|
||||
|
||||
ULONG SystemStorageDeviceNumber;
|
||||
BOOL SystemStorageDeviceNumberValid;
|
||||
|
||||
int64 ConfiguredEncryptedAreaStart;
|
||||
int64 ConfiguredEncryptedAreaEnd;
|
||||
|
||||
uint32 VolumeHeaderSaltCrc32;
|
||||
EncryptedIoQueue Queue;
|
||||
|
||||
BOOL BootDrive;
|
||||
BOOL VolumeHeaderPresent;
|
||||
BOOL DriveMounted;
|
||||
|
||||
KEVENT MountWorkItemCompletedEvent;
|
||||
|
||||
CRYPTO_INFO *HeaderCryptoInfo;
|
||||
BOOL HiddenSystem;
|
||||
|
||||
} DriveFilterExtension;
|
||||
|
||||
#define TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER 0x5452554542455854
|
||||
|
||||
extern BOOL BootArgsValid;
|
||||
extern BootArguments BootArgs;
|
||||
extern PKTHREAD EncryptionSetupThread;
|
||||
extern PKTHREAD DecoySystemWipeThread;
|
||||
|
||||
NTSTATUS AbortBootEncryptionSetup ();
|
||||
NTSTATUS DriveFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo);
|
||||
NTSTATUS DriveFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
void GetBootDriveVolumeProperties (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
void GetBootEncryptionAlgorithmName (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
void GetBootEncryptionStatus (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
void GetBootLoaderVersion (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
NTSTATUS GetSetupResult ();
|
||||
DriveFilterExtension *GetBootDriveFilterExtension ();
|
||||
CRYPTO_INFO *GetSystemDriveCryptoInfo ();
|
||||
BOOL IsBootDriveMounted ();
|
||||
BOOL IsBootEncryptionSetupInProgress ();
|
||||
BOOL IsHiddenSystemRunning ();
|
||||
NTSTATUS LoadBootArguments ();
|
||||
static NTSTATUS SaveDriveVolumeHeader (DriveFilterExtension *Extension);
|
||||
NTSTATUS StartBootEncryptionSetup (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
void ReopenBootVolumeHeader (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
NTSTATUS StartDecoySystemWipe (PDEVICE_OBJECT DeviceObject, PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
void StartLegacyHibernationDriverFilter ();
|
||||
NTSTATUS AbortDecoySystemWipe ();
|
||||
BOOL IsDecoySystemWipeInProgress();
|
||||
NTSTATUS GetDecoySystemWipeResult();
|
||||
void GetDecoySystemWipeStatus (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
uint64 GetBootDriveLength ();
|
||||
NTSTATUS WriteBootDriveSector (PIRP irp, PIO_STACK_LOCATION irpSp);
|
||||
|
||||
#define TC_ENCRYPTION_SETUP_IO_BLOCK_SIZE (1536 * 1024)
|
||||
#define TC_ENCRYPTION_SETUP_HEADER_UPDATE_THRESHOLD (64 * 1024 * 1024)
|
||||
#define TC_HIBERNATION_WRITE_BUFFER_SIZE (128 * 1024)
|
||||
|
||||
#endif // TC_HEADER_DRIVER_DRIVE_FILTER
|
||||
101
src/Driver/Driver.rc
Normal file
101
src/Driver/Driver.rc
Normal file
@@ -0,0 +1,101 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 7,1,1,0
|
||||
PRODUCTVERSION 7,1,1,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x4L
|
||||
FILETYPE 0x3L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", "TrueCrypt Foundation"
|
||||
VALUE "FileDescription", "TrueCrypt Driver"
|
||||
VALUE "FileVersion", "7.1a"
|
||||
VALUE "LegalTrademarks", "TrueCrypt"
|
||||
VALUE "OriginalFilename", "truecrypt.sys"
|
||||
VALUE "ProductName", "TrueCrypt"
|
||||
VALUE "ProductVersion", "7.1a"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
414
src/Driver/Driver.vcproj
Normal file
414
src/Driver/Driver.vcproj
Normal file
@@ -0,0 +1,414 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="Driver"
|
||||
ProjectGUID="{EF5EF444-18D0-40D7-8DFA-775EC4448602}"
|
||||
RootNamespace="Driver"
|
||||
Keyword="MakeFileProj"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="echo ------ Building truecrypt.sys: Debug x86 ------
cmd.exe /c BuildDriver.cmd -build -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Building truecrypt.sys: Debug x64 ------
BuildDriver.cmd -build -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="echo ------ Rebuilding truecrypt.sys: Debug x86 ------
cmd.exe /c BuildDriver.cmd -rebuild -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Rebuilding truecrypt.sys: Debug x64 ------
BuildDriver.cmd -rebuild -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="echo ------ Cleaning truecrypt.sys: Debug x86 ------
cmd.exe /c BuildDriver.cmd -clean -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Cleaning truecrypt.sys: Debug x64 ------
BuildDriver.cmd -clean -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output=""
|
||||
PreprocessorDefinitions="DEBUG;_DEBUG;TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="echo ------ Building truecrypt.sys: Release x86 ------
cmd.exe /c BuildDriver.cmd -build -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Building truecrypt.sys: Release x64 ------
BuildDriver.cmd -build -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="echo ------ Rebuilding truecrypt.sys: Release x86 ------
cmd.exe /c BuildDriver.cmd -rebuild -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Rebuilding truecrypt.sys: Release x64 ------
BuildDriver.cmd -rebuild -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="echo ------ Cleaning truecrypt.sys: Release x86 ------
cmd.exe /c BuildDriver.cmd -clean -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)"
if errorlevel 1 exit %errorlevel%
echo.
echo ------ Cleaning truecrypt.sys: Release x64 ------
BuildDriver.cmd -clean -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output=""
|
||||
PreprocessorDefinitions="TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release x86|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="BuildDriver.cmd -build -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="BuildDriver.cmd -rebuild -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="BuildDriver.cmd -clean -release -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output=""
|
||||
PreprocessorDefinitions="TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug x86|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="if exist $(SolutionDir)\Mount\Debug\TrueCrypt.exe ( copy $(SolutionDir)\Mount\Debug\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\i386\TrueCrypt.exe >NUL:
) else ( copy $(SolutionDir)\Mount\Release\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\i386\TrueCrypt.exe >NUL: )

BuildDriver.cmd -build -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="if exist $(SolutionDir)\Mount\Debug\TrueCrypt.exe ( copy $(SolutionDir)\Mount\Debug\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\i386\TrueCrypt.exe >NUL:
) else ( copy $(SolutionDir)\Mount\Release\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\i386\TrueCrypt.exe >NUL: )

BuildDriver.cmd -rebuild -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="BuildDriver.cmd -clean -debug -x86 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output="$(ProjectDir)\obj_driver_debug\i386\TrueCrypt.exe"
|
||||
PreprocessorDefinitions="DEBUG;_DEBUG;TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release x64|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="BuildDriver.cmd -build -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="BuildDriver.cmd -rebuild -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="BuildDriver.cmd -clean -release -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output=""
|
||||
PreprocessorDefinitions="TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug x64|Win32"
|
||||
OutputDirectory="$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="0"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCNMakeTool"
|
||||
BuildCommandLine="if exist $(SolutionDir)\Mount\Debug\TrueCrypt.exe ( copy $(SolutionDir)\Mount\Debug\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\amd64\TrueCrypt.exe >NUL:
) else ( copy $(SolutionDir)\Mount\Release\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\amd64\TrueCrypt.exe >NUL: )

BuildDriver.cmd -build -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
ReBuildCommandLine="if exist $(SolutionDir)\Mount\Debug\TrueCrypt.exe ( copy $(SolutionDir)\Mount\Debug\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\amd64\TrueCrypt.exe >NUL:
) else ( copy $(SolutionDir)\Mount\Release\TrueCrypt.exe $(ProjectDir)\obj_driver_debug\amd64\TrueCrypt.exe >NUL: )

BuildDriver.cmd -rebuild -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
CleanCommandLine="BuildDriver.cmd -clean -debug -x64 "$(SolutionDir)\Common" "$(SolutionDir)\Crypto" "$(ProjectDir)""
|
||||
Output="$(ProjectDir)\obj_driver_debug\amd64\TrueCrypt.exe"
|
||||
PreprocessorDefinitions="DEBUG;_DEBUG;TC_WINDOWS_DRIVER"
|
||||
IncludeSearchPath=""$(ProjectDir)";"$(SolutionDir)";"$(SolutionDir)\Common";"$(SolutionDir)\Crypto";"$(WINDDK_ROOT)\inc\ddk";"$(WINDDK_ROOT)\inc\api""
|
||||
ForcedIncludes=""
|
||||
AssemblySearchPath=""
|
||||
ForcedUsingAssemblies=""
|
||||
CompileAsManaged=""
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\DriveFilter.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DumpFilter.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\EncryptedIoQueue.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Ntdriver.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Ntvol.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\VolumeFilter.c"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Common"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\Common\Cache.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Crc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Crypto.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\EncryptionThreadPool.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Endian.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\GfMul.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Pkcs5.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Tests.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Volumes.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Wipe.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Xts.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Crypto"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\Crypto\Aes_hw_cpu.asm"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Aes_x64.asm"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Aes_x86.asm"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Aeskey.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Aestab.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Blowfish.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Cast.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Des.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Rmd160.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Serpent.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Sha1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Sha2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Twofish.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Whirlpool.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\Common\Apidrvr.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Cache.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Common.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DriveFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\DumpFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\EncryptedIoQueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\EncryptionThreadPool.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\GfMul.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Ntdriver.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Ntvol.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Tcdefs.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\VolumeFilter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Volumes.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Wipe.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Xts.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\Driver.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Build Files"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\BuildDriver.cmd"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Sources"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Common"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\Common\Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Common\Sources"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Crypto"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\Crypto\Makefile"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Makefile.inc"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\Crypto\Sources"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
244
src/Driver/DumpFilter.c
Normal file
244
src/Driver/DumpFilter.c
Normal file
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
Copyright (c) 2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#include "DumpFilter.h"
|
||||
#include "DriveFilter.h"
|
||||
#include "Ntdriver.h"
|
||||
#include "Tests.h"
|
||||
|
||||
static DriveFilterExtension *BootDriveFilterExtension = NULL;
|
||||
static LARGE_INTEGER DumpPartitionOffset;
|
||||
static byte *WriteFilterBuffer = NULL;
|
||||
static SIZE_T WriteFilterBufferSize;
|
||||
|
||||
|
||||
NTSTATUS DumpFilterEntry (PFILTER_EXTENSION filterExtension, PFILTER_INITIALIZATION_DATA filterInitData)
|
||||
{
|
||||
GetSystemDriveDumpConfigRequest dumpConfig;
|
||||
PHYSICAL_ADDRESS highestAcceptableWriteBufferAddr;
|
||||
STORAGE_DEVICE_NUMBER storageDeviceNumber;
|
||||
PARTITION_INFORMATION partitionInfo;
|
||||
LONG version;
|
||||
NTSTATUS status;
|
||||
|
||||
Dump ("DumpFilterEntry type=%d\n", filterExtension->DumpType);
|
||||
|
||||
filterInitData->MajorVersion = DUMP_FILTER_MAJOR_VERSION;
|
||||
filterInitData->MinorVersion = DUMP_FILTER_MINOR_VERSION;
|
||||
filterInitData->Flags |= DUMP_FILTER_CRITICAL;
|
||||
|
||||
// Check driver version of the main device
|
||||
status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_DRIVER_VERSION, NULL, 0, &version, sizeof (version));
|
||||
if (!NT_SUCCESS (status))
|
||||
goto err;
|
||||
|
||||
if (version != VERSION_NUM)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Get dump configuration from the main device
|
||||
status = TCDeviceIoControl (NT_ROOT_PREFIX, TC_IOCTL_GET_SYSTEM_DRIVE_DUMP_CONFIG, NULL, 0, &dumpConfig, sizeof (dumpConfig));
|
||||
if (!NT_SUCCESS (status))
|
||||
goto err;
|
||||
|
||||
BootDriveFilterExtension = dumpConfig.BootDriveFilterExtension;
|
||||
|
||||
if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
|
||||
{
|
||||
status = STATUS_CRC_ERROR;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// KeSaveFloatingPointState() may generate a bug check during crash dump
|
||||
#if !defined (_WIN64)
|
||||
if (filterExtension->DumpType == DumpTypeCrashdump)
|
||||
dumpConfig.HwEncryptionEnabled = FALSE;
|
||||
#endif
|
||||
|
||||
EnableHwEncryption (dumpConfig.HwEncryptionEnabled);
|
||||
|
||||
if (!AutoTestAlgorithms())
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Check dump volume is located on the system drive
|
||||
status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
|
||||
if (!NT_SUCCESS (status))
|
||||
goto err;
|
||||
|
||||
if (!BootDriveFilterExtension->SystemStorageDeviceNumberValid)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (storageDeviceNumber.DeviceNumber != BootDriveFilterExtension->SystemStorageDeviceNumber)
|
||||
{
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Check dump volume is located within the scope of system encryption
|
||||
status = SendDeviceIoControlRequest (filterExtension->DeviceObject, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, &partitionInfo, sizeof (partitionInfo));
|
||||
if (!NT_SUCCESS (status))
|
||||
goto err;
|
||||
|
||||
DumpPartitionOffset = partitionInfo.StartingOffset;
|
||||
|
||||
if (DumpPartitionOffset.QuadPart < BootDriveFilterExtension->ConfiguredEncryptedAreaStart
|
||||
|| DumpPartitionOffset.QuadPart > BootDriveFilterExtension->ConfiguredEncryptedAreaEnd)
|
||||
{
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// Allocate buffer for encryption
|
||||
if (filterInitData->MaxPagesPerWrite == 0)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
WriteFilterBufferSize = filterInitData->MaxPagesPerWrite * PAGE_SIZE;
|
||||
|
||||
#ifdef _WIN64
|
||||
highestAcceptableWriteBufferAddr.QuadPart = 0x7FFffffFFFFLL;
|
||||
#else
|
||||
highestAcceptableWriteBufferAddr.QuadPart = 0xffffFFFFLL;
|
||||
#endif
|
||||
|
||||
WriteFilterBuffer = MmAllocateContiguousMemory (WriteFilterBufferSize, highestAcceptableWriteBufferAddr);
|
||||
if (!WriteFilterBuffer)
|
||||
{
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto err;
|
||||
}
|
||||
|
||||
filterInitData->DumpStart = DumpFilterStart;
|
||||
filterInitData->DumpWrite = DumpFilterWrite;
|
||||
filterInitData->DumpFinish = DumpFilterFinish;
|
||||
filterInitData->DumpUnload = DumpFilterUnload;
|
||||
|
||||
Dump ("Dump filter loaded type=%d\n", filterExtension->DumpType);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
err:
|
||||
Dump ("DumpFilterEntry error %x\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DumpFilterStart (PFILTER_EXTENSION filterExtension)
|
||||
{
|
||||
Dump ("DumpFilterStart type=%d\n", filterExtension->DumpType);
|
||||
|
||||
if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
|
||||
TC_BUG_CHECK (STATUS_CRC_ERROR);
|
||||
|
||||
return BootDriveFilterExtension->DriveMounted ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEGER diskWriteOffset, PMDL writeMdl)
|
||||
{
|
||||
ULONG dataLength = MmGetMdlByteCount (writeMdl);
|
||||
uint64 offset = DumpPartitionOffset.QuadPart + diskWriteOffset->QuadPart;
|
||||
uint64 intersectStart;
|
||||
uint32 intersectLength;
|
||||
PVOID writeBuffer;
|
||||
CSHORT origMdlFlags;
|
||||
|
||||
if (BootDriveFilterExtension->MagicNumber != TC_BOOT_DRIVE_FILTER_EXTENSION_MAGIC_NUMBER)
|
||||
TC_BUG_CHECK (STATUS_CRC_ERROR);
|
||||
|
||||
if (BootDriveFilterExtension->Queue.EncryptedAreaEndUpdatePending) // Hibernation should always abort the setup thread
|
||||
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
|
||||
|
||||
if (BootDriveFilterExtension->Queue.EncryptedAreaStart == -1 || BootDriveFilterExtension->Queue.EncryptedAreaEnd == -1)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
if (dataLength > WriteFilterBufferSize)
|
||||
TC_BUG_CHECK (STATUS_BUFFER_OVERFLOW); // Bug check is required as returning an error does not prevent data from being written to disk
|
||||
|
||||
if ((dataLength & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
|
||||
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
|
||||
|
||||
if ((offset & (ENCRYPTION_DATA_UNIT_SIZE - 1)) != 0)
|
||||
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
|
||||
|
||||
writeBuffer = MmGetSystemAddressForMdlSafe (writeMdl, HighPagePriority);
|
||||
if (!writeBuffer)
|
||||
TC_BUG_CHECK (STATUS_INSUFFICIENT_RESOURCES);
|
||||
|
||||
memcpy (WriteFilterBuffer, writeBuffer, dataLength);
|
||||
|
||||
GetIntersection (offset,
|
||||
dataLength,
|
||||
BootDriveFilterExtension->Queue.EncryptedAreaStart,
|
||||
BootDriveFilterExtension->Queue.EncryptedAreaEnd,
|
||||
&intersectStart,
|
||||
&intersectLength);
|
||||
|
||||
if (intersectLength > 0)
|
||||
{
|
||||
UINT64_STRUCT dataUnit;
|
||||
dataUnit.Value = intersectStart / ENCRYPTION_DATA_UNIT_SIZE;
|
||||
|
||||
if (BootDriveFilterExtension->Queue.RemapEncryptedArea)
|
||||
{
|
||||
diskWriteOffset->QuadPart += BootDriveFilterExtension->Queue.RemappedAreaOffset;
|
||||
dataUnit.Value += BootDriveFilterExtension->Queue.RemappedAreaDataUnitOffset;
|
||||
}
|
||||
|
||||
EncryptDataUnitsCurrentThread (WriteFilterBuffer + (intersectStart - offset),
|
||||
&dataUnit,
|
||||
intersectLength / ENCRYPTION_DATA_UNIT_SIZE,
|
||||
BootDriveFilterExtension->Queue.CryptoInfo);
|
||||
}
|
||||
|
||||
origMdlFlags = writeMdl->MdlFlags;
|
||||
|
||||
MmInitializeMdl (writeMdl, WriteFilterBuffer, dataLength);
|
||||
MmBuildMdlForNonPagedPool (writeMdl);
|
||||
|
||||
// Instead of using MmGetSystemAddressForMdlSafe(), some buggy custom storage drivers may directly test MDL_MAPPED_TO_SYSTEM_VA flag,
|
||||
// disregarding the fact that other MDL flags may be set by the system or a dump filter (e.g. MDL_SOURCE_IS_NONPAGED_POOL flag only).
|
||||
// Therefore, to work around this issue, the original flags will be restored even if they do not match the new MDL.
|
||||
// MS BitLocker also uses this hack/workaround (it should be safe to use until the MDL structure is changed).
|
||||
|
||||
writeMdl->MdlFlags = origMdlFlags;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DumpFilterFinish (PFILTER_EXTENSION filterExtension)
|
||||
{
|
||||
Dump ("DumpFilterFinish type=%d\n", filterExtension->DumpType);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension)
|
||||
{
|
||||
Dump ("DumpFilterUnload type=%d\n", filterExtension->DumpType);
|
||||
|
||||
if (WriteFilterBuffer)
|
||||
{
|
||||
memset (WriteFilterBuffer, 0, WriteFilterBufferSize);
|
||||
MmFreeContiguousMemory (WriteFilterBuffer);
|
||||
WriteFilterBuffer = NULL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
21
src/Driver/DumpFilter.h
Normal file
21
src/Driver/DumpFilter.h
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright (c) 2010 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_DRIVER_DUMP_FILTER
|
||||
#define TC_HEADER_DRIVER_DUMP_FILTER
|
||||
|
||||
#include "Tcdefs.h"
|
||||
#include <ntdddump.h>
|
||||
|
||||
NTSTATUS DumpFilterEntry (PFILTER_EXTENSION filterExtension, PFILTER_INITIALIZATION_DATA filterInitData);
|
||||
static NTSTATUS DumpFilterStart (PFILTER_EXTENSION filterExtension);
|
||||
static NTSTATUS DumpFilterWrite (PFILTER_EXTENSION filterExtension, PLARGE_INTEGER diskWriteOffset, PMDL writeMdl);
|
||||
static NTSTATUS DumpFilterFinish (PFILTER_EXTENSION filterExtension);
|
||||
static NTSTATUS DumpFilterUnload (PFILTER_EXTENSION filterExtension);
|
||||
|
||||
#endif // TC_HEADER_DRIVER_DUMP_FILTER
|
||||
1008
src/Driver/EncryptedIoQueue.c
Normal file
1008
src/Driver/EncryptedIoQueue.c
Normal file
File diff suppressed because it is too large
Load Diff
161
src/Driver/EncryptedIoQueue.h
Normal file
161
src/Driver/EncryptedIoQueue.h
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright (c) 2008-2009 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE
|
||||
#define TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE
|
||||
|
||||
#include "TCdefs.h"
|
||||
#include "Apidrvr.h"
|
||||
|
||||
#if 0
|
||||
# define TC_TRACE_IO_QUEUE
|
||||
#endif
|
||||
|
||||
#define TC_ENC_IO_QUEUE_MAX_FRAGMENT_SIZE (256 * 1024)
|
||||
|
||||
#define TC_ENC_IO_QUEUE_PREALLOCATED_ITEM_COUNT 8
|
||||
#define TC_ENC_IO_QUEUE_PREALLOCATED_IO_REQUEST_COUNT 16
|
||||
|
||||
|
||||
typedef struct EncryptedIoQueueBufferStruct
|
||||
{
|
||||
struct EncryptedIoQueueBufferStruct *NextBuffer;
|
||||
|
||||
void *Address;
|
||||
ULONG Size;
|
||||
BOOL InUse;
|
||||
|
||||
} EncryptedIoQueueBuffer;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
|
||||
KMUTEX BufferPoolMutex;
|
||||
EncryptedIoQueueBuffer *FirstPoolBuffer;
|
||||
|
||||
CRYPTO_INFO *CryptoInfo;
|
||||
|
||||
// File-handle-based IO
|
||||
HANDLE HostFileHandle;
|
||||
int64 VirtualDeviceLength;
|
||||
SECURITY_CLIENT_CONTEXT *SecurityClientContext;
|
||||
|
||||
// Filter device
|
||||
BOOL IsFilterDevice;
|
||||
PDEVICE_OBJECT LowerDeviceObject;
|
||||
int64 EncryptedAreaStart;
|
||||
volatile int64 EncryptedAreaEnd;
|
||||
volatile BOOL EncryptedAreaEndUpdatePending;
|
||||
BOOL RemapEncryptedArea;
|
||||
int64 RemappedAreaOffset;
|
||||
int64 RemappedAreaDataUnitOffset;
|
||||
IO_REMOVE_LOCK RemoveLock;
|
||||
|
||||
// Main tread
|
||||
PKTHREAD MainThread;
|
||||
LIST_ENTRY MainThreadQueue;
|
||||
KSPIN_LOCK MainThreadQueueLock;
|
||||
KEVENT MainThreadQueueNotEmptyEvent;
|
||||
|
||||
// IO thread
|
||||
PKTHREAD IoThread;
|
||||
LIST_ENTRY IoThreadQueue;
|
||||
KSPIN_LOCK IoThreadQueueLock;
|
||||
KEVENT IoThreadQueueNotEmptyEvent;
|
||||
|
||||
// Completion thread
|
||||
PKTHREAD CompletionThread;
|
||||
LIST_ENTRY CompletionThreadQueue;
|
||||
KSPIN_LOCK CompletionThreadQueueLock;
|
||||
KEVENT CompletionThreadQueueNotEmptyEvent;
|
||||
|
||||
// Fragment buffers
|
||||
byte *FragmentBufferA;
|
||||
byte *FragmentBufferB;
|
||||
KEVENT FragmentBufferAFreeEvent;
|
||||
KEVENT FragmentBufferBFreeEvent;
|
||||
|
||||
// Read-ahead buffer
|
||||
BOOL ReadAheadBufferValid;
|
||||
LARGE_INTEGER LastReadOffset;
|
||||
ULONG LastReadLength;
|
||||
LARGE_INTEGER ReadAheadOffset;
|
||||
ULONG ReadAheadLength;
|
||||
byte *ReadAheadBuffer;
|
||||
LARGE_INTEGER MaxReadAheadOffset;
|
||||
|
||||
LONG OutstandingIoCount;
|
||||
KEVENT NoOutstandingIoEvent;
|
||||
LONG IoThreadPendingRequestCount;
|
||||
|
||||
KEVENT PoolBufferFreeEvent;
|
||||
|
||||
__int64 TotalBytesRead;
|
||||
__int64 TotalBytesWritten;
|
||||
|
||||
volatile BOOL StartPending;
|
||||
volatile BOOL ThreadExitRequested;
|
||||
|
||||
volatile BOOL Suspended;
|
||||
volatile BOOL SuspendPending;
|
||||
volatile BOOL StopPending;
|
||||
|
||||
KEVENT QueueResumedEvent;
|
||||
|
||||
#ifdef TC_TRACE_IO_QUEUE
|
||||
LARGE_INTEGER LastPerformanceCounter;
|
||||
#endif
|
||||
|
||||
} EncryptedIoQueue;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EncryptedIoQueue *Queue;
|
||||
PIRP OriginalIrp;
|
||||
BOOL Write;
|
||||
ULONG OriginalLength;
|
||||
LARGE_INTEGER OriginalOffset;
|
||||
NTSTATUS Status;
|
||||
|
||||
#ifdef TC_TRACE_IO_QUEUE
|
||||
LARGE_INTEGER OriginalIrpOffset;
|
||||
#endif
|
||||
|
||||
} EncryptedIoQueueItem;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
EncryptedIoQueueItem *Item;
|
||||
|
||||
BOOL CompleteOriginalIrp;
|
||||
LARGE_INTEGER Offset;
|
||||
ULONG Length;
|
||||
int64 EncryptedOffset;
|
||||
ULONG EncryptedLength;
|
||||
byte *Data;
|
||||
byte *OrigDataBufferFragment;
|
||||
|
||||
LIST_ENTRY ListEntry;
|
||||
LIST_ENTRY CompletionListEntry;
|
||||
} EncryptedIoRequest;
|
||||
|
||||
|
||||
NTSTATUS EncryptedIoQueueAddIrp (EncryptedIoQueue *queue, PIRP irp);
|
||||
BOOL EncryptedIoQueueIsRunning (EncryptedIoQueue *queue);
|
||||
BOOL EncryptedIoQueueIsSuspended (EncryptedIoQueue *queue);
|
||||
NTSTATUS EncryptedIoQueueResumeFromHold (EncryptedIoQueue *queue);
|
||||
NTSTATUS EncryptedIoQueueStart (EncryptedIoQueue *queue);
|
||||
NTSTATUS EncryptedIoQueueStop (EncryptedIoQueue *queue);
|
||||
NTSTATUS EncryptedIoQueueHoldWhenIdle (EncryptedIoQueue *queue, int64 timeout);
|
||||
|
||||
|
||||
#endif // TC_HEADER_DRIVER_ENCRYPTED_IO_QUEUE
|
||||
1
src/Driver/Makefile
Normal file
1
src/Driver/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
!INCLUDE $(NTMAKEENV)\makefile.def
|
||||
3293
src/Driver/Ntdriver.c
Normal file
3293
src/Driver/Ntdriver.c
Normal file
File diff suppressed because it is too large
Load Diff
174
src/Driver/Ntdriver.h
Normal file
174
src/Driver/Ntdriver.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Legal Notice: Some portions of the source code contained in this file were
|
||||
derived from the source code of Encryption for the Masses 2.02a, which is
|
||||
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
|
||||
Agreement for Encryption for the Masses'. Modifications and additions to
|
||||
the original source code (contained in this file) and all other portions
|
||||
of this file are Copyright (c) 2003-2011 TrueCrypt Developers Association
|
||||
and are governed by the TrueCrypt License 3.0 the full text of which is
|
||||
contained in the file License.txt included in TrueCrypt binary and source
|
||||
code distribution packages. */
|
||||
|
||||
#ifndef TC_HEADER_NTDRIVER
|
||||
#define TC_HEADER_NTDRIVER
|
||||
|
||||
#include "Common.h"
|
||||
#include "EncryptedIoQueue.h"
|
||||
|
||||
/* This structure is used to start new threads */
|
||||
typedef struct _THREAD_BLOCK_
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
NTSTATUS ntCreateStatus;
|
||||
WCHAR wszMountVolume[TC_MAX_PATH + 8];
|
||||
MOUNT_STRUCT *mount;
|
||||
} THREAD_BLOCK, *PTHREAD_BLOCK;
|
||||
|
||||
|
||||
/* This structure is allocated for non-root devices! WARNING: bRootDevice
|
||||
must be the first member of the structure! */
|
||||
typedef struct EXTENSION
|
||||
{
|
||||
BOOL bRootDevice; /* Is this the root device ? which the user-mode apps talk to */
|
||||
BOOL IsVolumeDevice;
|
||||
BOOL IsDriveFilterDevice;
|
||||
BOOL IsVolumeFilterDevice;
|
||||
|
||||
int UniqueVolumeId;
|
||||
int nDosDriveNo; /* Drive number this extension is mounted against */
|
||||
|
||||
BOOL bShuttingDown; /* Is the driver shutting down ? */
|
||||
BOOL bThreadShouldQuit; /* Instruct per device worker thread to quit */
|
||||
PETHREAD peThread; /* Thread handle */
|
||||
KEVENT keCreateEvent; /* Device creation event */
|
||||
KSPIN_LOCK ListSpinLock; /* IRP spinlock */
|
||||
LIST_ENTRY ListEntry; /* IRP listentry */
|
||||
KSEMAPHORE RequestSemaphore; /* IRP list request Semaphore */
|
||||
|
||||
HANDLE hDeviceFile; /* Device handle for this device */
|
||||
PFILE_OBJECT pfoDeviceFile; /* Device fileobject for this device */
|
||||
PDEVICE_OBJECT pFsdDevice; /* lower level device handle */
|
||||
|
||||
CRYPTO_INFO *cryptoInfo; /* Cryptographic and other information for this device */
|
||||
|
||||
__int64 HostLength;
|
||||
__int64 DiskLength; /* The length of the disk referred to by this device */
|
||||
__int64 NumberOfCylinders; /* Partition info */
|
||||
ULONG TracksPerCylinder; /* Partition info */
|
||||
ULONG SectorsPerTrack; /* Partition info */
|
||||
ULONG BytesPerSector; /* Partition info */
|
||||
UCHAR PartitionType; /* Partition info */
|
||||
|
||||
uint32 HostBytesPerSector;
|
||||
|
||||
KEVENT keVolumeEvent; /* Event structure used when setting up a device */
|
||||
|
||||
EncryptedIoQueue Queue;
|
||||
|
||||
BOOL bReadOnly; /* Is this device read-only ? */
|
||||
BOOL bRemovable; /* Is this device removable media ? */
|
||||
BOOL PartitionInInactiveSysEncScope;
|
||||
BOOL bRawDevice; /* Is this a raw-partition or raw-floppy device ? */
|
||||
BOOL bMountManager; /* Mount manager knows about volume */
|
||||
BOOL SystemFavorite;
|
||||
|
||||
WCHAR wszVolume[TC_MAX_PATH]; /* DONT change this size without also changing MOUNT_LIST_STRUCT! */
|
||||
|
||||
LARGE_INTEGER fileCreationTime;
|
||||
LARGE_INTEGER fileLastAccessTime;
|
||||
LARGE_INTEGER fileLastWriteTime;
|
||||
LARGE_INTEGER fileLastChangeTime;
|
||||
BOOL bTimeStampValid;
|
||||
|
||||
PSID UserSid;
|
||||
BOOL SecurityClientContextValid;
|
||||
SECURITY_CLIENT_CONTEXT SecurityClientContext;
|
||||
|
||||
} EXTENSION, *PEXTENSION;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ValidateInput,
|
||||
ValidateOutput,
|
||||
ValidateInputOutput
|
||||
} ValidateIOBufferSizeType;
|
||||
|
||||
|
||||
extern PDRIVER_OBJECT TCDriverObject;
|
||||
extern PDEVICE_OBJECT RootDeviceObject;
|
||||
extern BOOL DriverShuttingDown;
|
||||
extern ULONG OsMajorVersion;
|
||||
extern ULONG OsMinorVersion;
|
||||
extern BOOL VolumeClassFilterRegistered;
|
||||
extern BOOL CacheBootPassword;
|
||||
|
||||
/* Helper macro returning x seconds in units of 100 nanoseconds */
|
||||
#define WAIT_SECONDS(x) ((x)*10000000)
|
||||
|
||||
NTSTATUS DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
||||
NTSTATUS DriverAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo);
|
||||
void DumpMemory (void *memory, int size);
|
||||
BOOL IsAccessibleByUser (PUNICODE_STRING objectFileName, BOOL readOnly);
|
||||
NTSTATUS ProcessMainDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp);
|
||||
NTSTATUS ProcessVolumeDeviceControlIrp (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp);
|
||||
NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize);
|
||||
NTSTATUS TCDispatchQueueIRP (PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
NTSTATUS TCCreateRootDeviceObject (PDRIVER_OBJECT DriverObject);
|
||||
NTSTATUS TCCreateDeviceObject (PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT * ppDeviceObject, MOUNT_STRUCT * mount);
|
||||
NTSTATUS TCReadDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length);
|
||||
NTSTATUS TCWriteDevice (PDEVICE_OBJECT deviceObject, PVOID buffer, LARGE_INTEGER offset, ULONG length);
|
||||
NTSTATUS TCStartThread (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread);
|
||||
NTSTATUS TCStartThreadInProcess (PKSTART_ROUTINE threadProc, PVOID threadArg, PKTHREAD *kThread, PEPROCESS process);
|
||||
NTSTATUS TCStartVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT * mount);
|
||||
void TCStopThread (PKTHREAD kThread, PKEVENT wakeUpEvent);
|
||||
void TCStopVolumeThread (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension);
|
||||
VOID VolumeThreadProc (PVOID Context);
|
||||
void TCSleep (int milliSeconds);
|
||||
void TCGetNTNameFromNumber (LPWSTR ntname, int nDriveNo);
|
||||
void TCGetDosNameFromNumber (LPWSTR dosname, int nDriveNo);
|
||||
LPWSTR TCTranslateCode (ULONG ulCode);
|
||||
void TCDeleteDeviceObject (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension);
|
||||
VOID TCUnloadDriver (PDRIVER_OBJECT DriverObject);
|
||||
void OnShutdownPending ();
|
||||
NTSTATUS TCDeviceIoControl (PWSTR deviceName, ULONG IoControlCode, void *InputBuffer, ULONG InputBufferSize, void *OutputBuffer, ULONG OutputBufferSize);
|
||||
NTSTATUS TCOpenFsVolume (PEXTENSION Extension, PHANDLE volumeHandle, PFILE_OBJECT * fileObject);
|
||||
void TCCloseFsVolume (HANDLE volumeHandle, PFILE_OBJECT fileObject);
|
||||
NTSTATUS TCFsctlCall (PFILE_OBJECT fileObject, LONG IoControlCode, void *InputBuffer, int InputBufferSize, void *OutputBuffer, int OutputBufferSize);
|
||||
NTSTATUS CreateDriveLink (int nDosDriveNo);
|
||||
NTSTATUS RemoveDriveLink (int nDosDriveNo);
|
||||
NTSTATUS MountManagerMount (MOUNT_STRUCT *mount);
|
||||
NTSTATUS MountManagerUnmount (int nDosDriveNo);
|
||||
NTSTATUS MountDevice (PDEVICE_OBJECT deviceObject, MOUNT_STRUCT *mount);
|
||||
NTSTATUS UnmountDevice (UNMOUNT_STRUCT *unmountRequest, PDEVICE_OBJECT deviceObject, BOOL ignoreOpenFiles);
|
||||
NTSTATUS UnmountAllDevices (UNMOUNT_STRUCT *unmountRequest, BOOL ignoreOpenFiles);
|
||||
NTSTATUS SymbolicLinkToTarget (PWSTR symlinkName, PWSTR targetName, USHORT maxTargetNameLength);
|
||||
BOOL RootDeviceControlMutexAcquireNoWait ();
|
||||
void RootDeviceControlMutexRelease ();
|
||||
BOOL RegionsOverlap (unsigned __int64 start1, unsigned __int64 end1, unsigned __int64 start2, unsigned __int64 end2);
|
||||
void GetIntersection (uint64 start1, uint32 length1, uint64 start2, uint64 end2, uint64 *intersectStart, uint32 *intersectLength);
|
||||
NTSTATUS TCCompleteIrp (PIRP irp, NTSTATUS status, ULONG_PTR information);
|
||||
NTSTATUS TCCompleteDiskIrp (PIRP irp, NTSTATUS status, ULONG_PTR information);
|
||||
NTSTATUS ProbeRealDriveSize (PDEVICE_OBJECT driveDeviceObject, LARGE_INTEGER *driveSize);
|
||||
BOOL UserCanAccessDriveDevice ();
|
||||
size_t GetCpuCount ();
|
||||
void EnsureNullTerminatedString (wchar_t *str, size_t maxSizeInBytes);
|
||||
void *AllocateMemoryWithTimeout (size_t size, int retryDelay, int timeout);
|
||||
BOOL IsDriveLetterAvailable (int nDosDriveNo);
|
||||
NTSTATUS TCReadRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, PKEY_VALUE_PARTIAL_INFORMATION *keyData);
|
||||
NTSTATUS TCWriteRegistryKey (PUNICODE_STRING keyPath, wchar_t *keyValueName, ULONG keyValueType, void *valueData, ULONG valueSize);
|
||||
BOOL IsVolumeClassFilterRegistered ();
|
||||
NTSTATUS ReadRegistryConfigFlags (BOOL driverEntry);
|
||||
NTSTATUS WriteRegistryConfigFlags (uint32 flags);
|
||||
BOOL ValidateIOBufferSize (PIRP irp, size_t requiredBufferSize, ValidateIOBufferSizeType type);
|
||||
NTSTATUS GetDeviceSectorSize (PDEVICE_OBJECT deviceObject, ULONG *bytesPerSector);
|
||||
NTSTATUS ZeroUnreadableSectors (PDEVICE_OBJECT deviceObject, LARGE_INTEGER startOffset, ULONG size, uint64 *zeroedSectorCount);
|
||||
NTSTATUS ReadDeviceSkipUnreadableSectors (PDEVICE_OBJECT deviceObject, byte *buffer, LARGE_INTEGER startOffset, ULONG size, uint64 *badSectorCount);
|
||||
BOOL IsVolumeAccessibleByCurrentUser (PEXTENSION volumeDeviceExtension);
|
||||
void GetElapsedTimeInit (LARGE_INTEGER *lastPerfCounter);
|
||||
int64 GetElapsedTime (LARGE_INTEGER *lastPerfCounter);
|
||||
BOOL IsOSAtLeast (OSVersionEnum reqMinOS);
|
||||
|
||||
#define TC_BUG_CHECK(status) KeBugCheckEx (SECURITY_SYSTEM, __LINE__, (ULONG_PTR) status, 0, 'TC')
|
||||
|
||||
#endif // TC_HEADER_NTDRIVER
|
||||
862
src/Driver/Ntvol.c
Normal file
862
src/Driver/Ntvol.c
Normal file
@@ -0,0 +1,862 @@
|
||||
/*
|
||||
Legal Notice: Some portions of the source code contained in this file were
|
||||
derived from the source code of Encryption for the Masses 2.02a, which is
|
||||
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
|
||||
Agreement for Encryption for the Masses'. Modifications and additions to
|
||||
the original source code (contained in this file) and all other portions
|
||||
of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
|
||||
and are governed by the TrueCrypt License 3.0 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 <wchar.h>
|
||||
#include "Crypto.h"
|
||||
#include "Volumes.h"
|
||||
|
||||
#include "Apidrvr.h"
|
||||
#include "DriveFilter.h"
|
||||
#include "Ntdriver.h"
|
||||
#include "Ntvol.h"
|
||||
#include "VolumeFilter.h"
|
||||
|
||||
#include "Boot/Windows/BootCommon.h"
|
||||
|
||||
#include "Cache.h"
|
||||
|
||||
#if 0 && _DEBUG
|
||||
#define EXTRA_INFO 1
|
||||
#endif
|
||||
|
||||
#pragma warning( disable : 4127 )
|
||||
|
||||
volatile BOOL ProbingHostDeviceForWrite = FALSE;
|
||||
|
||||
|
||||
NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject,
|
||||
PEXTENSION Extension,
|
||||
MOUNT_STRUCT *mount,
|
||||
PWSTR pwszMountVolume,
|
||||
BOOL bRawDevice)
|
||||
{
|
||||
FILE_STANDARD_INFORMATION FileStandardInfo;
|
||||
FILE_BASIC_INFORMATION FileBasicInfo;
|
||||
OBJECT_ATTRIBUTES oaFileAttributes;
|
||||
UNICODE_STRING FullFileName;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PCRYPTO_INFO cryptoInfoPtr = NULL;
|
||||
PCRYPTO_INFO tmpCryptoInfo = NULL;
|
||||
LARGE_INTEGER lDiskLength;
|
||||
__int64 partitionStartingOffset = 0;
|
||||
int volumeType;
|
||||
char *readBuffer = 0;
|
||||
NTSTATUS ntStatus = 0;
|
||||
BOOL forceAccessCheck = (!bRawDevice && !(OsMajorVersion == 5 &&OsMinorVersion == 0)); // Windows 2000 does not support OBJ_FORCE_ACCESS_CHECK attribute
|
||||
BOOL disableBuffering = TRUE;
|
||||
BOOL exclusiveAccess = mount->bExclusiveAccess;
|
||||
|
||||
Extension->pfoDeviceFile = NULL;
|
||||
Extension->hDeviceFile = NULL;
|
||||
Extension->bTimeStampValid = FALSE;
|
||||
|
||||
RtlInitUnicodeString (&FullFileName, pwszMountVolume);
|
||||
InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
|
||||
|
||||
if (Extension->SecurityClientContextValid)
|
||||
{
|
||||
ntStatus = SeImpersonateClientEx (&Extension->SecurityClientContext, NULL);
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
goto error;
|
||||
}
|
||||
|
||||
mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = FALSE;
|
||||
|
||||
// If we are opening a device, query its size first
|
||||
if (bRawDevice)
|
||||
{
|
||||
PARTITION_INFORMATION pi;
|
||||
PARTITION_INFORMATION_EX pix;
|
||||
LARGE_INTEGER diskLengthInfo;
|
||||
DISK_GEOMETRY dg;
|
||||
|
||||
ntStatus = IoGetDeviceObjectPointer (&FullFileName,
|
||||
FILE_READ_DATA | FILE_READ_ATTRIBUTES,
|
||||
&Extension->pfoDeviceFile,
|
||||
&Extension->pFsdDevice);
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
goto error;
|
||||
|
||||
ntStatus = TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg));
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
goto error;
|
||||
|
||||
lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector;
|
||||
Extension->HostBytesPerSector = dg.BytesPerSector;
|
||||
|
||||
// Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails
|
||||
if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix))))
|
||||
{
|
||||
lDiskLength.QuadPart = pix.PartitionLength.QuadPart;
|
||||
partitionStartingOffset = pix.StartingOffset.QuadPart;
|
||||
}
|
||||
// Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX
|
||||
else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi))))
|
||||
{
|
||||
lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
|
||||
partitionStartingOffset = pi.StartingOffset.QuadPart;
|
||||
}
|
||||
else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_LENGTH_INFO, &diskLengthInfo, sizeof (diskLengthInfo))))
|
||||
{
|
||||
lDiskLength = diskLengthInfo;
|
||||
}
|
||||
|
||||
ProbingHostDeviceForWrite = TRUE;
|
||||
|
||||
if (!mount->bMountReadOnly
|
||||
&& TCSendHostDeviceIoControlRequest (DeviceObject, Extension,
|
||||
IsHiddenSystemRunning() ? TC_IOCTL_DISK_IS_WRITABLE : IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED)
|
||||
{
|
||||
mount->bMountReadOnly = TRUE;
|
||||
DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
|
||||
mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = TRUE;
|
||||
}
|
||||
|
||||
ProbingHostDeviceForWrite = FALSE;
|
||||
|
||||
// Some Windows tools (e.g. diskmgmt, diskpart, vssadmin) fail or experience timeouts when there is a raw device
|
||||
// open for exclusive access. Therefore, exclusive access is used only for file-hosted volumes.
|
||||
// Applications requiring a consistent device image need to acquire exclusive write access first. This is prevented
|
||||
// when a device-hosted volume is mounted.
|
||||
|
||||
exclusiveAccess = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Limit the maximum required buffer size
|
||||
if (mount->BytesPerSector > 128 * BYTES_PER_KB)
|
||||
{
|
||||
ntStatus = STATUS_INVALID_PARAMETER;
|
||||
goto error;
|
||||
}
|
||||
|
||||
Extension->HostBytesPerSector = mount->BytesPerSector;
|
||||
|
||||
if (Extension->HostBytesPerSector != TC_SECTOR_SIZE_FILE_HOSTED_VOLUME)
|
||||
disableBuffering = FALSE;
|
||||
}
|
||||
|
||||
// Open the volume hosting file/device
|
||||
if (!mount->bMountReadOnly)
|
||||
{
|
||||
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
|
||||
GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
|
||||
&oaFileAttributes,
|
||||
&IoStatusBlock,
|
||||
NULL,
|
||||
FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_SYSTEM,
|
||||
exclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
FILE_RANDOM_ACCESS |
|
||||
FILE_WRITE_THROUGH |
|
||||
(disableBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
/* 26-4-99 NT for some partitions returns this code, it is really a access denied */
|
||||
if (ntStatus == 0xc000001b)
|
||||
ntStatus = STATUS_ACCESS_DENIED;
|
||||
|
||||
mount->VolumeMountedReadOnlyAfterAccessDenied = FALSE;
|
||||
|
||||
if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
|
||||
{
|
||||
ntStatus = ZwCreateFile (&Extension->hDeviceFile,
|
||||
GENERIC_READ | SYNCHRONIZE,
|
||||
&oaFileAttributes,
|
||||
&IoStatusBlock,
|
||||
NULL,
|
||||
FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_SYSTEM,
|
||||
exclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
FILE_RANDOM_ACCESS |
|
||||
FILE_WRITE_THROUGH |
|
||||
(disableBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly)
|
||||
mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE;
|
||||
|
||||
Extension->bReadOnly = TRUE;
|
||||
DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
|
||||
}
|
||||
else
|
||||
Extension->bReadOnly = FALSE;
|
||||
|
||||
/* 26-4-99 NT for some partitions returns this code, it is really a
|
||||
access denied */
|
||||
if (ntStatus == 0xc000001b)
|
||||
{
|
||||
/* Partitions which return this code can still be opened with
|
||||
FILE_SHARE_READ but this causes NT problems elsewhere in
|
||||
particular if you do FILE_SHARE_READ NT will die later if
|
||||
anyone even tries to open the partition (or file for that
|
||||
matter...) */
|
||||
ntStatus = STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
// If we have opened a file, query its size now
|
||||
if (bRawDevice == FALSE)
|
||||
{
|
||||
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
|
||||
&IoStatusBlock,
|
||||
&FileBasicInfo,
|
||||
sizeof (FileBasicInfo),
|
||||
FileBasicInformation);
|
||||
|
||||
if (NT_SUCCESS (ntStatus))
|
||||
{
|
||||
if (mount->bPreserveTimestamp)
|
||||
{
|
||||
Extension->fileCreationTime = FileBasicInfo.CreationTime;
|
||||
Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
|
||||
Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
|
||||
Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
|
||||
Extension->bTimeStampValid = TRUE;
|
||||
}
|
||||
|
||||
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
|
||||
&IoStatusBlock,
|
||||
&FileStandardInfo,
|
||||
sizeof (FileStandardInfo),
|
||||
FileStandardInformation);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
{
|
||||
Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
|
||||
ntStatus);
|
||||
goto error;
|
||||
}
|
||||
|
||||
lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
|
||||
|
||||
if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
|
||||
{
|
||||
Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
|
||||
mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
|
||||
FILE_ALL_ACCESS,
|
||||
*IoFileObjectType,
|
||||
KernelMode,
|
||||
&Extension->pfoDeviceFile,
|
||||
0);
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Get the FSD device for the file (probably either NTFS or FAT) */
|
||||
Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise,
|
||||
// the NTFS driver guards hidden sectors and prevents mounting using a backup header e.g. after the user
|
||||
// accidentally quick-formats a dismounted partition-hosted TrueCrypt volume as NTFS).
|
||||
|
||||
PFILE_OBJECT pfoTmpDeviceFile = NULL;
|
||||
|
||||
if (NT_SUCCESS (ObReferenceObjectByHandle (Extension->hDeviceFile, FILE_ALL_ACCESS, *IoFileObjectType, KernelMode, &pfoTmpDeviceFile, NULL))
|
||||
&& pfoTmpDeviceFile != NULL)
|
||||
{
|
||||
TCFsctlCall (pfoTmpDeviceFile, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0);
|
||||
ObDereferenceObject (pfoTmpDeviceFile);
|
||||
}
|
||||
}
|
||||
|
||||
// Check volume size
|
||||
if (lDiskLength.QuadPart < TC_MIN_VOLUME_SIZE_LEGACY || lDiskLength.QuadPart > TC_MAX_VOLUME_SIZE)
|
||||
{
|
||||
mount->nReturnCode = ERR_VOL_SIZE_WRONG;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
Extension->DiskLength = lDiskLength.QuadPart;
|
||||
Extension->HostLength = lDiskLength.QuadPart;
|
||||
|
||||
readBuffer = TCalloc (max (max (TC_VOLUME_HEADER_EFFECTIVE_SIZE, PAGE_SIZE), Extension->HostBytesPerSector));
|
||||
if (readBuffer == NULL)
|
||||
{
|
||||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Go through all volume types (e.g., normal, hidden)
|
||||
for (volumeType = TC_VOLUME_TYPE_NORMAL;
|
||||
volumeType < TC_VOLUME_TYPE_COUNT;
|
||||
volumeType++)
|
||||
{
|
||||
Dump ("Trying to open volume type %d\n", volumeType);
|
||||
|
||||
if (mount->bPartitionInInactiveSysEncScope
|
||||
&& volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
|
||||
continue;
|
||||
|
||||
/* Read the volume header */
|
||||
|
||||
if (!mount->bPartitionInInactiveSysEncScope
|
||||
|| (mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_HIDDEN))
|
||||
{
|
||||
// Header of a volume that is not within the scope of system encryption, or
|
||||
// header of a system hidden volume (containing a hidden OS)
|
||||
|
||||
LARGE_INTEGER headerOffset;
|
||||
|
||||
if (mount->UseBackupHeader && lDiskLength.QuadPart <= TC_TOTAL_VOLUME_HEADERS_SIZE)
|
||||
continue;
|
||||
|
||||
switch (volumeType)
|
||||
{
|
||||
case TC_VOLUME_TYPE_NORMAL:
|
||||
headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET;
|
||||
break;
|
||||
|
||||
case TC_VOLUME_TYPE_HIDDEN:
|
||||
if (lDiskLength.QuadPart <= TC_VOLUME_HEADER_GROUP_SIZE)
|
||||
continue;
|
||||
|
||||
headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_HIDDEN_VOLUME_HEADER_OFFSET;
|
||||
break;
|
||||
|
||||
case TC_VOLUME_TYPE_HIDDEN_LEGACY:
|
||||
if (mount->UseBackupHeader)
|
||||
continue;
|
||||
|
||||
if (bRawDevice && Extension->HostBytesPerSector != TC_SECTOR_SIZE_LEGACY)
|
||||
continue;
|
||||
|
||||
headerOffset.QuadPart = lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
|
||||
break;
|
||||
}
|
||||
|
||||
Dump ("Reading volume header at %I64d\n", headerOffset.QuadPart);
|
||||
|
||||
ntStatus = ZwReadFile (Extension->hDeviceFile,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
readBuffer,
|
||||
bRawDevice ? max (TC_VOLUME_HEADER_EFFECTIVE_SIZE, Extension->HostBytesPerSector) : TC_VOLUME_HEADER_EFFECTIVE_SIZE,
|
||||
&headerOffset,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Header of a partition that is within the scope of system encryption
|
||||
|
||||
WCHAR parentDrivePath [47+1] = {0};
|
||||
HANDLE hParentDeviceFile = NULL;
|
||||
UNICODE_STRING FullParentPath;
|
||||
OBJECT_ATTRIBUTES oaParentFileAttributes;
|
||||
LARGE_INTEGER parentKeyDataOffset;
|
||||
|
||||
_snwprintf (parentDrivePath,
|
||||
sizeof (parentDrivePath) / sizeof (WCHAR) - 1,
|
||||
WIDE ("\\Device\\Harddisk%d\\Partition0"),
|
||||
mount->nPartitionInInactiveSysEncScopeDriveNo);
|
||||
|
||||
Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath);
|
||||
|
||||
RtlInitUnicodeString (&FullParentPath, parentDrivePath);
|
||||
InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
|
||||
|
||||
ntStatus = ZwCreateFile (&hParentDeviceFile,
|
||||
GENERIC_READ | SYNCHRONIZE,
|
||||
&oaParentFileAttributes,
|
||||
&IoStatusBlock,
|
||||
NULL,
|
||||
FILE_ATTRIBUTE_NORMAL |
|
||||
FILE_ATTRIBUTE_SYSTEM,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_OPEN,
|
||||
FILE_RANDOM_ACCESS |
|
||||
FILE_WRITE_THROUGH |
|
||||
FILE_NO_INTERMEDIATE_BUFFERING |
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0);
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
{
|
||||
if (hParentDeviceFile != NULL)
|
||||
ZwClose (hParentDeviceFile);
|
||||
|
||||
Dump ("Cannot open %ls\n", parentDrivePath);
|
||||
|
||||
goto error;
|
||||
}
|
||||
|
||||
parentKeyDataOffset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
|
||||
|
||||
ntStatus = ZwReadFile (hParentDeviceFile,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
readBuffer,
|
||||
max (TC_VOLUME_HEADER_EFFECTIVE_SIZE, Extension->HostBytesPerSector),
|
||||
&parentKeyDataOffset,
|
||||
NULL);
|
||||
|
||||
if (hParentDeviceFile != NULL)
|
||||
ZwClose (hParentDeviceFile);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS (ntStatus) && ntStatus != STATUS_END_OF_FILE)
|
||||
{
|
||||
Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ntStatus == STATUS_END_OF_FILE || IoStatusBlock.Information < TC_VOLUME_HEADER_EFFECTIVE_SIZE)
|
||||
{
|
||||
Dump ("Read didn't read enough data\n");
|
||||
|
||||
// If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the
|
||||
// filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is
|
||||
// shorter than the partition). This can happen for example after the user quick-formats a dismounted
|
||||
// partition-hosted TrueCrypt volume and then tries to mount the volume using the embedded backup header.
|
||||
memset (readBuffer, 0, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
|
||||
}
|
||||
|
||||
/* Attempt to recognize the volume (decrypt the header) */
|
||||
|
||||
ReadVolumeHeaderRecoveryMode = mount->RecoveryMode;
|
||||
|
||||
if ((volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) && mount->bProtectHiddenVolume)
|
||||
{
|
||||
mount->nReturnCode = ReadVolumeHeaderWCache (
|
||||
FALSE,
|
||||
mount->bCache,
|
||||
readBuffer,
|
||||
&mount->ProtectedHidVolPassword,
|
||||
&tmpCryptoInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
mount->nReturnCode = ReadVolumeHeaderWCache (
|
||||
mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_NORMAL,
|
||||
mount->bCache,
|
||||
readBuffer,
|
||||
&mount->VolumePassword,
|
||||
&Extension->cryptoInfo);
|
||||
}
|
||||
|
||||
ReadVolumeHeaderRecoveryMode = FALSE;
|
||||
|
||||
if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)
|
||||
{
|
||||
/* Volume header successfully decrypted */
|
||||
|
||||
Dump ("Volume header decrypted\n");
|
||||
Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion);
|
||||
Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume);
|
||||
|
||||
if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume)
|
||||
{
|
||||
Extension->bReadOnly = mount->bMountReadOnly = TRUE;
|
||||
HiddenSysLeakProtectionCount++;
|
||||
}
|
||||
|
||||
Extension->cryptoInfo->bProtectHiddenVolume = FALSE;
|
||||
Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE;
|
||||
|
||||
Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope;
|
||||
|
||||
if (volumeType == TC_VOLUME_TYPE_NORMAL)
|
||||
{
|
||||
if (mount->bPartitionInInactiveSysEncScope)
|
||||
{
|
||||
if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset
|
||||
|| Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset)
|
||||
{
|
||||
// The partition is not within the key scope of system encryption
|
||||
mount->nReturnCode = ERR_PASSWORD_WRONG;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value)
|
||||
{
|
||||
// Partial encryption is not supported for volumes mounted as regular
|
||||
mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else if (Extension->cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC)
|
||||
{
|
||||
if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value)
|
||||
{
|
||||
// Non-system in-place encryption process has not been completed on this volume
|
||||
mount->nReturnCode = ERR_NONSYS_INPLACE_ENC_INCOMPLETE;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Extension->cryptoInfo->FirstDataUnitNo.Value = 0;
|
||||
|
||||
if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning())
|
||||
{
|
||||
// Prevent mount of a hidden system partition if the system hosted on it is currently running
|
||||
if (memcmp (Extension->cryptoInfo->master_keydata, GetSystemDriveCryptoInfo()->master_keydata, EAGetKeySize (Extension->cryptoInfo->ea)) == 0)
|
||||
{
|
||||
mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
switch (volumeType)
|
||||
{
|
||||
case TC_VOLUME_TYPE_NORMAL:
|
||||
|
||||
Extension->cryptoInfo->hiddenVolume = FALSE;
|
||||
|
||||
if (mount->bPartitionInInactiveSysEncScope)
|
||||
{
|
||||
Extension->cryptoInfo->volDataAreaOffset = 0;
|
||||
Extension->DiskLength = lDiskLength.QuadPart;
|
||||
Extension->cryptoInfo->FirstDataUnitNo.Value = partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE;
|
||||
}
|
||||
else if (Extension->cryptoInfo->LegacyVolume)
|
||||
{
|
||||
Extension->cryptoInfo->volDataAreaOffset = TC_VOLUME_HEADER_SIZE_LEGACY;
|
||||
Extension->DiskLength = lDiskLength.QuadPart - TC_VOLUME_HEADER_SIZE_LEGACY;
|
||||
}
|
||||
else
|
||||
{
|
||||
Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->EncryptedAreaStart.Value;
|
||||
Extension->DiskLength = Extension->cryptoInfo->VolumeSize.Value;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case TC_VOLUME_TYPE_HIDDEN:
|
||||
case TC_VOLUME_TYPE_HIDDEN_LEGACY:
|
||||
|
||||
cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo;
|
||||
|
||||
if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
|
||||
Extension->cryptoInfo->hiddenVolumeOffset = lDiskLength.QuadPart - cryptoInfoPtr->hiddenVolumeSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
|
||||
else
|
||||
Extension->cryptoInfo->hiddenVolumeOffset = cryptoInfoPtr->EncryptedAreaStart.Value;
|
||||
|
||||
Dump ("Hidden volume offset = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset);
|
||||
Dump ("Hidden volume size = %I64d\n", cryptoInfoPtr->hiddenVolumeSize);
|
||||
Dump ("Hidden volume end = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset + cryptoInfoPtr->hiddenVolumeSize - 1);
|
||||
|
||||
// Validate the offset
|
||||
if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0)
|
||||
{
|
||||
mount->nReturnCode = ERR_VOL_SIZE_WRONG;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// If we are supposed to actually mount the hidden volume (not just to protect it)
|
||||
if (!mount->bProtectHiddenVolume)
|
||||
{
|
||||
Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize;
|
||||
Extension->cryptoInfo->hiddenVolume = TRUE;
|
||||
Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hidden volume protection
|
||||
Extension->cryptoInfo->hiddenVolume = FALSE;
|
||||
Extension->cryptoInfo->bProtectHiddenVolume = TRUE;
|
||||
|
||||
Extension->cryptoInfo->hiddenVolumeProtectedSize = tmpCryptoInfo->hiddenVolumeSize;
|
||||
|
||||
if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
|
||||
Extension->cryptoInfo->hiddenVolumeProtectedSize += TC_VOLUME_HEADER_SIZE_LEGACY;
|
||||
|
||||
Dump ("Hidden volume protection active: %I64d-%I64d (%I64d)\n", Extension->cryptoInfo->hiddenVolumeOffset, Extension->cryptoInfo->hiddenVolumeProtectedSize + Extension->cryptoInfo->hiddenVolumeOffset - 1, Extension->cryptoInfo->hiddenVolumeProtectedSize);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset);
|
||||
Dump ("Volume data size = %I64d\n", Extension->DiskLength);
|
||||
Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1);
|
||||
|
||||
if (Extension->DiskLength == 0)
|
||||
{
|
||||
Dump ("Incorrect volume size\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// If this is a hidden volume, make sure we are supposed to actually
|
||||
// mount it (i.e. not just to protect it)
|
||||
if (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume)
|
||||
{
|
||||
// Validate sector size
|
||||
if (bRawDevice && Extension->cryptoInfo->SectorSize != Extension->HostBytesPerSector)
|
||||
{
|
||||
mount->nReturnCode = ERR_PARAMETER_INCORRECT;
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Calculate virtual volume geometry
|
||||
Extension->TracksPerCylinder = 1;
|
||||
Extension->SectorsPerTrack = 1;
|
||||
Extension->BytesPerSector = Extension->cryptoInfo->SectorSize;
|
||||
Extension->NumberOfCylinders = Extension->DiskLength / Extension->BytesPerSector;
|
||||
Extension->PartitionType = 0;
|
||||
|
||||
Extension->bRawDevice = bRawDevice;
|
||||
|
||||
memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume));
|
||||
if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume)
|
||||
{
|
||||
/* UNC path */
|
||||
_snwprintf (Extension->wszVolume,
|
||||
sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1,
|
||||
WIDE ("\\??\\\\%s"),
|
||||
pwszMountVolume + 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// If we are to protect a hidden volume we cannot exit yet, for we must also
|
||||
// decrypt the hidden volume header.
|
||||
if (!(volumeType == TC_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
|
||||
{
|
||||
TCfree (readBuffer);
|
||||
|
||||
if (tmpCryptoInfo != NULL)
|
||||
{
|
||||
crypto_close (tmpCryptoInfo);
|
||||
tmpCryptoInfo = NULL;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if ((mount->bProtectHiddenVolume && volumeType == TC_VOLUME_TYPE_NORMAL)
|
||||
|| mount->nReturnCode != ERR_PASSWORD_WRONG)
|
||||
{
|
||||
/* If we are not supposed to protect a hidden volume, the only error that is
|
||||
tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume).
|
||||
|
||||
If we _are_ supposed to protect a hidden volume, we do not tolerate any error
|
||||
(both volume headers must be successfully decrypted). */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed due to some non-OS reason so we drop through and return NT
|
||||
SUCCESS then nReturnCode is checked later in user-mode */
|
||||
|
||||
if (mount->nReturnCode == ERR_OUTOFMEMORY)
|
||||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||||
else
|
||||
ntStatus = STATUS_SUCCESS;
|
||||
|
||||
error:
|
||||
if (mount->nReturnCode == ERR_SUCCESS)
|
||||
mount->nReturnCode = ERR_PASSWORD_WRONG;
|
||||
|
||||
if (tmpCryptoInfo != NULL)
|
||||
{
|
||||
crypto_close (tmpCryptoInfo);
|
||||
tmpCryptoInfo = NULL;
|
||||
}
|
||||
|
||||
if (Extension->cryptoInfo)
|
||||
{
|
||||
crypto_close (Extension->cryptoInfo);
|
||||
Extension->cryptoInfo = NULL;
|
||||
}
|
||||
|
||||
if (Extension->bTimeStampValid)
|
||||
{
|
||||
RestoreTimeStamp (Extension);
|
||||
}
|
||||
|
||||
/* Close the hDeviceFile */
|
||||
if (Extension->hDeviceFile != NULL)
|
||||
ZwClose (Extension->hDeviceFile);
|
||||
|
||||
/* The cryptoInfo pointer is deallocated if the readheader routines
|
||||
fail so there is no need to deallocate here */
|
||||
|
||||
/* Dereference the user-mode file object */
|
||||
if (Extension->pfoDeviceFile != NULL)
|
||||
ObDereferenceObject (Extension->pfoDeviceFile);
|
||||
|
||||
/* Free the tmp IO buffers */
|
||||
if (readBuffer != NULL)
|
||||
TCfree (readBuffer);
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
|
||||
{
|
||||
if (DeviceObject); /* Remove compiler warning */
|
||||
|
||||
if (Extension->hDeviceFile != NULL)
|
||||
{
|
||||
if (Extension->bRawDevice == FALSE
|
||||
&& Extension->bTimeStampValid)
|
||||
{
|
||||
RestoreTimeStamp (Extension);
|
||||
}
|
||||
ZwClose (Extension->hDeviceFile);
|
||||
}
|
||||
ObDereferenceObject (Extension->pfoDeviceFile);
|
||||
crypto_close (Extension->cryptoInfo);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
|
||||
PEXTENSION Extension,
|
||||
ULONG IoControlCode,
|
||||
void *OutputBuffer,
|
||||
ULONG OutputBufferSize)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
NTSTATUS ntStatus;
|
||||
PIRP Irp;
|
||||
|
||||
if (DeviceObject); /* Remove compiler warning */
|
||||
|
||||
KeClearEvent (&Extension->keVolumeEvent);
|
||||
|
||||
Irp = IoBuildDeviceIoControlRequest (IoControlCode,
|
||||
Extension->pFsdDevice,
|
||||
NULL, 0,
|
||||
OutputBuffer, OutputBufferSize,
|
||||
FALSE,
|
||||
&Extension->keVolumeEvent,
|
||||
&IoStatusBlock);
|
||||
|
||||
if (Irp == NULL)
|
||||
{
|
||||
Dump ("IRP allocation failed\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// Disk device may be used by filesystem driver which needs file object
|
||||
IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
|
||||
|
||||
ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
|
||||
if (ntStatus == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL);
|
||||
ntStatus = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
NTSTATUS COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
NTSTATUS IrpStatus,
|
||||
ULONG_PTR IrpInformation)
|
||||
{
|
||||
Irp->IoStatus.Status = IrpStatus;
|
||||
Irp->IoStatus.Information = IrpInformation;
|
||||
|
||||
if (DeviceObject); /* Remove compiler warning */
|
||||
|
||||
#if EXTRA_INFO
|
||||
if (!NT_SUCCESS (IrpStatus))
|
||||
{
|
||||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||||
Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
|
||||
(ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||||
Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
|
||||
(ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
|
||||
}
|
||||
#endif
|
||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||
return IrpStatus;
|
||||
}
|
||||
|
||||
|
||||
static void RestoreTimeStamp (PEXTENSION Extension)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
FILE_BASIC_INFORMATION FileBasicInfo;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
|
||||
if (Extension->hDeviceFile != NULL
|
||||
&& Extension->bRawDevice == FALSE
|
||||
&& Extension->bReadOnly == FALSE
|
||||
&& Extension->bTimeStampValid)
|
||||
{
|
||||
ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
|
||||
&IoStatusBlock,
|
||||
&FileBasicInfo,
|
||||
sizeof (FileBasicInfo),
|
||||
FileBasicInformation);
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
{
|
||||
Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
|
||||
ntStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileBasicInfo.CreationTime = Extension->fileCreationTime;
|
||||
FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
|
||||
FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
|
||||
FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
|
||||
|
||||
ntStatus = ZwSetInformationFile(
|
||||
Extension->hDeviceFile,
|
||||
&IoStatusBlock,
|
||||
&FileBasicInfo,
|
||||
sizeof (FileBasicInfo),
|
||||
FileBasicInformation);
|
||||
|
||||
if (!NT_SUCCESS (ntStatus))
|
||||
Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
19
src/Driver/Ntvol.h
Normal file
19
src/Driver/Ntvol.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Legal Notice: Some portions of the source code contained in this file were
|
||||
derived from the source code of Encryption for the Masses 2.02a, which is
|
||||
Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
|
||||
Agreement for Encryption for the Masses'. Modifications and additions to
|
||||
the original source code (contained in this file) and all other portions
|
||||
of this file are Copyright (c) 2003-2008 TrueCrypt Developers Association
|
||||
and are governed by the TrueCrypt License 3.0 the full text of which is
|
||||
contained in the file License.txt included in TrueCrypt binary and source
|
||||
code distribution packages. */
|
||||
|
||||
extern volatile BOOL ProbingHostDeviceForWrite;
|
||||
|
||||
NTSTATUS TCOpenVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , MOUNT_STRUCT *mount , PWSTR pwszMountVolume , BOOL bRawDevice );
|
||||
void TCCloseVolume ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension );
|
||||
NTSTATUS TCCompletion ( PDEVICE_OBJECT DeviceObject , PIRP Irp , PVOID pUserBuffer );
|
||||
static NTSTATUS TCSendHostDeviceIoControlRequest ( PDEVICE_OBJECT DeviceObject , PEXTENSION Extension , ULONG IoControlCode , void *OutputBuffer , ULONG OutputBufferSize );
|
||||
NTSTATUS COMPLETE_IRP ( PDEVICE_OBJECT DeviceObject , PIRP Irp , NTSTATUS IrpStatus , ULONG_PTR IrpInformation );
|
||||
static void RestoreTimeStamp ( PEXTENSION Extension );
|
||||
16
src/Driver/Resource.h
Normal file
16
src/Driver/Resource.h
Normal file
@@ -0,0 +1,16 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Driver.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NO_MFC 1
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
21
src/Driver/Sources
Normal file
21
src/Driver/Sources
Normal file
@@ -0,0 +1,21 @@
|
||||
TARGETNAME=truecrypt
|
||||
TARGETTYPE=DRIVER
|
||||
|
||||
USER_C_FLAGS=$(USER_C_FLAGS) -D_UNICODE
|
||||
LINKER_FLAGS=$(LINKER_FLAGS) -map
|
||||
|
||||
INCLUDES = ../Common;../Crypto
|
||||
|
||||
SOURCES = \
|
||||
DriveFilter.c \
|
||||
DumpFilter.c \
|
||||
EncryptedIoQueue.c \
|
||||
Ntdriver.c \
|
||||
Ntvol.c \
|
||||
VolumeFilter.c \
|
||||
Driver.rc
|
||||
|
||||
TARGETLIBS = \
|
||||
$(SDK_LIB_PATH)/uuid.lib \
|
||||
../Common/obj$(BUILD_ALT_DIR)/*/Common.lib \
|
||||
../Crypto/obj$(BUILD_ALT_DIR)/*/Crypto.lib
|
||||
290
src/Driver/VolumeFilter.c
Normal file
290
src/Driver/VolumeFilter.c
Normal file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
Copyright (c) 2008-2011 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 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 "Ntdriver.h"
|
||||
#include "Ntvol.h"
|
||||
#include "DriveFilter.h"
|
||||
#include "VolumeFilter.h"
|
||||
|
||||
typedef DriveFilterExtension VolumeFilterExtension;
|
||||
|
||||
// Number of times the filter driver answered that an unencrypted volume
|
||||
// is read-only (or mounted an outer/normal TrueCrypt volume as read only)
|
||||
uint32 HiddenSysLeakProtectionCount = 0;
|
||||
|
||||
|
||||
NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo)
|
||||
{
|
||||
VolumeFilterExtension *Extension;
|
||||
NTSTATUS status;
|
||||
PDEVICE_OBJECT filterDeviceObject = NULL;
|
||||
PDEVICE_OBJECT attachedDeviceObject;
|
||||
|
||||
Dump ("VolumeFilterAddDevice pdo=%p\n", pdo);
|
||||
|
||||
attachedDeviceObject = IoGetAttachedDeviceReference (pdo);
|
||||
status = IoCreateDevice (driverObject, sizeof (VolumeFilterExtension), NULL, attachedDeviceObject->DeviceType, 0, FALSE, &filterDeviceObject);
|
||||
|
||||
ObDereferenceObject (attachedDeviceObject);
|
||||
|
||||
if (!NT_SUCCESS (status))
|
||||
{
|
||||
filterDeviceObject = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
Extension = (VolumeFilterExtension *) filterDeviceObject->DeviceExtension;
|
||||
memset (Extension, 0, sizeof (VolumeFilterExtension));
|
||||
|
||||
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->IsVolumeFilterDevice = TRUE;
|
||||
Extension->DeviceObject = filterDeviceObject;
|
||||
Extension->Pdo = pdo;
|
||||
|
||||
IoInitializeRemoveLock (&Extension->Queue.RemoveLock, 'LRCT', 0, 0);
|
||||
|
||||
filterDeviceObject->Flags |= Extension->LowerDeviceObject->Flags & (DO_DIRECT_IO | DO_BUFFERED_IO | DO_POWER_PAGABLE);
|
||||
filterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
|
||||
return status;
|
||||
|
||||
err:
|
||||
if (filterDeviceObject)
|
||||
{
|
||||
if (Extension->LowerDeviceObject)
|
||||
IoDetachDevice (Extension->LowerDeviceObject);
|
||||
|
||||
IoDeleteDevice (filterDeviceObject);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS PassIrp (PDEVICE_OBJECT deviceObject, PIRP irp)
|
||||
{
|
||||
IoSkipCurrentIrpStackLocation (irp);
|
||||
return IoCallDriver (deviceObject, irp);
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS PassFilteredIrp (PDEVICE_OBJECT deviceObject, PIRP irp, PIO_COMPLETION_ROUTINE completionRoutine, PVOID completionRoutineArg)
|
||||
{
|
||||
IoCopyCurrentIrpStackLocationToNext (irp);
|
||||
|
||||
if (completionRoutine)
|
||||
IoSetCompletionRoutine (irp, completionRoutine, completionRoutineArg, TRUE, TRUE, TRUE);
|
||||
|
||||
return IoCallDriver (deviceObject, irp);
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS OnDeviceUsageNotificationCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension)
|
||||
{
|
||||
if (Irp->PendingReturned)
|
||||
IoMarkIrpPending (Irp);
|
||||
|
||||
if (!(Extension->LowerDeviceObject->Flags & DO_POWER_PAGABLE))
|
||||
filterDeviceObject->Flags &= ~DO_POWER_PAGABLE;
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return STATUS_CONTINUE_COMPLETION;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS OnStartDeviceCompleted (PDEVICE_OBJECT filterDeviceObject, PIRP Irp, VolumeFilterExtension *Extension)
|
||||
{
|
||||
if (Irp->PendingReturned)
|
||||
IoMarkIrpPending (Irp);
|
||||
|
||||
if (Extension->LowerDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA)
|
||||
filterDeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return STATUS_CONTINUE_COMPLETION;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DispatchControl (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
|
||||
{
|
||||
NTSTATUS status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
if (!NT_SUCCESS (status))
|
||||
return TCCompleteIrp (Irp, status, 0);
|
||||
|
||||
if (IsHiddenSystemRunning())
|
||||
{
|
||||
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
|
||||
{
|
||||
case IOCTL_DISK_IS_WRITABLE:
|
||||
{
|
||||
// All volumes except the system volume must be read-only
|
||||
|
||||
DriveFilterExtension *bootDriveExtension = GetBootDriveFilterExtension();
|
||||
STORAGE_DEVICE_NUMBER storageDeviceNumber;
|
||||
|
||||
if (!bootDriveExtension->SystemStorageDeviceNumberValid)
|
||||
TC_BUG_CHECK (STATUS_INVALID_PARAMETER);
|
||||
|
||||
status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &storageDeviceNumber, sizeof (storageDeviceNumber));
|
||||
|
||||
if (NT_SUCCESS (status) && bootDriveExtension->SystemStorageDeviceNumber == storageDeviceNumber.DeviceNumber)
|
||||
{
|
||||
PARTITION_INFORMATION_EX partition;
|
||||
status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, &partition, sizeof (partition));
|
||||
|
||||
if (NT_SUCCESS (status) && partition.StartingOffset.QuadPart == bootDriveExtension->ConfiguredEncryptedAreaStart)
|
||||
{
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
|
||||
++HiddenSysLeakProtectionCount;
|
||||
return TCCompleteDiskIrp (Irp, STATUS_MEDIA_WRITE_PROTECTED, 0);
|
||||
}
|
||||
|
||||
case TC_IOCTL_DISK_IS_WRITABLE:
|
||||
Dump ("TC_IOCTL_DISK_IS_WRITABLE pdo=%p\n", Extension->Pdo);
|
||||
|
||||
if (!ProbingHostDeviceForWrite)
|
||||
break;
|
||||
|
||||
// Probe the real state of the device as the user is mounting a TrueCrypt volume.
|
||||
|
||||
// Volume filter may be attached to a merged drive+volume PDO. First test if TC_IOCTL_DISK_IS_WRITABLE works for the underlying device.
|
||||
status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, TC_IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0);
|
||||
|
||||
if (NT_SUCCESS (status) || status == STATUS_MEDIA_WRITE_PROTECTED)
|
||||
{
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return TCCompleteDiskIrp (Irp, status, 0);
|
||||
}
|
||||
|
||||
status = SendDeviceIoControlRequest (Extension->LowerDeviceObject, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0);
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return TCCompleteDiskIrp (Irp, status, 0);
|
||||
|
||||
case IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES:
|
||||
|
||||
// Filter IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES to enable potential future use of hidden systems on drives that use the trim operation but not wear-leveling (if any appear in future). The documentation forbids users to create hidden volumes/systems on drives that use wear-leveling and consequently also on drives that use trim (as trim is used only by drives that use wear-leveling, as of 2010).
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return TCCompleteDiskIrp (Irp, STATUS_SUCCESS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
status = PassIrp (Extension->LowerDeviceObject, Irp);
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DispatchPnp (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
if (!NT_SUCCESS (status))
|
||||
return TCCompleteIrp (Irp, status, 0);
|
||||
|
||||
switch (irpSp->MinorFunction)
|
||||
{
|
||||
case IRP_MN_START_DEVICE:
|
||||
Dump ("IRP_MN_START_DEVICE volume pdo=%p\n", Extension->Pdo);
|
||||
return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnStartDeviceCompleted, Extension);
|
||||
|
||||
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
|
||||
{
|
||||
PDEVICE_OBJECT attachedDevice = IoGetAttachedDeviceReference (DeviceObject);
|
||||
|
||||
if (attachedDevice == DeviceObject || (attachedDevice->Flags & DO_POWER_PAGABLE))
|
||||
DeviceObject->Flags |= DO_POWER_PAGABLE;
|
||||
|
||||
ObDereferenceObject (attachedDevice);
|
||||
}
|
||||
|
||||
return PassFilteredIrp (Extension->LowerDeviceObject, Irp, OnDeviceUsageNotificationCompleted, Extension);
|
||||
|
||||
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
Dump ("IRP_MN_REMOVE_DEVICE volume pdo=%p\n", Extension->Pdo);
|
||||
|
||||
IoReleaseRemoveLockAndWait (&Extension->Queue.RemoveLock, Irp);
|
||||
status = PassIrp (Extension->LowerDeviceObject, Irp);
|
||||
|
||||
IoDetachDevice (Extension->LowerDeviceObject);
|
||||
|
||||
IoDeleteDevice (DeviceObject);
|
||||
return status;
|
||||
|
||||
default:
|
||||
status = PassIrp (Extension->LowerDeviceObject, Irp);
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static NTSTATUS DispatchPower (PDEVICE_OBJECT DeviceObject, PIRP Irp, VolumeFilterExtension *Extension, PIO_STACK_LOCATION irpSp)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PoStartNextPowerIrp (Irp);
|
||||
|
||||
status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
if (!NT_SUCCESS (status))
|
||||
return TCCompleteIrp (Irp, status, 0);
|
||||
|
||||
IoSkipCurrentIrpStackLocation (Irp);
|
||||
status = PoCallDriver (Extension->LowerDeviceObject, Irp);
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
VolumeFilterExtension *Extension = (VolumeFilterExtension *) DeviceObject->DeviceExtension;
|
||||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
|
||||
NTSTATUS status;
|
||||
|
||||
ASSERT (!Extension->bRootDevice && Extension->IsVolumeFilterDevice);
|
||||
|
||||
switch (irpSp->MajorFunction)
|
||||
{
|
||||
case IRP_MJ_DEVICE_CONTROL:
|
||||
return DispatchControl (DeviceObject, Irp, Extension, irpSp);
|
||||
|
||||
case IRP_MJ_PNP:
|
||||
return DispatchPnp (DeviceObject, Irp, Extension, irpSp);
|
||||
|
||||
case IRP_MJ_POWER:
|
||||
return DispatchPower (DeviceObject, Irp, Extension, irpSp);
|
||||
|
||||
default:
|
||||
status = IoAcquireRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
if (!NT_SUCCESS (status))
|
||||
return TCCompleteIrp (Irp, status, 0);
|
||||
|
||||
status = PassIrp (Extension->LowerDeviceObject, Irp);
|
||||
|
||||
IoReleaseRemoveLock (&Extension->Queue.RemoveLock, Irp);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
19
src/Driver/VolumeFilter.h
Normal file
19
src/Driver/VolumeFilter.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
Copyright (c) 2008 TrueCrypt Developers Association. All rights reserved.
|
||||
|
||||
Governed by the TrueCrypt License 3.0 the full text of which is contained in
|
||||
the file License.txt included in TrueCrypt binary and source code distribution
|
||||
packages.
|
||||
*/
|
||||
|
||||
#ifndef TC_HEADER_DRIVER_VOLUME_FILTER
|
||||
#define TC_HEADER_DRIVER_VOLUME_FILTER
|
||||
|
||||
#include "TCdefs.h"
|
||||
|
||||
extern uint32 HiddenSysLeakProtectionCount;
|
||||
|
||||
NTSTATUS VolumeFilterAddDevice (PDRIVER_OBJECT driverObject, PDEVICE_OBJECT pdo);
|
||||
NTSTATUS VolumeFilterDispatchIrp (PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||
|
||||
#endif // TC_HEADER_DRIVER_VOLUME_FILTER
|
||||
Reference in New Issue
Block a user