From 5df7d8a06c1df258d252a5d7d137c9972edfe83a Mon Sep 17 00:00:00 2001 From: tux3 Date: Thu, 23 Apr 2015 22:59:12 +0200 Subject: [PATCH] Port profile encryption support to new API Profile encryption should be fairly stable. History encryption was *NOT* tested yet and as such may not work, cause profile corruption, or invoke nasal daemons. --- src/core.cpp | 24 +++++++++--------- src/coreencryption.cpp | 55 +++++++++++++++++++++++------------------- src/misc/settings.cpp | 1 - 3 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/core.cpp b/src/core.cpp index fb454f7c3..8791d428e 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -52,7 +52,7 @@ QThread* Core::coreThread{nullptr}; #define MAX_GROUP_MESSAGE_LEN 1024 Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) : - tox(nullptr), camera(cam), loadPath(loadPath), ready{false} + tox(nullptr), toxav(nullptr), camera(cam), loadPath(loadPath), ready{false} { qDebug() << "Core: loading Tox from" << loadPath; @@ -238,6 +238,13 @@ void Core::start() QByteArray savedata = loadToxSave(loadPath); + // Do we need to create a new save & profile? + if (savedata.isNull()) + { + qDebug() << "Save file not found, creating a new profile"; + Settings::getInstance().load(); + } + make_tox(savedata); qsrand(time(nullptr)); @@ -247,6 +254,9 @@ void Core::start() * Let's write something clear that doesn't rely on magic global state instead * We need to: 1) Find a qTox profile, create if needed 2) Find a tox save, decrypt/create if needed * Not sure about the order tho. Look into this. + * + * Okay we fixed encrypted profiles at least partially (needs testing wrt profile switching, corruption?) + * Need to make sure history encrypted and not is handled correctly if (true) { if (loadPath.isEmpty()) @@ -1280,14 +1290,7 @@ QByteArray Core::loadToxSave(QString path) if (fileSize > 0) { data = configurationFile.readAll(); - /* TODO: Clean this up - int error = tox_load(tox, reinterpret_cast(data.data()), data.size()); - if (error < 0) - { - qWarning() << "Core: tox_load failed with error "<< error; - } - else if (error == 1) // Encrypted data save - { + if (tox_is_data_encrypted((uint8_t*)data.data())) { if (!loadEncryptedSave(data)) { configurationFile.close(); @@ -1300,10 +1303,9 @@ QByteArray Core::loadToxSave(QString path) Settings::getInstance().switchProfile(profile); HistoryKeeper::resetInstance(); } - return false; + return QByteArray(); } } - */ } configurationFile.close(); diff --git a/src/coreencryption.cpp b/src/coreencryption.cpp index f62faa6d5..f6deef235 100644 --- a/src/coreencryption.cpp +++ b/src/coreencryption.cpp @@ -57,12 +57,12 @@ void Core::useOtherPassword(PasswordType type) PasswordType other = (type == ptMain) ? ptHistory : ptMain; - std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+TOX_PASS_KEY_LENGTH, pwsaltedkeys[type]); + std::copy(pwsaltedkeys[other], pwsaltedkeys[other]+1, pwsaltedkeys[type]); } void Core::clearPassword(PasswordType passtype) { - delete[] pwsaltedkeys[passtype]; + delete pwsaltedkeys[passtype]; pwsaltedkeys[passtype] = nullptr; } @@ -72,12 +72,12 @@ void Core::saveCurrentInformation() if (pwsaltedkeys[ptMain]) { backupkeys[ptMain] = new TOX_PASS_KEY; - std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+TOX_PASS_KEY_LENGTH, backupkeys[ptMain]); + std::copy(pwsaltedkeys[ptMain], pwsaltedkeys[ptMain]+1, backupkeys[ptMain]); } if (pwsaltedkeys[ptHistory]) { backupkeys[ptHistory] = new TOX_PASS_KEY; - std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+TOX_PASS_KEY_LENGTH, backupkeys[ptHistory]); + std::copy(pwsaltedkeys[ptHistory], pwsaltedkeys[ptHistory]+1, backupkeys[ptHistory]); } backupProfile = new QString(Settings::getInstance().getCurrentProfile()); } @@ -168,11 +168,10 @@ QByteArray Core::getSaltFromFile(QString filename) bool Core::loadEncryptedSave(QByteArray& data) { - assert(0); - /* if (!Settings::getInstance().getEncryptTox()) GUI::showWarning(tr("Encryption error"), tr("The .tox file is encrypted, but encryption was not checked, continuing regardless.")); + size_t fileSize = data.size(); int error = -1; QString a(tr("Please enter the password for the %1 profile.", "used in load() when no pw is already set").arg(Settings::getInstance().getCurrentProfile())); QString b(tr("The previous password is incorrect; please try again:", "used on retries in load()")); @@ -180,12 +179,15 @@ bool Core::loadEncryptedSave(QByteArray& data) if (pwsaltedkeys[ptMain]) // password set, try it { - error = tox_encrypted_key_load(tox, reinterpret_cast(data.data()), data.size(), pwsaltedkeys[ptMain]); - if (!error) + QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0); + if (tox_pass_key_decrypt((uint8_t*)data.data(), fileSize, pwsaltedkeys[ptMain], + (uint8_t*)newData.data(), nullptr)) { + data = newData; Settings::getInstance().setEncryptTox(true); return true; } + dialogtxt = tr("The profile password failed. Please try another?", "used only when pw set before load() doesn't work"); } else @@ -206,13 +208,17 @@ bool Core::loadEncryptedSave(QByteArray& data) else setPassword(pw, ptMain, salt); - error = tox_encrypted_key_load(tox, reinterpret_cast(data.data()), data.size(), pwsaltedkeys[ptMain]); + QByteArray newData(fileSize-TOX_PASS_ENCRYPTION_EXTRA_LENGTH, 0); + error = !tox_pass_key_decrypt((uint8_t*)data.data(), data.size(), pwsaltedkeys[ptMain], + (uint8_t*)newData.data(), nullptr); + if (!error) + data = newData; + dialogtxt = a + "\n" + b; } while (error != 0); Settings::getInstance().setEncryptTox(true); return true; - */ } void Core::checkEncryptedHistory() @@ -299,15 +305,8 @@ void Core::saveConfiguration(const QString& path) qDebug() << "Core: writing tox_save to " << path; - uint32_t fileSize; + uint32_t fileSize = tox_get_savedata_size(tox); bool encrypt = Settings::getInstance().getEncryptTox(); - if (encrypt) - { - qCritical() << "Encrypted saving not implemented!"; - exit(-1); - } - else - fileSize = tox_get_savedata_size(tox); if (fileSize > 0 && fileSize <= std::numeric_limits::max()) { @@ -324,16 +323,22 @@ void Core::saveConfiguration(const QString& path) } else { - qCritical() << "Encryption not implemented"; - exit(-1); - /* - int ret = tox_encrypted_key_save(tox, data, pwsaltedkeys[ptMain]); - if (ret == -1) + tox_get_savedata(tox, data); + uint8_t* newData = new uint8_t[fileSize+TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + if (tox_pass_key_encrypt(data, fileSize, pwsaltedkeys[ptMain], newData, nullptr)) { - qCritical() << "Core::saveConfiguration: encryption of save file failed!!!"; + delete[] data; + data = newData; + fileSize+=TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + } + else + { + delete[] newData; + delete[] data; + qCritical() << "Core::saveConfiguration(QString): Encryption failed, couldn't save"; + configurationFile.cancelWriting(); return; } - */ } } else diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 198befbc9..2f3ef8652 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -297,7 +297,6 @@ void Settings::load() loaded = true; - if (!currentProfile.isEmpty()) // new profile in Core::switchConfiguration { // load from a profile specific friend data list if possible QString tmp = dir.filePath(currentProfile + ".ini");