📄 driverinterfacetwo.c
字号:
// Description:
// By Sarah Dean
// Email: sdean12@sdean12.org
// WWW: http://www.FreeOTFE.org/
//
// -----------------------------------------------------------------------------
//
#include <storemgr.h> // Required for STORAGE_DEVICE_TYPE_PCCARD, etc
#include "SDUGeneral.h"
#include "SDUHexDump.h"
#include "FreeOTFENULLGUID.h"
#include "DriverInterface.h"
#include "DriverInterfaceTwo.h"
#include "FreeOTFEDebug.h"
#include "FreeOTFEAPIConstsCommon.h"
#include "FreeOTFEPlatform.h"
#include "FreeOTFElib.h"
#include "FreeOTFE4PDAlib.h"
#include "DriverInterfaceHash.h"
#include "DriverInterfaceCypher.h"
#include "DriverInterfaceCommon.h"
// =========================================================================
// Constants...
// In *bits*
#define CDB_MAX_MAC_LENGTH 512
// These are artifical maximums; they must be enough to store the results of
// the DIOC calls when the amount of data output is variable
// In *bits*
#define MAX_DERIVED_KEY_LENGTH (1024 * 1024)
// In *bits*
#define MAX_MAC_LENGTH (1024 * 1024)
// In *bits*
#define MML 512
#define CDB_VERSION 3
// =========================================================================
// Forward declarations...
void driver_UnloadMainDLL(MODULE_DETAILS_MAIN* DLLDetails);
BOOL
_driver_BackupRestoreCDB(
WCHAR* SrcFilename,
LARGE_INTEGER SrcOffset,
WCHAR* DestFilename,
LARGE_INTEGER DestOffset
);
// =========================================================================
// Note: Ignores any random padding data
BOOL _driver_ParseVolumeDetailsBlock(
unsigned int rawDataSize, // In bytes
FREEOTFEBYTE* rawData,
CDB_DETAILS* volumeDetailsBlock
)
{
BOOL allOK = TRUE;
FREEOTFEBYTE* ptr;
int CDBFormatID;
LARGE_INTEGER tmpLargeInteger;
DWORD tmpDWORD;
char tmpChar;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("_driver_ParseVolumeDetailsBlock\n")));
ptr = rawData;
if (allOK)
{
// 8 bits: CDB Format ID...
ptr = SDUUnpack_char(ptr, &tmpChar);
CDBFormatID = tmpChar;
volumeDetailsBlock->CDBFormatID = CDBFormatID;
// We only support CDB v3 format and later (i.e. Desktop FreeOTFE
// v00.54.00 and later)
if (CDBFormatID < 3)
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Unsupported CDB version (CDB is version: %d)\n"), CDBFormatID));
allOK = FALSE;
}
}
if (allOK)
{
// 32 bits: Volume flags...
ptr = SDUUnpack_DWORD(ptr, &tmpDWORD);
volumeDetailsBlock->VolumeFlags = tmpDWORD;
}
if (allOK)
{
// 64 bits: Partition length...
ptr = SDUUnpack_LARGE_INTEGER(ptr, &tmpLargeInteger);
volumeDetailsBlock->PartitionSize.QuadPart = tmpLargeInteger.QuadPart;
}
if (allOK)
{
// 32 bits: Master key length...
ptr = SDUUnpack_DWORD(ptr, &tmpDWORD);
volumeDetailsBlock->MasterKeyLength = tmpDWORD;
// Note: If decrypted badly, can't rely on: criticalData.MasterKeyLen to be
// valid
// We check if the volume details block's master key length implies
// would put idx beyond the amount of data we have
if (((ptr - rawData) + (volumeDetailsBlock->MasterKeyLength / 8)) >
rawDataSize)
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Invalid MasterKeyLength in CDB (length: %d *bits*)\n"), volumeDetailsBlock->MasterKeyLength));
allOK = FALSE;
}
}
if (allOK)
{
// Variable bits: Master key...
volumeDetailsBlock->MasterKey = malloc((volumeDetailsBlock->MasterKeyLength / 8));
if (volumeDetailsBlock->MasterKey == NULL)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to malloc memory for MasterKey (length: %d *bits*)\n"), volumeDetailsBlock->MasterKeyLength));
allOK = FALSE;
}
else
{
memcpy(volumeDetailsBlock->MasterKey, ptr, (volumeDetailsBlock->MasterKeyLength / 8));
ptr += (volumeDetailsBlock->MasterKeyLength / 8);
}
}
if (allOK)
{
// 8 bits: Requested drive letter...
// Not used under WinCE, but preserved in case user wants to change
// password
ptr = SDUUnpack_char(ptr, &tmpChar);
volumeDetailsBlock->DefaultDrive = tmpChar;
}
if (allOK)
{
// 32 bits: Volume IV length...
ptr = SDUUnpack_DWORD(ptr, &tmpDWORD);
volumeDetailsBlock->VolumeIVLength = tmpDWORD;
// Note: If decrypted badly, can't rely on: criticalData.VolumeIVLength to be
// valid
// We check if the volume details block's master key length implies
// would put idx beyond the amount of data we have
if (((ptr - rawData) + (volumeDetailsBlock->VolumeIVLength / 8)) >
rawDataSize)
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Invalid VolumeIVLength in CDB (length: %d *bits*)\n"), volumeDetailsBlock->VolumeIVLength));
allOK = FALSE;
}
}
if (allOK)
{
// Variable bits: Volume IV...
volumeDetailsBlock->VolumeIV = malloc((volumeDetailsBlock->VolumeIVLength / 8));
if (volumeDetailsBlock->VolumeIV == NULL)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to malloc memory for VolumeIV (length: %d *bits*)\n"), volumeDetailsBlock->VolumeIVLength));
allOK = FALSE;
}
else
{
memcpy(volumeDetailsBlock->VolumeIV, ptr, (volumeDetailsBlock->VolumeIVLength / 8));
ptr += (volumeDetailsBlock->VolumeIVLength / 8);
}
}
if (allOK)
{
// 8 bits: Sector IV generation method...
ptr = SDUUnpack_char(ptr, &tmpChar);
volumeDetailsBlock->SectorIVGenMethod = (SECTOR_IV_GEN_METHOD)tmpChar;
}
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("_driver_ParseVolumeDetailsBlock\n")));
return allOK;
}
// =========================================================================
// Key derivation function
// Note: *Caller* is responsible for freeing of DK
BOOL driver_DeriveKey(
MODULE_DETAILS_MAIN* mainDriver,
KDF_ALGORITHM kdfAlgorithm,
WCHAR* hashKernelModeDeviceName,
GUID hashGUID,
WCHAR* cypherKernelModeDeviceName,
GUID cypherGUID,
char* Password,
FREEOTFEBYTE* Salt,
unsigned int SaltLength, // In *bits*
unsigned int Iterations,
unsigned int dkLenBits, // In *bits*
FREEOTFEBYTE* DK
)
{
BOOL retval = FALSE;
DIOC_DERIVE_KEY_IN* DIOCIn;
DIOC_DERIVE_KEY_OUT* DIOCOut;
DWORD DIOCInSize;
DWORD DIOCOutSize;
unsigned int passLen; // In bytes
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_DeriveKey\n")));
passLen = strlen(Password);
DIOCInSize = (
(
sizeof(*DIOCIn) -
sizeof(DIOCIn->Password)
) -
sizeof(DIOCIn->Salt)
) +
passLen +
(SaltLength / 8);
// We use the maximum buffer possible, as the full MAC length depends on
// the MAC, hash, etc
DIOCOutSize = sizeof(*DIOCOut) -
sizeof(DIOCOut->DerivedKey) +
(max(MAX_DERIVED_KEY_LENGTH, dkLenBits) / 8);
DIOCIn = malloc(DIOCInSize);
DIOCOut = malloc(DIOCOutSize);
if (
(DIOCIn != NULL) &&
(DIOCOut != NULL)
)
{
DIOCIn->KDFAlgorithm = kdfAlgorithm;
wcscpy(DIOCIn->HashDeviceName, hashKernelModeDeviceName);
DIOCIn->HashGUID = hashGUID;
wcscpy(DIOCIn->CypherDeviceName, cypherKernelModeDeviceName);
DIOCIn->CypherGUID = cypherGUID;
DIOCIn->Iterations = Iterations;
DIOCIn->LengthWanted = dkLenBits;
DIOCIn->PasswordLength = (passLen * 8);
DIOCIn->SaltLength = SaltLength;
memcpy(DIOCIn->Password, Password, passLen);
memcpy((DIOCIn->Password + passLen), Salt, (SaltLength / 8));
if (mainDriver->FnDeriveKey(
DIOCInSize,
DIOCIn,
DIOCOutSize,
DIOCOut
) == ERROR_SUCCESS)
{
if (DIOCOut->DerivedKeyLength >= dkLenBits)
{
memcpy(DK, DIOCOut->DerivedKey, (dkLenBits / 8));
retval = TRUE;
}
}
}
SecZeroAndFreeMemory(DIOCIn, DIOCInSize);
SecZeroAndFreeMemory(DIOCOut, DIOCOutSize);
DEBUGOUTGUI(DEBUGLEV_EXIT, (TEXT("driver_DeriveKey\n")));
return retval;
}
// =========================================================================
// Generate MAC of data using hash driver/encryption driver identified
// Note: "tBits" is in *bits* not *bytes*
// tBits - Set the the number of bits to return; set to -ve value for no
// truncation/padding
// If tBits is larger than the number of bits the MAC would normally
// be, then the MAC will be right-padded with NULLs
// If tBits is set to a -ve number, then this function will return
// an MAC of variable length
// This will be set to the length of MACOut on exit
// MACOut - This will be set to point to the MAC generated. This function
// allocates memory for the MAC; it is is *callers* responsibility to
// free this off after use
BOOL driver_MACData(
MODULE_DETAILS_MAIN* mainDriver,
MAC_ALGORITHM macAlgorithm,
const WCHAR* hashKernelModeDeviceName,
GUID hashGUID,
const WCHAR* cypherKernelModeDeviceName,
GUID cypherGUID,
unsigned int KeyLength,
FREEOTFEBYTE* Key,
unsigned int DataLength,
FREEOTFEBYTE* Data,
FREEOTFEBYTE** MACOut,
int* tBits
)
{
BOOL retval = FALSE;
DIOC_GENERATE_MAC_IN* DIOCIn;
DIOC_GENERATE_MAC_OUT* DIOCOut;
DWORD DIOCInSize;
DWORD DIOCOutSize;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("driver_MACData\n")));
DIOCInSize = sizeof(*DIOCIn) -
sizeof(DIOCIn->Key) -
sizeof(DIOCIn->Data) +
(KeyLength / 8) +
(DataLength / 8);
// We use the maximum buffer possible, as the full MAC length depends on
// the MAC, hash, etc
DIOCOutSize = (sizeof(*DIOCOut) - sizeof(DIOCOut->MAC)) +
(max(MAX_MAC_LENGTH, *tBits) / 8);
DIOCIn = malloc(DIOCInSize);
DIOCOut = malloc(DIOCOutSize);
if (
(DIOCIn != NULL) &&
(DIOCOut != NULL)
)
{
DIOCIn->MACAlgorithm = macAlgorithm;
wcscpy(DIOCIn->HashDeviceName, hashKernelModeDeviceName);
DIOCIn->HashGUID = hashGUID;
wcscpy(DIOCIn->CypherDeviceName, cypherKernelModeDeviceName);
DIOCIn->CypherGUID = cypherGUID;
DIOCIn->LengthWanted = *tBits;
DIOCIn->KeyLength = KeyLength;
DIOCIn->DataLength = DataLength;
memcpy(DIOCIn->Key, Key, (KeyLength / 8));
memcpy((DIOCIn->Key + (KeyLength / 8)), Data, (DataLength / 8));
if (mainDriver->FnMACData(
DIOCInSize,
DIOCIn,
DIOCOutSize,
DIOCOut
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -