Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Geyer <debfx@fobos.de>2014-06-15 13:17:40 +0400
committerFelix Geyer <debfx@fobos.de>2014-06-15 13:17:40 +0400
commit0d6117bf4c0ac1e604c5b2fa0dcf8d5d47c46a58 (patch)
treecb3421a2438fc659ffe91b31a1170832f0dbf7f0
parentb417bf91873ae760031cdc821d4e411701da71f5 (diff)
Do some basic self-checks when initializing the crypto backend.
-rw-r--r--src/crypto/Crypto.cpp105
-rw-r--r--src/crypto/Crypto.h11
-rw-r--r--src/main.cpp10
-rw-r--r--tests/TestAutoType.cpp2
-rw-r--r--tests/TestCryptoHash.cpp4
-rw-r--r--tests/TestDeletedObjects.cpp2
-rw-r--r--tests/TestEntry.cpp2
-rw-r--r--tests/TestEntryModel.cpp2
-rw-r--r--tests/TestExporter.cpp2
-rw-r--r--tests/TestGroup.cpp2
-rw-r--r--tests/TestGroupModel.cpp2
-rw-r--r--tests/TestHashedBlockStream.cpp2
-rw-r--r--tests/TestKeePass1Reader.cpp2
-rw-r--r--tests/TestKeePass2RandomStream.cpp2
-rw-r--r--tests/TestKeePass2Reader.cpp2
-rw-r--r--tests/TestKeePass2Writer.cpp2
-rw-r--r--tests/TestKeePass2XmlReader.cpp2
-rw-r--r--tests/TestKeys.cpp2
-rw-r--r--tests/TestModified.cpp2
-rw-r--r--tests/TestSymmetricCipher.cpp2
-rw-r--r--tests/gui/TestGui.cpp2
-rw-r--r--tests/gui/TestGuiPixmaps.cpp2
-rw-r--r--utils/kdbx-extract.cpp4
23 files changed, 143 insertions, 27 deletions
diff --git a/src/crypto/Crypto.cpp b/src/crypto/Crypto.cpp
index 1e28002b6..13c3c20ee 100644
--- a/src/crypto/Crypto.cpp
+++ b/src/crypto/Crypto.cpp
@@ -21,7 +21,12 @@
#include <gcrypt.h>
+#include "config-keepassx.h"
+#include "crypto/CryptoHash.h"
+#include "crypto/SymmetricCipher.h"
+
bool Crypto::m_initalized(false);
+QString Crypto::m_errorStr;
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
static int gcry_qt_mutex_init(void** p_sys)
@@ -64,11 +69,11 @@ Crypto::Crypto()
{
}
-void Crypto::init()
+bool Crypto::init()
{
if (m_initalized) {
qWarning("Crypto::init: already initalized");
- return;
+ return true;
}
// libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
@@ -78,7 +83,19 @@ void Crypto::init()
gcry_check_version(0);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
+ if (!checkAlgorithms()) {
+ return false;
+ }
+
+ // has to be set before testing Crypto classes
m_initalized = true;
+
+ if (!selfTest()) {
+ m_initalized = false;
+ return false;
+ }
+
+ return true;
}
bool Crypto::initalized()
@@ -86,7 +103,89 @@ bool Crypto::initalized()
return m_initalized;
}
-bool Crypto::selfTest()
+QString Crypto::errorString()
+{
+ return m_errorStr;
+}
+
+bool Crypto::backendSelfTest()
{
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;
+}
diff --git a/src/crypto/Crypto.h b/src/crypto/Crypto.h
index 63f117771..9926f14b2 100644
--- a/src/crypto/Crypto.h
+++ b/src/crypto/Crypto.h
@@ -18,18 +18,25 @@
#ifndef KEEPASSX_CRYPTO_H
#define KEEPASSX_CRYPTO_H
+#include <QString>
+
#include "core/Global.h"
class Crypto
{
public:
- static void init();
+ static bool init();
static bool initalized();
- static bool selfTest();
+ static bool backendSelfTest();
+ static QString errorString();
private:
Crypto();
+ static bool checkAlgorithms();
+ static bool selfTest();
+
static bool m_initalized;
+ static QString m_errorStr;
};
#endif // KEEPASSX_CRYPTO_H
diff --git a/src/main.cpp b/src/main.cpp
index d5e64b92c..b9659e45d 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -25,6 +25,7 @@
#include "crypto/Crypto.h"
#include "gui/Application.h"
#include "gui/MainWindow.h"
+#include "gui/MessageBox.h"
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
// 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;
parser.setApplicationDescription(QCoreApplication::translate("main", "KeePassX - cross-platform password manager"));
diff --git a/tests/TestAutoType.cpp b/tests/TestAutoType.cpp
index 4f4350e71..818f57c96 100644
--- a/tests/TestAutoType.cpp
+++ b/tests/TestAutoType.cpp
@@ -35,7 +35,7 @@ QTEST_GUILESS_MAIN(TestAutoType)
void TestAutoType::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
Config::createTempFileInstance();
AutoType::createTestInstance();
config()->set("AutoTypeEntryTitleMatch", false);
diff --git a/tests/TestCryptoHash.cpp b/tests/TestCryptoHash.cpp
index d189d456c..eb26ca83f 100644
--- a/tests/TestCryptoHash.cpp
+++ b/tests/TestCryptoHash.cpp
@@ -27,13 +27,13 @@ QTEST_GUILESS_MAIN(TestCryptoHash)
void TestCryptoHash::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestCryptoHash::test()
{
// TODO: move somewhere else
- QVERIFY(Crypto::selfTest());
+ QVERIFY(Crypto::backendSelfTest());
CryptoHash cryptoHash1(CryptoHash::Sha256);
QCOMPARE(cryptoHash1.result(),
diff --git a/tests/TestDeletedObjects.cpp b/tests/TestDeletedObjects.cpp
index 5967e58ee..277dbcb6b 100644
--- a/tests/TestDeletedObjects.cpp
+++ b/tests/TestDeletedObjects.cpp
@@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestDeletedObjects)
void TestDeletedObjects::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestDeletedObjects::createAndDelete(Database* db, int delObjectsSize)
diff --git a/tests/TestEntry.cpp b/tests/TestEntry.cpp
index 481250a20..477e83b86 100644
--- a/tests/TestEntry.cpp
+++ b/tests/TestEntry.cpp
@@ -27,7 +27,7 @@ QTEST_GUILESS_MAIN(TestEntry)
void TestEntry::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestEntry::testHistoryItemDeletion()
diff --git a/tests/TestEntryModel.cpp b/tests/TestEntryModel.cpp
index 5347a3c52..7ba886bc2 100644
--- a/tests/TestEntryModel.cpp
+++ b/tests/TestEntryModel.cpp
@@ -38,7 +38,7 @@ QTEST_GUILESS_MAIN(TestEntryModel)
void TestEntryModel::initTestCase()
{
qRegisterMetaType<QModelIndex>("QModelIndex");
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestEntryModel::test()
diff --git a/tests/TestExporter.cpp b/tests/TestExporter.cpp
index 16b4b23cb..d703e02f1 100644
--- a/tests/TestExporter.cpp
+++ b/tests/TestExporter.cpp
@@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestExporter)
void TestExporter::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestExporter::testToDbExporter()
diff --git a/tests/TestGroup.cpp b/tests/TestGroup.cpp
index 32398f01f..507cf155d 100644
--- a/tests/TestGroup.cpp
+++ b/tests/TestGroup.cpp
@@ -33,7 +33,7 @@ void TestGroup::initTestCase()
{
qRegisterMetaType<Entry*>("Entry*");
qRegisterMetaType<Group*>("Group*");
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestGroup::testParenting()
diff --git a/tests/TestGroupModel.cpp b/tests/TestGroupModel.cpp
index fe7018e84..32a4b8e9b 100644
--- a/tests/TestGroupModel.cpp
+++ b/tests/TestGroupModel.cpp
@@ -32,7 +32,7 @@ QTEST_GUILESS_MAIN(TestGroupModel)
void TestGroupModel::initTestCase()
{
qRegisterMetaType<QModelIndex>("QModelIndex");
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestGroupModel::test()
diff --git a/tests/TestHashedBlockStream.cpp b/tests/TestHashedBlockStream.cpp
index b062908f7..09179fef2 100644
--- a/tests/TestHashedBlockStream.cpp
+++ b/tests/TestHashedBlockStream.cpp
@@ -28,7 +28,7 @@ QTEST_GUILESS_MAIN(TestHashedBlockStream)
void TestHashedBlockStream::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestHashedBlockStream::testWriteRead()
diff --git a/tests/TestKeePass1Reader.cpp b/tests/TestKeePass1Reader.cpp
index 423087c91..249a3657b 100644
--- a/tests/TestKeePass1Reader.cpp
+++ b/tests/TestKeePass1Reader.cpp
@@ -37,7 +37,7 @@ QTEST_GUILESS_MAIN(TestKeePass1Reader)
void TestKeePass1Reader::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/basic.kdb");
diff --git a/tests/TestKeePass2RandomStream.cpp b/tests/TestKeePass2RandomStream.cpp
index 328decb30..7963e9af8 100644
--- a/tests/TestKeePass2RandomStream.cpp
+++ b/tests/TestKeePass2RandomStream.cpp
@@ -30,7 +30,7 @@ QTEST_GUILESS_MAIN(TestKeePass2RandomStream)
void TestKeePass2RandomStream::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestKeePass2RandomStream::test()
diff --git a/tests/TestKeePass2Reader.cpp b/tests/TestKeePass2Reader.cpp
index 3dd87c4f4..d6cb70c78 100644
--- a/tests/TestKeePass2Reader.cpp
+++ b/tests/TestKeePass2Reader.cpp
@@ -32,7 +32,7 @@ QTEST_GUILESS_MAIN(TestKeePass2Reader)
void TestKeePass2Reader::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestKeePass2Reader::testNonAscii()
diff --git a/tests/TestKeePass2Writer.cpp b/tests/TestKeePass2Writer.cpp
index f00b38e86..cf4ab1c56 100644
--- a/tests/TestKeePass2Writer.cpp
+++ b/tests/TestKeePass2Writer.cpp
@@ -33,7 +33,7 @@ QTEST_GUILESS_MAIN(TestKeePass2Writer)
void TestKeePass2Writer::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
CompositeKey key;
key.addKey(PasswordKey("test"));
diff --git a/tests/TestKeePass2XmlReader.cpp b/tests/TestKeePass2XmlReader.cpp
index d9935804d..8e87d6744 100644
--- a/tests/TestKeePass2XmlReader.cpp
+++ b/tests/TestKeePass2XmlReader.cpp
@@ -68,7 +68,7 @@ QDateTime TestKeePass2XmlReader::genDT(int year, int month, int day, int hour, i
void TestKeePass2XmlReader::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
KeePass2XmlReader reader;
QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml");
diff --git a/tests/TestKeys.cpp b/tests/TestKeys.cpp
index d5cba4abc..d6758d655 100644
--- a/tests/TestKeys.cpp
+++ b/tests/TestKeys.cpp
@@ -35,7 +35,7 @@ QTEST_GUILESS_MAIN(TestKeys)
void TestKeys::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestKeys::testComposite()
diff --git a/tests/TestModified.cpp b/tests/TestModified.cpp
index 85a6bf23e..e275e837b 100644
--- a/tests/TestModified.cpp
+++ b/tests/TestModified.cpp
@@ -31,7 +31,7 @@ QTEST_GUILESS_MAIN(TestModified)
void TestModified::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestModified::testSignals()
diff --git a/tests/TestSymmetricCipher.cpp b/tests/TestSymmetricCipher.cpp
index 9f05db1bd..6d4e94f6f 100644
--- a/tests/TestSymmetricCipher.cpp
+++ b/tests/TestSymmetricCipher.cpp
@@ -29,7 +29,7 @@ QTEST_GUILESS_MAIN(TestSymmetricCipher)
void TestSymmetricCipher::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestSymmetricCipher::testAes256CbcEncryption()
diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp
index 51dc39e5d..326c3497b 100644
--- a/tests/gui/TestGui.cpp
+++ b/tests/gui/TestGui.cpp
@@ -51,7 +51,7 @@
void TestGui::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
Config::createTempFileInstance();
m_mainWindow = new MainWindow();
m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget");
diff --git a/tests/gui/TestGuiPixmaps.cpp b/tests/gui/TestGuiPixmaps.cpp
index 401f68bc3..87e3f2488 100644
--- a/tests/gui/TestGuiPixmaps.cpp
+++ b/tests/gui/TestGuiPixmaps.cpp
@@ -29,7 +29,7 @@
void TestGuiPixmaps::initTestCase()
{
- Crypto::init();
+ QVERIFY(Crypto::init());
}
void TestGuiPixmaps::testDatabaseIcons()
diff --git a/utils/kdbx-extract.cpp b/utils/kdbx-extract.cpp
index beee71dc3..f5d2a19a6 100644
--- a/utils/kdbx-extract.cpp
+++ b/utils/kdbx-extract.cpp
@@ -38,7 +38,9 @@ int main(int argc, char **argv)
return 1;
}
- Crypto::init();
+ if (!Crypto::init()) {
+ qFatal("Fatal error while testing the cryptographic functions:\n%s", qPrintable(Crypto::errorString()));
+ }
CompositeKey key;
if (QFile::exists(app.arguments().at(1))) {