diff options
| -rw-r--r-- | include/m_crypto.h | 2 | ||||
| -rw-r--r-- | src/core/stdcrypt/src/encrypt.cpp | 67 | ||||
| -rw-r--r-- | src/core/stdcrypt/src/stdcrypt.h | 37 | ||||
| -rw-r--r-- | src/mir_app/src/MDatabaseCommonCrypt.cpp | 46 | 
4 files changed, 84 insertions, 68 deletions
diff --git a/include/m_crypto.h b/include/m_crypto.h index 3d6e81d3a3..d13a6b053e 100644 --- a/include/m_crypto.h +++ b/include/m_crypto.h @@ -37,7 +37,7 @@ struct MICryptoEngine  	// get/set the instance key
  	STDMETHOD_(size_t, getKeyLength)(void) PURE;
  	STDMETHOD_(bool, getKey)(BYTE *pKey, size_t cbKeyLen) PURE;
 -	STDMETHOD_(bool, setKey)(const BYTE *pKey, size_t cbKeyLen) PURE;
 +	STDMETHOD_(bool, setKey)(const char *pszPassword, const BYTE *pKey, size_t cbKeyLen) PURE;
  	STDMETHOD_(bool, generateKey)(void)PURE; // creates a new key inside
  	STDMETHOD_(void, purgeKey)(void)PURE;    // purges a key from memory
 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<BYTE>
 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<BYTE>
 -	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;
  };
 diff --git a/src/mir_app/src/MDatabaseCommonCrypt.cpp b/src/mir_app/src/MDatabaseCommonCrypt.cpp index ba9964b863..1e0258a318 100644 --- a/src/mir_app/src/MDatabaseCommonCrypt.cpp +++ b/src/mir_app/src/MDatabaseCommonCrypt.cpp @@ -118,13 +118,13 @@ __forceinline wchar_t *GetMenuTitle(bool bUsesPassword)  void MDatabaseCommon::SetPassword(const wchar_t *ptszPassword)  { -	if (ptszPassword == nullptr || *ptszPassword == 0) { +	if (mir_wstrlen(ptszPassword) == 0) {  		m_bUsesPassword = false;  		m_crypto->setPassword(nullptr);  	}  	else {  		m_bUsesPassword = true; -		m_crypto->setPassword(T2Utf(ptszPassword)); +		m_crypto->setPassword(pass_ptrA(mir_utf8encodeW(ptszPassword)));  	}  	Menu_ModifyItem(hSetPwdMenu, GetMenuTitle(m_bUsesPassword), Skin_GetIconHandle(SKINICON_OTHER_KEYS)); @@ -160,24 +160,14 @@ static bool CheckOldPassword(HWND hwndDlg, MDatabaseCommon *db)  	return true;  } -struct DlgChangePassParam -{ -	MDatabaseCommon *db; -	wchar_t newPass[100]; -	unsigned short wrongPass; -}; -  static INT_PTR CALLBACK sttChangePassword(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)  { -	DlgChangePassParam *param = (DlgChangePassParam*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); -	wchar_t buf[100]; +	MDatabaseCommon *db = (MDatabaseCommon *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);  	switch (uMsg) {  	case WM_INITDIALOG:  		TranslateDialogDefault(hwndDlg);  		SendDlgItemMessage(hwndDlg, IDC_HEADERBAR, WM_SETICON, ICON_SMALL, (LPARAM)g_plugin.getIcon(IDI_DATABASE, true)); - -		param = (DlgChangePassParam*)lParam;  		SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);  		oldLangID = 0; @@ -200,15 +190,15 @@ static INT_PTR CALLBACK sttChangePassword(HWND hwndDlg, UINT uMsg, WPARAM wParam  			break;  		case IDREMOVE: -			if (!CheckOldPassword(hwndDlg, param->db)) { +			if (!CheckOldPassword(hwndDlg, db)) {  LBL_Error:  				SendDlgItemMessage(hwndDlg, IDC_HEADERBAR, WM_NCPAINT, 0, 0);  				SetDlgItemTextA(hwndDlg, IDC_USERPASS1, "");  				SetDlgItemTextA(hwndDlg, IDC_USERPASS2, "");  			}  			else { -				param->db->SetPassword(nullptr); -				param->db->StoreCryptoKey(); +				db->SetPassword(nullptr); +				db->StoreCryptoKey();  				EndDialog(hwndDlg, IDREMOVE);  			}  			break; @@ -221,17 +211,19 @@ LBL_Error:  				goto LBL_Error;  			} +			wchar_t buf[100];  			GetDlgItemText(hwndDlg, IDC_USERPASS2, buf, _countof(buf));  			if (wcscmp(buf2, buf)) {  				SetDlgItemText(hwndDlg, IDC_HEADERBAR, TranslateT("Passwords do not match!"));  				goto LBL_Error;  			} -			if (!CheckOldPassword(hwndDlg, param->db)) +			if (!CheckOldPassword(hwndDlg, db))  				goto LBL_Error; -			param->db->SetPassword(buf2); -			param->db->StoreCryptoKey(); +			db->SetPassword(buf2); +			db->StoreCryptoKey(); +			SecureZeroMemory(buf, sizeof(buf));  			SecureZeroMemory(buf2, sizeof(buf2));  			EndDialog(hwndDlg, IDOK);  		} @@ -252,8 +244,7 @@ LBL_Error:  static INT_PTR ChangePassword(void* obj, WPARAM, LPARAM)  {  	MDatabaseCommon *db = (MDatabaseCommon*)obj; -	DlgChangePassParam param = { db }; -	DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(db->usesPassword() ? IDD_CHANGEPASS : IDD_NEWPASS), nullptr, sttChangePassword, (LPARAM)¶m); +	DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(db->usesPassword() ? IDD_CHANGEPASS : IDD_NEWPASS), nullptr, sttChangePassword, (LPARAM)db);  	return 0;  } @@ -379,6 +370,11 @@ public:  		m_timer.OnEvent = Callback(this, &CEnterPasswordDialog::OnTimer);  	} +	~CEnterPasswordDialog() +	{ +		SecureZeroMemory(m_newPass, sizeof(m_newPass)); +	} +  	bool OnInitDialog() override  	{  		m_header.SendMsg(WM_SETICON, ICON_SMALL, (LPARAM)g_plugin.getIcon(IDI_DATABASE, true)); @@ -426,16 +422,16 @@ int MDatabaseCommon::InitCrypt()  	MBinBuffer key;  	BOOL bSuccess = ReadCryptoKey(key);  	if (bSuccess && (key.length() == m_crypto->getKeyLength())) { -		if (!m_crypto->setKey((const BYTE*)key.data(), key.length())) { +		// first try to set a key without password +		if (!m_crypto->setKey(nullptr, (const BYTE*)key.data(), key.length())) {  			CEnterPasswordDialog dlg(this);  			while (true) {  				if (!dlg.DoModal())  					return 4; -				m_crypto->setPassword(pass_ptrA(mir_utf8encodeW(dlg.m_newPass))); -				if (m_crypto->setKey((const BYTE*)key.data(), key.length())) { +				pass_ptrA szPassword(mir_utf8encodeW(dlg.m_newPass)); +				if (m_crypto->setKey(szPassword, (const BYTE*)key.data(), key.length())) {  					m_bUsesPassword = true; -					SecureZeroMemory(&dlg.m_newPass, sizeof(dlg.m_newPass));  					break;  				}  				dlg.m_wrongPass++;  | 
