// ========================================================================= // 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; }
// ---------------------------------------------------------------------------- BOOL LUKS_DumpLUKSDataToFile( MODULE_DETAILS_MAIN* mainDriver, WCHAR* filename, unsigned char* userKey, BOOL baseIVCypherOnHashLength, WCHAR* dumpFilename ) { BOOL retval; LUKS_HEADER_EXT LUKSHeader; int i; char hashTitle[MAX_PRETTYPRINTED_TITLE]; char cypherTitle[MAX_PRETTYPRINTED_TITLE]; int keySlot; BYTE* keyMaterial; char IVHashTitle[MAX_PRETTYPRINTED_TITLE]; char IVCypherTitle[MAX_PRETTYPRINTED_TITLE]; char sectorIVGenMethodTitle[MAX_PRETTYPRINTED_TITLE]; char filenameAsChar[FREEOTFE_MAX_FILENAME_LENGTH * 4]; FILE* hFile; WCHAR* tmpStringGUID; char* prettyPrintData; int prettyPrintDataLength; retval = TRUE; // Sanity; source file must exist if (retval) { retval = ( SDUCheckFileExists(filename) && (!(SDUCheckFileExists(dumpFilename))) ); } if (retval) { hFile = _wfopen(dumpFilename, TEXT("w+")); driver_AddStdDumpHeader(hFile, "LUKS Dump"); // Get the LUKS header from the volume... if (!(LUKS_ReadLUKSHeader(filename, &LUKSHeader))) { if (LUKS_IsLUKSVolume(filename)) { fprintf(hFile, "ERROR: Unable to read LUKS header?!\n"); } else { fprintf(hFile, "Unable to read LUKS header; this does not appear to be a LUKS volume.\n"); } } else { fprintf(hFile, "\n"); fprintf(hFile, "\n"); driver_AddStdDumpSection(hFile, "cryptsetup Style Dump"); wcstombs(filenameAsChar, filename, sizeof(filenameAsChar)); fprintf(hFile, "LUKS header information for %s\n", filenameAsChar); SecZeroMemory(filenameAsChar, sizeof(filenameAsChar)); fprintf(hFile, "\n"); fprintf(hFile, "Version: %d\n", LUKSHeader.rawHeader.version); fprintf(hFile, "Cipher name: %s\n", LUKSHeader.rawHeader.cipher_name); fprintf(hFile, "Cipher mode: %s\n", LUKSHeader.rawHeader.cipher_mode); fprintf(hFile, "Hash spec: %s\n", LUKSHeader.rawHeader.hash_spec); fprintf(hFile, "Payload offset: %d\n", LUKSHeader.rawHeader.payload_offset); fprintf(hFile, "MK bits: %d\n", (LUKSHeader.rawHeader.key_bytes * 8)); // Convert from bytes to bits fprintf(hFile, "MK digest: "); LUKS_PrettyHex( hFile, (BYTE*)(&(LUKSHeader.rawHeader.mk_digest)), LUKS_DIGESTSIZE ); fprintf(hFile, "\n"); fprintf(hFile, "MK salt: "); LUKS_PrettyHex( hFile, &(LUKSHeader.rawHeader.mk_digest_salt[0]), (LUKS_SALTSIZE / 2) ); fprintf(hFile, "\n"); fprintf(hFile, " "); LUKS_PrettyHex( hFile, &(LUKSHeader.rawHeader.mk_digest_salt[(LUKS_SALTSIZE / 2)]), (LUKS_SALTSIZE / 2) ); fprintf(hFile, "\n"); fprintf(hFile, "MK iterations: %d\n", LUKSHeader.rawHeader.mk_digest_iter); fprintf(hFile, "UUID: %s\n", LUKSHeader.rawHeader.uuid); fprintf(hFile, "\n"); for (i = 0; i < LUKS_NUMKEYS; i++) { if (LUKSHeader.rawHeader.key_slot[i].active != LUKS_KEY_ENABLED) { fprintf(hFile, "Key Slot %d: DISABLED\n", i); } else { fprintf(hFile, "Key Slot %d: ENABLED\n", i); fprintf(hFile, " Iterations: %d\n", LUKSHeader.rawHeader.key_slot[i].iterations); fprintf(hFile, " Salt: "); LUKS_PrettyHex( hFile, &(LUKSHeader.rawHeader.key_slot[i].salt[0]), (LUKS_SALTSIZE / 2) ); fprintf(hFile, "\n"); fprintf(hFile, " "); LUKS_PrettyHex( hFile, &(LUKSHeader.rawHeader.key_slot[i].salt[(LUKS_SALTSIZE / 2)]), (LUKS_SALTSIZE / 2) ); fprintf(hFile, "\n"); fprintf(hFile, " Key material offset: %d\n", LUKSHeader.rawHeader.key_slot[i].key_material_offset); fprintf(hFile, " AF stripes: %d\n", LUKSHeader.rawHeader.key_slot[i].stripes); } } fprintf(hFile, "\n"); fprintf(hFile, "\n"); driver_AddStdDumpSection(hFile, "Mapped FreeOTFE Drivers"); if (!(LUKS_MapToFreeOTFE(baseIVCypherOnHashLength, &LUKSHeader))) { fprintf(hFile, "One or more of the following:\n"); fprintf(hFile, "\n"); fprintf(hFile, " *) The hash algorithm\n"); fprintf(hFile, " *) The cypher\n"); fprintf(hFile, " *) The IV generation method\n"); fprintf(hFile, "\n"); fprintf(hFile, "specified in the LUKS header could not be mapped to a FreeOTFE equivalent.\n"); fprintf(hFile, "This may be because the required FreeOTFE driver hasn''t been installed and\n"); fprintf(hFile, "started, or because the required LUKS option is not supported in this\n"); fprintf(hFile, "version of FreeOTFE\n"); } else { strcpy(hashTitle, "ERROR: Unable to determine hash title?!"); driver_HashPrettyprintAlgTechTitle_ByDriverAndGUID_char( LUKSHeader.hashKernelModeDeviceName, LUKSHeader.hashGUID, hashTitle, sizeof(hashTitle) ); strcpy(IVCypherTitle, "ERROR: Unable to determine cypher title?!"); driver_CypherPrettyprintAlgTechTitle_ByDriverAndGUID_char( LUKSHeader.cypherKernelModeDeviceName, LUKSHeader.cypherGUID, cypherTitle, sizeof(cypherTitle) ); if (LUKSHeader.sectorIVGenMethod != SCTRIVGEN_ESSIV) { strcpy(IVHashTitle, "IV hash n/a"); strcpy(IVCypherTitle, "IV cypher n/a"); } else { strcpy(IVHashTitle, "ERROR: Unable to determine IV hash title?!"); driver_HashPrettyprintAlgTechTitle_ByDriverAndGUID_char( LUKSHeader.IVHashKernelModeDeviceName, LUKSHeader.IVHashGUID, IVHashTitle, sizeof(IVHashTitle) ); strcpy(IVCypherTitle, "ERROR: Unable to determine IV cypher title?!"); driver_CypherPrettyprintAlgTechTitle_ByDriverAndGUID_char( LUKSHeader.IVCypherKernelModeDeviceName, LUKSHeader.IVCypherGUID, IVCypherTitle, sizeof(IVCypherTitle) ); } fprintf(hFile, "Hash pretty title : %s\n", hashTitle); fprintf(hFile, "Hash driver KM name : "); driver_DumpWCHAR(hFile, LUKSHeader.hashKernelModeDeviceName); fprintf(hFile, "\n"); fprintf(hFile, "Hash GUID : "); GUIDToWCHAR(&(LUKSHeader.hashGUID), &tmpStringGUID); SDUwcstoupper(tmpStringGUID, tmpStringGUID); driver_DumpWCHAR(hFile, tmpStringGUID); SecZeroAndFreeWCHARMemory(tmpStringGUID); fprintf(hFile, "\n"); fprintf(hFile, "Cypher pretty title : %s\n", cypherTitle); fprintf(hFile, "Cypher driver KM name : "); driver_DumpWCHAR(hFile, LUKSHeader.cypherKernelModeDeviceName); fprintf(hFile, "\n"); fprintf(hFile, "Cypher GUID : "); GUIDToWCHAR(&(LUKSHeader.cypherGUID), &tmpStringGUID); SDUwcstoupper(tmpStringGUID, tmpStringGUID); driver_DumpWCHAR(hFile, tmpStringGUID); SecZeroAndFreeWCHARMemory(tmpStringGUID); fprintf(hFile, "\n"); driver_PrettyprintSectorIVGenMethod_char( LUKSHeader.sectorIVGenMethod, sectorIVGenMethodTitle, sizeof(sectorIVGenMethodTitle) ); fprintf(hFile, "Sector IV generation : %s\n", sectorIVGenMethodTitle); if (LUKSHeader.sectorIVGenMethod == SCTRIVGEN_ESSIV) { fprintf(hFile, " IV hash pretty title : %s\n", IVHashTitle); fprintf(hFile, " IV hash driver KM name : "); driver_DumpWCHAR(hFile, LUKSHeader.IVHashKernelModeDeviceName); fprintf(hFile, "\n"); fprintf(hFile, " IV hash GUID : "); GUIDToWCHAR(&(LUKSHeader.IVHashGUID), &tmpStringGUID); SDUwcstoupper(tmpStringGUID, tmpStringGUID); driver_DumpWCHAR(hFile, tmpStringGUID); SecZeroAndFreeWCHARMemory(tmpStringGUID); fprintf(hFile, "\n"); if (baseIVCypherOnHashLength) { fprintf(hFile, " IV cypher : <based on IV hash length>\n"); } else { fprintf(hFile, " IV cypher : <same as main cypher>\n"); } fprintf(hFile, " IV cypher pretty title : %s\n", IVCypherTitle); fprintf(hFile, " IV cypher driver KM name: "); driver_DumpWCHAR(hFile, LUKSHeader.IVCypherKernelModeDeviceName); fprintf(hFile, "\n"); fprintf(hFile, " IV cypher GUID : "); GUIDToWCHAR(&(LUKSHeader.IVCypherGUID), &tmpStringGUID); SDUwcstoupper(tmpStringGUID, tmpStringGUID); driver_DumpWCHAR(hFile, tmpStringGUID); SecZeroAndFreeWCHARMemory(tmpStringGUID); fprintf(hFile, "\n"); } } fprintf(hFile, "\n"); fprintf(hFile, "\n"); driver_AddStdDumpSection(hFile, "Master Key"); fprintf(hFile, "User supplied password : %s\n", userKey); keyMaterial = NULL; if (!(LUKS_RecoverMasterKey( mainDriver, filename, userKey, baseIVCypherOnHashLength, &LUKSHeader, &keySlot, &keyMaterial ))) { fprintf(hFile, "No master key could be recovered with the specified password.\n"); } else { prettyPrintDataLength = SDUPrettyPrintHexBufReq( LUKSHeader.rawHeader.key_bytes, 8 ); prettyPrintData = malloc(prettyPrintDataLength); if (prettyPrintData == NULL) { fprintf(hFile, "Unable to allocate memory to store prettyprinted master key\n"); } else { SDUPrettyPrintHex( keyMaterial, 0, LUKSHeader.rawHeader.key_bytes, prettyPrintData, prettyPrintDataLength, 8 ); fprintf(hFile, "Password unlocks key slot: %d\n", keySlot); fprintf(hFile, "Recovered master key :\n"); fprintf(hFile, "%s", prettyPrintData); SecZeroAndFreeMemory(prettyPrintData, prettyPrintDataLength); } } SecZeroAndFreeMemory(keyMaterial, LUKSHeader.rawHeader.key_bytes); } retval = TRUE; fclose(hFile); } return retval; }
// ========================================================================= // Hash function 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; hash_state md; WCHAR* tmpGUIDStr; DEBUGOUTHASHIMPL(DEBUGLEV_ENTER, (TEXT("ImpHashHashData\n"))); if (IsEqualGUID(&HASH_GUID_SHA512, HashGUID)) { if (*HashLength < (sha512_desc.hashsize * 8)) { DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"), *HashLength, (sha512_desc.hashsize * 8) )); status = STATUS_BUFFER_TOO_SMALL; } else { sha512_desc.init(&md); sha512_desc.process(&md, Data, (DataLength / 8)); sha512_desc.done(&md, Hash); *HashLength = (sha512_desc.hashsize * 8); } } else if (IsEqualGUID(&HASH_GUID_SHA384, HashGUID)) { if (*HashLength < (sha384_desc.hashsize * 8)) { DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"), *HashLength, (sha384_desc.hashsize * 8) )); status = STATUS_BUFFER_TOO_SMALL; } else { sha384_desc.init(&md); sha384_desc.process(&md, Data, (DataLength / 8)); sha384_desc.done(&md, Hash); *HashLength = (sha384_desc.hashsize * 8); } } else if (IsEqualGUID(&HASH_GUID_SHA256, HashGUID)) { if (*HashLength < (sha256_desc.hashsize * 8)) { DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"), *HashLength, (sha256_desc.hashsize * 8) )); status = STATUS_BUFFER_TOO_SMALL; } else { sha256_desc.init(&md); sha256_desc.process(&md, Data, (DataLength / 8)); sha256_desc.done(&md, Hash); *HashLength = (sha256_desc.hashsize * 8); } } else if (IsEqualGUID(&HASH_GUID_SHA224, HashGUID)) { if (*HashLength < (sha224_desc.hashsize * 8)) { DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"), *HashLength, (sha224_desc.hashsize * 8) )); status = STATUS_BUFFER_TOO_SMALL; } else { sha224_desc.init(&md); sha224_desc.process(&md, Data, (DataLength / 8)); sha224_desc.done(&md, Hash); *HashLength = (sha224_desc.hashsize * 8); } } else if (IsEqualGUID(&HASH_GUID_SHA1, HashGUID)) { if (*HashLength < (sha1_desc.hashsize * 8)) { DEBUGOUTHASHIMPL(DEBUGLEV_ERROR, (TEXT("output hash length buffer too small (got: %d; need: %d)\n"), *HashLength, (sha1_desc.hashsize * 8) )); status = STATUS_BUFFER_TOO_SMALL; } else { sha1_desc.init(&md); sha1_desc.process(&md, Data, (DataLength / 8)); sha1_desc.done(&md, Hash); *HashLength = (sha1_desc.hashsize * 8); } } 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; }