diff options
author | Janek Bevendorff <janek@jbev.net> | 2018-01-17 22:52:29 +0300 |
---|---|---|
committer | Janek Bevendorff <janek@jbev.net> | 2018-01-18 03:51:37 +0300 |
commit | a595239624dd91f40074747c0ff5995d6bafb4e3 (patch) | |
tree | bf4acef9b94c9369233bcafa0b436c4e697f468d /tests/TestKdbx4.cpp | |
parent | cdefc7ea9bdfe89e86d57d3155ce35ac2347d719 (diff) |
Refactor and extend file format tests
Diffstat (limited to 'tests/TestKdbx4.cpp')
-rw-r--r-- | tests/TestKdbx4.cpp | 153 |
1 files changed, 137 insertions, 16 deletions
diff --git a/tests/TestKdbx4.cpp b/tests/TestKdbx4.cpp index e67274cbd..0a21215ac 100644 --- a/tests/TestKdbx4.cpp +++ b/tests/TestKdbx4.cpp @@ -17,8 +17,10 @@ #include "TestKdbx4.h" #include "core/Metadata.h" -#include "crypto/Crypto.h" +#include "keys/PasswordKey.h" #include "format/KeePass2.h" +#include "format/KeePass2Reader.h" +#include "format/KeePass2Writer.h" #include "format/KdbxXmlReader.h" #include "format/KdbxXmlWriter.h" #include "config-keepassx-tests.h" @@ -27,21 +29,15 @@ QTEST_GUILESS_MAIN(TestKdbx4) -void TestKdbx4::initTestCase() +void TestKdbx4::initTestCaseImpl() { - QVERIFY(Crypto::init()); - - KdbxXmlReader reader(KeePass2::FILE_VERSION_3); - reader.setStrictMode(true); - QString xmlFile = QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.xml"); - m_db.reset(reader.readDatabase(xmlFile)); - QVERIFY(m_db.data()); - QVERIFY(!reader.hasError()); + m_xmlDb->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); + m_kdbxSourceDb->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); } -Database* TestKdbx4::readDatabase(QString path, bool strictMode, bool& hasError, QString& errorString) +Database* TestKdbx4::readXml(const QString& path, bool strictMode, bool& hasError, QString& errorString) { - KdbxXmlReader reader(KeePass2::FILE_VERSION_3); + KdbxXmlReader reader(KeePass2::FILE_VERSION_4); reader.setStrictMode(strictMode); auto db = reader.readDatabase(path); hasError = reader.hasError(); @@ -49,9 +45,9 @@ Database* TestKdbx4::readDatabase(QString path, bool strictMode, bool& hasError, return db; } -Database* TestKdbx4::readDatabase(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) +Database* TestKdbx4::readXml(QBuffer* buf, bool strictMode, bool& hasError, QString& errorString) { - KdbxXmlReader reader(KeePass2::FILE_VERSION_3); + KdbxXmlReader reader(KeePass2::FILE_VERSION_4); reader.setStrictMode(strictMode); auto db = reader.readDatabase(buf); hasError = reader.hasError(); @@ -59,10 +55,135 @@ Database* TestKdbx4::readDatabase(QBuffer* buf, bool strictMode, bool& hasError, return db; } -void TestKdbx4::writeDatabase(QBuffer* buf, Database* db, bool& hasError, QString& errorString) +void TestKdbx4::writeXml(QBuffer* buf, Database* db, bool& hasError, QString& errorString) { - KdbxXmlWriter writer(KeePass2::FILE_VERSION_3); + KdbxXmlWriter writer(KeePass2::FILE_VERSION_4); writer.writeDatabase(buf, db); hasError = writer.hasError(); errorString = writer.errorString(); } + +void TestKdbx4::readKdbx(QIODevice* device, CompositeKey const& key, QScopedPointer<Database>& db, + bool& hasError, QString& errorString) +{ + KeePass2Reader reader; + db.reset(reader.readDatabase(device, key)); + hasError = reader.hasError(); + if (hasError) { + errorString = reader.errorString(); + } + QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4); +} + +void TestKdbx4::readKdbx(const QString& path, CompositeKey const& key, QScopedPointer<Database>& db, + bool& hasError, QString& errorString) +{ + KeePass2Reader reader; + db.reset(reader.readDatabase(path, key)); + hasError = reader.hasError(); + if (hasError) { + errorString = reader.errorString(); + } + QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4); +} + +void TestKdbx4::writeKdbx(QIODevice* device, Database* db, bool& hasError, QString& errorString) +{ + if (db->kdf()->uuid() == KeePass2::KDF_AES_KDBX3) { + db->changeKdf(KeePass2::uuidToKdf(KeePass2::KDF_ARGON2)); + } + KeePass2Writer writer; + hasError = writer.writeDatabase(device, db); + hasError = writer.hasError(); + if (hasError) { + errorString = writer.errorString(); + } + QCOMPARE(writer.version(), KeePass2::FILE_VERSION_4); +} + +Q_DECLARE_METATYPE(Uuid); +void TestKdbx4::testFormat400() +{ + QString filename = QString(KEEPASSX_TEST_DATA_DIR).append("/Format400.kdbx"); + CompositeKey key; + key.addKey(PasswordKey("t")); + KeePass2Reader reader; + QScopedPointer<Database> db(reader.readDatabase(filename, key)); + QCOMPARE(reader.version(), KeePass2::FILE_VERSION_4); + QVERIFY(db.data()); + QVERIFY(!reader.hasError()); + + QCOMPARE(db->rootGroup()->name(), QString("Format400")); + QCOMPARE(db->metadata()->name(), QString("Format400")); + QCOMPARE(db->rootGroup()->entries().size(), 1); + auto entry = db->rootGroup()->entries().at(0); + + QCOMPARE(entry->title(), QString("Format400")); + QCOMPARE(entry->username(), QString("Format400")); + QCOMPARE(entry->attributes()->keys().size(), 6); + QCOMPARE(entry->attributes()->value("Format400"), QString("Format400")); + QCOMPARE(entry->attachments()->keys().size(), 1); + QCOMPARE(entry->attachments()->value("Format400"), QByteArray("Format400\n")); +} + +void TestKdbx4::testFormat400Upgrade() +{ + QFETCH(Uuid, kdfUuid); + QFETCH(Uuid, cipherUuid); + QFETCH(quint32, expectedVersion); + + QScopedPointer<Database> sourceDb(new Database()); + sourceDb->metadata()->setName("Wubba lubba dub dub"); + QCOMPARE(sourceDb->kdf()->uuid(), KeePass2::KDF_AES_KDBX3); // default is legacy AES-KDF + + CompositeKey key; + key.addKey(PasswordKey("I am in great pain, please help me!")); + sourceDb->setKey(key, true, true); + + QBuffer buffer; + buffer.open(QBuffer::ReadWrite); + + // upgrade to KDBX 4 by changing KDF and Cipher + sourceDb->changeKdf(KeePass2::uuidToKdf(kdfUuid)); + sourceDb->setCipher(cipherUuid); + KeePass2Writer writer; + writer.writeDatabase(&buffer, sourceDb.data()); + if (writer.hasError()) { + QFAIL(qPrintable(QString("Error while writing database: %1").arg(writer.errorString()))); + } + + // read buffer back + buffer.seek(0); + KeePass2Reader reader; + QScopedPointer<Database> targetDb(reader.readDatabase(&buffer, key)); + if (reader.hasError()) { + QFAIL(qPrintable(QString("Error while reading database: %1").arg(reader.errorString()))); + } + + QVERIFY(targetDb->rootGroup()); + QCOMPARE(targetDb->metadata()->name(), sourceDb->metadata()->name()); + + QCOMPARE(reader.version(), expectedVersion); + QCOMPARE(targetDb->kdf()->uuid(), sourceDb->kdf()->uuid()); + QCOMPARE(targetDb->cipher(), cipherUuid); +} + +void TestKdbx4::testFormat400Upgrade_data() +{ + QTest::addColumn<Uuid>("kdfUuid"); + QTest::addColumn<Uuid>("cipherUuid"); + QTest::addColumn<quint32>("expectedVersion"); + + auto constexpr kdbx3 = KeePass2::FILE_VERSION_3_1 & KeePass2::FILE_VERSION_CRITICAL_MASK; + auto constexpr kdbx4 = KeePass2::FILE_VERSION_4 & KeePass2::FILE_VERSION_CRITICAL_MASK; + + QTest::newRow("Argon2 + AES") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_AES << kdbx4; + QTest::newRow("AES-KDF + AES") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_AES << kdbx4; + QTest::newRow("AES-KDF (legacy) + AES") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_AES << kdbx3; + QTest::newRow("Argon2 + ChaCha20") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_CHACHA20 << kdbx4; + QTest::newRow("AES-KDF + ChaCha20") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_CHACHA20 << kdbx4; + QTest::newRow("AES-KDF (legacy) + ChaCha20") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_CHACHA20 << kdbx3; + QTest::newRow("Argon2 + Twofish") << KeePass2::KDF_ARGON2 << KeePass2::CIPHER_TWOFISH << kdbx4; + QTest::newRow("AES-KDF + Twofish") << KeePass2::KDF_AES_KDBX4 << KeePass2::CIPHER_TWOFISH << kdbx4; + QTest::newRow("AES-KDF (legacy) + Twofish") << KeePass2::KDF_AES_KDBX3 << KeePass2::CIPHER_TWOFISH << kdbx3; +} |