freeotfecyphertwofish_hifncs.c

来自「文件驱动加密,功能强大,可产生加密分区,支持AES,MD2,MD4,MD5MD2」· C语言 代码 · 共 390 行

C
390
字号
// Description: 
// By Sarah Dean
// Email: sdean12@sdean12.org
// WWW:   http://www.FreeOTFE.org/
//
// -----------------------------------------------------------------------------
//

#ifndef WINCE
#include <ntddk.h>
#endif

#include "FreeOTFECypherTwofish_HifnCS.h"

#include "FreeOTFECypherImpl.h"
#include "FreeOTFECypherAPICommon.h"

#ifdef WINCE
#include "FreeOTFE4PDACypherDriver.h"  // Required for DRIVER_CYPHER_VERSION
#else
#include "FreeOTFECypherDriver.h"  // Required for DRIVER_CYPHER_VERSION
#endif

#include "FreeOTFEPlatform.h"
#include "FreeOTFEDebug.h"
#include "FreeOTFElib.h"


// Include Hi/fn and Counterpane Systems Twofish library...
#include "AES.H"


// =========================================================================
// Cypher driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpCypherDriverExtDetailsInit(
    IN OUT CYPHER_DRIVER_INFO* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDriverExtDetailsInit\n")));


    // -- POPULATE DRIVER IDENTIFICATION --
    FREEOTFE_MEMZERO(driverInfo->DriverTitle, sizeof(driverInfo->DriverTitle));
    FREEOTFE_MEMCPY(
                  driverInfo->DriverTitle,
                  DRIVER_TITLE,
                  strlen(DRIVER_TITLE)
                 );

    driverInfo->DriverGUID = DRIVER_GUID;
    driverInfo->DriverVersionID = DRIVER_CYPHER_VERSION;


    // -- POPULATE cyphers SUPPORTED --
    driverInfo->CypherDetails = FREEOTFE_MEMALLOC((sizeof(CYPHER) * CYPHERS_SUPPORTED));    

    driverInfo->CypherCount = CYPHERS_SUPPORTED;


    // -- Twofish-128 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->CypherDetails[idx].Title, MAX_CYPHER_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->CypherDetails[idx].Title,
                  DRIVER_CIPHER_TITLE_TWOFISH_128,
                  strlen(DRIVER_CIPHER_TITLE_TWOFISH_128)
                 );

    driverInfo->CypherDetails[idx].Mode       = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySize    = 128;
    driverInfo->CypherDetails[idx].BlockSize  = BLOCK_SIZE;  // From TWOFISH.C
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_128;


    // -- Twofish-192 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->CypherDetails[idx].Title, MAX_CYPHER_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->CypherDetails[idx].Title,
                  DRIVER_CIPHER_TITLE_TWOFISH_192,
                  strlen(DRIVER_CIPHER_TITLE_TWOFISH_192)
                 );

    driverInfo->CypherDetails[idx].Mode       = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySize    = 192;
    driverInfo->CypherDetails[idx].BlockSize  = BLOCK_SIZE;  // From TWOFISH.C
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_192;


    // -- Twofish-256 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->CypherDetails[idx].Title, MAX_CYPHER_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->CypherDetails[idx].Title,
                  DRIVER_CIPHER_TITLE_TWOFISH_256,
                  strlen(DRIVER_CIPHER_TITLE_TWOFISH_256)
                 );

    driverInfo->CypherDetails[idx].Mode       = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySize    = 256;
    driverInfo->CypherDetails[idx].BlockSize  = BLOCK_SIZE;  // From TWOFISH.C
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_256;


    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDriverExtDetailsInit\n")));

    return status;
}


// =========================================================================
// Cypher driver cleardown function
// driverInfo - The structure to be cleared down
NTSTATUS
ImpCypherDriverExtDetailsCleardown(    
    IN OUT CYPHER_DRIVER_INFO* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDriverExtDetailsCleardown\n")));

    if (driverInfo->CypherDetails != NULL)
        {
        FREEOTFE_FREE(driverInfo->CypherDetails);
        }

    driverInfo->CypherDetails = NULL;
    driverInfo->CypherCount = 0;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDriverExtDetailsCleardown\n")));

    return status;
}


// =========================================================================
// Encryption function
// Note: CyphertextLength must be set to the size of the CyphertextData buffer on
//       entry; on exit, this will be set to the size of the buffer used.
NTSTATUS
ImpCypherEncryptData(
    IN      GUID* CypherGUID,
    IN      int KeyLength,  // In bits
    IN      char *Key,
    IN      char *KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      char *IV,
    IN      int PlaintextLength,  // In bytes
    IN      char *PlaintextData,
    OUT     char *CyphertextData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    cipherInstance cipher;
    // NOTE: We can't do "keyInstance key;" as this causes a __chkstk error on
    //       building. For that reason, we have to manually allocate the memory
    //       outselves
    keyInstance* key;
    int countBitsProcessed;
    char* asciizIV;
    unsigned int asciizIVLen;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherEncryptData\n")));

    if (!(
		  (IsEqualGUID(&CIPHER_GUID_TWOFISH_128, CypherGUID)) || 
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_192, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_256, CypherGUID))
		 ))
        {
		DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n")));
        status = STATUS_INVALID_PARAMETER;
        }

    key = FREEOTFE_MEMALLOC(sizeof(keyInstance));    
    FREEOTFE_MEMZERO(key, sizeof(keyInstance));

    FREEOTFE_MEMZERO(&cipher, sizeof(cipherInstance));

    if NT_SUCCESS(status)
        {
        if ( (IV == NULL) && (IVLength != 0) )
            {
            // Sanity check failed...
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Inconsistant: NULL passed as %d bit long IV\n"), IVLength));
            status = STATUS_INVALID_PARAMETER;
            }
        else if ( (IV == NULL) || (IVLength == 0) )
            {
            // Note: The IV is NULL; it's zero's by the FREEOTFE_MEMZERO above
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Using NULL IV\n")));
            asciizIV = NULL;
            }
        else
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Using specific IV\n")));

            // Convert the IV to it's ASCIIZ representation
            // Horrific, but that's the cypher AES API for you...
            asciizIVLen = (IVLength / 4) + 1; // Convert bits into nibbles,
                                              // and add a NULL terminator

            asciizIV = FREEOTFE_MEMALLOC(asciizIVLen);
            ConvertDataToASCIIRep(IVLength, IV, asciizIV);
            }

        }

    if NT_SUCCESS(status)
        {
        if (cipherInit(&cipher, MODE_CBC, asciizIV) != TRUE)
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not cipherInit.\n")));
            status = STATUS_INTERNAL_ERROR;
            }
        }


    if NT_SUCCESS(status)
        {
        if (makeKey(key, DIR_DECRYPT, KeyLength, KeyASCII) != TRUE)
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not makeKey.\n")));
            status = STATUS_INTERNAL_ERROR;
            }
        }

    if NT_SUCCESS(status)
        {  
        countBitsProcessed = blockEncrypt(&cipher, key, (BYTE*)PlaintextData, (PlaintextLength * 8), (BYTE*)CyphertextData);
        if (countBitsProcessed != (PlaintextLength * 8))
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not encrypt/decrypt all; expected: %d; got: %d\n"), (PlaintextLength * 8), countBitsProcessed));
            status = STATUS_INTERNAL_ERROR;
            }
        }


    // Nuke the key and cipher instance...
    SecZeroMemory(&cipher, sizeof(cipherInstance));

    if (asciizIV != NULL)
        {
        SecZeroMemory(asciizIV, sizeof(asciizIVLen));
        FREEOTFE_FREE(asciizIV);
        }

    SecZeroMemory(key, sizeof(keyInstance));
    FREEOTFE_FREE(key);

    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherEncryptData\n")));

    return status;
}


// =========================================================================
// Decryption function
// Note: PlaintextLength must be set to the size of the PlaintextData buffer on
//       entry; on exit, this will be set to the size of the buffer used.
NTSTATUS
ImpCypherDecryptData(
    IN      GUID* CypherGUID,
    IN      int KeyLength,  // In bits
    IN      char *Key,
    IN      char *KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      char *IV,
    IN      int CyphertextLength,  // In bytes
    IN      char *CyphertextData,
    OUT     char *PlaintextData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    cipherInstance cipher;
    // NOTE: We can't do "keyInstance key;" as this causes a __chkstk error on
    //       building. For that reason, we have to manually allocate the memory
    //       outselves
    keyInstance* key;
    int countBitsProcessed;
    char* asciizIV;
    unsigned int asciizIVLen;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDecryptData\n")));

    if (!(
		  (IsEqualGUID(&CIPHER_GUID_TWOFISH_128, CypherGUID)) || 
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_192, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_256, CypherGUID))
		 ))
		{
		DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n")));
        status = STATUS_INVALID_PARAMETER;
        }

    key = FREEOTFE_MEMALLOC(sizeof(keyInstance));    
    FREEOTFE_MEMZERO(key, sizeof(keyInstance));

    FREEOTFE_MEMZERO(&cipher, sizeof(cipherInstance));

    if NT_SUCCESS(status)
        {
        if ( (IV == NULL) && (IVLength != 0) )
            {
            // Sanity check failed...
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Inconsistant: NULL passed as %d bit long IV\n"), IVLength));
            status = STATUS_INVALID_PARAMETER;
            }
        else if ( (IV == NULL) || (IVLength == 0) )
            {
            // Note: The IV is NULL; it's zero's by the FREEOTFE_MEMZERO above
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Using NULL IV\n")));
            asciizIV = NULL;
            }
        else
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_INFO, (TEXT("Using specific IV\n")));

            // Convert the IV to it's ASCIIZ representation
            // Horrific, but that's the cypher AES API for you...
            asciizIVLen = (IVLength / 4) + 1; // Convert bits into nibbles,
                                              // and add a NULL terminator

            asciizIV = FREEOTFE_MEMALLOC(asciizIVLen);
            ConvertDataToASCIIRep(IVLength, IV, asciizIV);
            }

        }

    if NT_SUCCESS(status)
        {
        if (cipherInit(&cipher, MODE_CBC, asciizIV) != TRUE)
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not cipherInit.\n")));
            status = STATUS_INTERNAL_ERROR;
            }
        }


    if NT_SUCCESS(status)
        {
        if (makeKey(key, DIR_DECRYPT, KeyLength, KeyASCII) != TRUE)
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not makeKey.\n")));
            status = STATUS_INTERNAL_ERROR;
            }
        }

    if NT_SUCCESS(status)
        {  
        countBitsProcessed = blockDecrypt(&cipher, key, (BYTE*)CyphertextData, (CyphertextLength * 8), (BYTE*)PlaintextData);
        if (countBitsProcessed != (CyphertextLength * 8))
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Could not encrypt/decrypt all; expected: %d; got: %d\n"), (CyphertextLength * 8), countBitsProcessed));
            status = STATUS_INTERNAL_ERROR;
            }
        }


    // Nuke the key and cipher instance...
    SecZeroMemory(&cipher, sizeof(cipherInstance));

    if (asciizIV != NULL)
        {
        SecZeroMemory(asciizIV, sizeof(asciizIVLen));
        FREEOTFE_FREE(asciizIV);
        }

    SecZeroMemory(key, sizeof(keyInstance));
    FREEOTFE_FREE(key);

    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDecryptData\n")));

    return status;
}


// =========================================================================
// =========================================================================

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?