diff --git a/client/client.pro b/client/client.pro index 316730f9..1ec8cf1f 100644 --- a/client/client.pro +++ b/client/client.pro @@ -40,6 +40,7 @@ HEADERS += \ managementserver.h \ platforms/linux/leakdetector.h \ protocols/protocols_defs.h \ + secureformat.h \ settings.h \ ui/notificationhandler.h \ ui/models/containers_model.h \ @@ -97,6 +98,7 @@ SOURCES += \ managementserver.cpp \ platforms/linux/leakdetector.cpp \ protocols/protocols_defs.cpp \ + secureformat.cpp \ settings.cpp \ ui/notificationhandler.cpp \ ui/models/containers_model.cpp \ diff --git a/client/main.cpp b/client/main.cpp index b1419f18..e3a1674f 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -136,6 +136,19 @@ int main(int argc, char *argv[]) return 0; } +// QSettings oldSettings(ORGANIZATION_NAME, APPLICATION_NAME); +// if (!oldSettings.allKeys().isEmpty()) { +// QSettings newSettings(QSettings::Format::CustomFormat1, QSettings::UserScope, +// ORGANIZATION_NAME, APPLICATION_NAME); +// QString oldSettingsFileName = oldSettings.fileName(); +// QString newSettingsFileName = newSettings.fileName(); +// qDebug() << "oldSettingsFileName:" << oldSettingsFileName; +// qDebug() << "newSettingsFileName:" << newSettingsFileName; +//// qDebug() << "New config removed:" << QFile::remove(newSettingsFileName); +// qDebug() << "Old config copied:" << QFile::copy(oldSettingsFileName, newSettingsFileName); +//// qDebug() << "Old config removed:" << QFile::remove(oldSettingsFileName); +// } + Settings settings; if (settings.isSaveLogs()) { diff --git a/client/secureformat.cpp b/client/secureformat.cpp new file mode 100644 index 00000000..bd12e907 --- /dev/null +++ b/client/secureformat.cpp @@ -0,0 +1,169 @@ +#include "secureformat.h" + +#include +#include + +#include "openssl/evp.h" + +void handleErrors() { + qDebug() << "handleErrors"; +} + +int gcm_encrypt(unsigned char *plaintext, int plaintext_len, + unsigned char *key, + unsigned char *iv, int iv_len, + unsigned char *ciphertext) +{ + EVP_CIPHER_CTX *ctx; + + int len; + + int ciphertext_len; + + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) + handleErrors(); + + /* Initialise the encryption operation. */ + if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) + handleErrors(); + + /* + * Set IV length if default 12 bytes (96 bits) is not appropriate + */ + if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + handleErrors(); + + /* Initialise key and IV */ + if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) + handleErrors(); + + /* + * Provide the message to be encrypted, and obtain the encrypted output. + * EVP_EncryptUpdate can be called multiple times if necessary + */ + if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) + handleErrors(); + ciphertext_len = len; + + /* + * Finalise the encryption. Normally ciphertext bytes may be written at + * this stage, but this does not occur in GCM mode + */ + if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) + handleErrors(); + ciphertext_len += len; + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); + + return ciphertext_len; +} + +int gcm_decrypt(unsigned char *ciphertext, int ciphertext_len, + unsigned char *key, + unsigned char *iv, int iv_len, + unsigned char *plaintext) +{ + EVP_CIPHER_CTX *ctx; + int len; + int plaintext_len; + int ret; + + /* Create and initialise the context */ + if(!(ctx = EVP_CIPHER_CTX_new())) + handleErrors(); + + /* Initialise the decryption operation. */ + if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) + handleErrors(); + + /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ + if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL)) + handleErrors(); + + /* Initialise key and IV */ + if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) + handleErrors(); + + /* + * Provide the message to be decrypted, and obtain the plaintext output. + * EVP_DecryptUpdate can be called multiple times if necessary + */ + if(!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) + handleErrors(); + plaintext_len = len; + + /* + * Finalise the decryption. A positive return value indicates success, + * anything else is a failure - the plaintext is not trustworthy. + */ + ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); + + /* Clean up */ + EVP_CIPHER_CTX_free(ctx); + + if(ret > 0) { + /* Success */ + plaintext_len += len; + return plaintext_len; + } else { + /* Verify failed */ + return -1; + } +} + +SecureFormat::SecureFormat() +{ + m_format = QSettings::registerFormat("plist", + readSecureFile, + writeSecureFile); + qDebug() << "SecureFormat" << m_format; + + unsigned char plainText[] = "Hello world!"; + qDebug("%s", plainText); + unsigned char key[] = "12345qwerty"; + unsigned char iv[] = "000000000000"; + unsigned char chipherText[1024]; + unsigned char decryptPlainText[1024]; + gcm_encrypt(plainText, std::strlen((const char *)plainText), + key, + iv, 12, + chipherText); + qDebug("%s", chipherText); + + gcm_decrypt(chipherText, std::strlen((const char *)chipherText), + key, + iv, 12, + decryptPlainText); + qDebug("%s", decryptPlainText); +} + +bool SecureFormat::readSecureFile(QIODevice& device, QSettings::SettingsMap& map) { + if (!device.isOpen()) { + return false; + } + + QTextStream inStream(&device); + while (!inStream.atEnd()) { + QString line = inStream.readLine(); + qDebug() << "SecureFormat::readSecureFile" << line; + } + + return true; +} + +bool SecureFormat::writeSecureFile(QIODevice& device, const QSettings::SettingsMap& map) { + if (!device.isOpen()) { + return false; + } + + QTextStream outStream(&device); + + return true; +} + +const QSettings::Format& SecureFormat::format() const{ + return m_format; +} diff --git a/client/secureformat.h b/client/secureformat.h new file mode 100644 index 00000000..bb93d77e --- /dev/null +++ b/client/secureformat.h @@ -0,0 +1,21 @@ +#ifndef SECUREFORMAT_H +#define SECUREFORMAT_H + +#include +#include + +class SecureFormat +{ +public: + SecureFormat(); + + static bool readSecureFile(QIODevice &device, QSettings::SettingsMap &map); + static bool writeSecureFile(QIODevice &device, const QSettings::SettingsMap &map); + + const QSettings::Format& format() const; + +private: + QSettings::Format m_format; +}; + +#endif // SECUREFORMAT_H diff --git a/client/settings.cpp b/client/settings.cpp index 317df740..e35a14ac 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -8,10 +8,15 @@ const char Settings::cloudFlareNs1[] = "1.1.1.1"; const char Settings::cloudFlareNs2[] = "1.0.0.1"; +SecureFormat Settings::m_secureFormat; + Settings::Settings(QObject* parent) : QObject(parent), - m_settings (ORGANIZATION_NAME, APPLICATION_NAME, this) + m_settings(m_secureFormat.format(), QSettings::UserScope, + ORGANIZATION_NAME, APPLICATION_NAME, this) { + qDebug() << "Settings::Settings()" << this; + qDebug() << "Settings::Settings()" << m_settings.fileName(); // Import old settings if (serversCount() == 0) { QString user = m_settings.value("Server/userName").toString(); diff --git a/client/settings.h b/client/settings.h index d5cb1639..7b0066b9 100644 --- a/client/settings.h +++ b/client/settings.h @@ -11,6 +11,7 @@ #include "core/defs.h" #include "containers/containers_defs.h" +#include "secureformat.h" using namespace amnezia; @@ -110,14 +111,9 @@ public: // static constexpr char openNicNs5[] = "94.103.153.176"; // static constexpr char openNicNs13[] = "144.76.103.143"; - -public: - - - private: + static SecureFormat m_secureFormat; QSettings m_settings; - }; #endif // SETTINGS_H