Formatting the code.

This commit is contained in:
Louis-Bertrand Varin 2018-03-31 16:01:30 -04:00
parent 74efc57369
commit 8324d03f0a
294 changed files with 3796 additions and 3740 deletions

View file

@ -18,19 +18,21 @@
#include "Kdbx3Reader.h"
#include "core/Group.h"
#include "core/Endian.h"
#include "core/Group.h"
#include "crypto/CryptoHash.h"
#include "format/KeePass2RandomStream.h"
#include "format/KdbxXmlReader.h"
#include "format/KeePass2RandomStream.h"
#include "streams/HashedBlockStream.h"
#include "streams/QtIOCompressor"
#include "streams/SymmetricCipherStream.h"
#include <QBuffer>
Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
const CompositeKey& key, bool keepDatabase)
Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device,
const QByteArray& headerData,
const CompositeKey& key,
bool keepDatabase)
{
Q_ASSERT(m_kdbxVersion <= KeePass2::FILE_VERSION_3_1);
@ -39,8 +41,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
}
// check if all required headers were present
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty()
|| m_streamStartBytes.isEmpty() || m_protectedStreamKey.isEmpty()
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_streamStartBytes.isEmpty()
|| m_protectedStreamKey.isEmpty()
|| m_db->cipher().isNull()) {
raiseError(tr("missing database headers"));
return nullptr;
@ -63,8 +65,8 @@ Database* Kdbx3Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
QByteArray finalKey = hash.result();
SymmetricCipher::Algorithm cipher = SymmetricCipher::cipherToAlgorithm(m_db->cipher());
SymmetricCipherStream cipherStream(device, cipher,
SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
SymmetricCipherStream cipherStream(
device, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
if (!cipherStream.init(finalKey, m_encryptionIV)) {
raiseError(cipherStream.errorString());
return nullptr;

View file

@ -24,13 +24,15 @@
/**
* KDBX 2/3 reader implementation.
*/
class Kdbx3Reader: public KdbxReader
class Kdbx3Reader : public KdbxReader
{
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
Q_DECLARE_TR_FUNCTIONS(Kdbx3Reader)
public:
Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
const CompositeKey& key, bool keepDatabase) override;
Database* readDatabaseImpl(QIODevice* device,
const QByteArray& headerData,
const CompositeKey& key,
bool keepDatabase) override;
protected:
bool readHeaderField(StoreDataStream& headerStream) override;

View file

@ -23,9 +23,9 @@
#include "core/Database.h"
#include "crypto/CryptoHash.h"
#include "crypto/Random.h"
#include "format/KdbxXmlWriter.h"
#include "format/KeePass2.h"
#include "format/KeePass2RandomStream.h"
#include "format/KdbxXmlWriter.h"
#include "streams/HashedBlockStream.h"
#include "streams/QtIOCompressor"
#include "streams/SymmetricCipherStream.h"
@ -65,23 +65,27 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_3_1);
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(
writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
CHECK_RETURN_FALSE(
writeHeaderField<quint16>(&header,
KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes<qint32>(db->compressionAlgo(), KeePass2::BYTEORDER)));
auto kdf = db->kdf();
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformSeed, kdf->seed()));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::TransformRounds,
Endian::sizedIntToBytes<qint64>(kdf->rounds(),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header,
KeePass2::HeaderFieldID::TransformRounds,
Endian::sizedIntToBytes<qint64>(kdf->rounds(), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey));
CHECK_RETURN_FALSE(
writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::ProtectedStreamKey, protectedStreamKey));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::StreamStartBytes, startBytes));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::InnerRandomStreamID,
Endian::sizedIntToBytes<qint32>(static_cast<qint32>(
KeePass2::ProtectedStreamAlgo::Salsa20),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(
&header,
KeePass2::HeaderFieldID::InnerRandomStreamID,
Endian::sizedIntToBytes<qint32>(static_cast<qint32>(KeePass2::ProtectedStreamAlgo::Salsa20),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint16>(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader));
header.close();
@ -93,8 +97,7 @@ bool Kdbx3Writer::writeDatabase(QIODevice* device, Database* db)
// write cipher stream
SymmetricCipher::Algorithm algo = SymmetricCipher::cipherToAlgorithm(db->cipher());
SymmetricCipherStream cipherStream(device, algo,
SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt);
SymmetricCipherStream cipherStream(device, algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt);
cipherStream.init(finalKey, encryptionIV);
if (!cipherStream.open(QIODevice::WriteOnly)) {
raiseError(cipherStream.errorString());

View file

@ -23,9 +23,9 @@
/**
* KDBX2/3 writer implementation.
*/
class Kdbx3Writer: public KdbxWriter
class Kdbx3Writer : public KdbxWriter
{
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
Q_DECLARE_TR_FUNCTIONS(Kdbx3Writer)
public:
bool writeDatabase(QIODevice* device, Database* db) override;

View file

@ -19,17 +19,19 @@
#include <QBuffer>
#include "core/Group.h"
#include "core/Endian.h"
#include "core/Group.h"
#include "crypto/CryptoHash.h"
#include "format/KeePass2RandomStream.h"
#include "format/KdbxXmlReader.h"
#include "format/KeePass2RandomStream.h"
#include "streams/HmacBlockStream.h"
#include "streams/QtIOCompressor"
#include "streams/SymmetricCipherStream.h"
Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
const CompositeKey& key, bool keepDatabase)
Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device,
const QByteArray& headerData,
const CompositeKey& key,
bool keepDatabase)
{
Q_ASSERT(m_kdbxVersion == KeePass2::FILE_VERSION_4);
@ -40,9 +42,7 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
}
// check if all required headers were present
if (m_masterSeed.isEmpty()
|| m_encryptionIV.isEmpty()
|| m_db->cipher().isNull()) {
if (m_masterSeed.isEmpty() || m_encryptionIV.isEmpty() || m_db->cipher().isNull()) {
raiseError(tr("missing database headers"));
return nullptr;
}
@ -69,8 +69,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
}
QByteArray hmacKey = KeePass2::hmacKey(m_masterSeed, m_db->transformedMasterKey());
if (headerHmac != CryptoHash::hmac(headerData,
HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) {
if (headerHmac
!= CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256)) {
raiseError(tr("Wrong key or database file is corrupt. (HMAC mismatch)"));
return nullptr;
}
@ -85,8 +85,8 @@ Database* Kdbx4Reader::readDatabaseImpl(QIODevice* device, const QByteArray& hea
raiseError(tr("Unknown cipher"));
return nullptr;
}
SymmetricCipherStream cipherStream(&hmacStream, cipher,
SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
SymmetricCipherStream cipherStream(
&hmacStream, cipher, SymmetricCipher::algorithmMode(cipher), SymmetricCipher::Decrypt);
if (!cipherStream.init(finalKey, m_encryptionIV)) {
raiseError(cipherStream.errorString());
return nullptr;
@ -304,8 +304,8 @@ bool Kdbx4Reader::readInnerHeaderField(QIODevice* device)
QVariantMap Kdbx4Reader::readVariantMap(QIODevice* device)
{
bool ok;
quint16 version = Endian::readSizedInt<quint16>(device, KeePass2::BYTEORDER, &ok)
& KeePass2::VARIANTMAP_CRITICAL_MASK;
quint16 version =
Endian::readSizedInt<quint16>(device, KeePass2::BYTEORDER, &ok) & KeePass2::VARIANTMAP_CRITICAL_MASK;
quint16 maxVersion = KeePass2::VARIANTMAP_VERSION & KeePass2::VARIANTMAP_CRITICAL_MASK;
if (!ok || (version > maxVersion)) {
//: Translation: variant map = data structure for storing meta data

View file

@ -27,11 +27,13 @@
*/
class Kdbx4Reader : public KdbxReader
{
Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader)
Q_DECLARE_TR_FUNCTIONS(Kdbx4Reader)
public:
Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
const CompositeKey& key, bool keepDatabase) override;
Database* readDatabaseImpl(QIODevice* device,
const QByteArray& headerData,
const CompositeKey& key,
bool keepDatabase) override;
QHash<QByteArray, QString> binaryPoolInverse() const;
QHash<QString, QByteArray> binaryPool() const;

View file

@ -20,14 +20,14 @@
#include <QBuffer>
#include <QFile>
#include "streams/HmacBlockStream.h"
#include "core/CustomData.h"
#include "core/Database.h"
#include "core/Metadata.h"
#include "core/CustomData.h"
#include "crypto/CryptoHash.h"
#include "crypto/Random.h"
#include "format/KeePass2RandomStream.h"
#include "format/KdbxXmlWriter.h"
#include "format/KeePass2RandomStream.h"
#include "streams/HmacBlockStream.h"
#include "streams/QtIOCompressor"
#include "streams/SymmetricCipherStream.h"
@ -73,10 +73,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
writeMagicNumbers(&header, KeePass2::SIGNATURE_1, KeePass2::SIGNATURE_2, KeePass2::FILE_VERSION_4);
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgo()),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(
writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::CipherID, db->cipher().toByteArray()));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(
&header,
KeePass2::HeaderFieldID::CompressionFlags,
Endian::sizedIntToBytes(static_cast<int>(db->compressionAlgo()), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::MasterSeed, masterSeed));
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EncryptionIV, encryptionIV));
@ -94,8 +96,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
if (!publicCustomData.isEmpty()) {
QByteArray serialized;
serializeVariantMap(publicCustomData, serialized);
CHECK_RETURN_FALSE(writeHeaderField<quint32>(
&header, KeePass2::HeaderFieldID::PublicCustomData, serialized));
CHECK_RETURN_FALSE(
writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::PublicCustomData, serialized));
}
CHECK_RETURN_FALSE(writeHeaderField<quint32>(&header, KeePass2::HeaderFieldID::EndOfHeader, endOfHeader));
@ -109,8 +111,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
// write HMAC-authenticated cipher stream
QByteArray hmacKey = KeePass2::hmacKey(masterSeed, db->transformedMasterKey());
QByteArray headerHmac = CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey),
CryptoHash::Sha256);
QByteArray headerHmac =
CryptoHash::hmac(headerData, HmacBlockStream::getHmacKey(UINT64_MAX, hmacKey), CryptoHash::Sha256);
CHECK_RETURN_FALSE(writeData(device, headerHash));
CHECK_RETURN_FALSE(writeData(device, headerHmac));
@ -123,9 +125,8 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
return false;
}
cipherStream.reset(new SymmetricCipherStream(hmacBlockStream.data(), algo,
SymmetricCipher::algorithmMode(algo),
SymmetricCipher::Encrypt));
cipherStream.reset(new SymmetricCipherStream(
hmacBlockStream.data(), algo, SymmetricCipher::algorithmMode(algo), SymmetricCipher::Encrypt));
if (!cipherStream->init(finalKey, encryptionIV)) {
raiseError(cipherStream->errorString());
@ -153,11 +154,12 @@ bool Kdbx4Writer::writeDatabase(QIODevice* device, Database* db)
Q_ASSERT(outputDevice);
CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamID,
Endian::sizedIntToBytes(static_cast<int>(KeePass2::ProtectedStreamAlgo::ChaCha20),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey,
protectedStreamKey));
CHECK_RETURN_FALSE(writeInnerHeaderField(
outputDevice,
KeePass2::InnerHeaderFieldID::InnerRandomStreamID,
Endian::sizedIntToBytes(static_cast<int>(KeePass2::ProtectedStreamAlgo::ChaCha20), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(
writeInnerHeaderField(outputDevice, KeePass2::InnerHeaderFieldID::InnerRandomStreamKey, protectedStreamKey));
// Write attachments to the inner header
writeAttachments(outputDevice, db);
@ -208,7 +210,8 @@ bool Kdbx4Writer::writeInnerHeaderField(QIODevice* device, KeePass2::InnerHeader
QByteArray fieldIdArr;
fieldIdArr[0] = static_cast<char>(fieldId);
CHECK_RETURN_FALSE(writeData(device, fieldIdArr));
CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes(static_cast<quint32>(data.size()), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(
writeData(device, Endian::sizedIntToBytes(static_cast<quint32>(data.size()), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeData(device, data));
return true;

View file

@ -25,7 +25,7 @@
*/
class Kdbx4Writer : public KdbxWriter
{
Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer)
Q_DECLARE_TR_FUNCTIONS(Kdbx4Writer)
public:
bool writeDatabase(QIODevice* device, Database* db) override;

View file

@ -249,8 +249,8 @@ void KdbxReader::setInnerRandomStreamID(const QByteArray& data)
}
auto id = Endian::bytesToSizedInt<quint32>(data, KeePass2::BYTEORDER);
KeePass2::ProtectedStreamAlgo irsAlgo = KeePass2::idToProtectedStreamAlgo(id);
if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo ||
irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) {
if (irsAlgo == KeePass2::ProtectedStreamAlgo::InvalidProtectedStreamAlgo
|| irsAlgo == KeePass2::ProtectedStreamAlgo::ArcFourVariant) {
raiseError(tr("Invalid inner random stream cipher"));
return;
}

View file

@ -33,7 +33,7 @@ class QIODevice;
*/
class KdbxReader
{
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
public:
KdbxReader() = default;
@ -61,8 +61,8 @@ protected:
* @param keepDatabase keep database in case of read failure
* @return pointer to the read database, nullptr on failure
*/
virtual Database* readDatabaseImpl(QIODevice* device, const QByteArray& headerData,
const CompositeKey& key, bool keepDatabase) = 0;
virtual Database*
readDatabaseImpl(QIODevice* device, const QByteArray& headerData, const CompositeKey& key, bool keepDatabase) = 0;
/**
* Read next header field from stream.
@ -103,5 +103,4 @@ private:
QString m_errorStr = "";
};
#endif //KEEPASSXC_KDBXREADER_H
#endif // KEEPASSXC_KDBXREADER_H

View file

@ -35,7 +35,7 @@ class Database;
*/
class KdbxWriter
{
Q_DECLARE_TR_FUNCTIONS(KdbxWriter)
Q_DECLARE_TR_FUNCTIONS(KdbxWriter)
public:
KdbxWriter() = default;
@ -56,7 +56,6 @@ public:
QString errorString() const;
protected:
/**
* Helper method for writing a KDBX header field to a device.
*
@ -74,8 +73,8 @@ protected:
QByteArray fieldIdArr;
fieldIdArr[0] = static_cast<char>(fieldId);
CHECK_RETURN_FALSE(writeData(device, fieldIdArr));
CHECK_RETURN_FALSE(writeData(device, Endian::sizedIntToBytes<SizedQInt>(static_cast<SizedQInt>(data.size()),
KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeData(
device, Endian::sizedIntToBytes<SizedQInt>(static_cast<SizedQInt>(data.size()), KeePass2::BYTEORDER)));
CHECK_RETURN_FALSE(writeData(device, data));
return true;
@ -88,5 +87,4 @@ protected:
QString m_errorStr = "";
};
#endif //KEEPASSXC_KDBXWRITER_H
#endif // KEEPASSXC_KDBXWRITER_H

View file

@ -17,16 +17,16 @@
#include "KdbxXmlReader.h"
#include "KeePass2RandomStream.h"
#include "core/Global.h"
#include "core/Tools.h"
#include "core/Entry.h"
#include "core/Group.h"
#include "core/DatabaseIcons.h"
#include "core/Endian.h"
#include "core/Entry.h"
#include "core/Global.h"
#include "core/Group.h"
#include "core/Tools.h"
#include "streams/QtIOCompressor"
#include <QFile>
#include <QBuffer>
#include <QFile>
/**
* @param version KDBX version
@ -114,13 +114,11 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random
}
if (!m_tmpParent->children().isEmpty()) {
qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)",
m_tmpParent->children().size());
qWarning("KdbxXmlReader::readDatabase: found %d invalid group reference(s)", m_tmpParent->children().size());
}
if (!m_tmpParent->entries().isEmpty()) {
qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)",
m_tmpParent->children().size());
qWarning("KdbxXmlReader::readDatabase: found %d invalid entry reference(s)", m_tmpParent->children().size());
}
const QSet<QString> poolKeys = m_binaryPool.keys().toSet();
@ -136,7 +134,7 @@ void KdbxXmlReader::readDatabase(QIODevice* device, Database* db, KeePass2Random
qWarning("KdbxXmlReader::readDatabase: found unused key \"%s\"", qPrintable(key));
}
QHash<QString, QPair<Entry*, QString> >::const_iterator i;
QHash<QString, QPair<Entry*, QString>>::const_iterator i;
for (i = m_binaryMap.constBegin(); i != m_binaryMap.constEnd(); ++i) {
const QPair<Entry*, QString>& target = i.value();
target.first->attachments()->set(target.second, m_binaryPool[i.key()]);
@ -191,8 +189,7 @@ QString KdbxXmlReader::errorString() const
bool KdbxXmlReader::isTrueValue(const QStringRef& value)
{
return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0
|| value == "1";
return value.compare(QLatin1String("true"), Qt::CaseInsensitive) == 0 || value == "1";
}
void KdbxXmlReader::raiseError(const QString& errorMessage)
@ -386,12 +383,10 @@ void KdbxXmlReader::parseBinaries()
QXmlStreamAttributes attr = m_xml.attributes();
QString id = attr.value("ID").toString();
QByteArray data = isTrueValue(attr.value("Compressed"))
? readCompressedBinary() : readBinary();
QByteArray data = isTrueValue(attr.value("Compressed")) ? readCompressedBinary() : readBinary();
if (m_binaryPool.contains(id)) {
qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"",
qPrintable(id));
qWarning("KdbxXmlReader::parseBinaries: overwriting binary item \"%s\"", qPrintable(id));
}
m_binaryPool.insert(id, data);
@ -1192,4 +1187,3 @@ void KdbxXmlReader::skipCurrentElement()
qWarning("KdbxXmlReader::skipCurrentElement: skip element \"%s\"", qPrintable(m_xml.name().toString()));
m_xml.skipCurrentElement();
}

View file

@ -18,14 +18,14 @@
#ifndef KEEPASSXC_KDBXXMLREADER_H
#define KEEPASSXC_KDBXXMLREADER_H
#include "core/Database.h"
#include "core/Metadata.h"
#include "core/TimeInfo.h"
#include "core/Uuid.h"
#include "core/Database.h"
#include <QCoreApplication>
#include <QString>
#include <QPair>
#include <QString>
#include <QXmlStreamReader>
class QIODevice;
@ -38,7 +38,7 @@ class KeePass2RandomStream;
*/
class KdbxXmlReader
{
Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader)
Q_DECLARE_TR_FUNCTIONS(KdbxXmlReader)
public:
explicit KdbxXmlReader(quint32 version);
@ -112,11 +112,11 @@ protected:
QHash<Uuid, Entry*> m_entries;
QHash<QString, QByteArray> m_binaryPool;
QHash<QString, QPair<Entry*, QString> > m_binaryMap;
QHash<QString, QPair<Entry*, QString>> m_binaryMap;
QByteArray m_headerHash;
bool m_error = false;
QString m_errorStr = "";
};
#endif //KEEPASSXC_KDBXXMLREADER_H
#endif // KEEPASSXC_KDBXXMLREADER_H

View file

@ -33,7 +33,10 @@ KdbxXmlWriter::KdbxXmlWriter(quint32 version)
{
}
void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream, const QByteArray& headerHash)
void KdbxXmlWriter::writeDatabase(QIODevice* device,
Database* db,
KeePass2RandomStream* randomStream,
const QByteArray& headerHash)
{
m_db = db;
m_meta = db->metadata();
@ -64,7 +67,7 @@ void KdbxXmlWriter::writeDatabase(QIODevice* device, Database* db, KeePass2Rando
void KdbxXmlWriter::writeDatabase(const QString& filename, Database* db)
{
QFile file(filename);
file.open(QIODevice::WriteOnly|QIODevice::Truncate);
file.open(QIODevice::WriteOnly | QIODevice::Truncate);
writeDatabase(&file, db);
}
@ -204,8 +207,7 @@ void KdbxXmlWriter::writeBinaries()
buffer.seek(0);
data = buffer.readAll();
}
else {
} else {
data = i.key();
}
@ -354,12 +356,12 @@ void KdbxXmlWriter::writeEntry(const Entry* entry)
for (const QString& key : attributesKeyList) {
m_xml.writeStartElement("String");
bool protect = ( ((key == "Title") && m_meta->protectTitle()) ||
((key == "UserName") && m_meta->protectUsername()) ||
((key == "Password") && m_meta->protectPassword()) ||
((key == "URL") && m_meta->protectUrl()) ||
((key == "Notes") && m_meta->protectNotes()) ||
entry->attributes()->isProtected(key) );
bool protect =
(((key == "Title") && m_meta->protectTitle()) || ((key == "UserName") && m_meta->protectUsername())
|| ((key == "Password") && m_meta->protectPassword())
|| ((key == "URL") && m_meta->protectUrl())
|| ((key == "Notes") && m_meta->protectNotes())
|| entry->attributes()->isProtected(key));
writeString("Key", key);
@ -375,13 +377,11 @@ void KdbxXmlWriter::writeEntry(const Entry* entry)
raiseError(m_randomStream->errorString());
}
value = QString::fromLatin1(rawData.toBase64());
}
else {
} else {
m_xml.writeAttribute("ProtectInMemory", "True");
value = entry->attributes()->value(key);
}
}
else {
} else {
value = entry->attributes()->value(key);
}
@ -462,8 +462,7 @@ void KdbxXmlWriter::writeString(const QString& qualifiedName, const QString& str
{
if (string.isEmpty()) {
m_xml.writeEmptyElement(qualifiedName);
}
else {
} else {
m_xml.writeTextElement(qualifiedName, stripInvalidXml10Chars(string));
}
}
@ -477,8 +476,7 @@ void KdbxXmlWriter::writeBool(const QString& qualifiedName, bool b)
{
if (b) {
writeString(qualifiedName, "True");
}
else {
} else {
writeString(qualifiedName, "False");
}
}
@ -513,8 +511,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Group* group)
{
if (group) {
writeUuid(qualifiedName, group->uuid());
}
else {
} else {
writeUuid(qualifiedName, Uuid());
}
}
@ -523,8 +520,7 @@ void KdbxXmlWriter::writeUuid(const QString& qualifiedName, const Entry* entry)
{
if (entry) {
writeUuid(qualifiedName, entry->uuid());
}
else {
} else {
writeUuid(qualifiedName, Uuid());
}
}
@ -539,9 +535,8 @@ void KdbxXmlWriter::writeColor(const QString& qualifiedName, const QColor& color
QString colorStr;
if (color.isValid()) {
colorStr = QString("#%1%2%3").arg(colorPartToString(color.red()),
colorPartToString(color.green()),
colorPartToString(color.blue()));
colorStr = QString("#%1%2%3").arg(
colorPartToString(color.red()), colorPartToString(color.green()), colorPartToString(color.blue()));
}
writeString(qualifiedName, colorStr);
@ -553,11 +548,9 @@ void KdbxXmlWriter::writeTriState(const QString& qualifiedName, Group::TriState
if (triState == Group::Inherit) {
value = "null";
}
else if (triState == Group::Enable) {
} else if (triState == Group::Enable) {
value = "true";
}
else {
} else {
value = "false";
}
@ -583,13 +576,12 @@ QString KdbxXmlWriter::stripInvalidXml10Chars(QString str)
if (ch.isLowSurrogate() && i != 0 && str.at(i - 1).isHighSurrogate()) {
// keep valid surrogate pair
i--;
}
else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
|| (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
|| (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
|| (uc > 0xFFFD) // noncharacter
|| ch.isLowSurrogate() // single low surrogate
|| ch.isHighSurrogate()) // single high surrogate
} else if ((uc < 0x20 && uc != 0x09 && uc != 0x0A && uc != 0x0D) // control characters
|| (uc >= 0x7F && uc <= 0x84) // control characters, valid but discouraged by XML
|| (uc >= 0x86 && uc <= 0x9F) // control characters, valid but discouraged by XML
|| (uc > 0xFFFD) // noncharacter
|| ch.isLowSurrogate() // single low surrogate
|| ch.isHighSurrogate()) // single high surrogate
{
qWarning("Stripping invalid XML 1.0 codepoint %x", uc);
str.remove(i, 1);

View file

@ -37,7 +37,9 @@ class KdbxXmlWriter
public:
explicit KdbxXmlWriter(quint32 version);
void writeDatabase(QIODevice* device, Database* db, KeePass2RandomStream* randomStream = nullptr,
void writeDatabase(QIODevice* device,
Database* db,
KeePass2RandomStream* randomStream = nullptr,
const QByteArray& headerHash = QByteArray());
void writeDatabase(const QString& filename, Database* db);
bool hasError();

View file

@ -21,7 +21,6 @@
#include <QImage>
#include <QTextCodec>
#include "crypto/kdf/AesKdf.h"
#include "core/Database.h"
#include "core/Endian.h"
#include "core/Entry.h"
@ -29,6 +28,7 @@
#include "core/Metadata.h"
#include "core/Tools.h"
#include "crypto/CryptoHash.h"
#include "crypto/kdf/AesKdf.h"
#include "format/KeePass1.h"
#include "keys/FileKey.h"
#include "keys/PasswordKey.h"
@ -47,7 +47,6 @@ private:
QByteArray m_keyfileData;
};
KeePass1Reader::KeePass1Reader()
: m_db(nullptr)
, m_tmpParent(nullptr)
@ -58,8 +57,7 @@ KeePass1Reader::KeePass1Reader()
{
}
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password,
QIODevice* keyfileDevice)
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice)
{
m_error = false;
m_errorStr.clear();
@ -112,8 +110,9 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
}
auto version = Endian::readSizedInt<quint32>(m_device, KeePass1::BYTEORDER, &ok);
if (!ok || (version & KeePass1::FILE_VERSION_CRITICAL_MASK)
!= (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) {
if (!ok
|| (version & KeePass1::FILE_VERSION_CRITICAL_MASK)
!= (KeePass1::FILE_VERSION & KeePass1::FILE_VERSION_CRITICAL_MASK)) {
raiseError(tr("Unsupported KeePass database version."));
return nullptr;
}
@ -200,8 +199,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
parseMetaStream(entry);
delete entry;
}
else {
} else {
quint32 groupId = m_entryGroupIds.value(entry);
if (!m_groupIds.contains(groupId)) {
qWarning("Orphaned entry found, assigning to root group.");
@ -251,8 +249,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
return db.take();
}
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password,
const QString& keyfileName)
Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& password, const QString& keyfileName)
{
QScopedPointer<QFile> keyFile;
if (!keyfileName.isEmpty()) {
@ -268,8 +265,7 @@ Database* KeePass1Reader::readDatabase(QIODevice* device, const QString& passwor
return db.take();
}
Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password,
const QString& keyfileName)
Database* KeePass1Reader::readDatabase(const QString& filename, const QString& password, const QString& keyfileName)
{
QFile dbFile(filename);
if (!dbFile.open(QFile::ReadOnly)) {
@ -297,10 +293,10 @@ QString KeePass1Reader::errorString()
return m_errorStr;
}
SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData,
qint64 contentPos)
SymmetricCipherStream*
KeePass1Reader::testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos)
{
const QList<PasswordEncoding> encodings = { Windows1252, Latin1, UTF8 };
const QList<PasswordEncoding> encodings = {Windows1252, Latin1, UTF8};
QScopedPointer<SymmetricCipherStream> cipherStream;
QByteArray passwordData;
@ -310,28 +306,24 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
for (PasswordEncoding encoding : encodings) {
if (encoding == Windows1252) {
passwordData = passwordDataCorrect;
}
else if (encoding == Latin1) {
} else if (encoding == Latin1) {
// KeePassX used Latin-1 encoding for passwords until version 0.3.1
// but KeePass/Win32 uses Windows Codepage 1252.
passwordData = password.toLatin1();
if (passwordData == passwordDataCorrect) {
continue;
}
else {
} else {
qWarning("Testing password encoded as Latin-1.");
}
}
else if (encoding == UTF8) {
} else if (encoding == UTF8) {
// KeePassX used UTF-8 encoding for passwords until version 0.2.2
// but KeePass/Win32 uses Windows Codepage 1252.
passwordData = password.toUtf8();
if (passwordData == passwordDataCorrect) {
continue;
}
else {
} else {
qWarning("Testing password encoded as UTF-8.");
}
}
@ -341,12 +333,11 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
return nullptr;
}
if (m_encryptionFlags & KeePass1::Rijndael) {
cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Aes256,
SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
}
else {
cipherStream.reset(new SymmetricCipherStream(m_device, SymmetricCipher::Twofish,
SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
cipherStream.reset(new SymmetricCipherStream(
m_device, SymmetricCipher::Aes256, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
} else {
cipherStream.reset(new SymmetricCipherStream(
m_device, SymmetricCipher::Twofish, SymmetricCipher::Cbc, SymmetricCipher::Decrypt));
}
if (!cipherStream->init(finalKey, m_encryptionIV)) {
@ -375,8 +366,7 @@ SymmetricCipherStream* KeePass1Reader::testKeys(const QString& password, const Q
if (success) {
break;
}
else {
} else {
cipherStream.reset();
}
}
@ -476,8 +466,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
case 0x0002:
group->setName(QString::fromUtf8(fieldData.constData()));
break;
case 0x0003:
{
case 0x0003: {
if (fieldSize != 5) {
raiseError(tr("Incorrect group creation time field size"));
return nullptr;
@ -488,8 +477,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
}
break;
}
case 0x0004:
{
case 0x0004: {
if (fieldSize != 5) {
raiseError(tr("Incorrect group modification time field size"));
return nullptr;
@ -500,8 +488,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
}
break;
}
case 0x0005:
{
case 0x0005: {
if (fieldSize != 5) {
raiseError(tr("Incorrect group access time field size"));
}
@ -511,8 +498,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
}
break;
}
case 0x0006:
{
case 0x0006: {
if (fieldSize != 5) {
raiseError(tr("Incorrect group expiry time field size"));
}
@ -523,8 +509,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
}
break;
}
case 0x0007:
{
case 0x0007: {
if (fieldSize != 4) {
raiseError(tr("Incorrect group icon field size"));
return nullptr;
@ -533,8 +518,7 @@ Group* KeePass1Reader::readGroup(QIODevice* cipherStream)
group->setIcon(iconNumber);
break;
}
case 0x0008:
{
case 0x0008: {
if (fieldSize != 2) {
raiseError(tr("Incorrect group level field size"));
return nullptr;
@ -610,8 +594,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
}
m_entryUuids.insert(fieldData, entry.data());
break;
case 0x0002:
{
case 0x0002: {
if (fieldSize != 4) {
raiseError(tr("Invalid entry group id field size"));
return nullptr;
@ -620,8 +603,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
m_entryGroupIds.insert(entry.data(), groupId);
break;
}
case 0x0003:
{
case 0x0003: {
if (fieldSize != 4) {
raiseError(tr("Invalid entry icon field size"));
return nullptr;
@ -645,8 +627,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
case 0x0008:
parseNotes(QString::fromUtf8(fieldData.constData()), entry.data());
break;
case 0x0009:
{
case 0x0009: {
if (fieldSize != 5) {
raiseError(tr("Invalid entry creation time field size"));
return nullptr;
@ -657,8 +638,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
}
break;
}
case 0x000A:
{
case 0x000A: {
if (fieldSize != 5) {
raiseError(tr("Invalid entry modification time field size"));
return nullptr;
@ -669,8 +649,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
}
break;
}
case 0x000B:
{
case 0x000B: {
if (fieldSize != 5) {
raiseError(tr("Invalid entry creation time field size"));
return nullptr;
@ -681,8 +660,7 @@ Entry* KeePass1Reader::readEntry(QIODevice* cipherStream)
}
break;
}
case 0x000C:
{
case 0x000C: {
if (fieldSize != 5) {
raiseError(tr("Invalid entry expiry time field size"));
return nullptr;
@ -734,27 +712,23 @@ void KeePass1Reader::parseNotes(const QString& rawNotes, Entry* entry)
if (sequenceRegexp.exactMatch(line)) {
if (sequenceRegexp.cap(1).isEmpty()) {
entry->setDefaultAutoTypeSequence(sequenceRegexp.cap(2));
}
else {
} else {
sequences[sequenceRegexp.cap(1).toInt()] = sequenceRegexp.cap(2);
}
lastLineAutoType = true;
}
else if (windowRegexp.exactMatch(line)) {
} else if (windowRegexp.exactMatch(line)) {
int nr;
if (windowRegexp.cap(1).isEmpty()) {
nr = -1; // special number that matches no other sequence
}
else {
} else {
nr = windowRegexp.cap(1).toInt();
}
windows[nr].append(windowRegexp.cap(2));
lastLineAutoType = true;
}
else {
} else {
// don't add empty lines following a removed auto-type line
if (!lastLineAutoType || !line.isEmpty()) {
notes.append(line);
@ -788,8 +762,7 @@ bool KeePass1Reader::constructGroupTree(const QList<Group*>& groups)
if (level == 0) {
groups[i]->setParent(m_db->rootGroup());
}
else {
} else {
for (int j = (i - 1); j >= 0; j--) {
if (m_groupLevels.value(groups[j]) < level) {
if ((level - m_groupLevels.value(groups[j])) != 1) {
@ -818,13 +791,11 @@ void KeePass1Reader::parseMetaStream(const Entry* entry)
if (!parseGroupTreeState(data)) {
qWarning("Unable to parse group tree state metastream.");
}
}
else if (entry->notes() == "KPX_CUSTOM_ICONS_4") {
} else if (entry->notes() == "KPX_CUSTOM_ICONS_4") {
if (!parseCustomIcons4(data)) {
qWarning("Unable to parse custom icons metastream.");
}
}
else {
} else {
qWarning("Ignoring unknown metastream \"%s\".", entry->notes().toLocal8Bit().constData());
}
}
@ -962,20 +933,16 @@ QDateTime KeePass1Reader::dateFromPackedStruct(const QByteArray& data)
// check for the special "never" datetime
if (dateTime == QDateTime(QDate(2999, 12, 28), QTime(23, 59, 59), Qt::UTC)) {
return QDateTime();
}
else {
} else {
return dateTime;
}
}
bool KeePass1Reader::isMetaStream(const Entry* entry)
{
return entry->attachments()->keys().contains("bin-stream")
&& !entry->notes().isEmpty()
&& entry->title() == "Meta-Info"
&& entry->username() == "SYSTEM"
&& entry->url() == "$"
&& entry->iconNumber() == 0;
return entry->attachments()->keys().contains("bin-stream") && !entry->notes().isEmpty()
&& entry->title() == "Meta-Info" && entry->username() == "SYSTEM" && entry->url() == "$"
&& entry->iconNumber() == 0;
}
QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
@ -1002,8 +969,7 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
if (Tools::isHex(data)) {
return QByteArray::fromHex(data);
}
else {
} else {
device->seek(0);
}
}
@ -1021,16 +987,13 @@ QByteArray KeePass1Reader::readKeyfile(QIODevice* device)
return cryptoHash.result();
}
QByteArray KeePass1Key::rawKey() const
{
if (m_keyfileData.isEmpty()) {
return CryptoHash::hash(m_password, CryptoHash::Sha256);
}
else if (m_password.isEmpty()) {
} else if (m_password.isEmpty()) {
return m_keyfileData;
}
else {
} else {
CryptoHash keyHash(CryptoHash::Sha256);
keyHash.addData(CryptoHash::hash(m_password, CryptoHash::Sha256));
keyHash.addData(m_keyfileData);

View file

@ -34,12 +34,9 @@ class KeePass1Reader
public:
KeePass1Reader();
Database* readDatabase(QIODevice* device, const QString& password,
QIODevice* keyfileDevice);
Database* readDatabase(QIODevice* device, const QString& password,
const QString& keyfileName);
Database* readDatabase(const QString& filename, const QString& password,
const QString& keyfileName);
Database* readDatabase(QIODevice* device, const QString& password, QIODevice* keyfileDevice);
Database* readDatabase(QIODevice* device, const QString& password, const QString& keyfileName);
Database* readDatabase(const QString& filename, const QString& password, const QString& keyfileName);
bool hasError();
QString errorString();
@ -51,8 +48,7 @@ private:
UTF8
};
SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData,
qint64 contentPos);
SymmetricCipherStream* testKeys(const QString& password, const QByteArray& keyfileData, qint64 contentPos);
QByteArray key(const QByteArray& password, const QByteArray& keyfileData);
bool verifyKey(SymmetricCipherStream* cipherStream);
Group* readGroup(QIODevice* cipherStream);

View file

@ -16,10 +16,10 @@
*/
#include "KeePass2.h"
#include <QSharedPointer>
#include "crypto/CryptoHash.h"
#include "crypto/kdf/AesKdf.h"
#include "crypto/kdf/Argon2Kdf.h"
#include "crypto/CryptoHash.h"
#include <QSharedPointer>
const Uuid KeePass2::CIPHER_AES = Uuid(QByteArray::fromHex("31c1f2e6bf714350be5805216afc5aff"));
const Uuid KeePass2::CIPHER_TWOFISH = Uuid(QByteArray::fromHex("ad68f29f576f4bb9a36ad47af965346c"));
@ -47,16 +47,15 @@ const QString KeePass2::KDFPARAM_ARGON2_ASSOCDATA("A");
const QList<QPair<Uuid, QString>> KeePass2::CIPHERS{
qMakePair(KeePass2::CIPHER_AES, QString(QT_TRANSLATE_NOOP("KeePass2", "AES: 256-bit"))),
qMakePair(KeePass2::CIPHER_TWOFISH, QString(QT_TRANSLATE_NOOP("KeePass2", "Twofish: 256-bit"))),
qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))
};
qMakePair(KeePass2::CIPHER_CHACHA20, QString(QT_TRANSLATE_NOOP("KeePass2", "ChaCha20: 256-bit")))};
const QList<QPair<Uuid, QString>> KeePass2::KDFS{
qMakePair(KeePass2::KDF_ARGON2, QString(QT_TRANSLATE_NOOP("KeePass2", "Argon2 (KDBX 4 recommended)"))),
qMakePair(KeePass2::KDF_AES_KDBX4, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 4)"))),
qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))
};
qMakePair(KeePass2::KDF_AES_KDBX3, QString(QT_TRANSLATE_NOOP("KeePass2", "AES-KDF (KDBX 3.1)")))};
QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey) {
QByteArray KeePass2::hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey)
{
CryptoHash hmacKeyHash(CryptoHash::Sha512);
hmacKeyHash.addData(masterSeed);
hmacKeyHash.addData(transformedMasterKey);

View file

@ -1,137 +1,137 @@
/*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 or (at your option)
* version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_KEEPASS2_H
#define KEEPASSX_KEEPASS2_H
#include <QtGlobal>
#include <QMap>
#include <QVariantMap>
#include <QList>
#include <QMap>
#include <QSharedPointer>
#include <QVariantMap>
#include <QtGlobal>
#include "core/Uuid.h"
#include "crypto/SymmetricCipher.h"
#include "crypto/kdf/Kdf.h"
#include "core/Uuid.h"
namespace KeePass2
{
constexpr quint32 SIGNATURE_1 = 0x9AA2D903;
constexpr quint32 SIGNATURE_2 = 0xB54BFB67;
constexpr quint32 SIGNATURE_1 = 0x9AA2D903;
constexpr quint32 SIGNATURE_2 = 0xB54BFB67;
constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000;
constexpr quint32 FILE_VERSION_4 = 0x00040000;
constexpr quint32 FILE_VERSION_3_1 = 0x00030001;
constexpr quint32 FILE_VERSION_3 = 0x00030000;
constexpr quint32 FILE_VERSION_2 = 0x00020000;
constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2;
constexpr quint32 FILE_VERSION_CRITICAL_MASK = 0xFFFF0000;
constexpr quint32 FILE_VERSION_4 = 0x00040000;
constexpr quint32 FILE_VERSION_3_1 = 0x00030001;
constexpr quint32 FILE_VERSION_3 = 0x00030000;
constexpr quint32 FILE_VERSION_2 = 0x00020000;
constexpr quint32 FILE_VERSION_MIN = FILE_VERSION_2;
constexpr quint16 VARIANTMAP_VERSION = 0x0100;
constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00;
constexpr quint16 VARIANTMAP_VERSION = 0x0100;
constexpr quint16 VARIANTMAP_CRITICAL_MASK = 0xFF00;
const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian;
const QSysInfo::Endian BYTEORDER = QSysInfo::LittleEndian;
extern const Uuid CIPHER_AES;
extern const Uuid CIPHER_TWOFISH;
extern const Uuid CIPHER_CHACHA20;
extern const Uuid CIPHER_AES;
extern const Uuid CIPHER_TWOFISH;
extern const Uuid CIPHER_CHACHA20;
extern const Uuid KDF_AES_KDBX3;
extern const Uuid KDF_AES_KDBX4;
extern const Uuid KDF_ARGON2;
extern const Uuid KDF_AES_KDBX3;
extern const Uuid KDF_AES_KDBX4;
extern const Uuid KDF_ARGON2;
extern const QByteArray INNER_STREAM_SALSA20_IV;
extern const QByteArray INNER_STREAM_SALSA20_IV;
extern const QString KDFPARAM_UUID;
extern const QString KDFPARAM_AES_ROUNDS;
extern const QString KDFPARAM_AES_SEED;
extern const QString KDFPARAM_ARGON2_SALT;
extern const QString KDFPARAM_ARGON2_PARALLELISM;
extern const QString KDFPARAM_ARGON2_MEMORY;
extern const QString KDFPARAM_ARGON2_ITERATIONS;
extern const QString KDFPARAM_ARGON2_VERSION;
extern const QString KDFPARAM_ARGON2_SECRET;
extern const QString KDFPARAM_ARGON2_ASSOCDATA;
extern const QString KDFPARAM_UUID;
extern const QString KDFPARAM_AES_ROUNDS;
extern const QString KDFPARAM_AES_SEED;
extern const QString KDFPARAM_ARGON2_SALT;
extern const QString KDFPARAM_ARGON2_PARALLELISM;
extern const QString KDFPARAM_ARGON2_MEMORY;
extern const QString KDFPARAM_ARGON2_ITERATIONS;
extern const QString KDFPARAM_ARGON2_VERSION;
extern const QString KDFPARAM_ARGON2_SECRET;
extern const QString KDFPARAM_ARGON2_ASSOCDATA;
extern const QList<QPair<Uuid, QString>> CIPHERS;
extern const QList<QPair<Uuid, QString>> KDFS;
extern const QList<QPair<Uuid, QString>> CIPHERS;
extern const QList<QPair<Uuid, QString>> KDFS;
enum class HeaderFieldID
{
EndOfHeader = 0,
Comment = 1,
CipherID = 2,
CompressionFlags = 3,
MasterSeed = 4,
TransformSeed = 5,
TransformRounds = 6,
EncryptionIV = 7,
ProtectedStreamKey = 8,
StreamStartBytes = 9,
InnerRandomStreamID = 10,
KdfParameters = 11,
PublicCustomData = 12
};
enum class HeaderFieldID
{
EndOfHeader = 0,
Comment = 1,
CipherID = 2,
CompressionFlags = 3,
MasterSeed = 4,
TransformSeed = 5,
TransformRounds = 6,
EncryptionIV = 7,
ProtectedStreamKey = 8,
StreamStartBytes = 9,
InnerRandomStreamID = 10,
KdfParameters = 11,
PublicCustomData = 12
};
enum class InnerHeaderFieldID : quint8
{
End = 0,
InnerRandomStreamID = 1,
InnerRandomStreamKey = 2,
Binary = 3
};
enum class InnerHeaderFieldID : quint8
{
End = 0,
InnerRandomStreamID = 1,
InnerRandomStreamKey = 2,
Binary = 3
};
enum class ProtectedStreamAlgo
{
ArcFourVariant = 1,
Salsa20 = 2,
ChaCha20 = 3,
InvalidProtectedStreamAlgo = -1
};
enum class ProtectedStreamAlgo
{
ArcFourVariant = 1,
Salsa20 = 2,
ChaCha20 = 3,
InvalidProtectedStreamAlgo = -1
};
enum class VariantMapFieldType : quint8
{
End = 0,
// Byte = 0x02,
// UInt16 = 0x03,
UInt32 = 0x04,
UInt64 = 0x05,
// Signed mask: 0x08
Bool = 0x08,
// SByte = 0x0A,
// Int16 = 0x0B,
Int32 = 0x0C,
Int64 = 0x0D,
// Float = 0x10,
// Double = 0x11,
// Decimal = 0x12,
// Char = 0x17, // 16-bit Unicode character
String = 0x18,
// Array mask: 0x40
ByteArray = 0x42
};
enum class VariantMapFieldType : quint8
{
End = 0,
// Byte = 0x02,
// UInt16 = 0x03,
UInt32 = 0x04,
UInt64 = 0x05,
// Signed mask: 0x08
Bool = 0x08,
// SByte = 0x0A,
// Int16 = 0x0B,
Int32 = 0x0C,
Int64 = 0x0D,
// Float = 0x10,
// Double = 0x11,
// Decimal = 0x12,
// Char = 0x17, // 16-bit Unicode character
String = 0x18,
// Array mask: 0x40
ByteArray = 0x42
};
QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey);
QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p);
QVariantMap kdfToParameters(QSharedPointer<Kdf> kdf);
QSharedPointer<Kdf> uuidToKdf(const Uuid& uuid);
Uuid kdfToUuid(QSharedPointer<Kdf> kdf);
ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id);
QByteArray hmacKey(QByteArray masterSeed, QByteArray transformedMasterKey);
QSharedPointer<Kdf> kdfFromParameters(const QVariantMap& p);
QVariantMap kdfToParameters(QSharedPointer<Kdf> kdf);
QSharedPointer<Kdf> uuidToKdf(const Uuid& uuid);
Uuid kdfToUuid(QSharedPointer<Kdf> kdf);
ProtectedStreamAlgo idToProtectedStreamAlgo(quint32 id);
} // namespace KeePass2
} // namespace KeePass2
#endif // KEEPASSX_KEEPASS2_H

View file

@ -30,8 +30,7 @@ bool KeePass2RandomStream::init(const QByteArray& key)
{
switch (m_cipher.algorithm()) {
case SymmetricCipher::Salsa20:
return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256),
KeePass2::INNER_STREAM_SALSA20_IV);
return m_cipher.init(CryptoHash::hash(key, CryptoHash::Sha256), KeePass2::INNER_STREAM_SALSA20_IV);
case SymmetricCipher::ChaCha20: {
QByteArray keyIv = CryptoHash::hash(key, CryptoHash::Sha512);
return m_cipher.init(keyIv.left(32), keyIv.mid(32, 12));
@ -121,7 +120,8 @@ bool KeePass2RandomStream::loadBlock()
return true;
}
SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo) {
SymmetricCipher::Algorithm KeePass2RandomStream::mapAlgo(KeePass2::ProtectedStreamAlgo algo)
{
switch (algo) {
case KeePass2::ProtectedStreamAlgo::ChaCha20:
return SymmetricCipher::ChaCha20;

View file

@ -20,8 +20,8 @@
#include <QByteArray>
#include "crypto/SymmetricCipher.h"
#include "KeePass2.h"
#include "crypto/SymmetricCipher.h"
class KeePass2RandomStream
{

View file

@ -16,9 +16,9 @@
*/
#include "format/KeePass2Reader.h"
#include "format/KeePass1.h"
#include "format/Kdbx3Reader.h"
#include "format/Kdbx4Reader.h"
#include "format/KeePass1.h"
#include <QFile>

View file

@ -18,21 +18,21 @@
#ifndef KEEPASSX_KEEPASS2READER_H
#define KEEPASSX_KEEPASS2READER_H
#include "format/KeePass2.h"
#include "core/Database.h"
#include "keys/CompositeKey.h"
#include "KdbxReader.h"
#include "core/Database.h"
#include "format/KeePass2.h"
#include "keys/CompositeKey.h"
#include <QtGlobal>
#include <QByteArray>
#include <QString>
#include <QCoreApplication>
#include <QScopedPointer>
#include <QIODevice>
#include <QScopedPointer>
#include <QString>
#include <QtGlobal>
class KeePass2Reader
{
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
Q_DECLARE_TR_FUNCTIONS(KdbxReader)
public:
Database* readDatabase(const QString& filename, const CompositeKey& key);
@ -46,6 +46,7 @@ public:
QSharedPointer<KdbxReader> reader() const;
quint32 version() const;
private:
void raiseError(const QString& errorMessage);

View file

@ -21,11 +21,11 @@
#include <QBuffer>
#include "core/Group.h"
#include "format/Kdbx4Reader.h"
#include "format/KdbxXmlReader.h"
#include "format/KeePass2.h"
#include "format/KeePass2RandomStream.h"
#include "format/KeePass2Reader.h"
#include "format/Kdbx4Reader.h"
#include "format/KdbxXmlReader.h"
KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device, const CompositeKey& key)
{
@ -51,8 +51,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device,
QRegExp encodingRegExp("encoding=\"([^\"]+)\"", Qt::CaseInsensitive, QRegExp::RegExp2);
if (encodingRegExp.indexIn(xmlStart) != -1) {
if (encodingRegExp.cap(1).compare("utf-8", Qt::CaseInsensitive) != 0
&& encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0)
{
&& encodingRegExp.cap(1).compare("utf8", Qt::CaseInsensitive) != 0) {
// database is not utf-8 encoded, we don't support repairing that
return qMakePair(RepairFailed, nullptr);
}
@ -92,8 +91,7 @@ KeePass2Repair::RepairOutcome KeePass2Repair::repairDatabase(QIODevice* device,
if (hasError) {
return qMakePair(RepairFailed, nullptr);
}
else {
} else {
return qMakePair(RepairSuccess, db.take());
}
}

View file

@ -15,16 +15,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QIODevice>
#include <QFile>
#include <QIODevice>
#include "core/Database.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "crypto/kdf/AesKdf.h"
#include "format/KeePass2Writer.h"
#include "format/Kdbx3Writer.h"
#include "format/Kdbx4Writer.h"
#include "format/KeePass2Writer.h"
/**
* Write a database to a KDBX file.
@ -52,17 +52,17 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const
return true;
}
for (const auto& group: db->rootGroup()->groupsRecursive(true)) {
for (const auto& group : db->rootGroup()->groupsRecursive(true)) {
if (group->customData() && !group->customData()->isEmpty()) {
return true;
}
for (const auto& entry: group->entries()) {
for (const auto& entry : group->entries()) {
if (entry->customData() && !entry->customData()->isEmpty()) {
return true;
}
for (const auto& historyItem: entry->historyItems()) {
for (const auto& historyItem : entry->historyItems()) {
if (historyItem->customData() && !historyItem->customData()->isEmpty()) {
return true;
}
@ -81,7 +81,8 @@ bool KeePass2Writer::implicitUpgradeNeeded(Database const* db) const
* @return true on success
*/
bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db) {
bool KeePass2Writer::writeDatabase(QIODevice* device, Database* db)
{
m_error = false;
m_errorStr.clear();

View file

@ -28,7 +28,7 @@ class Database;
class KeePass2Writer
{
Q_DECLARE_TR_FUNCTIONS(KeePass2Writer)
Q_DECLARE_TR_FUNCTIONS(KeePass2Writer)
public:
bool writeDatabase(const QString& filename, Database* db);