BlowFish::~BlowFish() { // trashMemory((unsigned char*)tempbf_P, 18*4); // trashMemory((unsigned char*)tempbf_S, 256*4); trashMemory(bf_P, sizeof(bf_P)); trashMemory(bf_S, sizeof(bf_S)); }
size_t PWSfileV1V2::ReadCBC(unsigned char &type, StringX &data) { unsigned char *buffer = NULL; size_t buffer_len = 0; size_t retval; ASSERT(m_fish != NULL && m_IV != NULL); retval = _readcbc(m_fd, buffer, buffer_len, type, m_fish, m_IV, m_terminal); if (buffer_len > 0) { wchar_t *wc = new wchar_t[buffer_len+1]; size_t wcLen = pws_os::mbstowcs(wc, buffer_len + 1, reinterpret_cast<const char *>(buffer), buffer_len, false); ASSERT(wcLen != 0); if (wcLen < buffer_len + 1) wc[wcLen] = TCHAR('\0'); else wc[buffer_len] = TCHAR('\0'); data = wc; trashMemory(wc, wcLen); delete[] wc; trashMemory(buffer, buffer_len); delete[] buffer; } else { data = _T(""); // no need to delete[] buffer, since _readcbc will not allocate if // buffer_len is zero } return retval; }
BYTE* CSMemFile::Realloc(BYTE* lpOldMem, SIZE_T nBytes) { if (nBytes == 0) { trashMemory(lpOldMem, m_size); Free(lpOldMem); m_size = 0; return NULL; } size_t old_size = _msize((void *)lpOldMem); ASSERT(m_size == old_size); BYTE* lpNewMem = (BYTE *)malloc(nBytes); if (lpNewMem == NULL) { trashMemory(lpOldMem, old_size); free(lpOldMem); m_size = 0; return NULL; } memcpy_s((void *)lpNewMem, nBytes, (void *)lpOldMem, old_size); trashMemory(lpOldMem, old_size); free(lpOldMem); m_size = nBytes; return lpNewMem; }
CUTF8Conv::~CUTF8Conv() { if (m_utf8 != NULL) { trashMemory(m_utf8, m_utf8MaxLen * sizeof(m_utf8[0])); delete[] m_utf8; } if (m_wc != NULL) { trashMemory(m_wc, m_wcMaxLen); delete[] m_wc; } if (m_tmp != NULL) { trashMemory(m_tmp, m_tmpMaxLen * sizeof(m_tmp[0])); delete[] m_tmp; } }
void CYubiMixin::yubiRequestHMACSha1(const CSecString &challenge) { if (m_pending) { // no-op if a request's already in the air } else { CSingleLock singeLock(&m_mutex); singeLock.Lock(); // open key // if zero or >1 key, we'll fail if (m_yk.openKey() != YKLIB_OK) { return; } // Prepare the HMAC-SHA1 challenge here BYTE chalBuf[SHA1_MAX_BLOCK_SIZE]; BYTE chalLength = BYTE(challenge.GetLength()*sizeof(TCHAR)); memset(chalBuf, 0, SHA1_MAX_BLOCK_SIZE); if (chalLength > SHA1_MAX_BLOCK_SIZE) chalLength = SHA1_MAX_BLOCK_SIZE; memcpy(chalBuf, challenge, chalLength); // Initiate HMAC-SHA1 operation now if (m_yk.writeChallengeBegin(YKLIB_SECOND_SLOT, YKLIB_CHAL_HMAC, chalBuf, chalLength) == YKLIB_OK) { m_pending = true; yubiShowChallengeSent(); // request's in the air, setup GUI to wait for reply } else { TRACE(_T("m_yk.writeChallengeBegin() failed")); } trashMemory(chalBuf, chalLength); } }
void CItemField::Get(StringX &value, Fish *bf) const { // Sanity check: length is 0 iff data ptr is NULL ASSERT((m_Length == 0 && m_Data == NULL) || (m_Length > 0 && m_Data != NULL)); if (m_Length == 0) { value = _T(""); } else { // we have data to decrypt size_t BlockLength = GetBlockSize(m_Length); unsigned char *tempmem = new unsigned char[BlockLength]; TCHAR *pt = reinterpret_cast<TCHAR *>(tempmem); size_t x; // decrypt block by block for (x = 0; x < BlockLength; x += 8) bf->Decrypt(m_Data + x, tempmem + x); // copy to value TCHAR by TCHAR for (x = 0; x < m_Length/sizeof(TCHAR); x++) value += pt[x]; trashMemory(tempmem, BlockLength); delete [] tempmem; } }
PWSfileHeader &PWSfileHeader::operator=(const PWSfileHeader &h) { if (this != &h) { m_nCurrentMajorVersion = h.m_nCurrentMajorVersion; m_nCurrentMinorVersion = h.m_nCurrentMinorVersion; m_file_uuid = h.m_file_uuid; m_displaystatus = h.m_displaystatus; m_prefString = h.m_prefString; m_whenlastsaved = h.m_whenlastsaved; m_lastsavedby = h.m_lastsavedby; m_lastsavedon = h.m_lastsavedon; m_whatlastsaved = h.m_whatlastsaved; m_whenpwdlastchanged = h.m_whenpwdlastchanged; m_DB_Name = h.m_DB_Name; m_DB_Description = h.m_DB_Description; m_RUEList = h.m_RUEList; if (h.m_yubi_sk != nullptr) { if (m_yubi_sk) trashMemory(m_yubi_sk, YUBI_SK_LEN); delete[] m_yubi_sk; m_yubi_sk = new unsigned char[YUBI_SK_LEN]; memcpy(m_yubi_sk, h.m_yubi_sk, YUBI_SK_LEN); } else { m_yubi_sk = nullptr; } } return *this; }
/** Burn some stack memory @param len amount of stack to burn in bytes */ void burnStack(unsigned long len) { unsigned char buf[32]; trashMemory(buf, sizeof(buf)); if (len > static_cast<unsigned long>(sizeof(buf))) burnStack(len - sizeof(buf)); }
PWSfile::HeaderRecord &PWSfile::HeaderRecord::operator=(const PWSfile::HeaderRecord &h) { if (this != &h) { m_nCurrentMajorVersion = h.m_nCurrentMajorVersion; m_nCurrentMinorVersion = h.m_nCurrentMinorVersion; m_file_uuid = h.m_file_uuid; m_displaystatus = h.m_displaystatus; m_prefString = h.m_prefString; m_whenlastsaved = h.m_whenlastsaved; m_lastsavedby = h.m_lastsavedby; m_lastsavedon = h.m_lastsavedon; m_whatlastsaved = h.m_whatlastsaved; m_dbname = h.m_dbname; m_dbdesc = h.m_dbdesc; m_RUEList = h.m_RUEList; if (h.m_yubi_sk != NULL) { if (m_yubi_sk) trashMemory(m_yubi_sk, YUBI_SK_LEN); delete[] m_yubi_sk; m_yubi_sk = new unsigned char[YUBI_SK_LEN]; memcpy(m_yubi_sk, h.m_yubi_sk, YUBI_SK_LEN); } else { m_yubi_sk = NULL; } } return *this; }
size_t PWSfile::ReadCBC(unsigned char &type, unsigned char* &data, size_t &length) { unsigned char *buffer = NULL; size_t buffer_len = 0; size_t retval; ASSERT(m_fish != NULL && m_IV != NULL); retval = _readcbc(m_fd, buffer, buffer_len, type, m_fish, m_IV, m_terminal, m_fileLength); if (buffer_len > 0) { if (buffer_len < length || data == NULL) length = buffer_len; // set to length read // if buffer_len > length, data is truncated to length // probably an error. if (data != NULL) { memcpy(data, buffer, length); trashMemory(buffer, buffer_len); delete[] buffer; } else { // NULL data means pass buffer directly to caller data = buffer; // caller must trash & delete[]! } } else { // no need to delete[] buffer, since _readcbc will not allocate if // buffer_len is zero } return retval; }
UnknownFieldEntry::~UnknownFieldEntry() { if (st_length > 0 && uc_pUField != NULL) { trashMemory(reinterpret_cast<void *>(uc_pUField), st_length); delete[] uc_pUField; st_length = 0; uc_pUField = NULL; } }
CPasskeyEntry::~CPasskeyEntry() { ::DestroyIcon(m_hIcon); if (m_yubi_sk != NULL) { trashMemory(m_yubi_sk, PWSfile::HeaderRecord::YUBI_SK_LEN); delete[] m_yubi_sk; } }
/* Terminate the hash to get the digest @param digest The destination of the hash (32 bytes) */ void SHA256::Final(unsigned char digest[HASHLEN]) { int i; ASSERT(digest != NULL); ASSERT(curlen < sizeof(buf)); /* increase the length of the message */ length += curlen * 8; /* append the '1' bit */ buf[curlen++] = static_cast<unsigned char>(0x80); /* if the length is currently above 56 bytes we append zeros * then compress. Then we can fall back to padding zeros and length * encoding like normal. */ if (curlen > 56) { while (curlen < 64) { buf[curlen++] = 0; } sha256_compress(state, buf); curlen = 0; } /* pad upto 56 bytes of zeroes */ while (curlen < 56) { buf[curlen++] = 0; } /* store length */ STORE64H(length, buf+56); sha256_compress(state, buf); /* copy output */ for (i = 0; i < 8; i++) { STORE32H(state[i], digest+(4*i)); } #ifdef LTC_CLEAN_STACK trashMemory(state, sizeof(state)); trashMemory(buf, sizeof(buf)); #endif }
void CSMemFile::Free(BYTE* lpMem) { size_t mem_size = _msize((void *)lpMem); ASSERT(m_size == mem_size); m_size = 0; if (lpMem == NULL) return; if (mem_size != 0) trashMemory(lpMem, mem_size); free(lpMem); }
UnknownFieldEntry &UnknownFieldEntry::operator=(const UnknownFieldEntry &that) { if (this != &that) { uc_Type = that.uc_Type; st_length = that.st_length; if (uc_pUField != NULL) { ASSERT(st_length != 0); trashMemory(uc_pUField, st_length); } uc_pUField = new unsigned char[st_length]; memcpy(uc_pUField, that.uc_pUField, st_length); } return *this; }
size_t PWSfileV1V2::WriteCBC(unsigned char type, const StringX &data) { wchar_t *wcPtr = const_cast<wchar_t *>(data.c_str()); size_t wcLen = data.length() + 1; size_t mbLen = 3 * wcLen; unsigned char *acp = new unsigned char[mbLen]; size_t acpLen = pws_os::wcstombs(reinterpret_cast<char *>(acp), mbLen, wcPtr, wcLen, false); ASSERT(acpLen != 0); acpLen--; // remove unneeded null termination size_t retval = PWSfile::WriteCBC(type, acp, acpLen); trashMemory(acp, mbLen); delete[] acp; return retval; }
void CViewReport::Finish() { if (m_bMemoryAllocOK) { HLOCAL h = m_editreport.GetHandle(); LPCWSTR lpszText = (LPCWSTR)::LocalLock(h); if (m_dwDatasize > 0) { trashMemory((void *)lpszText, m_dwDatasize); m_dwDatasize = 0; } ::LocalUnlock(h); } CPWResizeDialog::OnCancel(); }
BlowFish *BlowFish::MakeBlowFish(const unsigned char *pass, int passlen, const unsigned char *salt, int saltlen) { unsigned char passkey[SHA1::HASHLEN]; pws_os::mlock(passkey, sizeof(passkey)); SHA1 context; context.Update(pass, passlen); context.Update(salt, saltlen); context.Final(passkey); BlowFish *retval = new BlowFish(passkey, sizeof(passkey)); trashMemory(passkey, sizeof(passkey)); pws_os::munlock(passkey, sizeof(passkey)); return retval; }
void CYubiMixin::yubiCheckCompleted() { // We now wait for a response with the HMAC-SHA1 digest BYTE respBuf[SHA1_DIGEST_SIZE]; memset(respBuf, 0, sizeof(respBuf)); unsigned short timer; CSingleLock singeLock(&m_mutex); singeLock.Lock(); YKLIB_RC rc = m_yk.waitForCompletion(YKLIB_NO_WAIT, respBuf, sizeof(respBuf), &timer); if (rc != YKLIB_PROCESSING && rc != YKLIB_TIMER_WAIT) { m_pending = false; m_yk.closeKey(); } yubiProcessCompleted(rc, timer, respBuf); trashMemory(respBuf, sizeof(respBuf)); }
bool CUTF8Conv::ToUTF8(const StringX &data, const unsigned char *&utf8, size_t &utf8Len) { // If we're not in Unicode, call MultiByteToWideChar to get from // current codepage to Unicode, and then WideCharToMultiByte to // get to UTF-8 encoding. if (data.empty()) { utf8Len = 0; return true; } wchar_t *wcPtr = const_cast<wchar_t *>(data.c_str()); size_t wcLen = data.length()+1; // first get needed utf8 buffer size size_t mbLen = pws_os::wcstombs(NULL, 0, wcPtr, wcLen); if (mbLen == 0) { // uh-oh ASSERT(0); m_utf8Len = 0; return false; } // Allocate buffer (if previous allocation was smaller) if (mbLen > m_utf8MaxLen) { if (m_utf8 != NULL) trashMemory(m_utf8, m_utf8MaxLen); delete[] m_utf8; m_utf8 = new unsigned char[mbLen]; m_utf8MaxLen = mbLen; } // Finally get result m_utf8Len = pws_os::wcstombs(reinterpret_cast<char *>(m_utf8), mbLen, wcPtr, wcLen); ASSERT(m_utf8Len != 0); m_utf8Len--; // remove unneeded null termination utf8 = m_utf8; utf8Len = m_utf8Len; return true; }
int PWSfileV1V2::Open(const StringX &passkey) { int status = SUCCESS; ASSERT(m_curversion == V17 || m_curversion == V20); m_passkey = passkey; FOpen(); if (m_fd == NULL) return CANT_OPEN_FILE; LPCTSTR passstr = m_passkey.c_str(); size_t passLen = passkey.length(); unsigned char *pstr; #ifdef UNICODE size_t pstr_len = 3 * passLen; pstr = new unsigned char[pstr_len]; size_t len = pws_os::wcstombs(reinterpret_cast<char *>(pstr), 3 * passLen, passstr, passLen, false); ASSERT(len != 0); // hack around OS-dependent semantics - too widespread to fix systematically :-( pstr[len < pstr_len ? len : pstr_len - 1] = '\0'; passLen = strlen(reinterpret_cast<const char *>(pstr)); #else pstr = reinterpret_cast<unsigned char *>(passstr); #endif if (m_rw == Write) { // Following used to verify passkey against file's passkey unsigned char randstuff[StuffSize]; unsigned char randhash[20]; // HashSize PWSrand::GetInstance()->GetRandomData( randstuff, 8 ); randstuff[8] = randstuff[9] = TCHAR('\0'); GenRandhash(m_passkey, randstuff, randhash); SAFE_FWRITE(randstuff, 1, 8, m_fd); SAFE_FWRITE(randhash, 1, 20, m_fd); PWSrand::GetInstance()->GetRandomData(m_salt, SaltLength); SAFE_FWRITE(m_salt, 1, SaltLength, m_fd); PWSrand::GetInstance()->GetRandomData( m_ipthing, 8); SAFE_FWRITE(m_ipthing, 1, 8, m_fd); m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen), m_salt, SaltLength); if (m_curversion == V20) { status = WriteV2Header(); } } else { // open for read status = CheckPasskey(m_filename, m_passkey, m_fd); if (status != SUCCESS) { #ifdef UNICODE trashMemory(pstr, pstr_len); delete[] pstr; #endif Close(); return status; } fread(m_salt, 1, SaltLength, m_fd); fread(m_ipthing, 1, 8, m_fd); m_fish = BlowFish::MakeBlowFish(pstr, reinterpret_cast<int &>(passLen), m_salt, SaltLength); if (m_curversion == V20) status = ReadV2Header(); } // read mode exit: if (status != SUCCESS) Close(); #ifdef UNICODE trashMemory(pstr, pstr_len); delete[] pstr; #endif return status; }
void CDDStatic::OnMouseMove(UINT nFlags, CPoint point) { if (!m_bMouseInClient) { m_bMouseInClient = true; m_pci = app.GetMainDlg()->GetLastSelected(); TRACKMOUSEEVENT tme = {sizeof(TRACKMOUSEEVENT), TME_LEAVE, CStatic::GetSafeHwnd(), 0}; TrackMouseEvent(&tme); } if (m_TimerID == 0) goto StandardProcessing; // Check if we really moved enough int iX = m_StartPoint.x - point.x; int iY = m_StartPoint.y - point.y; if ((iX * iX + iY * iY) > MINIMUM_MOVE_SQUARE) { m_pci = app.GetMainDlg()->GetLastSelected(); if (m_pci == NULL) { m_groupname = app.GetMainDlg()->GetGroupName(); } else { m_groupname = L""; } // Get client rectangle RECT rClient; GetClientRect(&rClient); // Copy data to Clipboard if Control pressed if (nFlags & MK_CONTROL) SendToClipboard(); // Start dragging m_bDropped = false; //pws_os::Trace(L"CDDStatic::OnMouseMove: call m_pDataSource->StartDragging\n"); DROPEFFECT de = m_pDataSource->StartDragging(&rClient); if (de == DROPEFFECT_NONE) { // Do cleanup - otherwise this is the responsibility of the recipient! if (m_hgDataTXT != NULL) { LPVOID lpData = GlobalLock(m_hgDataTXT); SIZE_T memsize = GlobalSize(m_hgDataTXT); if (lpData != NULL) { trashMemory(lpData, memsize); GlobalUnlock(m_hgDataTXT); } GlobalFree(m_hgDataTXT); m_hgDataTXT = NULL; } if (m_hgDataUTXT != NULL) { LPVOID lpData = GlobalLock(m_hgDataUTXT); SIZE_T memsize = GlobalSize(m_hgDataUTXT); if (lpData != NULL) { trashMemory(lpData, memsize); GlobalUnlock(m_hgDataUTXT); } GlobalFree(m_hgDataUTXT); m_hgDataUTXT = NULL; } pws_os::Trace(L"m_pDataSource->StartDragging() failed\n"); } else { pws_os::Trace(L"CDDStatic::OnMouseMove() show cursor\n"); while (ShowCursor(TRUE) < 0) ; } LPARAM lparam = (LPARAM(point.y) << 16) | LPARAM(point.x); ::SendMessage(GetActiveWindow()->GetSafeHwnd(), WM_LBUTTONUP, 0, lparam); } StandardProcessing: CStatic::OnMouseMove(nFlags, point); }
// In following, char * is managed by caller. bool CUTF8Conv::FromUTF8(const unsigned char *utf8, size_t utf8Len, StringX &data) { // Call MultiByteToWideChar to get from UTF-8 to Unicode. // If we're not in Unicode, call WideCharToMultiByte to // get to current codepage. // // Due to a bug in pre-3.08 versions, data may be in ACP // instead of UTF-8. We try to detect and workaround this. if (utf8Len == 0 || (utf8Len == 1 && utf8[0] == '\0')) { data = _T(""); return true; } ASSERT(utf8 != NULL); // first get needed wide char buffer size size_t wcLen = pws_os::mbstowcs(NULL, 0, reinterpret_cast<const char *>(utf8), size_t(-1), !m_cp_acp); if (wcLen == 0) { // uh-oh // it seems that this always returns non-zero, even if encoding // broken. Therefore, we'll give a conservative value here, // and try to recover later pws_os::Trace0(_T("FromUTF8: Couldn't get buffer size - guessing!")); wcLen = sizeof(StringX::value_type) * (utf8Len + 1); } // Allocate buffer (if previous allocation was smaller) if (wcLen > m_wcMaxLen) { if (m_wc != NULL) trashMemory(m_wc, m_wcMaxLen); delete[] m_wc; m_wc = new wchar_t[wcLen]; m_wcMaxLen = wcLen; } // next translate to buffer wcLen = pws_os::mbstowcs(m_wc, wcLen, reinterpret_cast<const char *>(utf8), size_t(-1), !m_cp_acp); #ifdef _WIN32 if (wcLen == 0) { DWORD errCode = GetLastError(); switch (errCode) { case ERROR_INSUFFICIENT_BUFFER: pws_os::Trace0(_T("INSUFFICIENT BUFFER")); break; case ERROR_INVALID_FLAGS: pws_os::Trace0(_T("INVALID FLAGS")); break; case ERROR_INVALID_PARAMETER: pws_os::Trace0(_T("INVALID PARAMETER")); break; case ERROR_NO_UNICODE_TRANSLATION: // try to recover pws_os::Trace0(_T("NO UNICODE TRANSLATION")); wcLen = MultiByteToWideChar(CP_ACP, // code page 0, // character-type options LPSTR(utf8), // string to map -1, // -1 means null-terminated m_wc, // output buffer reinterpret_cast<int &>(wcLen)); // output buffer size if (wcLen > 0) { pws_os::Trace0(_T("FromUTF8: recovery succeeded!")); } break; default: ASSERT(0); } } ASSERT(wcLen != 0); #endif /* _WIN32 */ #ifdef UNICODE if (wcLen != 0) { m_wc[wcLen - 1] = TCHAR('\0'); data = m_wc; return true; } else return false; #else /* Go from Unicode to Locale encoding */ // first get needed utf8 buffer size size_t mbLen = pws_os::wcstombs(NULL, 0, m_wc, size_t(-1), false); if (mbLen == 0) { // uh-oh ASSERT(0); data = _T(""); return false; } // Allocate buffer (if previous allocation was smaller) if (mbLen > m_tmpMaxLen) { if (m_tmp != NULL) trashMemory(m_tmp, m_tmpMaxLen); delete[] m_tmp; m_tmp = new unsigned char[mbLen]; m_tmpMaxLen = mbLen; } // Finally get result size_t tmpLen = pws_os::wcstombs((char *)m_tmp, mbLen, m_wc, size_t(-1), false); ASSERT(tmpLen == mbLen); m_tmp[mbLen - 1] = '\0'; // char, no need to _T()... data = (char *)m_tmp; ASSERT(!data.empty()); return true; #endif /* !UNICODE */ }
PWSfileHeader::~PWSfileHeader() { if (m_yubi_sk) trashMemory(m_yubi_sk, YUBI_SK_LEN); delete[] m_yubi_sk; }
BOOL CDDStatic::OnRenderGlobalData(LPFORMATETC lpFormatEtc, HGLOBAL* phGlobal) { pws_os::Trace(L"CDDStatic::OnRenderGlobalData: %s; ci == %p\n", lpFormatEtc->cfFormat == CF_UNICODETEXT ? L"CF_UNICODETEXT" : L"CF_TEXT", m_pci); if (lpFormatEtc->cfFormat != CF_UNICODETEXT && lpFormatEtc->cfFormat != CF_TEXT) return FALSE; if (m_hgDataTXT != NULL) { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - Unlock/Free m_hgDataTXT\n"); GlobalUnlock(m_hgDataTXT); GlobalFree(m_hgDataTXT); m_hgDataTXT = NULL; } if (m_hgDataUTXT != NULL) { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - Unlock/Free m_hgDataUTXT\n"); GlobalUnlock(m_hgDataUTXT); GlobalFree(m_hgDataUTXT); m_hgDataUTXT = NULL; } StringX cs_dragdata; if (m_pci == NULL) { if (m_groupname.empty()) { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - mpci == NULL\n"); return FALSE; } else { cs_dragdata = m_groupname; } } else { // m_pci != NULL const CItemData *pci(m_pci); // Handle shortcut or alias if ((m_nID == IDC_STATIC_DRAGPASSWORD && pci->IsAlias()) || (pci->IsShortcut() && (m_nID != IDC_STATIC_DRAGGROUP && m_nID != IDC_STATIC_DRAGTITLE && m_nID != IDC_STATIC_DRAGUSER))) { pci = app.GetMainDlg()->GetBaseEntry(pci); } cs_dragdata = GetData(pci); if (cs_dragdata.empty() && m_nID != IDC_STATIC_DRAGAUTO) return FALSE; } const size_t ilen = cs_dragdata.length(); if (ilen == 0 && m_nID != IDC_STATIC_DRAGAUTO) { // Nothing to do - why were we even called??? return FALSE; } DWORD dwBufLen; LPSTR lpszA(NULL); LPWSTR lpszW(NULL); if (lpFormatEtc->cfFormat == CF_UNICODETEXT) { // So is requested data! dwBufLen = (DWORD)((ilen + 1) * sizeof(wchar_t)); lpszW = new WCHAR[ilen + 1]; //pws_os::Trace(L"lpszW allocated %p, size %d\n", lpszW, dwBufLen); if (ilen == 0) { lpszW[ilen] = L'\0'; } else { (void) wcsncpy_s(lpszW, ilen + 1, cs_dragdata.c_str(), ilen); } } else { // They want it in ASCII - use lpszW temporarily if (ilen == 0) { dwBufLen = 1; lpszA = new char[dwBufLen]; lpszA = '\0'; } else { lpszW = const_cast<LPWSTR>(cs_dragdata.c_str()); dwBufLen = WideCharToMultiByte(CP_ACP, 0, lpszW, -1, NULL, 0, NULL, NULL); ASSERT(dwBufLen != 0); lpszA = new char[dwBufLen]; pws_os::Trace(L"lpszA allocated %p, size %d\n", lpszA, dwBufLen); WideCharToMultiByte(CP_ACP, 0, lpszW, -1, lpszA, dwBufLen, NULL, NULL); lpszW = NULL; } } LPVOID lpData(NULL); LPVOID lpDataBuffer; HGLOBAL *phgData; if (lpFormatEtc->cfFormat == CF_UNICODETEXT) { lpDataBuffer = (LPVOID)lpszW; phgData = &m_hgDataUTXT; } else { lpDataBuffer = (LPVOID)lpszA; phgData = &m_hgDataTXT; } BOOL retval(FALSE); if (*phGlobal == NULL) { //pws_os::Trace(L"CDDStatic::OnRenderGlobalData - Alloc global memory\n"); *phgData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBufLen); ASSERT(*phgData != NULL); if (*phgData == NULL) goto bad_return; lpData = GlobalLock(*phgData); ASSERT(lpData != NULL); if (lpData == NULL) goto bad_return; // Copy data memcpy(lpData, lpDataBuffer, dwBufLen); *phGlobal = *phgData; retval = TRUE; } else { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - *phGlobal NOT NULL!\n"); SIZE_T inSize = GlobalSize(*phGlobal); SIZE_T ourSize = GlobalSize(*phgData); if (inSize < ourSize) { // Pre-allocated space too small. Not allowed to increase it - FAIL pws_os::Trace(L"CDDStatic::OnRenderGlobalData - NOT enough room - FAIL\n"); } else { // Enough room - copy our data into supplied area pws_os::Trace(L"CDDStatic::OnRenderGlobalData - enough room - copy our data\n"); LPVOID pInGlobalLock = GlobalLock(*phGlobal); ASSERT(pInGlobalLock != NULL); if (pInGlobalLock == NULL) goto bad_return; memcpy(pInGlobalLock, lpDataBuffer, ourSize); GlobalUnlock(*phGlobal); retval = TRUE; } } bad_return: // Finished with buffer - trash it trashMemory(lpDataBuffer, dwBufLen); // Free the strings (only one is actually in use) //pws_os::Trace(L"lpszA freed %p\n", lpszA); delete[] lpszA; //pws_os::Trace(L"lpszW freed %p\n", lpszW); delete[] lpszW; // Since lpDataBuffer pointed to one of the above - just zero the pointer lpDataBuffer = NULL; // If retval == TRUE, recipient is responsible for freeing the global memory // if D&D succeeds (see after StartDragging in OnMouseMove) if (retval == FALSE) { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - returning FALSE!\n"); if (lpData != NULL) { GlobalFree(*phgData); *phgData = NULL; } } else { pws_os::Trace(L"CDDStatic::OnRenderGlobalData - D&D Data:"); if (lpFormatEtc->cfFormat == CF_UNICODETEXT) { pws_os::Trace(L"\"%ls\"\n", (LPWSTR)lpData); // data is Unicode } else { pws_os::Trace(L"\"%hs\"\n", (LPSTR)lpData); // data is NOT Unicode } } // Unlock our buffer if (lpData != NULL) GlobalUnlock(*phgData); return retval; }
bool PWSfile::Encrypt(const stringT &fn, const StringX &passwd, stringT &errmess) { ulong64 len = 0; size_t slen = 0; unsigned char* buf = nullptr; Fish *fish = nullptr; bool status = true; const stringT out_fn = fn + CIPHERTEXT_SUFFIX; unsigned char *pwd = nullptr; size_t passlen = 0; FILE *out = nullptr; FILE *in = pws_os::FOpen(fn, _T("rb")); if (in == nullptr) { status = false; goto exit; } len = pws_os::fileLength(in); if (len > std::numeric_limits<uint32>::max()) { fclose(in); errno = EFBIG; status = false; goto exit; } slen = static_cast<size_t>(len); buf = new unsigned char[slen]; fread(buf, 1, slen, in); if (ferror(in)) { // this is how to detect fread errors status = false; int save_error = errno; fclose(in); errno = save_error; goto exit; } if (fclose(in) != 0) { status = false; goto exit; } out = pws_os::FOpen(out_fn, _T("wb")); if (out == nullptr) { status = false; goto exit; } unsigned char randstuff[StuffSize]; unsigned char randhash[SHA1::HASHLEN]; // HashSize PWSrand::GetInstance()->GetRandomData( randstuff, 8 ); // miserable bug - have to fix this way to avoid breaking existing files randstuff[8] = randstuff[9] = TCHAR('\0'); GenRandhash(passwd, randstuff, randhash); SAFE_FWRITE(randstuff, 1, 8, out); SAFE_FWRITE(randhash, 1, sizeof(randhash), out); unsigned char thesalt[SaltLength]; PWSrand::GetInstance()->GetRandomData( thesalt, SaltLength ); SAFE_FWRITE(thesalt, 1, SaltLength, out); unsigned char ipthing[8]; PWSrand::GetInstance()->GetRandomData( ipthing, 8 ); SAFE_FWRITE(ipthing, 1, 8, out); ConvertPasskey(passwd, pwd, passlen); fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<unsigned int &>(passlen), thesalt, SaltLength); trashMemory(pwd, passlen); delete[] pwd; // gross - ConvertPasskey allocates. try { _writecbc(out, buf, slen, 0, fish, ipthing); } catch (...) { // _writecbc throws an exception if it fails to write fclose(out); errno = EIO; status = false; goto exit; } status = (fclose(out) == 0); exit: if (!status) errmess = ErrorMessages(); delete fish; delete[] buf; return status; }
bool PWSfile::Decrypt(const stringT &fn, const StringX &passwd, stringT &errmess) { size_t len; unsigned char* buf = NULL; bool status = true; unsigned char salt[SaltLength]; unsigned char ipthing[8]; unsigned char randstuff[StuffSize]; unsigned char randhash[SHA1::HASHLEN]; unsigned char temphash[SHA1::HASHLEN]; FILE *in = pws_os::FOpen(fn, _T("rb")); if (in == NULL) { status = false; goto exit; } #ifdef KEEP_FILE_MODE_BWD_COMPAT uint32 i32; fread(&i32, 1, sizeof(uint32), in); // XXX portability issue len = i32; #else fread(randstuff, 1, 8, in); randstuff[8] = randstuff[9] = TCHAR('\0'); // ugly bug workaround fread(randhash, 1, sizeof(randhash), in); GenRandhash(passwd, randstuff, temphash); if (memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), SHA1::HASHLEN) != 0) { fclose(in); LoadAString(errmess, IDSC_BADPASSWORD); return false; } #endif // KEEP_FILE_MODE_BWD_COMPAT { // decryption in a block, since we use goto fread(salt, 1, SaltLength, in); fread(ipthing, 1, 8, in); unsigned char dummyType; unsigned char *pwd = NULL; size_t passlen = 0; long file_len = pws_os::fileLength(in); ConvertString(passwd, pwd, passlen); Fish *fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<int &>(passlen), salt, SaltLength); trashMemory(pwd, passlen); #ifdef UNICODE delete[] pwd; // gross - ConvertString allocates only if UNICODE. #endif if (_readcbc(in, buf, len,dummyType, fish, ipthing, 0, file_len) == 0) { delete fish; delete[] buf; // if not yet allocated, delete[] NULL, which is OK return false; } delete fish; fclose(in); } // decrypt { // write decrypted data size_t suffix_len = CIPHERTEXT_SUFFIX.length(); size_t filepath_len = fn.length(); stringT out_fn = fn; out_fn = out_fn.substr(0,filepath_len - suffix_len); FILE *out = pws_os::FOpen(out_fn, _T("wb")); if (out != NULL) { size_t fret = fwrite(buf, 1, len, out); if (fret != len) { int save_errno = errno; fclose(out); errno = save_errno; goto exit; } if (fclose(out) != 0) { status = false; goto exit; } } else { // open failed status = false; goto exit; } } // write decrypted exit: if (!status) errmess = ErrorMessages(); delete[] buf; // allocated by _readcbc return status; }
bool PWSfile::Encrypt(const stringT &fn, const StringX &passwd, stringT &errmess) { unsigned int len = 0; unsigned char* buf = NULL; Fish *fish = NULL; bool status = true; stringT out_fn; unsigned char *pwd = NULL; size_t passlen = 0; FILE *out = NULL; FILE *in = pws_os::FOpen(fn, _T("rb"));; if (in != NULL) { len = pws_os::fileLength(in); buf = new unsigned char[len]; fread(buf, 1, len, in); if (ferror(in)) { // this is how to detect fread errors status = false; int save_error = errno; fclose(in); errno = save_error; goto exit; } if (fclose(in) != 0) { status = false; goto exit; } } else { status = false; goto exit; } out_fn = fn; out_fn += CIPHERTEXT_SUFFIX; out = pws_os::FOpen(out_fn, _T("wb")); if (out == NULL) { status = false; goto exit; } #ifdef KEEP_FILE_MODE_BWD_COMPAT uint32 i32 = len; SAFE_FWRITE(&i32, 1, sizeof(uint32), out); #else unsigned char randstuff[StuffSize]; unsigned char randhash[SHA1::HASHLEN]; // HashSize PWSrand::GetInstance()->GetRandomData( randstuff, 8 ); // miserable bug - have to fix this way to avoid breaking existing files randstuff[8] = randstuff[9] = TCHAR('\0'); GenRandhash(passwd, randstuff, randhash); SAFE_FWRITE(randstuff, 1, 8, out); SAFE_FWRITE(randhash, 1, sizeof(randhash), out); #endif // KEEP_FILE_MODE_BWD_COMPAT unsigned char thesalt[SaltLength]; PWSrand::GetInstance()->GetRandomData( thesalt, SaltLength ); SAFE_FWRITE(thesalt, 1, SaltLength, out); unsigned char ipthing[8]; PWSrand::GetInstance()->GetRandomData( ipthing, 8 ); SAFE_FWRITE(ipthing, 1, 8, out); ConvertString(passwd, pwd, passlen); fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<int &>(passlen), thesalt, SaltLength); trashMemory(pwd, passlen); #ifdef UNICODE delete[] pwd; // gross - ConvertString allocates only if UNICODE. #endif try { _writecbc(out, buf, len, 0, fish, ipthing); } catch (...) { // _writecbc throws an exception if it fails to write fclose(out); errno = EIO; status = false; goto exit; } status = (fclose(out) == 0); exit: if (!status) errmess = ErrorMessages(); delete fish; delete[] buf; return status; }
bool PWSfile::Decrypt(const stringT &fn, const StringX &passwd, stringT &errmess) { ulong64 file_len; size_t len; unsigned char* buf = nullptr; bool status = true; unsigned char salt[SaltLength]; unsigned char ipthing[8]; unsigned char randstuff[StuffSize]; unsigned char randhash[SHA1::HASHLEN]; unsigned char temphash[SHA1::HASHLEN]; FILE *in = pws_os::FOpen(fn, _T("rb")); if (in == nullptr) { status = false; goto exit; } file_len = pws_os::fileLength(in); if (file_len < (8 + sizeof(randhash) + 8 + SaltLength)) { fclose(in); LoadAString(errmess, IDSC_FILE_TOO_SHORT); return false; } fread(randstuff, 1, 8, in); randstuff[8] = randstuff[9] = TCHAR('\0'); // ugly bug workaround fread(randhash, 1, sizeof(randhash), in); GenRandhash(passwd, randstuff, temphash); if (memcmp(reinterpret_cast<char *>(randhash), reinterpret_cast<char *>(temphash), SHA1::HASHLEN) != 0) { fclose(in); LoadAString(errmess, IDSC_BADPASSWORD); return false; } { // decryption in a block, since we use goto fread(salt, 1, SaltLength, in); fread(ipthing, 1, 8, in); unsigned char dummyType; unsigned char *pwd = nullptr; size_t passlen = 0; ConvertPasskey(passwd, pwd, passlen); Fish *fish = BlowFish::MakeBlowFish(pwd, reinterpret_cast<unsigned int &>(passlen), salt, SaltLength); trashMemory(pwd, passlen); delete[] pwd; // gross - ConvertPasskey allocates. if (_readcbc(in, buf, len,dummyType, fish, ipthing, 0, file_len) == 0) { delete fish; delete[] buf; // if not yet allocated, delete[] nullptr, which is OK return false; } delete fish; fclose(in); } // decrypt { // write decrypted data size_t suffix_len = CIPHERTEXT_SUFFIX.length(); size_t filepath_len = fn.length(); stringT out_fn = fn; out_fn = out_fn.substr(0,filepath_len - suffix_len); FILE *out = pws_os::FOpen(out_fn, _T("wb")); if (out != nullptr) { size_t fret = fwrite(buf, 1, len, out); if (fret != len) { int save_errno = errno; fclose(out); errno = save_errno; goto exit; } if (fclose(out) != 0) { status = false; goto exit; } } else { // open failed status = false; goto exit; } } // write decrypted exit: if (!status) errmess = ErrorMessages(); delete[] buf; // allocated by _readcbc return status; }
PWSfile::HeaderRecord::~HeaderRecord() { if (m_yubi_sk) trashMemory(m_yubi_sk, YUBI_SK_LEN); delete[] m_yubi_sk; }