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 + -
显示快捷键?