mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-22 23:49:58 -05:00
Do some basic self-checks when initializing the crypto backend.
This commit is contained in:
parent
b417bf9187
commit
0d6117bf4c
@ -21,7 +21,12 @@
|
|||||||
|
|
||||||
#include <gcrypt.h>
|
#include <gcrypt.h>
|
||||||
|
|
||||||
|
#include "config-keepassx.h"
|
||||||
|
#include "crypto/CryptoHash.h"
|
||||||
|
#include "crypto/SymmetricCipher.h"
|
||||||
|
|
||||||
bool Crypto::m_initalized(false);
|
bool Crypto::m_initalized(false);
|
||||||
|
QString Crypto::m_errorStr;
|
||||||
|
|
||||||
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
|
||||||
static int gcry_qt_mutex_init(void** p_sys)
|
static int gcry_qt_mutex_init(void** p_sys)
|
||||||
@ -64,11 +69,11 @@ Crypto::Crypto()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Crypto::init()
|
bool Crypto::init()
|
||||||
{
|
{
|
||||||
if (m_initalized) {
|
if (m_initalized) {
|
||||||
qWarning("Crypto::init: already initalized");
|
qWarning("Crypto::init: already initalized");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
|
// libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
|
||||||
@ -78,7 +83,19 @@ void Crypto::init()
|
|||||||
gcry_check_version(0);
|
gcry_check_version(0);
|
||||||
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||||
|
|
||||||
|
if (!checkAlgorithms()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// has to be set before testing Crypto classes
|
||||||
m_initalized = true;
|
m_initalized = true;
|
||||||
|
|
||||||
|
if (!selfTest()) {
|
||||||
|
m_initalized = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Crypto::initalized()
|
bool Crypto::initalized()
|
||||||
@ -86,7 +103,89 @@ bool Crypto::initalized()
|
|||||||
return m_initalized;
|
return m_initalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Crypto::selfTest()
|
QString Crypto::errorString()
|
||||||
|
{
|
||||||
|
return m_errorStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Crypto::backendSelfTest()
|
||||||
{
|
{
|
||||||
return (gcry_control(GCRYCTL_SELFTEST) == 0);
|
return (gcry_control(GCRYCTL_SELFTEST) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Crypto::checkAlgorithms()
|
||||||
|
{
|
||||||
|
if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
|
||||||
|
m_errorStr = "GCRY_CIPHER_AES256 not found.";
|
||||||
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
|
||||||
|
m_errorStr = "GCRY_CIPHER_TWOFISH not found.";
|
||||||
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#ifdef GCRYPT_HAS_SALSA20
|
||||||
|
if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
|
||||||
|
m_errorStr = "GCRY_CIPHER_SALSA20 not found.";
|
||||||
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (gcry_md_test_algo(GCRY_MD_SHA256) != 0) {
|
||||||
|
m_errorStr = "GCRY_MD_SHA256 not found.";
|
||||||
|
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Crypto::selfTest()
|
||||||
|
{
|
||||||
|
QByteArray sha256Test = CryptoHash::hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
|
||||||
|
CryptoHash::Sha256);
|
||||||
|
|
||||||
|
if (sha256Test != QByteArray::fromHex("248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1")) {
|
||||||
|
m_errorStr = "SHA-256 mismatch.";
|
||||||
|
qWarning("Crypto::selfTest: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray key = QByteArray::fromHex("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4");
|
||||||
|
QByteArray iv = QByteArray::fromHex("000102030405060708090a0b0c0d0e0f");
|
||||||
|
QByteArray plainText = QByteArray::fromHex("6bc1bee22e409f96e93d7e117393172a");
|
||||||
|
plainText.append(QByteArray::fromHex("ae2d8a571e03ac9c9eb76fac45af8e51"));
|
||||||
|
QByteArray cipherText = QByteArray::fromHex("f58c4c04d6e5f1ba779eabfb5f7bfbd6");
|
||||||
|
cipherText.append(QByteArray::fromHex("9cfc4e967edb808d679f777bc6702c7d"));
|
||||||
|
|
||||||
|
SymmetricCipher aes256Encrypt(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Encrypt, key, iv);
|
||||||
|
if (aes256Encrypt.process(plainText) != cipherText) {
|
||||||
|
m_errorStr = "AES-256 encryption mismatch.";
|
||||||
|
qWarning("Crypto::selfTest: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SymmetricCipher aes256Descrypt(SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt, key, iv);
|
||||||
|
if (aes256Descrypt.process(cipherText) != plainText) {
|
||||||
|
m_errorStr = "AES-256 decryption mismatch.";
|
||||||
|
qWarning("Crypto::selfTest: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray salsa20Key = QByteArray::fromHex("F3F4F5F6F7F8F9FAFBFCFDFEFF000102030405060708090A0B0C0D0E0F101112");
|
||||||
|
QByteArray salsa20iv = QByteArray::fromHex("0000000000000000");
|
||||||
|
QByteArray salsa20Plain = QByteArray::fromHex("00000000000000000000000000000000");
|
||||||
|
QByteArray salsa20Cipher = QByteArray::fromHex("B4C0AFA503BE7FC29A62058166D56F8F");
|
||||||
|
|
||||||
|
SymmetricCipher salsa20Stream(SymmetricCipher::Salsa20, SymmetricCipher::Stream,
|
||||||
|
SymmetricCipher::Encrypt, salsa20Key, salsa20iv);
|
||||||
|
|
||||||
|
if (salsa20Stream.process(salsa20Plain) != salsa20Cipher) {
|
||||||
|
m_errorStr = "Salsa20 stream cipher mismatch.";
|
||||||
|
qWarning("Crypto::selfTest: %s", qPrintable(m_errorStr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -18,18 +18,25 @@
|
|||||||
#ifndef KEEPASSX_CRYPTO_H
|
#ifndef KEEPASSX_CRYPTO_H
|
||||||
#define KEEPASSX_CRYPTO_H
|
#define KEEPASSX_CRYPTO_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include "core/Global.h"
|
#include "core/Global.h"
|
||||||
|
|
||||||
class Crypto
|
class Crypto
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static void init();
|
static bool init();
|
||||||
static bool initalized();
|
static bool initalized();
|
||||||
static bool selfTest();
|
static bool backendSelfTest();
|
||||||
|
static QString errorString();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Crypto();
|
Crypto();
|
||||||
|
static bool checkAlgorithms();
|
||||||
|
static bool selfTest();
|
||||||
|
|
||||||
static bool m_initalized;
|
static bool m_initalized;
|
||||||
|
static QString m_errorStr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // KEEPASSX_CRYPTO_H
|
#endif // KEEPASSX_CRYPTO_H
|
||||||
|
10
src/main.cpp
10
src/main.cpp
@ -25,6 +25,7 @@
|
|||||||
#include "crypto/Crypto.h"
|
#include "crypto/Crypto.h"
|
||||||
#include "gui/Application.h"
|
#include "gui/Application.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
|
#include "gui/MessageBox.h"
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
@ -38,7 +39,14 @@ int main(int argc, char** argv)
|
|||||||
// don't set organizationName as that changes the return value of
|
// don't set organizationName as that changes the return value of
|
||||||
// QDesktopServices::storageLocation(QDesktopServices::DataLocation)
|
// QDesktopServices::storageLocation(QDesktopServices::DataLocation)
|
||||||
|
|
||||||
Crypto::init();
|
if (!Crypto::init()) {
|
||||||
|
QString error = QCoreApplication::translate("Main",
|
||||||
|
"Fatal error while testing the cryptographic functions.");
|
||||||
|
error.append("\n");
|
||||||
|
error.append(Crypto::errorString());
|
||||||
|
MessageBox::critical(Q_NULLPTR, QCoreApplication::translate("Main", "KeePassX - Error"), error);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
parser.setApplicationDescription(QCoreApplication::translate("main", "KeePassX - cross-platform password manager"));
|
parser.setApplicationDescription(QCoreApplication::translate("main", "KeePassX - cross-platform password manager"));
|
||||||
|
@ -35,7 +35,7 @@ QTEST_GUILESS_MAIN(TestAutoType)
|
|||||||
|
|
||||||
void TestAutoType::initTestCase()
|
void TestAutoType::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
Config::createTempFileInstance();
|
Config::createTempFileInstance();
|
||||||
AutoType::createTestInstance();
|
AutoType::createTestInstance();
|
||||||
config()->set("AutoTypeEntryTitleMatch", false);
|
config()->set("AutoTypeEntryTitleMatch", false);
|
||||||
|
@ -27,13 +27,13 @@ QTEST_GUILESS_MAIN(TestCryptoHash)
|
|||||||
|
|
||||||
void TestCryptoHash::initTestCase()
|
void TestCryptoHash::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCryptoHash::test()
|
void TestCryptoHash::test()
|
||||||
{
|
{
|
||||||
// TODO: move somewhere else
|
// TODO: move somewhere else
|
||||||
QVERIFY(Crypto::selfTest());
|
QVERIFY(Crypto::backendSelfTest());
|
||||||
|
|
||||||
CryptoHash cryptoHash1(CryptoHash::Sha256);
|
CryptoHash cryptoHash1(CryptoHash::Sha256);
|
||||||
QCOMPARE(cryptoHash1.result(),
|
QCOMPARE(cryptoHash1.result(),
|
||||||
|
@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestDeletedObjects)
|
|||||||
|
|
||||||
void TestDeletedObjects::initTestCase()
|
void TestDeletedObjects::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize)
|
void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize)
|
||||||
|
@ -27,7 +27,7 @@ QTEST_GUILESS_MAIN(TestEntry)
|
|||||||
|
|
||||||
void TestEntry::initTestCase()
|
void TestEntry::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEntry::testHistoryItemDeletion()
|
void TestEntry::testHistoryItemDeletion()
|
||||||
|
@ -38,7 +38,7 @@ QTEST_GUILESS_MAIN(TestEntryModel)
|
|||||||
void TestEntryModel::initTestCase()
|
void TestEntryModel::initTestCase()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QModelIndex>("QModelIndex");
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEntryModel::test()
|
void TestEntryModel::test()
|
||||||
|
@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestExporter)
|
|||||||
|
|
||||||
void TestExporter::initTestCase()
|
void TestExporter::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestExporter::testToDbExporter()
|
void TestExporter::testToDbExporter()
|
||||||
|
@ -33,7 +33,7 @@ void TestGroup::initTestCase()
|
|||||||
{
|
{
|
||||||
qRegisterMetaType<Entry*>("Entry*");
|
qRegisterMetaType<Entry*>("Entry*");
|
||||||
qRegisterMetaType<Group*>("Group*");
|
qRegisterMetaType<Group*>("Group*");
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGroup::testParenting()
|
void TestGroup::testParenting()
|
||||||
|
@ -32,7 +32,7 @@ QTEST_GUILESS_MAIN(TestGroupModel)
|
|||||||
void TestGroupModel::initTestCase()
|
void TestGroupModel::initTestCase()
|
||||||
{
|
{
|
||||||
qRegisterMetaType<QModelIndex>("QModelIndex");
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGroupModel::test()
|
void TestGroupModel::test()
|
||||||
|
@ -28,7 +28,7 @@ QTEST_GUILESS_MAIN(TestHashedBlockStream)
|
|||||||
|
|
||||||
void TestHashedBlockStream::initTestCase()
|
void TestHashedBlockStream::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestHashedBlockStream::testWriteRead()
|
void TestHashedBlockStream::testWriteRead()
|
||||||
|
@ -37,7 +37,7 @@ QTEST_GUILESS_MAIN(TestKeePass1Reader)
|
|||||||
|
|
||||||
void TestKeePass1Reader::initTestCase()
|
void TestKeePass1Reader::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
|
|
||||||
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb");
|
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb");
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestKeePass2RandomStream)
|
|||||||
|
|
||||||
void TestKeePass2RandomStream::initTestCase()
|
void TestKeePass2RandomStream::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass2RandomStream::test()
|
void TestKeePass2RandomStream::test()
|
||||||
|
@ -32,7 +32,7 @@ QTEST_GUILESS_MAIN(TestKeePass2Reader)
|
|||||||
|
|
||||||
void TestKeePass2Reader::initTestCase()
|
void TestKeePass2Reader::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeePass2Reader::testNonAscii()
|
void TestKeePass2Reader::testNonAscii()
|
||||||
|
@ -33,7 +33,7 @@ QTEST_GUILESS_MAIN(TestKeePass2Writer)
|
|||||||
|
|
||||||
void TestKeePass2Writer::initTestCase()
|
void TestKeePass2Writer::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
|
|
||||||
CompositeKey key;
|
CompositeKey key;
|
||||||
key.addKey(PasswordKey("test"));
|
key.addKey(PasswordKey("test"));
|
||||||
|
@ -68,7 +68,7 @@ QDateTime TestKeePass2XmlReader::genDT(int year, int month, int day, int hour, i
|
|||||||
|
|
||||||
void TestKeePass2XmlReader::initTestCase()
|
void TestKeePass2XmlReader::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
|
|
||||||
KeePass2XmlReader reader;
|
KeePass2XmlReader reader;
|
||||||
QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml");
|
QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml");
|
||||||
|
@ -35,7 +35,7 @@ QTEST_GUILESS_MAIN(TestKeys)
|
|||||||
|
|
||||||
void TestKeys::initTestCase()
|
void TestKeys::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestKeys::testComposite()
|
void TestKeys::testComposite()
|
||||||
|
@ -31,7 +31,7 @@ QTEST_GUILESS_MAIN(TestModified)
|
|||||||
|
|
||||||
void TestModified::initTestCase()
|
void TestModified::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestModified::testSignals()
|
void TestModified::testSignals()
|
||||||
|
@ -29,7 +29,7 @@ QTEST_GUILESS_MAIN(TestSymmetricCipher)
|
|||||||
|
|
||||||
void TestSymmetricCipher::initTestCase()
|
void TestSymmetricCipher::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestSymmetricCipher::testAes256CbcEncryption()
|
void TestSymmetricCipher::testAes256CbcEncryption()
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
|
|
||||||
void TestGui::initTestCase()
|
void TestGui::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
Config::createTempFileInstance();
|
Config::createTempFileInstance();
|
||||||
m_mainWindow = new MainWindow();
|
m_mainWindow = new MainWindow();
|
||||||
m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget");
|
m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget");
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
void TestGuiPixmaps::initTestCase()
|
void TestGuiPixmaps::initTestCase()
|
||||||
{
|
{
|
||||||
Crypto::init();
|
QVERIFY(Crypto::init());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGuiPixmaps::testDatabaseIcons()
|
void TestGuiPixmaps::testDatabaseIcons()
|
||||||
|
@ -38,7 +38,9 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Crypto::init();
|
if (!Crypto::init()) {
|
||||||
|
qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString()));
|
||||||
|
}
|
||||||
|
|
||||||
CompositeKey key;
|
CompositeKey key;
|
||||||
if (QFile::exists(app.arguments().at(1))) {
|
if (QFile::exists(app.arguments().at(1))) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user