diff --git a/src/core.cpp b/src/core.cpp index 710497af6..f2fd27c24 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -53,6 +53,9 @@ Core::Core(Camera* cam, QThread *coreThread, QString loadPath) : videobuf = new uint8_t[videobufsize]; videoBusyness=0; + for (int i = 0; i < ptCounter; i++) + pwsaltedkey[i] = nullptr; + toxTimer = new QTimer(this); toxTimer->setSingleShot(true); connect(toxTimer, &QTimer::timeout, this, &Core::process); @@ -116,7 +119,8 @@ Core::~Core() if (alInDev) alcCaptureCloseDevice(alInDev); - clearPassword(); + clearPassword(Core::ptMain); + clearPassword(Core::ptHistory); } Core* Core::getInstance() @@ -1096,10 +1100,10 @@ bool Core::loadConfiguration(QString path) if (Settings::getInstance().getEncryptTox()) { - while (!isPasswordSet()) + while (!isPasswordSet(ptMain)) { - emit blockingGetPassword(tr("Tox datafile decryption password")); - if (!isPasswordSet()) + emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain); + if (!isPasswordSet(ptMain)) QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); } } @@ -1116,15 +1120,15 @@ bool Core::loadConfiguration(QString path) { do { - while (!isPasswordSet()) + while (!isPasswordSet(ptMain)) { - emit blockingGetPassword(tr("Tox datafile decryption password")); - if (!isPasswordSet()) + emit blockingGetPassword(tr("Tox datafile decryption password"), ptMain); + if (!isPasswordSet(ptMain)) QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); } error = tox_encrypted_load(tox, reinterpret_cast(data.data()), data.size(), - reinterpret_cast(barePassword.data()), barePassword.size()); + reinterpret_cast(barePassword[ptMain].data()), barePassword[ptMain].size()); if (error != 0) { QMessageBox msgb; @@ -1140,14 +1144,14 @@ bool Core::loadConfiguration(QString path) if (msgb.clickedButton() == tryAgain) { - clearPassword(); + clearPassword(ptMain); } else if (msgb.clickedButton() == cancel) { configurationFile.close(); return false; } else if (msgb.clickedButton() == wipe) { - clearPassword(); + clearPassword(ptMain); Settings::getInstance().setEncryptTox(false); error = 0; } @@ -1161,46 +1165,35 @@ bool Core::loadConfiguration(QString path) // tox core is already decrypted if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs()) { - if (isPasswordSet()) + bool error = true; + do { + while (!isPasswordSet(ptHistory)) + { + emit blockingGetPassword(tr("History Log decpytion password"), Core::ptHistory); + if (!isPasswordSet(ptHistory)) + QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); + } + if (!HistoryKeeper::checkPassword()) { - QMessageBox::warning(nullptr, tr("Different passwords!"), - tr("Tox datafile and history log encrypted with different passwords.")); - Settings::getInstance().setEncryptLogs(false); - Settings::getInstance().setEnableLogging(false); - } - } else { - bool error = true; - do - { - while (!isPasswordSet()) + if (QMessageBox::Ok == QMessageBox::warning(nullptr, tr("Encrypted log"), + tr("Your history encrypted with different password\nDo you want to try another password?"), + QMessageBox::Ok | QMessageBox::Cancel)) { - emit blockingGetPassword(tr("History Log decpytion password")); - if (!isPasswordSet()) - QMessageBox::warning(nullptr, tr("Password error"), tr("Failed to setup password.\nEmpty password.")); - } - - if (!HistoryKeeper::checkPassword()) - { - if (QMessageBox::Ok == QMessageBox::warning(nullptr, tr("Encrypted log"), - tr("Your history encrypted with different password\nDo you want to try another password?"), - QMessageBox::Ok | QMessageBox::Cancel)) - { - error = true; - clearPassword(); - } else { - error = false; - clearPassword(); - QMessageBox::warning(nullptr, tr("Loggin"), tr("Due to incorret password logging will be disabled")); - Settings::getInstance().setEncryptLogs(false); - Settings::getInstance().setEnableLogging(false); - } + error = true; + clearPassword(ptHistory); } else { error = false; + clearPassword(ptHistory); + QMessageBox::warning(nullptr, tr("Loggin"), tr("Due to incorret password logging will be disabled")); + Settings::getInstance().setEncryptLogs(false); + Settings::getInstance().setEnableLogging(false); } - } while (error); - } + } else { + error = false; + } + } while (error); } configurationFile.close(); @@ -1273,13 +1266,14 @@ void Core::saveConfiguration(const QString& path) if (Settings::getInstance().getEncryptTox()) { - if (!isPasswordSet()) + if (!isPasswordSet(ptMain)) { // probably zero chance event QMessageBox::warning(nullptr, tr("NO Password"), tr("Will be saved without encryption!")); tox_save(tox, data); } else { - int ret = tox_encrypted_save(tox, data, reinterpret_cast(barePassword.data()), barePassword.size()); + int ret = tox_encrypted_save(tox, data, reinterpret_cast(barePassword[ptMain].data()), + barePassword[ptMain].size()); if (ret == -1) { qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; @@ -1307,7 +1301,8 @@ void Core::switchConfiguration(const QString& profile) qDebug() << "Core: switching from" << Settings::getInstance().getCurrentProfile() << "to" << profile; saveConfiguration(); - clearPassword(); + clearPassword(ptMain); + clearPassword(ptHistory); toxTimer->stop(); if (tox) { @@ -1322,7 +1317,6 @@ void Core::switchConfiguration(const QString& profile) loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT); Settings::getInstance().setCurrentProfile(profile); HistoryKeeper::getInstance()->resetInstance(); - clearPassword(); start(); } @@ -1604,43 +1598,43 @@ QList Core::splitMessage(const QString &message) return splittedMsgs; } -void Core::setPassword(QString& password) +void Core::setPassword(QString& password, PasswordType passtype) { if (password.isEmpty()) { - clearPassword(); + clearPassword(passtype); return; } - if (!pwsaltedkey) - pwsaltedkey = new uint8_t[tox_pass_key_length()]; + if (!pwsaltedkey[passtype]) + pwsaltedkey[passtype] = new uint8_t[tox_pass_key_length()]; CString str(password); - tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey); + tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey[passtype]); - barePassword.clear(); - barePassword.append(password); + barePassword[passtype].clear(); + barePassword[passtype].append(password); password.clear(); } -void Core::clearPassword() +void Core::clearPassword(PasswordType passtype) { - if (pwsaltedkey) + if (pwsaltedkey[passtype]) { - delete[] pwsaltedkey; - pwsaltedkey = nullptr; - barePassword.clear(); + delete[] pwsaltedkey[passtype]; + pwsaltedkey[passtype] = nullptr; + barePassword[passtype].clear(); } } -QByteArray Core::encryptData(const QByteArray& data) +QByteArray Core::encryptData(const QByteArray& data, PasswordType passtype) { - if (!pwsaltedkey) + if (!pwsaltedkey[passtype]) return QByteArray(); uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()]; - // if (tox_pass_key_encrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkey, encrypted) == -1) + // if (tox_pass_key_encrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkey[passtype], encrypted) == -1) if (tox_pass_encrypt(reinterpret_cast(data.data()), data.size(), - reinterpret_cast(barePassword.data()), barePassword.size(), encrypted) == -1) + reinterpret_cast(barePassword[passtype].data()), barePassword[passtype].size(), encrypted) == -1) { qWarning() << "Core::encryptData: encryption failed"; return QByteArray(); @@ -1648,15 +1642,15 @@ QByteArray Core::encryptData(const QByteArray& data) return QByteArray(reinterpret_cast(encrypted), data.size() + tox_pass_encryption_extra_length()); } -QByteArray Core::decryptData(const QByteArray& data) +QByteArray Core::decryptData(const QByteArray& data, PasswordType passtype) { - if (!pwsaltedkey) + if (!pwsaltedkey[passtype]) return QByteArray(); int sz = data.size() - tox_pass_encryption_extra_length(); uint8_t decrypted[sz]; - // if (tox_pass_key_decrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkey, decrypted) != sz) + // if (tox_pass_key_decrypt(reinterpret_cast(data.data()), data.size(), pwsaltedkey[passtype], decrypted) != sz) if (tox_pass_decrypt(reinterpret_cast(data.data()), data.size(), - reinterpret_cast(barePassword.data()), barePassword.size(), decrypted) != sz) + reinterpret_cast(barePassword[passtype].data()), barePassword[passtype].size(), decrypted) != sz) { qWarning() << "Core::decryptData: decryption failed"; return QByteArray(); @@ -1664,9 +1658,9 @@ QByteArray Core::decryptData(const QByteArray& data) return QByteArray(reinterpret_cast(decrypted), sz); } -bool Core::isPasswordSet() +bool Core::isPasswordSet(PasswordType passtype) { - if (pwsaltedkey) + if (pwsaltedkey[passtype]) return true; return false; diff --git a/src/core.h b/src/core.h index a7600b1e9..0df2b405c 100644 --- a/src/core.h +++ b/src/core.h @@ -34,6 +34,8 @@ class Core : public QObject { Q_OBJECT public: + enum PasswordType {ptMain = 0, ptHistory, ptCounter}; + explicit Core(Camera* cam, QThread* coreThread, QString initialLoadPath); static Core* getInstance(); ///< Returns the global widget's Core instance ~Core(); @@ -64,7 +66,7 @@ public: void decreaseVideoBusyness(); bool anyActiveCalls(); - bool isPasswordSet(); + bool isPasswordSet(PasswordType passtype); public slots: void start(); @@ -105,16 +107,16 @@ public slots: void micMuteToggle(int callId); - void setPassword(QString& password); - void clearPassword(); - QByteArray encryptData(const QByteArray& data); - QByteArray decryptData(const QByteArray& data); + void setPassword(QString& password, PasswordType passtype); + void clearPassword(PasswordType passtype); + QByteArray encryptData(const QByteArray& data, PasswordType passtype); + QByteArray decryptData(const QByteArray& data, PasswordType passtype); signals: void connected(); void disconnected(); void blockingClearContacts(); - void blockingGetPassword(QString info); + void blockingGetPassword(QString info, int passtype); void friendRequestReceived(const QString& userId, const QString& message); void friendMessageReceived(int friendId, const QString& message, bool isAction); @@ -251,8 +253,9 @@ private: int dhtServerId; static QList fileSendQueue, fileRecvQueue; static ToxCall calls[]; - uint8_t* pwsaltedkey = nullptr; // use the pw's hash as the "pw" - QByteArray barePassword; // to be deleted after tox_pass_key_decrypt/tox_pass_key_encrypt fix + + uint8_t* pwsaltedkey[PasswordType::ptCounter]; // use the pw's hash as the "pw" + QByteArray barePassword[PasswordType::ptCounter]; // to be deleted after tox_pass_key_decrypt/tox_pass_key_encrypt fix static const int videobufsize; static uint8_t* videobuf; diff --git a/src/historykeeper.h b/src/historykeeper.h index 8100cc503..ac05eebf2 100644 --- a/src/historykeeper.h +++ b/src/historykeeper.h @@ -39,8 +39,9 @@ public: static HistoryKeeper* getInstance(); static void resetInstance(); - static bool checkPassword(); + static QString getHistoryPath(); + static bool checkPassword(); static void renameHistory(QString from, QString to); void addChatEntry(const QString& chat, const QString& message, const QString& sender, const QDateTime &dt); diff --git a/src/misc/db/encrypteddb.cpp b/src/misc/db/encrypteddb.cpp index a407510a9..408a94471 100644 --- a/src/misc/db/encrypteddb.cpp +++ b/src/misc/db/encrypteddb.cpp @@ -24,7 +24,7 @@ #include #include -qint64 EncryptedDb::plainChunkSize = 1024; +qint64 EncryptedDb::plainChunkSize = 4096; qint64 EncryptedDb::encryptedChunkSize = EncryptedDb::plainChunkSize + tox_pass_encryption_extra_length(); EncryptedDb::EncryptedDb(const QString &fname, QList initList) : @@ -50,7 +50,8 @@ EncryptedDb::EncryptedDb(const QString &fname, QList initList) : EncryptedDb::~EncryptedDb() { - encrFile.close(); // what if program is killed without being able to clean up? + encrFile.close(); // Q: what if program is killed without being able to clean up? + // A: cleanup isn't necessary, everything handled int appendToEncrypted(..) function } QSqlQuery EncryptedDb::exec(const QString &query) @@ -70,7 +71,7 @@ bool EncryptedDb::pullFileContent() while (!encrFile.atEnd()) { QByteArray encrChunk = encrFile.read(encryptedChunkSize); - buffer = Core::getInstance()->decryptData(encrChunk); + buffer = Core::getInstance()->decryptData(encrChunk, Core::ptHistory); if (buffer.size() > 0) { fileContent += buffer; @@ -129,7 +130,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql) { QByteArray filledChunk = buffer.left(plainChunkSize); encrFile.seek(chunkPosition * encryptedChunkSize); - QByteArray encr = Core::getInstance()->encryptData(filledChunk); + QByteArray encr = Core::getInstance()->encryptData(filledChunk, Core::ptHistory); if (encr.size() > 0) { encrFile.write(encr); @@ -140,7 +141,7 @@ void EncryptedDb::appendToEncrypted(const QString &sql) } encrFile.seek(chunkPosition * encryptedChunkSize); - QByteArray encr = Core::getInstance()->encryptData(buffer); + QByteArray encr = Core::getInstance()->encryptData(buffer, Core::ptHistory); if (encr.size() > 0) { encrFile.write(encr); @@ -157,7 +158,7 @@ bool EncryptedDb::check(const QString &fname) if (file.size() > 0) { QByteArray encrChunk = file.read(encryptedChunkSize); - QByteArray buf = Core::getInstance()->decryptData(encrChunk); + QByteArray buf = Core::getInstance()->decryptData(encrChunk, Core::ptHistory); if (buf.size() == 0) { state = false; diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 815c9c55f..628352a19 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -65,7 +65,7 @@ void PrivacyForm::onEncryptLogsUpdated() if (encrytionState) { - if (!Core::getInstance()->isPasswordSet()) + if (!Core::getInstance()->isPasswordSet(Core::ptHistory)) { SetPasswordDialog dialog; if (dialog.exec()) @@ -74,10 +74,10 @@ void PrivacyForm::onEncryptLogsUpdated() if (pswd.size() == 0) encrytionState = false; - Core::getInstance()->setPassword(pswd); + Core::getInstance()->setPassword(pswd, Core::ptHistory); } else { encrytionState = false; - Core::getInstance()->clearPassword(); + Core::getInstance()->clearPassword(Core::ptHistory); } } } @@ -100,8 +100,8 @@ void PrivacyForm::onEncryptLogsUpdated() if (encrytionState) HistoryKeeper::resetInstance(); - if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox()) - Core::getInstance()->clearPassword(); + if (!Settings::getInstance().getEncryptLogs()) + Core::getInstance()->clearPassword(Core::ptHistory); } void PrivacyForm::onEncryptToxUpdated() @@ -110,7 +110,7 @@ void PrivacyForm::onEncryptToxUpdated() if (encrytionState) { - if (!Core::getInstance()->isPasswordSet()) + if (!Core::getInstance()->isPasswordSet(Core::ptMain)) { SetPasswordDialog dialog; if (dialog.exec()) @@ -119,10 +119,10 @@ void PrivacyForm::onEncryptToxUpdated() if (pswd.size() == 0) encrytionState = false; - Core::getInstance()->setPassword(pswd); + Core::getInstance()->setPassword(pswd, Core::ptMain); } else { encrytionState = false; - Core::getInstance()->clearPassword(); + Core::getInstance()->clearPassword(Core::ptMain); } } } @@ -130,6 +130,6 @@ void PrivacyForm::onEncryptToxUpdated() bodyUI->cbEncryptTox->setChecked(encrytionState); Settings::getInstance().setEncryptTox(encrytionState); - if (!Settings::getInstance().getEncryptLogs() && !Settings::getInstance().getEncryptTox()) - Core::getInstance()->clearPassword(); + if (!Settings::getInstance().getEncryptTox()) + Core::getInstance()->clearPassword(Core::ptMain); } diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 380159bd8..906802b02 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -134,6 +134,7 @@ Widget::Widget(QWidget *parent) qRegisterMetaType("QPixmap"); qRegisterMetaType("ToxFile"); qRegisterMetaType("ToxFile::FileDirection"); + qRegisterMetaType("Core::PasswordType"); QString profilePath = detectProfile(); coreThread = new QThread(this); @@ -911,15 +912,16 @@ void Widget::onGroupSendResult(int groupId, const QString& message, int result) g->chatForm->addSystemInfoMessage("Message failed to send", "red", QDateTime::currentDateTime()); } -void Widget::getPassword(QString info) +void Widget::getPassword(QString info, int passtype) { + Core::PasswordType pt = static_cast(passtype); InputPasswordDialog dialog(info); if (dialog.exec()) { QString pswd = dialog.getPassword(); if (pswd.isEmpty()) - core->clearPassword(); + core->clearPassword(pt); else - core->setPassword(pswd); + core->setPassword(pswd, pt); } } diff --git a/src/widget/widget.h b/src/widget/widget.h index 28bfd3483..59fdae7cd 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -112,7 +112,7 @@ private slots: void playRingtone(); void onIconClick(); void onUserAway(); - void getPassword(QString info); + void getPassword(QString info, int passtype); private: void hideMainForms();