freeotfegenerateblockiv.c
来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 458 行 · 第 1/2 页
C
458 行
// Description: FreeOTFE IV Generation
// By Sarah Dean
// Email: sdean12@sdean12.org
// WWW: http://www.FreeOTFE.org/
//
// -----------------------------------------------------------------------------
//
#include "FreeOTFEGenerateBlockIV.h"
#include "FreeOTFEPlatform.h"
#include "FreeOTFEDebug.h"
#include "FreeOTFECallModuleFn.h"
// =========================================================================
// Generate block IV: Sector ID
NTSTATUS
GenerateBlockIV_SectorID(
IN LARGE_INTEGER blockID,
IN unsigned int blockIDBits, // The number of bits in blockID to be used
// Set to either 32 or 64 bits
IN unsigned int blockIVLength, // The size of the required IV (and length of
// "blockIV"), in bits
OUT unsigned char* blockIV // Pointer to where the IV should be written
// Note: Caller must pre-initialise to 0x00s
)
{
NTSTATUS status;
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_ENTER, (TEXT("GenerateBlockIV_SectorID\n")));
status = STATUS_SUCCESS;
// Sanity check...
if (blockIVLength < blockIDBits)
{
DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("blockIDBits must be >= blockIVLength (blockIDBits: %d; blockIVLength: %d)\n"),
blockIDBits, blockIVLength));
status = STATUS_INTERNAL_ERROR;
}
else
{
// Generate the IV...
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("%d bit block IDs being used\n"), blockIDBits));
if (blockIDBits == 32)
{
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
*(ULONG*)blockIV = blockID.LowPart;
}
else if (blockIDBits == 64)
{
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
*(ULONG*)blockIV = blockID.LowPart;
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
// The IV is offset by sizeof(ULONG), since the IV is in unsigned chars,
// before it is cast
*(ULONG*)(blockIV+sizeof(ULONG)) = blockID.HighPart;
}
else
{
DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("blockIDBits must be set to either 32 or 64 (set to: %d)\n"), blockIDBits));
status = STATUS_INTERNAL_ERROR;
}
}
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_EXIT, (TEXT("GenerateBlockIV_SectorID\n")));
return status;
}
// =========================================================================
// Generate block IV: Hashed block ID
NTSTATUS
GenerateBlockIV_HashedSectorID(
IN DEVICE_CONTEXT* devContext,
IN LARGE_INTEGER blockID,
IN unsigned int blockIDBits, // The number of bits in blockID to be used
// Set to either 32 or 64 bits
IN unsigned int blockIVLength, // The size of the required IV (and length of
// "blockIV"), in bits
OUT unsigned char* blockIV // Pointer to where the IV should be written
// Note: Caller must pre-initialise to 0x00s
)
{
NTSTATUS status;
unsigned char hashOutput[FREEOTFE_MAX_HASH_LENGTH / 8]; // Divide by 8 to get bytes from bits
unsigned int hashLength;
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_ENTER, (TEXT("GenerateBlockIV_HashedSectorID\n")));
status = STATUS_SUCCESS;
// Generate the IV...
hashLength = sizeof(hashOutput) * 8; // Multiply by 8 to get size of buffer in *bits*
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("%d bit block IDs being used\n"), blockIDBits));
if (blockIDBits == 32)
{
// Only use the LSB 32 bits
status = DataHash(
&(devContext->IVHash),
blockIDBits, // Size in bits
(FREEOTFEBYTE*)&(blockID.LowPart),
&hashLength, // Size in bits
(FREEOTFEBYTE*)&hashOutput
);
}
else if (blockIDBits == 64)
{
// Use the full 64-bit block ID
status = DataHash(
&(devContext->IVHash),
blockIDBits, // Size in bits
(FREEOTFEBYTE*)&blockID,
&hashLength, // Size in bits
(FREEOTFEBYTE*)&hashOutput
);
}
else
{
DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("blockIDBits must be set to either 32 or 64 (set to: %d)\n"), blockIDBits));
status = STATUS_INTERNAL_ERROR;
}
if (!(NT_SUCCESS(status)))
{
DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("Failed to hash block ID to form IV.\n")));
}
else
{
// Copy the first 'n' bits of the hash to be the block IV
FREEOTFE_MEMCPY(
blockIV,
&hashOutput,
((min(blockIVLength, hashLength)) / 8) // Divide by 8 to get bytes from bits
);
}
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_EXIT, (TEXT("GenerateBlockIV_HashedSectorID\n")));
return status;
}
// =========================================================================
// Generate block IV: ESS_IV
// From Linux's dm_crypt kernel source (drivers/md/dm-crypt.c):
// * ess_iv: "encrypted sector|salt initial vector", the sector number is
// * encrypted with the bulk cipher using a salt as key. The salt
// * should be derived from the bulk cipher's key via hashing.
// i.e.:
// Let salt = malloc(IV length) bits of memory (This is done when first mounting)
// Set salt to be hash(key) (This is done when first mounting)
// Encrypt the n-bit block ID using the above salt as the key
// - Note: Linux's dm-crypt volumes use 64 bit block IDs
// Use the result as the IV
NTSTATUS
GenerateBlockIV_ESSIV(
IN DEVICE_CONTEXT* devContext,
IN LARGE_INTEGER blockID,
IN unsigned int blockIDBits, // The number of bits in blockID to be used
// Set to either 32 or 64 bits
IN unsigned int blockIVLength, // The size of the required IV (and length of
// "blockIV"), in bits
OUT unsigned char* blockIV // Pointer to where the IV should be written
// Note: Caller must pre-initialise to 0x00s
)
{
NTSTATUS status;
unsigned char cypherInput[FREEOTFE_MAX_CYPHER_BLOCKSIZE / 8]; // Divide by 8 to get bytes from bits
unsigned char cypherOutput[FREEOTFE_MAX_CYPHER_BLOCKSIZE / 8]; // Divide by 8 to get bytes from bits
unsigned int encryptLengthBytes;
unsigned int useBitsFromHash;
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_ENTER, (TEXT("GenerateBlockIV_ESSIV\n")));
status = STATUS_SUCCESS;
// Generate the IV...
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("%d bit block IDs being used\n"), blockIDBits));
DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("Block ID is: %lld\n"), blockID.QuadPart));
FREEOTFE_MEMZERO(&cypherInput, sizeof(cypherInput));
if (blockIDBits == 32)
{
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
*(ULONG*)cypherInput = blockID.LowPart;
}
else if (blockIDBits == 64)
{
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
*(ULONG*)cypherInput = blockID.LowPart;
// Cast the IV (unsigned cast) as a ptr to a ULONG, then dereference to set
// The IV is offset by sizeof(ULONG), since the IV is in unsigned chars,
// before it is cast
*(ULONG*)(cypherInput+sizeof(ULONG)) = blockID.HighPart;
}
else
{
DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("blockIDBits must be set to either 32 or 64 (set to: %d)\n"), blockIDBits));
status = STATUS_INTERNAL_ERROR;
}
encryptLengthBytes = (devContext->IVCypher.Details.BlockSize / 8);
// Allow for IV cyphers with a variable length blocksize
if (devContext->IVCypher.Details.BlockSize < 0)
{
encryptLengthBytes = (blockIDBits / 8);
}
if (NT_SUCCESS(status))
{
// Note: We use a NULL IV for this encryption
status = devContext->IVCypher.FnEncrypt(
&devContext->IVCypher.CypherGUID,
devContext->ESSIVKeyLength,
(char*)devContext->ESSIVKey,
(char*)devContext->ESSIVKeyASCII,
0,
NULL,
encryptLengthBytes,
(char*)&cypherInput,
(char*)&cypherOutput
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?