Ejemplo n.º 1
0
// =========================================================================
// Cypher driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpCypherDriverExtDetailsInit_v3(
    IN OUT CYPHER_DRIVER_INFO_v3* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDriverExtDetailsInit_v3\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->CypherCount = CYPHERS_SUPPORTED;
    driverInfo->CypherDetails = FREEOTFE_MEMCALLOC(
                                                   sizeof(CYPHER_v3),
                                                   driverInfo->CypherCount
                                                  );


    // -- CAST5 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->CypherDetails[idx].Title, MAX_CYPHER_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->CypherDetails[idx].Title,
                  DRIVER_CIPHER_TITLE_CAST5,
                  strlen(DRIVER_CIPHER_TITLE_CAST5)
                 );

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 128;
    driverInfo->CypherDetails[idx].BlockSize         = (cast5_desc.block_length * 8);
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_CAST5;
    driverInfo->CypherDetails[idx].KeySizeRequired   = driverInfo->CypherDetails[idx].KeySizeUnderlying;


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

    return status;
}
Ejemplo n.º 2
0
// =========================================================================
// Hash driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpHashDriverExtDetailsInit(
    IN OUT HASH_DRIVER_INFO* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;

    DEBUGOUTHASHIMPL(DEBUGLEV_ENTER, (TEXT("ImpHashDriverExtDetailsInit\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_HASH_VERSION;


    // -- POPULATE HASHES SUPPORTED --
    driverInfo->HashCount = HASHES_SUPPORTED;
    driverInfo->HashDetails = FREEOTFE_MEMCALLOC(
                                                 sizeof(HASH),
                                                 driverInfo->HashCount
                                                );


    // -- Null --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_NULL,
                  strlen(DRIVER_HASH_TITLE_NULL)
                 );

    driverInfo->HashDetails[idx].Length = -1;
    driverInfo->HashDetails[idx].BlockSize = -1;
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_NULL;


    DEBUGOUTHASHIMPL(DEBUGLEV_EXIT, (TEXT("ImpHashDriverExtDetailsInit\n")));

    return status;
}
// =========================================================================
// Copy contents of CYPHER_DRIVER_INFO_v3 struct to CYPHER_DRIVER_INFO_v1
// struct
// ! WARNING !
void
CopyCYPHER_DRIVER_INFO_v1ToCYPHER_DRIVER_INFO_v3(
    IN     CYPHER_DRIVER_INFO_v1*  Source,
    OUT    CYPHER_DRIVER_INFO_v3*  Dest
)
{
    unsigned int i;

    Dest->DriverGUID = Source->DriverGUID;

    FREEOTFE_MEMZERO(Dest->DriverTitle, sizeof(Dest->DriverTitle));
    FREEOTFE_MEMCPY(
                    Dest->DriverTitle,
                    Source->DriverTitle,
                    strlen(Source->DriverTitle)
                   );

    Dest->DriverVersionID = Source->DriverVersionID;
    Dest->CypherCount = Source->CypherCount;

    Dest->CypherDetails = FREEOTFE_MEMCALLOC( 
                                             Source->CypherCount,
                                             sizeof(Dest->CypherDetails[0])
                                            );
    for (i = 0; i < Source->CypherCount; i++)
        {
        CopyCYPHER_v1ToCYPHER_v3(
                                 &(Source->CypherDetails[i]),
                                 &(Dest->CypherDetails[i])
                                );
        }
}
Ejemplo n.º 4
0
// =========================================================================
// Hash function
// driverInfo - The structure to be cleared down
NTSTATUS
ImpHashHashData(
    IN      GUID* HashGUID,
    IN      unsigned int DataLength,  // In bits
    IN      FREEOTFEBYTE* Data,
    IN OUT  unsigned int* HashLength,  // In bits
    OUT     FREEOTFEBYTE* Hash
)
{
    NTSTATUS status = STATUS_SUCCESS;
    WCHAR* tmpGUIDStr;

    DEBUGOUTHASHIMPL(DEBUGLEV_ENTER, (TEXT("ImpHashHashData\n")));
    if (IsEqualGUID(&HASH_GUID_NULL, HashGUID))
        {
        if (*HashLength < DataLength)
            {
            DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"),
                *HashLength,
                DataLength
                ));
            status = STATUS_BUFFER_TOO_SMALL;
            }
        else
            {
            FREEOTFE_MEMZERO(
                          Hash,
                          ((*HashLength) / 8)  // Convert bits to bytes
                         );

            FREEOTFE_MEMCPY(            
                          Hash,
                          Data,
                          (DataLength / 8)  // Convert bits to bytes
                         );

            *HashLength = DataLength;
            }
            
        }
    else
        {
        DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("Driver doesn't recognise GUID\n")));
        GUIDToWCHAR(HashGUID, &tmpGUIDStr);
        DEBUGOUTHASHIMPL(DEBUGLEV_INFO, (TEXT("Hash passed in: %ls\n"), tmpGUIDStr));
        SecZeroAndFreeWCHARMemory(tmpGUIDStr);
        status = STATUS_INVALID_PARAMETER;
        }
        
    DEBUGOUTHASHIMPL(DEBUGLEV_EXIT, (TEXT("ImpHashHashData\n")));
      
    return status;
}
// =========================================================================
// Copy contents of CYPHER_v3 struct to CYPHER_v1 struct
void
CopyCYPHER_v3ToCYPHER_v1(
    IN     CYPHER_v3*  Source,
    OUT    CYPHER_v1*  Dest
)
{
    FREEOTFE_MEMZERO(Dest->Title, sizeof(Dest->Title));
    FREEOTFE_MEMCPY(
                    Dest->Title,
                    Source->Title,
                    strlen(Source->Title)
                   );

    Dest->BlockSize         = Source->BlockSize;
    Dest->VersionID         = Source->VersionID;
    Dest->CypherGUID        = Source->CypherGUID;
    Dest->KeySizeUnderlying = Source->KeySizeRequired;
    Dest->Mode              = Source->Mode;
}
// =========================================================================
// Copy contents of CYPHER_v1 struct to CYPHER_v3 struct
void
CopyCYPHER_v1ToCYPHER_v3(
    IN     CYPHER_v1*  Source,
    OUT    CYPHER_v3*  Dest
)
{
    FREEOTFE_MEMZERO(Dest->Title, sizeof(Dest->Title));
    FREEOTFE_MEMCPY(
                    Dest->Title,
                    Source->Title,
                    strlen(Source->Title)
                   );

    Dest->BlockSize         = Source->BlockSize;
    Dest->VersionID         = Source->VersionID;
    Dest->CypherGUID        = Source->CypherGUID;
    Dest->KeySizeUnderlying = Source->KeySizeUnderlying;
    Dest->Mode              = Source->Mode;

    // Values which don't exist in the earlier struct...
    Dest->KeySizeRequired   = Dest->KeySizeUnderlying;
}
// =========================================================================
// Cypher driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpCypherDriverExtDetailsInit_v3(
    IN OUT CYPHER_DRIVER_INFO_v3* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;

    DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("ImpCypherDriverExtDetailsInit_v3\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->CypherCount = CYPHERS_SUPPORTED;
    driverInfo->CypherDetails = FREEOTFE_MEMCALLOC(
                                                   sizeof(CYPHER_v3),
                                                   driverInfo->CypherCount
                                                  );


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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_XTS;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 256;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_256_XTS;
    driverInfo->CypherDetails[idx].KeySizeRequired   = (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);

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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_XTS;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 192;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_192_XTS;
    driverInfo->CypherDetails[idx].KeySizeRequired   = (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);

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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_XTS;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 128;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_128_XTS;
    driverInfo->CypherDetails[idx].KeySizeRequired   = (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);


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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 256;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_256_CBC;
    driverInfo->CypherDetails[idx].KeySizeRequired   = driverInfo->CypherDetails[idx].KeySizeUnderlying;

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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 192;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_192_CBC;
    driverInfo->CypherDetails[idx].KeySizeRequired   = driverInfo->CypherDetails[idx].KeySizeUnderlying;

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

    driverInfo->CypherDetails[idx].Mode              = CYPHER_MODE_CBC;
    driverInfo->CypherDetails[idx].KeySizeUnderlying = 128;
    driverInfo->CypherDetails[idx].BlockSize         = TWOFISH_BLOCK_SIZE;
    driverInfo->CypherDetails[idx].VersionID         = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID        = CIPHER_GUID_TWOFISH_128_CBC;
    driverInfo->CypherDetails[idx].KeySizeRequired   = driverInfo->CypherDetails[idx].KeySizeUnderlying;


    DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("ImpCypherDriverExtDetailsInit_v3\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
ImpCypherDecryptSectorData(
    IN      GUID* CypherGUID,
    IN      LARGE_INTEGER SectorID,  // Indexed from zero
    IN      int SectorSize, // In bytes
    IN      int KeyLength,  // In bits
    IN      FREEOTFEBYTE* Key,
    IN      char* KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      FREEOTFEBYTE* IV,
    IN      int CyphertextLength,  // In bytes
    IN      FREEOTFEBYTE* CyphertextData,
    OUT     FREEOTFEBYTE* PlaintextData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    // Null IV in case we're not given an IV
    char zeroIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE];
    int i;
    INTEGER_128 blockID128;
    int errnum;
    TWOFISH(CONTEXT) context;

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

    if (
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_256_XTS, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_192_XTS, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_128_XTS, CypherGUID)) 
         )
        {
        // Generate index in correct format
        // XTS uses:
        //   *) The sector index (i.e. the number of N-bit sectors)
        //   *) The first sector is sector 0
        //   *) Littleendian format
        LARGE_INTEGER__To__INTEGER_128_LittleEndian(
                                            SectorID,
                                            blockID128
                                           );

        if ((errnum = xts_decrypt(
                              &context,
                              &(TWOFISH(set_key)),
                              &(TWOFISH(encrypt)),
                              &(TWOFISH(decrypt)),
                              ((KeyLength/2)),
                              Key, 
                              ((KeyLength/2)),
                              &(Key[(KeyLength/2)/8]),
                              CyphertextData, 
                              CyphertextLength, 
                              PlaintextData, 
                              blockID128
                             )) != CRYPT_OK)
            {
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
            status = STATUS_UNSUCCESSFUL;
            } 

        }
    else if (
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_256_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_192_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_TWOFISH_128_CBC, CypherGUID)) 
         )
        {
        // Handle situation where a NULL/zero length IV is passed in
        if ( (IVLength == 0) || (IV == NULL) )
            {
            FREEOTFE_MEMZERO(&zeroIV, sizeof(zeroIV));
            IV = (char*)&zeroIV;
            }


        // Process data using CBC mode
        //
        // CBC Mode DECRYPT:
        // *) Setup key
        // *) For each block...
        //     *) Decrypt cyphertext with key
        //     *) XOR output plaintext with IV
        //     *) IV = Cyphertext data

        // Note: "dec" specified; we're DECRYPTING
        TWOFISH(set_key)(&context, Key, KeyLength, dec);
        for (i=0; i < CyphertextLength; i += (TWOFISH_BLOCK_SIZE / 8))
            {
            TWOFISH(decrypt)(&context, CyphertextData+i, PlaintextData+i);
            XORBlock(PlaintextData+i, IV, PlaintextData+i, (TWOFISH_BLOCK_SIZE / 8));
            IV = CyphertextData+i;
            }

        }
    else
        {
        DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n")));
        status = STATUS_INVALID_PARAMETER;
        }

    SecZeroMemory(&context, sizeof(context));


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

    return status;
}
// =========================================================================
// Generate block IV
NTSTATUS
GenerateBlockIV(
    IN      DEVICE_CONTEXT* devContext,
    IN      LARGE_INTEGER fileOffset,  // The offset within the *volume file* where
                                       // the data was obtained from
    IN      unsigned int blockIVLength,  // The size of the required IV (and length of
	                                 // "sectorIV"), in bits
    OUT     unsigned char* blockIV
)
{
    NTSTATUS status;
    LARGE_INTEGER blockID;
    unsigned int useBytes;
    unsigned int i;
    unsigned int j;

    DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_ENTER, (TEXT("GenerateBlockIV\n")));

    status = STATUS_SUCCESS;

    DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("Block IV length is: %d\n"), blockIVLength));
    // Belt 'n braces - we should never be called if there isn't a fixed blocksize...
    if (blockIVLength <= 0)
        {
        DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("IV length requested is <= 0\n")));
        status = STATUS_INVALID_PARAMETER;
        }
    else
        {
        // Generate the IV...
        // Clear down the IV so we have a NULL IV/baseline IV to work from...
        FREEOTFE_MEMZERO(
                         blockIV,
                         (blockIVLength / 8)
                        );

        blockID = GetBlockID(devContext, fileOffset);

        DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("Block IV generation method: %d\n"), devContext->SectorIVGenMethod));
        switch (devContext->SectorIVGenMethod)
            {
            case SCTRIVGEN_NONE:
                {
                // Do nothing - sector IV already zero'd
                break;
                }

            case SCTRIVGEN_32BIT_SECTOR_ID:
                {
                status = GenerateBlockIV_SectorID(
                            blockID,
                            32,
                            blockIVLength,
                            blockIV
                            );
                break;
                }

            case SCTRIVGEN_64BIT_SECTOR_ID:
                {
                status = GenerateBlockIV_SectorID(
                            blockID,
                            64,
                            blockIVLength,
                            blockIV
                            );
                break;
                }

            case SCTRIVGEN_HASH_32BIT_SECTOR_ID:
                {
                status = GenerateBlockIV_HashedSectorID(
                            devContext,
                            blockID,
                            32,
                            blockIVLength,
                            blockIV
                            );
                break;
                }

            case SCTRIVGEN_HASH_64BIT_SECTOR_ID:
                {
                status = GenerateBlockIV_HashedSectorID(
                            devContext,
                            blockID,
                            64,
                            blockIVLength,
                            blockIV
                            );
                break;
                }

            case SCTRIVGEN_ESSIV:
                {
                status = GenerateBlockIV_ESSIV(
                            devContext,
                            blockID,
                            64,
                            blockIVLength,
                            blockIV
                            );
                break;
                }

            default:
                {
                DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("Unknown block IV generation method: %d\n"), devContext->SectorIVGenMethod));
                status = STATUS_INVALID_PARAMETER;;
                }

            }


        // If we have a per-volume IV, XOR it with IV...
	if (NT_SUCCESS(status))
            {
            DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("Block ID: %lld bits\n"), blockID.QuadPart));
            for(j = 0; j < (blockIVLength / 8); j++)
                { 
                DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("----- Block IV [%.2d]: %.2x\n"), j, blockIV[j]));
                }      

            useBytes = (min(blockIVLength, devContext->VolumeIVLength) / 8);
            DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("XORing block IV with %d bits of volume IV...\n"), (useBytes * 8)));
            for(i = 0; i < useBytes; i++)
                {
                blockIV[i] ^= devContext->VolumeIV[i];
                }

            if (useBytes > 0)
                {
                for(j = 0; j < (blockIVLength / 8); j++)
                    { 
                    DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("----- Actual block IV [%.2d]: %.2x\n"), j, blockIV[j]));
                    }      
                }

            }
        else
            {
            DEBUGOUTMAINDRV(DEBUGLEV_INFO, (TEXT("IV generation failed (status: %d)\n"), status));            
            }

        }  // ELSE PART - if (blockIVLength <= 0)


    DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_EXIT, (TEXT("GenerateBlockIV\n")));

    return status;
}
Ejemplo n.º 10
0
// =========================================================================
// 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

        if (devContext->IVCypher.FnEncryptSector != NULL) 
            {
		    status = devContext->IVCypher.FnEncryptSector(
                                                    &devContext->IVCypher.CypherGUID,
                                                    blockID,
                                                    devContext->EncryptionBlockSize,
                                                    devContext->ESSIVKeyLength,
                                                    (char*)devContext->ESSIVKey,
                                                    (char*)devContext->ESSIVKeyASCII,
                                                    0,
                                                    NULL,
                                                    encryptLengthBytes,
                                                    (char*)&cypherInput,
                                                    (char*)&cypherOutput
                                                   );
            }
        else if (devContext->IVCypher.FnEncrypt != NULL) 
            {
		    status = devContext->IVCypher.FnEncrypt(
                                                    &devContext->IVCypher.CypherGUID,
                                                    devContext->ESSIVKeyLength,
                                                    (char*)devContext->ESSIVKey,
                                                    (char*)devContext->ESSIVKeyASCII,
                                                    0,
                                                    NULL,
                                                    encryptLengthBytes,
                                                    (char*)&cypherInput,
                                                    (char*)&cypherOutput
                                                   );
            }
        else
            {
            DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("No encryption function?!\n")));
            status = STATUS_INVALID_PARAMETER;
            }

        if (!(NT_SUCCESS(status)))
            {
            DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("ESSIV encrypt failed\n")));
            }

        }


    if (!(NT_SUCCESS(status)))
        {
        DEBUGOUTMAINDRV(DEBUGLEV_ERROR, (TEXT("Failed to ESSIV to form IV.\n")));
        }
    else
        {
        // The number of useful bits we can take from the hash
        useBitsFromHash = (min(blockIVLength, (encryptLengthBytes * 8)));
        DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_INFO, (TEXT("Number of useful bits from cypher: %d\n"), useBitsFromHash));

        // If the block IV is larger than the number of bits the hash returns, ensure that
        // the remainder of the block IV is blanked
        if (useBitsFromHash < blockIVLength)
            {
            FREEOTFE_MEMZERO(blockIV, (blockIVLength / 8));
            }
                                                
        // Copy the first 'n' bits of the hash to be the block IV
        FREEOTFE_MEMCPY(            
                      blockIV,
                      &cypherOutput,
                      (useBitsFromHash / 8)  // Divide by 8 to get bytes from bits
                      );
        }

    DEBUGOUTMAINDRV(DEBUGLEV_VERBOSE_EXIT, (TEXT("GenerateblockIV_ESSIV\n")));

    return status;
}
Ejemplo n.º 11
0
// =========================================================================
// 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
ImpCypherDecryptSectorData(
    IN      GUID* CypherGUID,
    IN      LARGE_INTEGER SectorID,  // Indexed from zero
    IN      int SectorSize, // In bytes
    IN      int KeyLength,  // In bits
    IN      FREEOTFEBYTE* Key,
    IN      char* KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      FREEOTFEBYTE* IV,
    IN      int CyphertextLength,  // In bytes
    IN      FREEOTFEBYTE* CyphertextData,
    OUT     FREEOTFEBYTE* PlaintextData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE];
    int cipher;
    symmetric_CBC *cbc;
    int errnum;

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

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

    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    if ( (IVLength == 0) || (IV == NULL) )
        {
        FREEOTFE_MEMZERO(&ltcNullIV, sizeof(ltcNullIV));
        IV = (char*)&ltcNullIV;
        }

    cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC));    
    FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC));

  	if NT_SUCCESS(status) 
    		{
	    	status = InitLTCCypher(&cipher);
  		  }

    if NT_SUCCESS(status)
        {
        // Start a CBC session
        if ((errnum = cbc_start(
                                cipher, 
                                IV, 
                                Key, 
                                (KeyLength/8), 
                                0, 
                                cbc
                               )) != CRYPT_OK)
            {
            status = STATUS_UNSUCCESSFUL;
            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum));
            }
        else
            {
            if ((errnum = cbc_decrypt(
                                      CyphertextData, 
                                      PlaintextData, 
                                      CyphertextLength, 
                                      cbc
                                     )) != CRYPT_OK)
                {
                DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt/decrypt block (errnum: %d)\n"), errnum));
                status = STATUS_UNSUCCESSFUL;
                }

            cbc_done(cbc);
            }
        }

    SecZeroMemory(cbc, sizeof(symmetric_CBC));
    FREEOTFE_FREE(cbc);

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

    return status;
}
// =========================================================================
// Cypher driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpCypherDriverExtDetailsInit_v3(
    IN OUT CYPHER_DRIVER_INFO_v3* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;
    int blockSizeBits;

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

    blockSizeBits = (twofish_desc.block_length * 8);

    // -- 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->CypherCount = CYPHERS_SUPPORTED;
    driverInfo->CypherDetails = FREEOTFE_MEMCALLOC(
                                                   sizeof(CYPHER_v3),
                                                   driverInfo->CypherCount
                                                  );


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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_256_CBC;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying;

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_256_XTS;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_256_LRW;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying + 
                            driverInfo->CypherDetails[idx].BlockSize;

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_192_CBC;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying;

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_192_XTS;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_192_LRW;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying + 
                            driverInfo->CypherDetails[idx].BlockSize;

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_128_CBC;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying;

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_128_XTS;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            (2 * driverInfo->CypherDetails[idx].KeySizeUnderlying);

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

    driverInfo->CypherDetails[idx].BlockSize  = blockSizeBits;
    driverInfo->CypherDetails[idx].VersionID  = DRIVER_CYPHER_IMPL_VERSION;
    driverInfo->CypherDetails[idx].CypherGUID = CIPHER_GUID_TWOFISH_128_LRW;
    DetermineCypherDetails(
                           &driverInfo->CypherDetails[idx].CypherGUID,
                           &driverInfo->CypherDetails[idx].KeySizeUnderlying,
                           &driverInfo->CypherDetails[idx].Mode
                          );
    driverInfo->CypherDetails[idx].KeySizeRequired = 
                            driverInfo->CypherDetails[idx].KeySizeUnderlying + 
                            driverInfo->CypherDetails[idx].BlockSize;


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

    return status;
}
// =========================================================================
// Encrypt/Decrypt 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
ImpCypherCryptData(
    IN      GUID* CypherGUID,
    IN      LARGE_INTEGER SectorID,
    IN      int SectorSize, // In bytes
    IN      int KeyLength,  // In bits
    IN      FREEOTFEBYTE* Key,
    IN      char* KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      FREEOTFEBYTE* IV,
    IN      BOOLEAN encryptNotDecrypt,  // TRUE = encrypt; FALSE = decrypt
    IN      int InLength,  // In bytes
    IN      FREEOTFEBYTE* InData,
    OUT     FREEOTFEBYTE* OutData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    char ltcNullIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE];
    int cipher;
    symmetric_CBC *cbc;
    symmetric_LRW *lrw;
    symmetric_xts *xts;
    int errnum;
    CYPHER_MODE mode;
    int keySizeUnderlying;
    LARGE_INTEGER blockID64;
    INTEGER_128 blockID128;

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

    status = DetermineCypherDetails(
                                    CypherGUID,
                                    &keySizeUnderlying,
                                    &mode
                                   );

    // libtomcrypt can't handle NULL IVs in CBC mode - it ASSERTs that IV != NULL
    if ( (IVLength == 0) || (IV == NULL) )
        {
        FREEOTFE_MEMZERO(&ltcNullIV, sizeof(ltcNullIV));
        IV = (char*)&ltcNullIV;
        }

    // Sanity check on key supplied
    if NT_SUCCESS(status) 
        {
        switch (mode)
            {
            case CYPHER_MODE_CBC:
                {
                if (KeyLength != keySizeUnderlying)
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            case CYPHER_MODE_XTS:
                {
                if (KeyLength != (2 * keySizeUnderlying))
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            case CYPHER_MODE_LRW:
                {
                if (KeyLength != (keySizeUnderlying + (twofish_desc.block_length * 8)))
                    {
                    status = STATUS_INVALID_PARAMETER;
                    }

                break;
                }

            }
        }

    if NT_SUCCESS(status) 
        {
        status = InitLTCCypher(&cipher);
        }

    if NT_SUCCESS(status)
        {
        switch (mode)
            {
            case CYPHER_MODE_CBC:
                {
                cbc = FREEOTFE_MEMALLOC(sizeof(symmetric_CBC));    
                FREEOTFE_MEMZERO(cbc, sizeof(symmetric_CBC));

                // Start a CBC session
                if ((errnum = cbc_start(
                                        cipher, 
                                        IV, 
                                        Key, 
                                        (keySizeUnderlying/8), 
                                        0, 
                                        cbc
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start CBC session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = cbc_encrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  cbc
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else
                        {
                        if ((errnum = cbc_decrypt(
                                              InData, 
                                              OutData, 
                                              InLength, 
                                              cbc
                                             )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    cbc_done(cbc);
                    }

                SecZeroMemory(cbc, sizeof(symmetric_CBC));
                FREEOTFE_FREE(cbc);

                break;
                }

            case CYPHER_MODE_LRW:
                {
                lrw = FREEOTFE_MEMALLOC(sizeof(symmetric_LRW));    
                FREEOTFE_MEMZERO(lrw, sizeof(symmetric_LRW));

                // Generate index in correct format
                // LRW uses:
                //   *) The block index (i.e. the number of 128 bit blocks)
                //   *) The first block has block index 1 - not 0!
                //   *) Bigendian format
                // Note: LTC increments this itself as it processes each block
                SectorIDToBlockIdx_64Bit(SectorID, SectorSize, &blockID64);
                LARGE_INTEGER__To__INTEGER_128_BigEndian(
                                                    blockID64,
                                                    blockID128
                                                   );
                IV = blockID128;

                // Start a LRW session
                if ((errnum = lrw_start(
                                        cipher, 
                                        IV, 
                                        Key, 
                                        (keySizeUnderlying/8), 
                                        // 128 bits tweak key begins after the
                                        // cypher key
                                        (Key + (keySizeUnderlying/8)),
                                        0, 
                                        lrw
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start LRW session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = lrw_encrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  lrw
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else 
                        {
                            if ((errnum = lrw_decrypt(
                                                  InData, 
                                                  OutData, 
                                                  InLength, 
                                                  lrw
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    lrw_done(lrw);
                    }

                SecZeroMemory(lrw, sizeof(symmetric_LRW));
                FREEOTFE_FREE(lrw);

                break;
                }

            case CYPHER_MODE_XTS:
                {
                xts = FREEOTFE_MEMALLOC(sizeof(symmetric_xts));    
                FREEOTFE_MEMZERO(xts, sizeof(symmetric_xts));

                // Generate index in correct format
                // XTS uses:
                //   *) The sector index (i.e. the number of N-bit sectors)
                //   *) The first sector is sector 0
                //   *) Littleendian format
                LARGE_INTEGER__To__INTEGER_128_LittleEndian(
                                                    SectorID,
                                                    blockID128
                                                   );

                // Start an XTS session
                if ((errnum = xts_start(
                                        cipher, 
                                        Key, 
                                        &(Key[keySizeUnderlying/8]),
                                        (keySizeUnderlying/8), 
                                        0, 
                                        xts
                                       )) != CRYPT_OK)
                    {
                    status = STATUS_UNSUCCESSFUL;
                    DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to start XTS session (errnum: %d)\n"), errnum));
                    }
                else
                    {
                    if (encryptNotDecrypt)
                        {
                        if ((errnum = xts_encrypt(
                                                  InData, 
                                                  InLength, 
                                                  OutData, 
                                                  blockID128,
                                                  xts
                                                 )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to encrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }
                    else 
                        {
                        if ((errnum = xts_decrypt(
                                              InData, 
                                              InLength, 
                                              OutData, 
                                              blockID128,
                                              xts
                                             )) != CRYPT_OK)
                            {
                            DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unable to decrypt block (errnum: %d)\n"), errnum));
                            status = STATUS_UNSUCCESSFUL;
                            } 
                        }

                    xts_done(xts);
                    }

                SecZeroMemory(xts, sizeof(symmetric_xts));
                FREEOTFE_FREE(xts);

                break;
                }

            }

        }

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

    return status;
}
Ejemplo n.º 14
0
// =========================================================================
// Hash driver init function
// driverInfo - The structure to be initialized
NTSTATUS
ImpHashDriverExtDetailsInit(
    IN OUT HASH_DRIVER_INFO* driverInfo
)
{
    NTSTATUS status = STATUS_SUCCESS;
    int idx = -1;

    DEBUGOUTHASHIMPL(DEBUGLEV_ENTER, (TEXT("ImpHashDriverExtDetailsInit\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_HASH_VERSION;


    // -- POPULATE HASHES SUPPORTED --
    driverInfo->HashCount = HASHES_SUPPORTED;
    driverInfo->HashDetails = FREEOTFE_MEMCALLOC(
                                                 sizeof(HASH),
                                                 driverInfo->HashCount
                                                );


    // -- SHA-512 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_SHA512,
                  strlen(DRIVER_HASH_TITLE_SHA512)
                 );

    driverInfo->HashDetails[idx].Length = (sha512_desc.hashsize * 8);
    driverInfo->HashDetails[idx].BlockSize = (sha512_desc.blocksize * 8);
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_SHA512;

    // -- SHA-384 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_SHA384,
                  strlen(DRIVER_HASH_TITLE_SHA384)
                 );

    driverInfo->HashDetails[idx].Length = (sha384_desc.hashsize * 8);
    driverInfo->HashDetails[idx].BlockSize = (sha384_desc.blocksize * 8);
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_SHA384;

    // -- SHA-256 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_SHA256,
                  strlen(DRIVER_HASH_TITLE_SHA256)
                 );

    driverInfo->HashDetails[idx].Length = (sha256_desc.hashsize * 8);
    driverInfo->HashDetails[idx].BlockSize = (sha256_desc.blocksize * 8);
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_SHA256;

    // -- SHA-224 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_SHA224,
                  strlen(DRIVER_HASH_TITLE_SHA224)
                 );

    driverInfo->HashDetails[idx].Length = (sha224_desc.hashsize * 8);
    driverInfo->HashDetails[idx].BlockSize = (sha224_desc.blocksize * 8);
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_SHA224;

    // -- SHA-1 --
    idx++;
    FREEOTFE_MEMZERO(driverInfo->HashDetails[idx].Title, MAX_HASH_TITLE);
    FREEOTFE_MEMCPY(
                  driverInfo->HashDetails[idx].Title,
                  DRIVER_HASH_TITLE_SHA1,
                  strlen(DRIVER_HASH_TITLE_SHA1)
                 );

    driverInfo->HashDetails[idx].Length = (sha1_desc.hashsize * 8);
    driverInfo->HashDetails[idx].BlockSize = (sha1_desc.blocksize * 8);
    driverInfo->HashDetails[idx].VersionID = DRIVER_HASH_IMPL_VERSION;
    driverInfo->HashDetails[idx].HashGUID = HASH_GUID_SHA1;


    DEBUGOUTHASHIMPL(DEBUGLEV_EXIT, (TEXT("ImpHashDriverExtDetailsInit\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
ImpCypherDecryptSectorData(
    IN      GUID* CypherGUID,
    IN      LARGE_INTEGER SectorID,  // Indexed from zero
    IN      int SectorSize, // In bytes
    IN      int KeyLength,  // In bits
    IN      FREEOTFEBYTE* Key,
    IN      char* KeyASCII,  // ASCII representation of "Key"
    IN      int IVLength,  // In bits
    IN      FREEOTFEBYTE* IV,
    IN      int CyphertextLength,  // In bytes
    IN      FREEOTFEBYTE* CyphertextData,
    OUT     FREEOTFEBYTE* PlaintextData
)
{
    NTSTATUS status = STATUS_SUCCESS;
    // Null IV in case we're not given an IV
    char zeroIV[FREEOTFE_MAX_CYPHER_BLOCKSIZE];
    int i;
    CONTEXT context;

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

    if (
          (IsEqualGUID(&CIPHER_GUID_CAST6_256_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_CAST6_224_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_CAST6_192_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_CAST6_160_CBC, CypherGUID)) ||
          (IsEqualGUID(&CIPHER_GUID_CAST6_128_CBC, CypherGUID)) 
         )
        {
        // Handle situation where a NULL/zero length IV is passed in
        if ( (IVLength == 0) || (IV == NULL) )
            {
            FREEOTFE_MEMZERO(&zeroIV, sizeof(zeroIV));
            IV = (char*)&zeroIV;
            }


        // Process data using CBC mode
        //
        // CBC Mode DECRYPT:
        // *) Setup key
        // *) For each block...
        //     *) Decrypt cyphertext with key
        //     *) XOR output plaintext with IV
        //     *) IV = Cyphertext data

        // Note: "dec" specified; we're DECRYPTING
        set_key(&context, (u4byte *)Key, KeyLength);
        for (i=0; i < CyphertextLength; i += (CAST6_BLOCK_SIZE / 8))
            {
            decrypt(&context, (u4byte *)(CyphertextData+i), (u4byte *)(PlaintextData+i));
            XORBlock(PlaintextData+i, IV, PlaintextData+i, (CAST6_BLOCK_SIZE / 8));
            IV = CyphertextData+i;
            }

        }
    else
        {
        DEBUGOUTCYPHERIMPL(DEBUGLEV_ERROR, (TEXT("Unsupported cipher GUID passed in.\n")));
        status = STATUS_INVALID_PARAMETER;
        }

    SecZeroMemory(&context, sizeof(context));


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

    return status;
}