From cb80a37654ebc902769f87ffbadd38d161109333 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Wed, 27 Nov 2013 19:09:16 +0000 Subject: - strong cyphering for passwords in db3x_mmap; - unique signature for the new mmap profiles; git-svn-id: http://svn.miranda-ng.org/main/trunk@6997 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- include/m_crypto.h | 4 +- plugins/Db3x_mmap/src/dbcrypt.cpp | 109 +++++++++++++++- plugins/Db3x_mmap/src/dbintf.cpp | 2 +- plugins/Db3x_mmap/src/dbintf.h | 13 +- plugins/Db3x_mmap/src/dbsettings.cpp | 196 ++++++++++++++++------------- plugins/ExternalAPI/delphi/m_historypp.inc | 2 +- src/core/stdcrypt/Rijndael.cpp | 10 +- src/core/stdcrypt/commonheaders.h | 2 +- src/core/stdcrypt/encrypt.cpp | 112 ++++++++--------- src/core/stdcrypt/stdcrypt.h | 6 +- src/core/stdcrypt/utils.cpp | 6 +- 11 files changed, 294 insertions(+), 168 deletions(-) diff --git a/include/m_crypto.h b/include/m_crypto.h index 1634f7c93e..0d79e2f9ba 100644 --- a/include/m_crypto.h +++ b/include/m_crypto.h @@ -45,11 +45,11 @@ struct MICryptoEngine // result must be freed using mir_free or assigned to mir_ptr STDMETHOD_(BYTE*, encodeString)(const char *src, size_t *cbResultLen) PURE; - STDMETHOD_(BYTE*, encodeStringW)(const WCHAR* src, size_t *cbResultLen) PURE; + STDMETHOD_(BYTE*, encodeBuffer)(const void *src, size_t cbLen, size_t *cbResultLen) PURE; // result must be freed using mir_free or assigned to ptrA/ptrT STDMETHOD_(char*, decodeString)(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) PURE; - STDMETHOD_(WCHAR*, decodeStringW)(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) PURE; + STDMETHOD_(void*, decodeBuffer)(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) PURE; }; ///////////////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/Db3x_mmap/src/dbcrypt.cpp b/plugins/Db3x_mmap/src/dbcrypt.cpp index b0054bacbf..79a3744462 100644 --- a/plugins/Db3x_mmap/src/dbcrypt.cpp +++ b/plugins/Db3x_mmap/src/dbcrypt.cpp @@ -23,7 +23,101 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" -int CDb3Base::InitCrypt() +///////////////////////////////////////////////////////////////////////////////////////// + +bool isEncrypted(LPCSTR szModule, LPCSTR szSetting); + +//VERY VERY VERY BASIC ENCRYPTION FUNCTION + +static void Encrypt(char *msg, BOOL up) +{ + int jump = (up) ? 5 : -5; + for (int i = 0; msg[i]; i++) + msg[i] = msg[i] + jump; +} + +__forceinline void DecodeString(LPSTR buf) +{ + Encrypt(buf, FALSE); +} + +struct VarDescr +{ + VarDescr(LPCSTR var, LPCSTR value) : + szVar(mir_strdup(var)), + szValue(mir_strdup(value)) + {} + + ptrA szVar, szValue; +}; + +struct SettingUgraderParam +{ + CDb3Mmap *db; + LPCSTR szModule; + HANDLE hContact; + OBJLIST* pList; +}; + +int sttSettingUgrader(const char *szSetting, LPARAM lParam) +{ + SettingUgraderParam *param = (SettingUgraderParam*)lParam; + if (isEncrypted(param->szModule, szSetting)) { + DBVARIANT dbv = { DBVT_UTF8 }; + DBCONTACTGETSETTING dbcgs = { param->szModule, szSetting, &dbv }; + if (!param->db->GetContactSettingStr(param->hContact, &dbcgs)) { + if (dbv.type == DBVT_UTF8) { + DecodeString(dbv.pszVal); + param->pList->insert(new VarDescr(szSetting, dbv.pszVal)); + } + param->db->FreeVariant(&dbv); + } + } + return 0; +} + +void sttContactEnum(HANDLE hContact, const char *szModule, CDb3Mmap *db) +{ + OBJLIST arSettings(1); + SettingUgraderParam param = { db, szModule, hContact, &arSettings }; + + DBCONTACTENUMSETTINGS dbces = { 0 }; + dbces.pfnEnumProc = sttSettingUgrader; + dbces.szModule = szModule; + dbces.lParam = (LPARAM)¶m; + db->EnumContactSettings(NULL, &dbces); + + for (int i = 0; i < arSettings.getCount(); i++) { + VarDescr &p = arSettings[i]; + + size_t len; + BYTE *pResult = db->m_crypto->encodeString(p.szValue, &len); + if (pResult != NULL) { + DBCONTACTWRITESETTING dbcws = { szModule, p.szVar }; + dbcws.value.type = DBVT_ENCRYPTED; + dbcws.value.pbVal = pResult; + dbcws.value.cpbVal = (WORD)len; + db->WriteContactSetting(hContact, &dbcws); + + mir_free(pResult); + } + } +} + +int sttModuleEnum(const char *szModule, DWORD, LPARAM lParam) +{ + CDb3Mmap *db = (CDb3Mmap*)lParam; + sttContactEnum(NULL, szModule, db); + + for (HANDLE hContact = db->FindFirstContact(); hContact; hContact = db->FindNextContact(hContact)) + sttContactEnum(hContact, szModule, db); + + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CDb3Mmap::InitCrypt() { CRYPTO_PROVIDER *pProvider; @@ -78,8 +172,19 @@ LBL_SetNewKey: if (dbv.cpbVal != (WORD)iKeyLength) goto LBL_SetNewKey; - m_crypto->setKey(dbv.pbVal, iKeyLength); + if (!m_crypto->setKey(dbv.pbVal, iKeyLength)) + goto LBL_SetNewKey; + FreeVariant(&dbv); } + + if (memcmp(&m_dbHeader.signature, &dbSignature, sizeof(m_dbHeader.signature))) { + EnumModuleNames(sttModuleEnum, this); + + // upgrade signature + memcpy(&m_dbHeader.signature, &dbSignature, sizeof(dbSignature)); + DBWrite(0, &dbSignature, sizeof(dbSignature)); + } + return 0; } diff --git a/plugins/Db3x_mmap/src/dbintf.cpp b/plugins/Db3x_mmap/src/dbintf.cpp index f0d351a16e..398bd0c618 100644 --- a/plugins/Db3x_mmap/src/dbintf.cpp +++ b/plugins/Db3x_mmap/src/dbintf.cpp @@ -89,7 +89,7 @@ CDb3Base::~CDb3Base() if (!m_bReadOnly) { DWORD bytesWritten; SetFilePointer(m_hDbFile, 0, NULL, FILE_BEGIN); - WriteFile(m_hDbFile, &dbSignatureIM, sizeof(dbSignatureIM), &bytesWritten, NULL); + WriteFile(m_hDbFile, &dbSignatureIM, 1, &bytesWritten, NULL); } CloseHandle(m_hDbFile); diff --git a/plugins/Db3x_mmap/src/dbintf.h b/plugins/Db3x_mmap/src/dbintf.h index e5178bf1b1..7f0455c6f9 100644 --- a/plugins/Db3x_mmap/src/dbintf.h +++ b/plugins/Db3x_mmap/src/dbintf.h @@ -50,6 +50,8 @@ DBHeader #define WSOFS_END 0xFFFFFFFF #define WS_ERROR 0xFFFFFFFF +#define DBVT_ENCRYPTED 250 + struct DBSignature { char name[15]; BYTE eof; @@ -151,7 +153,7 @@ struct CDb3Base : public MIDatabase, public MIDatabaseChecker, public MZeroedObj __forceinline HANDLE getFile() const { return m_hDbFile; } -protected: +public: STDMETHODIMP_(void) SetCacheSafetyMode(BOOL); STDMETHODIMP_(LONG) GetContactCount(void); @@ -202,9 +204,7 @@ protected: virtual void DBFill(DWORD ofs, int bytes) = 0; virtual void DBFlush(int setting) = 0; virtual int InitCache(void) = 0; - -protected: - int InitCrypt(void); + virtual int InitCrypt(void) { return 0; } public: // Check functions int WorkInitialChecks(int); @@ -221,8 +221,6 @@ protected: DWORD m_ChunkSize; bool m_safetyMode, m_bReadOnly, m_bEncrypted; - MICryptoEngine *m_crypto; - //////////////////////////////////////////////////////////////////////////// // database stuff public: @@ -231,6 +229,8 @@ public: PBYTE m_pDbCache; HANDLE m_hMap; + MICryptoEngine *m_crypto; + protected: DWORD m_dwFileSize; HANDLE hSettingChangeEvent, hContactDeletedEvent, hContactAddedEvent; @@ -305,6 +305,7 @@ protected: virtual void DBFill(DWORD ofs, int bytes); virtual void DBFlush(int setting); virtual int InitCache(void); + virtual int InitCrypt(void); protected: PBYTE m_pNull; diff --git a/plugins/Db3x_mmap/src/dbsettings.cpp b/plugins/Db3x_mmap/src/dbsettings.cpp index eafc619f0c..cd7d8799a4 100644 --- a/plugins/Db3x_mmap/src/dbsettings.cpp +++ b/plugins/Db3x_mmap/src/dbsettings.cpp @@ -35,9 +35,9 @@ DWORD __forceinline GetSettingValueLength(PBYTE pSetting) #define NeedBytes(n) if (bytesRemaining<(n)) pBlob = (PBYTE)DBRead(ofsBlobPtr,(n),&bytesRemaining) #define MoveAlong(n) {int x = n; pBlob += (x); ofsBlobPtr += (x); bytesRemaining -= (x);} -#define VLT(n) ((n == DBVT_UTF8)?DBVT_ASCIIZ:n) +#define VLT(n) ((n == DBVT_UTF8 || n == DBVT_ENCRYPTED)?DBVT_ASCIIZ:n) -static bool isEncrypted(LPCSTR szModule, LPCSTR szSetting) +bool isEncrypted(LPCSTR szModule, LPCSTR szSetting) { if (!_strnicmp(szSetting, "password", 8)) return true; if (!strcmp(szSetting, "NLProxyAuthPassword")) return true; @@ -52,25 +52,6 @@ static bool isEncrypted(LPCSTR szModule, LPCSTR szSetting) return false; } -//VERY VERY VERY BASIC ENCRYPTION FUNCTION - -static void Encrypt(char *msg, BOOL up) -{ - int jump = (up) ? 5 : -5; - for (int i = 0; msg[i]; i++) - msg[i] = msg[i] + jump; -} - -__forceinline void EncodeString(LPSTR buf) -{ - Encrypt(buf, TRUE); -} - -__forceinline void DecodeString(LPSTR buf) -{ - Encrypt(buf, FALSE); -} - ///////////////////////////////////////////////////////////////////////////////////////// int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcgs, int isStatic) @@ -123,8 +104,6 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcg dbcgs->pValue->pszVal = (char*)mir_alloc(strlen(pCachedValue->pszVal)+1); strcpy(dbcgs->pValue->pszVal,pCachedValue->pszVal); } - if (bIsEncrypted) - DecodeString(dbcgs->pValue->pszVal); } else memcpy( dbcgs->pValue, pCachedValue, sizeof( DBVARIANT )); @@ -146,7 +125,7 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcg DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsContact, ofsModuleName); if (ofsSettingsGroup) { int bytesRemaining; - bool bEncrypted = false; + unsigned varLen; DWORD ofsBlobPtr = ofsSettingsGroup + offsetof(DBContactSettings, blob); PBYTE pBlob = DBRead(ofsBlobPtr, sizeof(DBContactSettings), &bytesRemaining); while (pBlob[0]) { @@ -157,8 +136,8 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcg if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbcgs->pValue->type) != VLT(pBlob[0])) return 1; - dbcgs->pValue->type = pBlob[0]; - switch (pBlob[0]) { + BYTE iType = dbcgs->pValue->type = pBlob[0]; + switch (iType) { case DBVT_DELETED: /* this setting is deleted */ dbcgs->pValue->type = DBVT_DELETED; return 2; @@ -166,41 +145,73 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcg case DBVT_BYTE: dbcgs->pValue->bVal = pBlob[1]; break; case DBVT_WORD: MoveMemory(&(dbcgs->pValue->wVal), (PWORD)(pBlob + 1), 2); break; case DBVT_DWORD: MoveMemory(&(dbcgs->pValue->dVal), (PDWORD)(pBlob + 1), 4); break; + case DBVT_UTF8: case DBVT_ASCIIZ: - bEncrypted = m_bEncrypted || isEncrypted(dbcgs->szModule, dbcgs->szSetting); - NeedBytes(3 + *(PWORD)(pBlob + 1)); + varLen = *(PWORD)(pBlob + 1); + NeedBytes(int(3 + varLen)); if (isStatic) { dbcgs->pValue->cchVal--; - if (*(PWORD)(pBlob + 1) < dbcgs->pValue->cchVal) - dbcgs->pValue->cchVal = *(PWORD)(pBlob + 1); + if (varLen < dbcgs->pValue->cchVal) + dbcgs->pValue->cchVal = varLen; MoveMemory(dbcgs->pValue->pszVal, pBlob + 3, dbcgs->pValue->cchVal); // decode dbcgs->pValue->pszVal[dbcgs->pValue->cchVal] = 0; - dbcgs->pValue->cchVal = *(PWORD)(pBlob + 1); + dbcgs->pValue->cchVal = varLen; } else { - dbcgs->pValue->pszVal = (char*)mir_alloc(1 + *(PWORD)(pBlob + 1)); - MoveMemory(dbcgs->pValue->pszVal, pBlob + 3, *(PWORD)(pBlob + 1)); - dbcgs->pValue->pszVal[*(PWORD)(pBlob + 1)] = 0; + dbcgs->pValue->pszVal = (char*)mir_alloc(1 + varLen); + MoveMemory(dbcgs->pValue->pszVal, pBlob + 3, varLen); + dbcgs->pValue->pszVal[varLen] = 0; } break; + case DBVT_BLOB: - NeedBytes(3 + *(PWORD)(pBlob + 1)); + varLen = *(PWORD)(pBlob + 1); + NeedBytes(int(3 + varLen)); if (isStatic) { - if (*(PWORD)(pBlob + 1) < dbcgs->pValue->cpbVal) - dbcgs->pValue->cpbVal = *(PWORD)(pBlob + 1); - MoveMemory(dbcgs->pValue->pbVal, pBlob + 3, dbcgs->pValue->cpbVal); // decode + if (varLen < dbcgs->pValue->cpbVal) + dbcgs->pValue->cpbVal = varLen; + MoveMemory(dbcgs->pValue->pbVal, pBlob + 3, dbcgs->pValue->cpbVal); + } + else { + dbcgs->pValue->pbVal = (BYTE *)mir_alloc(varLen); + MoveMemory(dbcgs->pValue->pbVal, pBlob + 3, varLen); } + dbcgs->pValue->cpbVal = varLen; + break; + + case DBVT_ENCRYPTED: + if (m_crypto == NULL) + return 1; else { - dbcgs->pValue->pbVal = (BYTE *)mir_alloc(*(PWORD)(pBlob + 1)); - MoveMemory(dbcgs->pValue->pbVal, pBlob + 3, *(PWORD)(pBlob + 1)); // decode + varLen = *(PWORD)(pBlob + 1); + NeedBytes(int(3 + varLen)); + size_t realLen; + ptrA decoded(m_crypto->decodeString(pBlob + 3, varLen, &realLen)); + if (decoded == NULL) + return 1; + + varLen = (WORD)realLen; + dbcgs->pValue->type = DBVT_UTF8; + if (isStatic) { + dbcgs->pValue->cchVal--; + if (varLen < dbcgs->pValue->cchVal) + dbcgs->pValue->cchVal = varLen; + MoveMemory(dbcgs->pValue->pszVal, decoded, dbcgs->pValue->cchVal); + dbcgs->pValue->pszVal[dbcgs->pValue->cchVal] = 0; + dbcgs->pValue->cchVal = varLen; + } + else { + dbcgs->pValue->pszVal = (char*)mir_alloc(1 + varLen); + MoveMemory(dbcgs->pValue->pszVal, decoded, varLen); + dbcgs->pValue->pszVal[varLen] = 0; + } } - dbcgs->pValue->cpbVal = *(PWORD)(pBlob + 1); break; } /**** add to cache **********************/ - if (dbcgs->pValue->type != DBVT_BLOB && !bEncrypted) { + if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) { DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 1); if (pCachedValue != NULL) { m_cache->SetCachedVariant(dbcgs->pValue, pCachedValue); @@ -208,10 +219,6 @@ int CDb3Base::GetContactSettingWorker(HANDLE hContact, DBCONTACTGETSETTING *dbcg } } - // don't cache decrypted values - if (dbcgs->pValue->type == DBVT_UTF8 || dbcgs->pValue->type == DBVT_ASCIIZ) - if (bEncrypted) - DecodeString(dbcgs->pValue->pszVal); return 0; } NeedBytes(1); @@ -403,23 +410,33 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT else return 1; } - if (tmp.value.type != DBVT_BYTE && tmp.value.type != DBVT_WORD && tmp.value.type != DBVT_DWORD && tmp.value.type != DBVT_ASCIIZ && tmp.value.type != DBVT_UTF8 && tmp.value.type != DBVT_BLOB) - return 1; - if ((!tmp.szModule) || (!tmp.szSetting) || ((tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8) && tmp.value.pszVal == NULL) || (tmp.value.type == DBVT_BLOB && tmp.value.pbVal == NULL)) + if (tmp.szModule == NULL || tmp.szSetting == NULL) return 1; - // the db can not tolerate strings/blobs longer than 0xFFFF since the format writes 2 lengths + mir_ptr pEncoded(NULL); bool bIsEncrypted = false; switch (tmp.value.type) { - case DBVT_ASCIIZ: case DBVT_BLOB: case DBVT_UTF8: - size_t len = (tmp.value.type != DBVT_BLOB) ? strlen(tmp.value.pszVal) : tmp.value.cpbVal; - if (len >= 0xFFFF) { -#ifdef _DEBUG - OutputDebugStringA("WriteContactSetting() writing huge string/blob, rejecting ( >= 0xFFFF ) \n"); -#endif - return 1; - } + case DBVT_BYTE: case DBVT_WORD: case DBVT_DWORD: + break; + case DBVT_ASCIIZ: case DBVT_UTF8: + if (tmp.value.pszVal == NULL) return 1; + tmp.value.cchVal = (WORD)strlen(tmp.value.pszVal); bIsEncrypted = m_bEncrypted || isEncrypted(dbcws->szModule, dbcws->szSetting); + if (bIsEncrypted) { + size_t len; + BYTE *pResult = m_crypto->encodeString(tmp.value.pszVal, &len); + if (pResult != NULL) { + pEncoded = tmp.value.pbVal = pResult; + tmp.value.cpbVal = (WORD)len; + tmp.value.type = DBVT_ENCRYPTED; + } + } + break; + case DBVT_BLOB: case DBVT_ENCRYPTED: + if (tmp.value.pbVal == NULL) return 1; + break; + default: + return 1; } mir_cslockfull lck(m_csDbAccess); @@ -427,7 +444,7 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT char *szCachedSettingName = m_cache->GetCachedSetting(tmp.szModule, tmp.szSetting, moduleNameLen, settingNameLen); log3("set [%08p] %s (%p)", hContact, szCachedSettingName, szCachedSettingName); - if (tmp.value.type != DBVT_BLOB && !bIsEncrypted) { + if (tmp.value.type != DBVT_BLOB && tmp.value.type != DBVT_ENCRYPTED && !bIsEncrypted) { DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(hContact, szCachedSettingName, 1); if (pCachedValue != NULL) { bool bIsIdentical = false; @@ -467,13 +484,16 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT DBContactSettings dbcs; DWORD ofsSettingsGroup = GetSettingsGroupOfsByModuleNameOfs(&dbc, ofsContact, ofsModuleName); if (ofsSettingsGroup == 0) { //module group didn't exist - make it - if (tmp.value.type & DBVTF_VARIABLELENGTH) { - if (tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8) - bytesRequired = (int)strlen(tmp.value.pszVal) + 2; - else if (tmp.value.type == DBVT_BLOB) - bytesRequired = tmp.value.cpbVal + 2; + switch (tmp.value.type) { + case DBVT_ASCIIZ: case DBVT_UTF8: + bytesRequired = tmp.value.cchVal + 2; + break; + case DBVT_BLOB: case DBVT_ENCRYPTED: + bytesRequired = tmp.value.cpbVal + 2; + break; + default: + bytesRequired = tmp.value.type; } - else bytesRequired = tmp.value.type; bytesRequired += 2 + settingNameLen; bytesRequired += (DB_SETTINGS_RESIZE_GRANULARITY - (bytesRequired % DB_SETTINGS_RESIZE_GRANULARITY)) % DB_SETTINGS_RESIZE_GRANULARITY; ofsSettingsGroup = CreateNewSpace(bytesRequired + offsetof(DBContactSettings, blob)); @@ -507,7 +527,10 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT MoveAlong(1 + settingNameLen); //if different type or variable length and length is different NeedBytes(3); - if (pBlob[0] != tmp.value.type || ((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob + 1) != strlen(tmp.value.pszVal)) || (pBlob[0] == DBVT_BLOB && *(PWORD)(pBlob + 1) != tmp.value.cpbVal)) { + if (pBlob[0] != tmp.value.type || + ((pBlob[0] == DBVT_ASCIIZ || pBlob[0] == DBVT_UTF8) && *(PWORD)(pBlob + 1) != tmp.value.cchVal) || + ((pBlob[0] == DBVT_BLOB || pBlob[0] == DBVT_ENCRYPTED) && *(PWORD)(pBlob + 1) != tmp.value.cpbVal)) + { //bin it NeedBytes(3); int nameLen = 1 + settingNameLen; @@ -533,13 +556,12 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT case DBVT_WORD: DBWrite(ofsBlobPtr, &tmp.value.wVal, 2); break; case DBVT_DWORD: DBWrite(ofsBlobPtr, &tmp.value.dVal, 4); break; case DBVT_BLOB: - DBWrite(ofsBlobPtr + 2, tmp.value.pbVal, tmp.value.cpbVal); // encode + case DBVT_ENCRYPTED: + DBWrite(ofsBlobPtr + 2, tmp.value.pbVal, tmp.value.cpbVal); break; case DBVT_UTF8: case DBVT_ASCIIZ: - if (bIsEncrypted) - EncodeString(tmp.value.pszVal); - DBWrite(ofsBlobPtr + 2, tmp.value.pszVal, (int)strlen(tmp.value.pszVal)); // encode + DBWrite(ofsBlobPtr + 2, tmp.value.pszVal, tmp.value.cchVal); break; } //quit @@ -554,13 +576,17 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT //cannot do a simple replace, add setting to end of list //pBlob already points to end of list //see if it fits - if (tmp.value.type & DBVTF_VARIABLELENGTH) { - if (tmp.value.type == DBVT_ASCIIZ || tmp.value.type == DBVT_UTF8) - bytesRequired = (int)strlen(tmp.value.pszVal) + 2; - else if (tmp.value.type == DBVT_BLOB) - bytesRequired = tmp.value.cpbVal + 2; + switch (tmp.value.type) { + case DBVT_ASCIIZ: case DBVT_UTF8: + bytesRequired = tmp.value.cchVal + 2; + break; + case DBVT_BLOB: case DBVT_ENCRYPTED: + bytesRequired = tmp.value.cpbVal + 2; + break; + default: + bytesRequired = tmp.value.type; } - else bytesRequired = tmp.value.type; + bytesRequired += 2 + settingNameLen; bytesRequired += ofsBlobPtr + 1 - (ofsSettingsGroup + offsetof(DBContactSettings, blob)); @@ -612,19 +638,17 @@ STDMETHODIMP_(BOOL) CDb3Base::WriteContactSetting(HANDLE hContact, DBCONTACTWRIT case DBVT_BYTE: DBWrite(ofsBlobPtr, &tmp.value.bVal, 1); MoveAlong(1); break; case DBVT_WORD: DBWrite(ofsBlobPtr, &tmp.value.wVal, 2); MoveAlong(2); break; case DBVT_DWORD: DBWrite(ofsBlobPtr, &tmp.value.dVal, 4); MoveAlong(4); break; - case DBVT_BLOB: + + case DBVT_BLOB: case DBVT_ENCRYPTED: DBWrite(ofsBlobPtr, &tmp.value.cpbVal, 2); - DBWrite(ofsBlobPtr + 2, tmp.value.pbVal, tmp.value.cpbVal); // encode + DBWrite(ofsBlobPtr + 2, tmp.value.pbVal, tmp.value.cpbVal); MoveAlong(2 + tmp.value.cpbVal); break; - case DBVT_UTF8: - case DBVT_ASCIIZ: - int len = (int)strlen(tmp.value.pszVal); - if (bIsEncrypted) - EncodeString(tmp.value.pszVal); - DBWrite(ofsBlobPtr, &len, 2); - DBWrite(ofsBlobPtr + 2, tmp.value.pszVal, len); // encode - MoveAlong(2 + len); + + case DBVT_UTF8: case DBVT_ASCIIZ: + DBWrite(ofsBlobPtr, &tmp.value.cchVal, 2); + DBWrite(ofsBlobPtr + 2, tmp.value.pszVal, tmp.value.cchVal); + MoveAlong(2 + tmp.value.cchVal); break; } diff --git a/plugins/ExternalAPI/delphi/m_historypp.inc b/plugins/ExternalAPI/delphi/m_historypp.inc index a0ff7e82d7..19fed89f4e 100644 --- a/plugins/ExternalAPI/delphi/m_historypp.inc +++ b/plugins/ExternalAPI/delphi/m_historypp.inc @@ -149,7 +149,7 @@ type cbSize : DWord; hContact : THandle; hDBEvent : THandle; - pPassword: PAnsiChar; + junkie: PAnsiChar; end; POpenEventParams = ^TOpenEventParams; diff --git a/src/core/stdcrypt/Rijndael.cpp b/src/core/stdcrypt/Rijndael.cpp index fd9cf84d83..95cc317099 100644 --- a/src/core/stdcrypt/Rijndael.cpp +++ b/src/core/stdcrypt/Rijndael.cpp @@ -963,8 +963,14 @@ int CRijndael::MakeKey(BYTE const* key, char const* chain, int keylength, int bl m_keylength = keylength; m_blockSize = blockSize; //Initialize the chain - memcpy(m_chain0, chain, m_blockSize); - memcpy(m_chain, chain, m_blockSize); + size_t len = strlen(chain); + if (len >= m_blockSize) + memcpy(m_chain0, chain, m_blockSize); + else { + memcpy(m_chain0, chain, len); + memset(m_chain0 + len, 0, m_blockSize - len); + } + memcpy(m_chain, m_chain0, m_blockSize); //Calculate Number of Rounds switch (m_keylength) { case 16: diff --git a/src/core/stdcrypt/commonheaders.h b/src/core/stdcrypt/commonheaders.h index 37168497d8..07daa68ac1 100644 --- a/src/core/stdcrypt/commonheaders.h +++ b/src/core/stdcrypt/commonheaders.h @@ -78,4 +78,4 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern HINSTANCE hInst; bool getRandomBytes(BYTE *buf, size_t bufLen); -void slow_hash(const void *buf, size_t bufLen, BYTE tmpHash[32]); +void slow_hash(const void *buf, size_t bufLen, BYTE *tmpHash); diff --git a/src/core/stdcrypt/encrypt.cpp b/src/core/stdcrypt/encrypt.cpp index 00e52935d8..5be76f1c54 100644 --- a/src/core/stdcrypt/encrypt.cpp +++ b/src/core/stdcrypt/encrypt.cpp @@ -67,24 +67,20 @@ bool CStdCrypt::getKey(BYTE *pKey, size_t cbKeyLen) bool CStdCrypt::setKey(const BYTE *pKey, size_t cbKeyLen) { - ExternalKey tmp = { 0 }; - // full external key. decode & check password - if (cbKeyLen == sizeof(tmp)) { - BYTE tmpHash[32]; - slow_hash(m_password, m_password.GetLength(), tmpHash); - - CRijndael tmpAes; - tmpAes.MakeKey(tmpHash, tmpAes.sm_chain0, KEY_LENGTH, BLOCK_SIZE); - tmpAes.Decrypt(pKey, &tmp, sizeof(tmp)); - if (tmp.m_crc32 != crc32(0xAbbaDead, (LPCBYTE)m_password.GetString(), m_password.GetLength())) - return false; - } - // new key. simply copy it - else if (cbKeyLen == KEY_LENGTH) { - memcpy(&tmp.m_key, pKey, KEY_LENGTH); - } - else return false; + if (cbKeyLen != sizeof(ExternalKey)) + return false; + + BYTE tmpHash[32]; + slow_hash(m_password, m_password.GetLength(), tmpHash); + + CRijndael tmpAes; + tmpAes.MakeKey(tmpHash, tmpAes.sm_chain0, KEY_LENGTH, BLOCK_SIZE); + + ExternalKey tmp = { 0 }; + tmpAes.Decrypt(pKey, &tmp, sizeof(tmp)); + if (tmp.m_crc32 != crc32(0xAbbaDead, (LPCBYTE)m_password.GetString(), m_password.GetLength())) + return false; memcpy(m_key, &tmp.m_key, KEY_LENGTH); m_aes.MakeKey(m_key, m_password, KEY_LENGTH, BLOCK_SIZE); @@ -97,7 +93,9 @@ bool CStdCrypt::generateKey(void) if (!getRandomBytes(tmp, sizeof(tmp))) return false; - return setKey(tmp, sizeof(tmp)); + memcpy(m_key, tmp, KEY_LENGTH); + m_aes.MakeKey(m_key, m_password, KEY_LENGTH, BLOCK_SIZE); + return m_valid = true; } void CStdCrypt::purgeKey(void) @@ -115,37 +113,34 @@ void CStdCrypt::setPassword(const char *pszPassword) // result must be freed using mir_free or assigned to mir_ptr BYTE* CStdCrypt::encodeString(const char *src, size_t *cbResultLen) { - if (cbResultLen) - *cbResultLen = 0; - - if (!m_valid || src == NULL || *src == 0) - return NULL; - - size_t cbLen = strlen(src); - cbLen += BLOCK_SIZE - (cbLen % BLOCK_SIZE); - BYTE *result = (BYTE*)mir_alloc(cbLen); - if (m_aes.Encrypt(src, LPSTR(result), cbLen)) { - mir_free(result); + if (!m_valid || src == NULL) { + if (cbResultLen) + *cbResultLen = 0; return NULL; } - if (cbResultLen) - *cbResultLen = cbLen; - return result; + return encodeBuffer(src, strlen(src)+1, cbResultLen); } -BYTE* CStdCrypt::encodeStringW(const WCHAR *src, size_t *cbResultLen) +BYTE* CStdCrypt::encodeBuffer(const void *src, size_t cbLen, size_t *cbResultLen) { if (cbResultLen) *cbResultLen = 0; - if (!m_valid || src == NULL || *src == 0) + if (!m_valid || src == NULL || cbLen >= 0xFFFE) return NULL; - size_t cbLen = wcslen(src) * sizeof(WCHAR); - cbLen += BLOCK_SIZE - (cbLen % BLOCK_SIZE); + BYTE *tmpBuf = (BYTE*)_alloca(cbLen + 2); + *(PWORD)tmpBuf = (WORD)cbLen; + memcpy(tmpBuf + 2, src, cbLen); + cbLen += 2; + size_t rest = cbLen % BLOCK_SIZE; + if (rest) + cbLen += BLOCK_SIZE - rest; + BYTE *result = (BYTE*)mir_alloc(cbLen); - if (m_aes.Encrypt(LPCSTR(src), LPSTR(result), cbLen)) { + m_aes.ResetChain(); + if (m_aes.Encrypt(tmpBuf, LPSTR(result), cbLen)) { mir_free(result); return NULL; } @@ -157,29 +152,21 @@ BYTE* CStdCrypt::encodeStringW(const WCHAR *src, size_t *cbResultLen) char* CStdCrypt::decodeString(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) { - if (cbResultLen) - *cbResultLen = 0; - - if (!m_valid || pBuf == NULL || (bufLen % BLOCK_SIZE) != 0) - return NULL; - - char *result = (char*)mir_alloc(bufLen+1); - if (m_aes.Decrypt(LPCSTR(pBuf), result, bufLen)) { - mir_free(result); - return NULL; + size_t resLen; + char *result = (char*)decodeBuffer(pBuf, bufLen, &resLen); + if (result) { + if (result[resLen-1] != 0) { // smth went wrong + mir_free(result); + return NULL; + } } - result[bufLen] = 0; - for (int i = (int)bufLen-1; i >= 0; i--) - if (result[i] == 0) - bufLen--; - if (cbResultLen) - *cbResultLen = bufLen; + *cbResultLen = resLen; return result; } -WCHAR* CStdCrypt::decodeStringW(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) +void* CStdCrypt::decodeBuffer(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) { if (cbResultLen) *cbResultLen = 0; @@ -187,20 +174,23 @@ WCHAR* CStdCrypt::decodeStringW(const BYTE *pBuf, size_t bufLen, size_t *cbResul if (!m_valid || pBuf == NULL || (bufLen % BLOCK_SIZE) != 0) return NULL; - WCHAR *result = (WCHAR*)mir_alloc(bufLen + sizeof(WCHAR)); - if (m_aes.Decrypt(LPCSTR(pBuf), LPSTR(result), bufLen)) { + char *result = (char*)mir_alloc(bufLen + 1); + m_aes.ResetChain(); + if (m_aes.Decrypt(LPCSTR(pBuf), result, bufLen)) { mir_free(result); return NULL; } - bufLen /= sizeof(WCHAR); result[bufLen] = 0; - for (int i = (int)bufLen - 1; i >= 0; i--) - if (result[i] == 0) - bufLen--; + WORD cbLen = *(PWORD)result; + if (cbLen > bufLen) { + mir_free(result); + return NULL; + } + memmove(result, result + 2, cbLen); if (cbResultLen) - *cbResultLen = bufLen; + *cbResultLen = cbLen; return result; } diff --git a/src/core/stdcrypt/stdcrypt.h b/src/core/stdcrypt/stdcrypt.h index c9a3a72315..6129cabcc8 100644 --- a/src/core/stdcrypt/stdcrypt.h +++ b/src/core/stdcrypt/stdcrypt.h @@ -49,9 +49,9 @@ struct CStdCrypt : public MICryptoEngine, public MZeroedObject // result must be freed using mir_free or assigned to mir_ptr STDMETHODIMP_(BYTE*) encodeString(const char *src, size_t *cbResultLen); - STDMETHODIMP_(BYTE*) encodeStringW(const WCHAR* src, size_t *cbResultLen); + STDMETHODIMP_(BYTE*) encodeBuffer(const void *src, size_t cbLen, size_t *cbResultLen); // result must be freed using mir_free or assigned to ptrA/ptrT - STDMETHODIMP_(char*) decodeString(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); - STDMETHODIMP_(WCHAR*) decodeStringW(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); + STDMETHODIMP_(char*) decodeString(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); + STDMETHODIMP_(void*) decodeBuffer(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); }; diff --git a/src/core/stdcrypt/utils.cpp b/src/core/stdcrypt/utils.cpp index 3ef8b7bdf7..99b2d3c8db 100644 --- a/src/core/stdcrypt/utils.cpp +++ b/src/core/stdcrypt/utils.cpp @@ -342,7 +342,7 @@ static void sha256_final(SHA256_CONTEXT *hd, BYTE tmpHash[32]) #undef X } -static void make_sha256(const void *buf, size_t bufLen, BYTE tmpHash[32]) +static void make_sha256(const void *buf, size_t bufLen, BYTE *tmpHash) { SHA256_CONTEXT tmp; sha256_init(&tmp); @@ -350,10 +350,10 @@ static void make_sha256(const void *buf, size_t bufLen, BYTE tmpHash[32]) sha256_final(&tmp, tmpHash); } -void slow_hash(const void *buf, size_t bufLen, BYTE tmpHash[32]) +void slow_hash(const void *buf, size_t bufLen, BYTE* tmpHash) { make_sha256(buf, bufLen, tmpHash); for (int i = 0; i < 50000; i++) - make_sha256(tmpHash, sizeof(tmpHash), tmpHash); + make_sha256(tmpHash, 32, tmpHash); } -- cgit v1.2.3