📄 driverinterfacetwo.c
字号:
memcpy(
_driver_DumpCriticalDataKey,
CriticalDataKey,
(_driver_DumpCriticalDataKeyBits / 8)
);
// Check MAC...
memcpy(
_driver_DumpCheckMAC,
CheckMAC,
(_driver_DumpCheckMACBits / 8)
);
// Encrypted block...
memcpy(
_driver_DumpPlaintextEncryptedBlock,
PlaintextEncryptedBlock,
(_driver_DumpPlaintextEncryptedBlockBits / 8)
);
// Volume details block...
memcpy(
_driver_DumpVolumeDetailsBlock,
VolumeDetailsBlock,
(_driver_DumpVolumeDetailsBlockBits / 8)
);
}
}
}
// =========================================================================
// Read and decrypt v2/v3 format CDB
BOOL _driver_ReadVolumeCriticalData_v2_v3(
WCHAR* Filename,
LARGE_INTEGER OffsetWithinFile,
char* UserPassword,
unsigned int SaltLength, // In *bits*
unsigned int KeyIterations,
CDB_DETAILS* CDBDetails,
CDB_METADATA* CDBMetaData
)
{
// Pointer to a list of strings (pointers to strings)
WCHAR** driverFilenamesHash;
WCHAR** driverFilenamesCypher;
int countDriversHash;
int countDriversCypher;
int i;
MODULE_DETAILS_MAIN mainDriver;
KDF_ALGORITHM currKDFAlg;
MAC_ALGORITHM currMACAlg;
int hashDriverIdx;
int cypherDriverIdx;
unsigned int hashImplIdx;
unsigned int cypherImplIdx;
WCHAR* currHashDriverFilename;
WCHAR* currCypherDriverFilename;
// Pointer to a list of algorithms the drivers support (pointers to structs)
HASH_DRIVER_INFO** driverInfoHash;
CYPHER_DRIVER_INFO** driverInfoCypher;
HASH_DRIVER_INFO* currDriverInfoHash;
CYPHER_DRIVER_INFO* currDriverInfoCypher;
HASH* currHashImpl;
CYPHER* currCypherImpl;
WCHAR* tmpGUIDStr;
int maxCDKSize_bits;
int maxIVSize_bits;
int cdkSize_bits;
unsigned int criticalDataKeySize;
FREEOTFEBYTE* criticalDataKey;
int leb_bits;
FREEOTFEBYTE* IV;
FREEOTFEBYTE* salt;
FREEOTFEBYTE* encryptedBlock;
FREEOTFEBYTE plaintextEncryptedBlock[CRITICAL_DATA_LENGTH / 8];
BOOL allOK;
FREEOTFEBYTE* generatedMAC;
int MACTest;
BOOL foundOK;
FREEOTFEBYTE* paddedCheckMAC;
FREEOTFEBYTE* volumeDetailsBlock;
int MACOutSize;
FREEOTFEBYTE CDB[(CRITICAL_DATA_LENGTH / 8)];
unsigned int IVSize;
DEBUGOUTGUI(DEBUGLEV_ENTER, (TEXT("_driver_ReadVolumeCriticalData_v2_v3\n")));
// Numbers...
maxCDKSize_bits = 0;
maxIVSize_bits = 0;
countDriversCypher = 0;
criticalDataKeySize = 0;
IVSize = 0;
countDriversHash = 0;
countDriversCypher = 0;
// Pointers...
criticalDataKey = NULL;
IV = NULL;
driverInfoHash = NULL;
driverInfoCypher = NULL;
driverFilenamesHash = NULL;
driverFilenamesCypher = NULL;
// Structs...
memset(&mainDriver, 0, sizeof(mainDriver));
/*
Load main FreeOTFE lib (needed for KDF, MAC, etc)
Identify all hash drivers
Identify all cypher drivers
Identify all hash algorithms supported by each of the hash drivers
Identify all cypher algorithms supported by each of the cypher drivers
Loop through all KDFs... (NOT ATM - we only support v3 CDBs)
Loop through all hash libs...
Loop through all hashes supported by current hash lib...
Loop through all cypher libs...
Loop through all cyphers supported by current cypher lib...
Loop through all MACs... (NOT ATM - we only support v3 CDBs)
If the combination can successfully decode the CDB, return
the matching combination
*/
foundOK = FALSE;
allOK = TRUE;
if (!(_driver_ReadWriteRawCDB(
Filename,
OffsetWithinFile,
TRUE,
&CDB
)))
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Unable to read raw CDB\n")));
allOK = FALSE;
}
else
{
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Raw CDB read in OK.\n")));
}
if (allOK)
{
// Load main FreeOTFE lib (needed for KDF, MAC, etc)
allOK = driver_LoadMainDLL(&mainDriver);
}
if (allOK)
{
allOK = driver_GetAllAlgorithmDriverDetails(
&countDriversHash,
&driverFilenamesHash,
&driverInfoHash,
&countDriversCypher,
&driverFilenamesCypher,
&driverInfoCypher
);
}
if (allOK)
{
// !!! OPTIMISATION !!!
// Determine the longest cypher key and IV size
maxIVSize_bits = 0;
maxCDKSize_bits = 0;
cypherDriverIdx = 0;
while (driverFilenamesCypher[cypherDriverIdx] != NULL)
{
currCypherDriverFilename = driverFilenamesCypher[cypherDriverIdx];
currDriverInfoCypher = driverInfoCypher[cypherDriverIdx];
// If we got the DLL filename, but no cypher details, skip this DLL file
if (currDriverInfoCypher == NULL)
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Optimisation skipping cypher DLL filename due to lack of driver details\n")));
cypherDriverIdx++;
continue;
}
for (cypherImplIdx = 0; cypherImplIdx < currDriverInfoCypher->CypherCount; cypherImplIdx++)
{
currCypherImpl = &(currDriverInfoCypher->CypherDetails[cypherImplIdx]);
// Determine size of "critical data key"...
cdkSize_bits = currCypherImpl->KeySize; // In *bits*
if (cdkSize_bits < 0)
{
cdkSize_bits = 512;
}
maxIVSize_bits = max(maxIVSize_bits, currCypherImpl->BlockSize);
maxCDKSize_bits = max(maxCDKSize_bits, cdkSize_bits);
}
cypherDriverIdx++;
}
IV = NULL;
criticalDataKeySize = (maxCDKSize_bits / 8);
criticalDataKey = malloc(criticalDataKeySize);
if (criticalDataKey == NULL)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to malloc storage for criticalDataKey\n")));
allOK = FALSE;
}
else
{
IV = malloc((maxIVSize_bits / 8));
if (IV == NULL)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Unable to malloc storage for IV\n")));
allOK = FALSE;
}
}
salt = CDB;
encryptedBlock = salt + (SaltLength / 8);
if (allOK)
{
// v3 CDBs use PBKDF2 as the KDF, and HMAC as the MAC
currKDFAlg = KDF_PBKDF2;
currMACAlg = MAC_HMAC;
// Loop through all hash libs...
hashDriverIdx = 0;
while (driverFilenamesHash[hashDriverIdx] != NULL)
{
currHashDriverFilename = driverFilenamesHash[hashDriverIdx];
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Testing hash driver (%d): %ls\n"), (hashDriverIdx+1), currHashDriverFilename));
currDriverInfoHash = driverInfoHash[hashDriverIdx];
if (currDriverInfoHash == NULL)
{
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Skipping; no supported algorithm details obtained.\n")));
// Skip out...
hashDriverIdx++;
continue;
}
// Loop through all hashes supported by current hash lib...
for (hashImplIdx = 0; hashImplIdx < currDriverInfoHash->HashCount; hashImplIdx++)
{
currHashImpl = &(currDriverInfoHash->HashDetails[hashImplIdx]);
GUIDToWCHAR(&(currHashImpl->HashGUID), &tmpGUIDStr);
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Hash implementation: %ls\n"), tmpGUIDStr));
SecZeroAndFreeWCHARMemory(tmpGUIDStr);
// v2 and later volumes won't work with hash algorithms with <= 0 length, or
// blocksize, as HMAC/PBKDF2 require these to be fixed
// - skip these, and move onto the next hash algorithm (if any)
if (
(currHashImpl->Length <= 0) ||
(currHashImpl->BlockSize <= 0)
)
{
// Skip - can't use
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Skipping hash; either length or blocksize <= 0.\n")));
continue;
}
// !!! OPTIMISATION !!!
// Because we only allow PBKDF2, which:
// a) Doesn't need a cypher
// b) Short keys are identical to truncated longer keys
// We derive the key *here*, outside the cypher loop
if (currKDFAlg != KDF_PBKDF2)
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("PBKDF2 assumed - optimisation failed\n")));
//MsgError('PBKDF2 assumed - optimisation failed');
allOK = FALSE;
break;
}
if (!(driver_DeriveKey(
&mainDriver,
currKDFAlg,
currHashDriverFilename,
currHashImpl->HashGUID,
TEXT(""),
FREEOTFE_NULL_GUID,
UserPassword,
CDB, // Salt at start of CDB
SaltLength, // In bits
KeyIterations,
maxCDKSize_bits, // In bits
criticalDataKey // Derived key
)))
{
DEBUGOUTGUI(DEBUGLEV_ERROR, (TEXT("Skipping hash; unable to derive key.\n")));
continue;
}
// Loop through all cypher libs...
cypherDriverIdx = 0;
while (driverFilenamesCypher[cypherDriverIdx] != NULL)
{
currCypherDriverFilename = driverFilenamesCypher[cypherDriverIdx];
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Testing cypher driver (%d): %ls\n"), (cypherDriverIdx+1), currCypherDriverFilename));
currDriverInfoCypher = driverInfoCypher[cypherDriverIdx];
if (currDriverInfoCypher == NULL)
{
// Skip out...
DEBUGOUTGUI(DEBUGLEV_WARN, (TEXT("Skipping; no supported algorithm details obtained.\n")));
cypherDriverIdx++;
continue;
}
// Loop through all cyphers supported by current cypher lib...
for (cypherImplIdx = 0; cypherImplIdx < currDriverInfoCypher->CypherCount; cypherImplIdx++)
{
currCypherImpl = &(currDriverInfoCypher->CypherDetails[cypherImplIdx]);
GUIDToWCHAR(&(currCypherImpl->CypherGUID), &tmpGUIDStr);
DEBUGOUTGUI(DEBUGLEV_INFO, (TEXT("Cypher implementation: %ls\n"), tmpGUIDStr));
SecZeroAndFreeWCHARMemory(tmpGUIDStr);
// Determine size of "critical data key"...
cdkSize_bits = currCypherImpl->KeySize; // In *bits*
if (cdkSize_bits < 0)
{
cdkSize_bits = 512;
}
// Calculate "leb"
if (currCypherImpl->BlockSize > 8)
{
leb_bits = ((CRITICAL_DATA_LENGTH - SaltLength) / currCypherImpl->BlockSize) * currCypherImpl->BlockSize;
}
else
{
leb_bits = (CRITICAL_DATA_LENGTH - SaltLength);
}
// Zero the IV for decryption, in case previous was "dirty"
IVSize = 0;
if (currCypherImpl->BlockSize > 0)
{
IVSize = currCypherImpl->BlockSize;
memset(IV, 0, (IVSize / 8));
}
if (!(driver_CypherDecryptData(
currCypherDriverFilename,
currCypherImpl->CypherGUID,
cdkSize_bits,
criticalDataKey,
IVSize,
IV,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -