// ========================================================================= // 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; }
// ========================================================================= // 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]) ); } }
// ========================================================================= // 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; }
// ========================================================================= // Internal function to carry out actual XOR encryption NTSTATUS _xor_data( IN int KeyLength, // In bits IN FREEOTFEBYTE* Key, IN int DataLength, // In bytes IN FREEOTFEBYTE* InData, OUT FREEOTFEBYTE* OutData ) { NTSTATUS status = STATUS_SUCCESS; int i; int keyOffset; int keyLenBytes; DEBUGOUTCYPHERIMPL(DEBUGLEV_ENTER, (TEXT("_xor_data\n"))); keyLenBytes = (KeyLength / 8); // Sanity check, just in case we were passed an empty password! if (keyLenBytes != 0) { keyOffset = 0; for(i = 0; i < DataLength; i++, keyOffset++) { if (keyOffset >= keyLenBytes) { keyOffset = 0; } OutData[i] = InData[i] ^ Key[keyOffset]; } } else { // No password? Just copy the data from the input buffer to the output FREEOTFE_MEMCPY( OutData, InData, DataLength ); } DEBUGOUTCYPHERIMPL(DEBUGLEV_EXIT, (TEXT("_xor_data\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; }
// ========================================================================= // This is the PBKDF2 PRF function "F" // The PRF used is HMAC NTSTATUS PBKDF2_F( IN PDataHashFn FnHash, IN GUID HashGUID, IN HASH HashDetails, IN unsigned int PLength, // In bits IN unsigned char* P, IN unsigned int SLength, // In bits IN unsigned char* S, IN unsigned int c, IN unsigned int i, OUT unsigned char* T_ ) { NTSTATUS status; unsigned char* U_; unsigned char* tmpU_Buffer; unsigned char* saltAndCount; unsigned int hLen; // In *bytes* unsigned int hLenBits; // In *Bits* unsigned int actualHLenBits; // In *bits* unsigned int saltAndCountSizeBytes; // In *bytes* unsigned int j, k; DEBUGOUTKDFDRV(DEBUGLEV_ENTER, ("PBKDF2_F\n")); status = STATUS_SUCCESS; U_ = NULL; tmpU_Buffer = NULL; saltAndCount = NULL; // From PKCS#5: // function F is defined as the exclusive-or sum of the // first c iterates of the underlying pseudorandom function PRF // applied to the password P and the concatenation of the salt S // and the block index i: // // F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c // // where // U_1 = PRF (P, S || INT (i)) , // U_2 = PRF (P, U_1) , // ... // U_c = PRF (P, U_{c-1}) . // // Here, INT (i) is a four-octet encoding of the integer i, most // significant octet first. DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("Iterations requested: %d\n", c)); // This is PBKDF2 based on HMAC - the HMAC function returns the same // number of bytes as is in the hash it uses hLen = (HashDetails.Length / 8); hLenBits = HashDetails.Length; // Convert bits to bytes, and add 4 (specified in PKCS #5) for the "i" saltAndCountSizeBytes = ((SLength / 8) + 4); saltAndCount = FREEOTFE_MEMALLOC(saltAndCountSizeBytes); FREEOTFE_MEMCPY( saltAndCount, S, (SLength / 8) ); // Concatenate the salt // Note: *Bitwise* AND :) saltAndCount[ (SLength / 8) ] = ((i & 0xFF000000) / 0x01000000); saltAndCount[((SLength / 8)+1)] = ((i & 0x00FF0000) / 0x00010000); saltAndCount[((SLength / 8)+2)] = ((i & 0x0000FF00) / 0x00000100); saltAndCount[((SLength / 8)+3)] = ((i & 0x000000FF) / 0x00000001); U_ = FREEOTFE_MEMALLOC(hLen); tmpU_Buffer = FREEOTFE_MEMALLOC(hLen); // Process U_1 if (NT_SUCCESS(status)) { actualHLenBits = hLenBits; DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("First HMAC: SLength = %d\n", SLength)); DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("First HMAC: actualHLenBits = %d\n", actualHLenBits)); if (!(NT_SUCCESS(ImplMACHMAC( FnHash, HashGUID, HashDetails, -1, // Retrieve full HMAC PLength, P, (saltAndCountSizeBytes * 8), // In *bits* saltAndCount, &actualHLenBits, // In bits U_ )))) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("First call to HMAC function \"F\" failed.\n")); status = STATUS_INTERNAL_ERROR; } else { // Sanity check if (actualHLenBits != hLenBits) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("HMAC function didn't return expected number of bits?!\n")); status = STATUS_INTERNAL_ERROR; } else { // Copy to output buffer - note that this will be XORd if // there's more c>1 FREEOTFE_MEMCPY( T_, U_, (actualHLenBits / 8) ); } } } // Process subsequent U_n if (NT_SUCCESS(status)) { for(j = 2; j <= c; j++) { actualHLenBits = hLenBits; DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("Subsequent HMAC: actualHLenBits = %d\n", actualHLenBits)); if (!(NT_SUCCESS(ImplMACHMAC( FnHash, HashGUID, HashDetails, -1, // Retrieve full HMAC PLength, P, hLenBits, // In bits U_, &actualHLenBits, // In bits tmpU_Buffer )))) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("Call to HMAC function \"F\" failed.\n")); status = STATUS_INTERNAL_ERROR; break; } else { // Move from temp buffer to U_ buffer DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("Copying (%d)\n", hLen)); FREEOTFE_MEMCPY( U_, tmpU_Buffer, hLen ); // XOR with previous iteration DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("XORing...\n")); for(k = 0; k < hLen; k++) { T_[k] ^= U_[k]; } DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("OK.\n")); } } } // Note: No need to set the output "T_" explicitly, as this is done during // processing if (tmpU_Buffer != NULL) { SecZeroMemory(tmpU_Buffer, hLen); FREEOTFE_FREE(tmpU_Buffer); } if (U_ != NULL) { SecZeroMemory(U_, hLen); FREEOTFE_FREE(U_); } if (saltAndCount != NULL) { SecZeroMemory(saltAndCount, saltAndCountSizeBytes); FREEOTFE_FREE(saltAndCount); } DEBUGOUTKDFDRV(DEBUGLEV_EXIT, ("PBKDF2_F\n")); return status; }
// ========================================================================= // Generate PBKDF2 key based on HMAC NTSTATUS ImplKDFPBKDF2( IN PDataHashFn FnHash, IN GUID HashGUID, IN HASH HashDetails, IN unsigned int PLength, // In bits IN unsigned char* P, IN unsigned int SLength, // In bits IN unsigned char* S, IN unsigned int c, // Iterations IN int dkLenBits, // In *bits* IN OUT unsigned int* DerivedKeyLength, // In bits OUT unsigned char* DerivedKey ) { NTSTATUS status; unsigned int i; unsigned int l; // unsigned int r; // In *bytes* unsigned int dkLen; // In *bytes* unsigned int hLen; // In *bytes* unsigned char* T_; unsigned int T_SizeBytes; // In *bytes* DEBUGOUTKDFDRV(DEBUGLEV_ENTER, ("ImplKDFPBKDF2\n")); status = STATUS_SUCCESS; T_ = NULL; T_SizeBytes = 0; // Sanity check // This should be picked up by the caller; this is belt & braces if ( (HashDetails.BlockSize <= 0) || (HashDetails.Length <= 0) ) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("PBKDF2 implementation called with a hash that has an undefined/zero length/blocksize\n")); status = STATUS_INTERNAL_ERROR; } else { // This is PBKDF2 based on HMAC - the HMAC function returns the same // number of bytes as is in the hash it uses hLen = (HashDetails.Length / 8); } if (dkLenBits < 0) { dkLenBits = DEFAULT_PBKDF2_KEY_SIZE; } dkLen = (dkLenBits / 8); DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("dkLenBits = %d bits\n", dkLenBits)); DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("dkLen = %d bytes\n", dkLen)); // Sanity check // This should be picked up by the caller; this is belt & braces if ((unsigned int)dkLenBits > *DerivedKeyLength) { // The output buffer can store the requested number of bits, right? // Note that dkLenBits can be -ve to indicate the full key length is to be // returned DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("Requested number of bits is larger than supplied buffer\n")); status = STATUS_BUFFER_TOO_SMALL; } // Step 1 // 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and // stop. DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("PBKDF2 Step 1: n/a; skipped...\n")); // (Step skipped - because dkLen is an integer, it can never be more // than 2^(31-1) - far less than (2^32 - 1) * hLen) // Step 2 // 2. Let l be the number of hLen-octet blocks in the derived key, // rounding up, and let r be the number of octets in the last // block: // // l = CEIL (dkLen / hLen) , // r = dkLen - (l - 1) * hLen . // // Here, CEIL (x) is the "ceiling" function, i.e. the smallest // integer greater than, or equal to, x. if (NT_SUCCESS(status)) { DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("PBKDF2 Step 2: Executing...\n")); // Note: div always rounds down towards zero l = (dkLen / hLen); // Because div always rounds down towards zero, we may need to increment it // by one if (dkLen > (l * hLen)) { l++; } DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("dkLen = %d bytes\n", dkLen)); DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("hLen = %d bytes\n", hLen)); DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("l = %d\n", l)); // r = dkLen - ((l - 1) * hLen); // DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("r = %d bytes\n", r)); } // Step 3 // 3. For each block of the derived key apply the function F if (NT_SUCCESS(status)) { DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("PBKDF2 Step 3: Executing...\n")); T_SizeBytes = (hLen * l); T_ = FREEOTFE_MEMALLOC(T_SizeBytes); for(i = 1; i<=l; i++) { DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("Loop: i = %d\n", i)); if (!(NT_SUCCESS(PBKDF2_F( FnHash, HashGUID, HashDetails, PLength, P, SLength, S, c, i, // This is correct (-1), as our loop starts // from 1 &T_[((i-1) * hLen)] )))) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("Call to PBKDF2 function \"F\" failed.\n")); status = STATUS_INTERNAL_ERROR; break; } } } // Step 4 // 4. Concatenate the blocks and extract the first dkLen octets to // produce a derived key DK: // // DK = T_1 || T_2 || ... || T_l<0..r-1> if (NT_SUCCESS(status)) { DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("PBKDF2 Step 4: Executing...\n")); FREEOTFE_MEMCPY( DerivedKey, T_, (dkLenBits / 8) ); } // Step 5 // 5. Output the derived key DK. if (NT_SUCCESS(status)) { DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("PBKDF2 Step 5: Executing...\n")); *DerivedKeyLength = dkLenBits; } // Cleanup... DEBUGOUTKDFDRV(DEBUGLEV_INFO, ("Freeing off any used buffers...\n")); if (T_ != NULL) { SecZeroMemory(T_, T_SizeBytes); FREEOTFE_FREE(T_); } DEBUGOUTKDFDRV(DEBUGLEV_EXIT, ("ImplKDFPBKDF2\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 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; }
// ========================================================================= // Generate HMAC NTSTATUS ImplMACHMAC( IN PDataHashFn FnHash, IN GUID HashGUID, IN HASH HashDetails, IN int tBits, // In *bits* IN unsigned int KLength, // In bits IN unsigned char* K, IN unsigned int textLength, // In bits IN unsigned char* text, IN OUT unsigned int* MACLength, // In bits OUT unsigned char* MAC ) { NTSTATUS status; unsigned int KLengthBytes; // In *bytes* unsigned int B; // In *bytes* unsigned int i; unsigned char* Kzero; unsigned char* step2TmpBuf; unsigned char* step4OutBuf; unsigned char* step5OutBuf; unsigned char* step6OutBuf; unsigned char* step7OutBuf; unsigned char* step8OutBuf; unsigned char* step9OutBuf; unsigned int step2TmpBufSize; // In *bytes* unsigned int step5OutBufSize; // In *bytes* unsigned int step6OutBufSize; // In *bytes* unsigned int step8OutBufSize; // In *bytes* unsigned int step9OutBufSize; // In *bytes* unsigned int step6ValidBits; unsigned int step9ValidBits; unsigned int hashValidBits; unsigned int hashUseLenBytes; unsigned int outputBits; DEBUGOUTMACDRV(DEBUGLEV_ENTER, ("ImplMACHMAC\n")); status = STATUS_SUCCESS; Kzero = NULL; step4OutBuf = NULL; step5OutBuf = NULL; step6OutBuf = NULL; step7OutBuf = NULL; step8OutBuf = NULL; step9OutBuf = NULL; // Sanity checks // This should be picked up by the caller; this is belt & braces if ( (HashDetails.BlockSize <= 0) || (HashDetails.Length <= 0) ) { DEBUGOUTMACDRV(DEBUGLEV_ERROR, ("HMAC implementation called with a hash that has an undefined blocksize/output\n")); status = STATUS_INTERNAL_ERROR; } B = (HashDetails.BlockSize / 8); KLengthBytes = (KLength / 8); // Compute the HMAC... // --------- // FIPS-198 Steps 1-3 // i.e. Set Kzero to be a "B" length string if (NT_SUCCESS(status)) { Kzero = FREEOTFE_MEMALLOC(B); if (KLengthBytes == B) { // Step 1 DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 1: Executing...\n")); // Set K0 = K FREEOTFE_MEMCPY( Kzero, K, B ); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 2: n/a; skipped\n")); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 3: n/a; skipped\n")); } else if (KLengthBytes > B) { // Step 2 DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 1: n/a; skipped\n")); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 2: Executing...\n")); // Hash K to get a hashlength string, then pad out to B bytes // with NULLs step2TmpBufSize = (HashDetails.Length / 8); // Divide by 8 to get bytes from bits hashValidBits = HashDetails.Length; // In *bits* DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Allocating tmp buffer (%d bytes)...\n", step2TmpBufSize)); step2TmpBuf = FREEOTFE_MEMALLOC(step2TmpBufSize); status = FnHash( &HashGUID, KLength, K, &hashValidBits, step2TmpBuf ); if (!(NT_SUCCESS(status))) { DEBUGOUTMACDRV(DEBUGLEV_ERROR, ("HMAC Step 2: Call to hash driver failed\n")); status = STATUS_INTERNAL_ERROR; } else { hashUseLenBytes = min(B, (hashValidBits / 8)); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Hash output: %d bits (%d bytes)...\n", hashValidBits, (hashValidBits / 8))); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Using first %d bytes...\n", hashUseLenBytes)); // Copy the hash value to K0 FREEOTFE_MEMCPY( Kzero, step2TmpBuf, hashUseLenBytes ); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Step 2 Kzero: Padding end with NULLs (%d bytes of nulls)...\n", (B - hashUseLenBytes))); // Pad K0 with NULLs SecZeroMemory(&Kzero[hashUseLenBytes], (B - hashUseLenBytes)); } DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Zeroing and freeing hash buffer\n")); SecZeroMemory(step2TmpBuf, step2TmpBufSize); FREEOTFE_FREE(step2TmpBuf); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 3: n/a; skipped\n")); } else { // Step 3 DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 1: n/a; skipped\n")); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 2: n/a; skipped\n")); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 3: Executing...\n")); FREEOTFE_MEMCPY( Kzero, K, KLengthBytes ); DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Step 3 Kzero: Padding end with NULLs (%d bytes of nulls)...\n", (B - KLengthBytes))); // Pad K0 with NULLs SecZeroMemory(&Kzero[KLengthBytes], (B - KLengthBytes)); } } // --------- // FIPS-198 Step 4 // XOR K0 with ipad (0x36) if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 4: Executing...\n")); step4OutBuf = FREEOTFE_MEMALLOC(B); for (i = 0; i < B; i++) { step4OutBuf[i] = Kzero[i] ^ 0x36; } } // --------- // FIPS-198 Step 5 // Append input text onto the end of the output from step 4 if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 5: Executing...\n")); step5OutBufSize = (B + (textLength / 8)); step5OutBuf = FREEOTFE_MEMALLOC(step5OutBufSize); FREEOTFE_MEMCPY( step5OutBuf, step4OutBuf, B ); FREEOTFE_MEMCPY( &step5OutBuf[B], text, (textLength / 8) ); } // --------- // FIPS-198 Step 6 // Apply H to the output from step 5 if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 6: Executing...\n")); step6ValidBits = HashDetails.Length; step6OutBufSize = (step6ValidBits / 8); step6OutBuf = FREEOTFE_MEMALLOC(step6OutBufSize); status = FnHash( &HashGUID, (step5OutBufSize * 8), step5OutBuf, &step6ValidBits, step6OutBuf ); } // --------- // FIPS-198 Step 7 // XOR K0 with opad (0x5C) if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 7: Executing...\n")); step7OutBuf = FREEOTFE_MEMALLOC(B); for (i = 0; i < B; i++) { step7OutBuf[i] = Kzero[i] ^ 0x5C; } } // --------- // FIPS-198 Step 8 // Append the result from step 6 to step 7 if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 8: Executing...\n")); step8OutBufSize = (B + (step6ValidBits / 8)); step8OutBuf = FREEOTFE_MEMALLOC(step8OutBufSize); FREEOTFE_MEMCPY( step8OutBuf, step7OutBuf, B ); FREEOTFE_MEMCPY( &step8OutBuf[B], step6OutBuf, (step6ValidBits / 8) ); } // --------- // FIPS-198 Step 9 // Apply H to the output from step 8 if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 9: Executing...\n")); step9ValidBits = HashDetails.Length; step9OutBufSize = (step9ValidBits / 8); step9OutBuf = FREEOTFE_MEMALLOC(step9OutBufSize); status = FnHash( &HashGUID, (step8OutBufSize * 8), step8OutBuf, &step9ValidBits, step9OutBuf ); } // --------- // FIPS-198 Step 10 // Select the leftmost t bytes of output from step 9 if (NT_SUCCESS(status)) { DEBUGOUTMACDRV(DEBUGLEV_INFO, ("HMAC Step 10: Executing...\n")); // Truncate, if necessary, to tBits of data if (tBits >= 0) { outputBits = tBits; } else { outputBits = step9ValidBits; } // Sanity check on the buffer... if (*MACLength < outputBits) { DEBUGOUTMACDRV(DEBUGLEV_ERROR, ("Buffer too small; supplied %d bits, need %d bits\n", MACLength, outputBits)); status = STATUS_BUFFER_TOO_SMALL; } else { // Copy the appropriate number of bits to the output buffer FREEOTFE_MEMCPY( MAC, step9OutBuf, (outputBits / 8) // Convert to bytes ); *MACLength = outputBits; } } // Cleanup... DEBUGOUTMACDRV(DEBUGLEV_INFO, ("Freeing off any used buffers...\n")); if (step9OutBuf != NULL) { SecZeroMemory(step9OutBuf, step9OutBufSize); FREEOTFE_FREE(step9OutBuf); } if (step8OutBuf != NULL) { SecZeroMemory(step8OutBuf, step8OutBufSize); FREEOTFE_FREE(step8OutBuf); } if (step7OutBuf != NULL) { SecZeroMemory(step7OutBuf, B); FREEOTFE_FREE(step7OutBuf); } if (step6OutBuf != NULL) { SecZeroMemory(step6OutBuf, step6OutBufSize); FREEOTFE_FREE(step6OutBuf); } if (step5OutBuf != NULL) { SecZeroMemory(step5OutBuf, step5OutBufSize); FREEOTFE_FREE(step5OutBuf); } if (step4OutBuf != NULL) { SecZeroMemory(step4OutBuf, B); FREEOTFE_FREE(step4OutBuf); } if (Kzero != NULL) { SecZeroMemory(Kzero, B); FREEOTFE_FREE(Kzero); } DEBUGOUTMACDRV(DEBUGLEV_EXIT, ("ImplMACHMAC\n")); return status; }
// ========================================================================= // Generate a key based on the hash of the salted password NTSTATUS ImplKDFHashSaltedPassword( IN PDataHashFn FnHash, IN GUID HashGUID, IN unsigned int Iterations, IN unsigned int PasswordLength, // In bits IN unsigned char* Password, IN unsigned int SaltLength, // In bits IN unsigned char* Salt, IN OUT unsigned int* DerivedKeyLength, // In bits OUT unsigned char* DerivedKey ) { NTSTATUS status; unsigned char* tmpBuffer; unsigned int tmpBufferSizeBytes; unsigned char* tmpIterateBuffer; unsigned int tmpIterateBufferSizeBytes; unsigned int i; DEBUGOUTKDFDRV(DEBUGLEV_ENTER, ("ImplKDFHashSaltedPassword\n")); tmpBufferSizeBytes = ((PasswordLength + SaltLength) / 8); tmpBuffer = FREEOTFE_MEMALLOC(tmpBufferSizeBytes); // Add the salt onto the end of the password before hashing the combined // password/salt FREEOTFE_MEMCPY( tmpBuffer, Password, (PasswordLength / 8) ); FREEOTFE_MEMCPY( &tmpBuffer[(PasswordLength / 8)], Salt, (SaltLength / 8) ); status = FnHash( &HashGUID, (tmpBufferSizeBytes * 8), // Get bits from bytes tmpBuffer, DerivedKeyLength, DerivedKey ); if (!(NT_SUCCESS(status))) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("First KDF call to hash driver failed\n")); } else { // Iterate, if needed... if (Iterations >= 2) { tmpIterateBufferSizeBytes = (*DerivedKeyLength / 8); tmpIterateBuffer = FREEOTFE_MEMALLOC(tmpIterateBufferSizeBytes); for (i = 2; i <= Iterations; i++) { // Copy to temp buffer... FREEOTFE_MEMCPY( tmpIterateBuffer, DerivedKey, tmpIterateBufferSizeBytes ); // Only pass a buffer that we can copy back into // Note: This value should never be bigger than the original // value passed in, otherwise the original hash would // fail *DerivedKeyLength = (tmpIterateBufferSizeBytes * 8); // Hash temp buffer... status = FnHash( &HashGUID, (tmpIterateBufferSizeBytes * 8), // Get bits from bytes tmpIterateBuffer, DerivedKeyLength, DerivedKey ); if (!(NT_SUCCESS(status))) { DEBUGOUTKDFDRV(DEBUGLEV_ERROR, ("Subsequent KDF call to hash driver failed\n")); break; } } SecZeroMemory(tmpIterateBuffer, tmpIterateBufferSizeBytes); FREEOTFE_FREE(tmpIterateBuffer); } } // Note: No need to explicitly set *MACLength as FnHash does this for us SecZeroMemory(tmpBuffer, tmpBufferSizeBytes); FREEOTFE_FREE(tmpBuffer); DEBUGOUTKDFDRV(DEBUGLEV_EXIT, ("ImplKDFHashSaltedPassword\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; }
// ========================================================================= // 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; }