From a31e88cd64c258da80d0bab3747c407862a792b0 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Tue, 13 Apr 2021 18:16:57 +0300 Subject: fixes #2836 (Miranda keeps profile password in memory after checking it) --- src/core/stdcrypt/src/encrypt.cpp | 67 +++++++++++++++++++++++---------------- src/core/stdcrypt/src/stdcrypt.h | 37 +++++++++++++-------- 2 files changed, 62 insertions(+), 42 deletions(-) (limited to 'src/core/stdcrypt') diff --git a/src/core/stdcrypt/src/encrypt.cpp b/src/core/stdcrypt/src/encrypt.cpp index e31d29d778..27a6500f5e 100644 --- a/src/core/stdcrypt/src/encrypt.cpp +++ b/src/core/stdcrypt/src/encrypt.cpp @@ -25,16 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "../../../libs/zlib/src/zlib.h" -struct ExternalKey +CStdCrypt::CStdCrypt() { - BYTE m_key[KEY_LENGTH]; - DWORD m_crc32; - BYTE slack[BLOCK_SIZE - sizeof(DWORD)]; -}; - -CStdCrypt::CStdCrypt() : - m_password("Miranda") -{} +} void CStdCrypt::destroy() { @@ -46,42 +39,59 @@ size_t CStdCrypt::getKeyLength() return sizeof(ExternalKey); } -bool CStdCrypt::getKey(BYTE *pKey, size_t cbKeyLen) +void CStdCrypt::key2ext(const char *pszPassword, ExternalKey &key) { - if (!m_valid || cbKeyLen < sizeof(ExternalKey)) - return false; + if (mir_strlen(pszPassword) == 0) + pszPassword = "Miranda"; - ExternalKey tmp = { 0 }; + ExternalKey tmp = {}; memcpy(&tmp.m_key, m_key, KEY_LENGTH); - tmp.m_crc32 = crc32(0xAbbaDead, (LPCBYTE)m_password.GetString(), m_password.GetLength()); + tmp.m_crc32 = crc32(0xAbbaDead, (LPCBYTE)pszPassword, (int)strlen(pszPassword)); getRandomBytes(tmp.slack, sizeof(tmp.slack)); BYTE tmpHash[32]; - slow_hash(m_password, m_password.GetLength(), tmpHash); + slow_hash(pszPassword, strlen(pszPassword), tmpHash); CRijndael tmpAes; tmpAes.MakeKey(tmpHash, tmpAes.sm_chain0, KEY_LENGTH, BLOCK_SIZE); - tmpAes.Encrypt(&tmp, pKey, sizeof(tmp)); - return true; + tmpAes.Encrypt(&tmp, &key, sizeof(ExternalKey)); } -bool CStdCrypt::setKey(const BYTE *pKey, size_t cbKeyLen) +bool CStdCrypt::getKey(BYTE *pKey, size_t cbKeyLen) { - // full external key. decode & check password - if (cbKeyLen != sizeof(ExternalKey)) + if (!m_valid || cbKeyLen < sizeof(m_extKey)) return false; - + + memcpy(pKey, &m_extKey, sizeof(m_extKey)); + return true; +} + +bool CStdCrypt::checkKey(const char *pszPassword, const ExternalKey *pPublic, ExternalKey &tmp) +{ + if (mir_strlen(pszPassword) == 0) + pszPassword = "Miranda"; + BYTE tmpHash[32]; - slow_hash(m_password, m_password.GetLength(), tmpHash); + slow_hash(pszPassword, strlen(pszPassword), 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())) + tmpAes.Decrypt(pPublic, &tmp, sizeof(tmp)); + return (tmp.m_crc32 == crc32(0xAbbaDead, (LPCBYTE)pszPassword, (int)strlen(pszPassword))); +} + +bool CStdCrypt::setKey(const char *pszPassword, const BYTE *pPublic, size_t cbKeyLen) +{ + // full external key. decode & check password + if (cbKeyLen != sizeof(m_extKey)) + return false; + + ExternalKey tmp = {}; + if (!checkKey(pszPassword, (const ExternalKey*)pPublic, tmp)) return false; + memcpy(&m_extKey, pPublic, sizeof(m_extKey)); memcpy(m_key, &tmp.m_key, KEY_LENGTH); m_aes.MakeKey(m_key, "Miranda", KEY_LENGTH, BLOCK_SIZE); return m_valid = true; @@ -95,6 +105,7 @@ bool CStdCrypt::generateKey(void) memcpy(m_key, tmp, KEY_LENGTH); m_aes.MakeKey(m_key, "Miranda", KEY_LENGTH, BLOCK_SIZE); + key2ext(nullptr, m_extKey); return m_valid = true; } @@ -107,13 +118,13 @@ void CStdCrypt::purgeKey(void) // checks the master password (in utf-8) bool CStdCrypt::checkPassword(const char *pszPassword) { - return m_password == pszPassword; + ExternalKey tmp; + return checkKey(pszPassword, &m_extKey, tmp); } -// sets the master password (in utf-8) void CStdCrypt::setPassword(const char *pszPassword) { - m_password = (pszPassword == NULL) ? "Miranda" : pszPassword; + key2ext(pszPassword, m_extKey); } // result must be freed using mir_free or assigned to mir_ptr diff --git a/src/core/stdcrypt/src/stdcrypt.h b/src/core/stdcrypt/src/stdcrypt.h index eeb35620b8..ce003bd27b 100644 --- a/src/core/stdcrypt/src/stdcrypt.h +++ b/src/core/stdcrypt/src/stdcrypt.h @@ -26,35 +26,44 @@ with this program; if not, write to the Free Software Foundation, Inc., #define KEY_LENGTH 32 #define BLOCK_SIZE 16 +struct ExternalKey +{ + BYTE m_key[KEY_LENGTH]; + DWORD m_crc32; + BYTE slack[BLOCK_SIZE - sizeof(DWORD)]; +}; + struct CStdCrypt : public MICryptoEngine, public MZeroedObject { CStdCrypt(); - BOOL m_valid; - CMStringA m_password; - - BYTE m_key[KEY_LENGTH]; + bool m_valid = false; + uint8_t m_key[KEY_LENGTH]; CRijndael m_aes; + ExternalKey m_extKey; + + bool checkKey(const char *pszPassword, const ExternalKey *pPublic, ExternalKey &key); + void key2ext(const char *pszPassword, ExternalKey &key); STDMETHODIMP_(void) destroy(); // get/set the instance key - STDMETHODIMP_(size_t) getKeyLength(void); - STDMETHODIMP_(bool) getKey(BYTE *pKey, size_t cbKeyLen); - STDMETHODIMP_(bool) setKey(const BYTE *pKey, size_t cbKeyLen); + STDMETHODIMP_(size_t) getKeyLength(void) override; + STDMETHODIMP_(bool) getKey(BYTE *pKey, size_t cbKeyLen) override; + STDMETHODIMP_(bool) setKey(const char *pszPassword, const BYTE *pKey, size_t cbKeyLen) override; - STDMETHODIMP_(bool) generateKey(void); // creates a new key inside - STDMETHODIMP_(void) purgeKey(void); // purges a key from memory + STDMETHODIMP_(bool) generateKey(void) override; // creates a new key inside + STDMETHODIMP_(void) purgeKey(void) override; // purges a key from memory // sets the master password (in utf-8) - STDMETHODIMP_(bool) checkPassword(const char *pszPassword); STDMETHODIMP_(void) setPassword(const char *pszPassword); + STDMETHODIMP_(bool) checkPassword(const char *pszPassword) override; // result must be freed using mir_free or assigned to mir_ptr - STDMETHODIMP_(BYTE*) encodeString(const char *src, size_t *cbResultLen); - STDMETHODIMP_(BYTE*) encodeBuffer(const void *src, size_t cbLen, size_t *cbResultLen); + STDMETHODIMP_(BYTE*) encodeString(const char *src, size_t *cbResultLen) override; + STDMETHODIMP_(BYTE*) encodeBuffer(const void *src, size_t cbLen, size_t *cbResultLen) override; // result must be freed using mir_free or assigned to ptrA/ptrW - STDMETHODIMP_(char*) decodeString(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); - STDMETHODIMP_(void*) decodeBuffer(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen); + STDMETHODIMP_(char*) decodeString(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) override; + STDMETHODIMP_(void*) decodeBuffer(const BYTE *pBuf, size_t bufLen, size_t *cbResultLen) override; }; -- cgit v1.2.3