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:
Diffstat (limited to 'src/crypto')
-rw-r--r--src/crypto/kdf/AesKdf.cpp63
-rw-r--r--src/crypto/kdf/AesKdf.h12
-rw-r--r--src/crypto/kdf/Argon2Kdf.cpp116
-rw-r--r--src/crypto/kdf/Argon2Kdf.h50
-rw-r--r--src/crypto/kdf/Kdf.cpp39
-rw-r--r--src/crypto/kdf/Kdf.h17
6 files changed, 229 insertions, 68 deletions
diff --git a/src/crypto/kdf/AesKdf.cpp b/src/crypto/kdf/AesKdf.cpp
index 7056698d7..3177506fc 100644
--- a/src/crypto/kdf/AesKdf.cpp
+++ b/src/crypto/kdf/AesKdf.cpp
@@ -15,12 +15,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "AesKdf.h"
+
#include <QtConcurrent>
#include "format/KeePass2.h"
#include "crypto/CryptoHash.h"
-#include "crypto/Random.h"
-#include "AesKdf.h"
+
+AesKdf::AesKdf()
+ : Kdf::Kdf(KeePass2::KDF_AES)
+{
+}
bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const
{
@@ -44,7 +49,7 @@ bool AesKdf::transform(const QByteArray& raw, QByteArray& result) const
return true;
}
-bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quint64 rounds, QByteArray* result)
+bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds, QByteArray* result)
{
QByteArray iv(16, 0);
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb,
@@ -65,44 +70,6 @@ bool AesKdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, quin
return true;
}
-AesKdf::AesKdf()
- : Kdf::Kdf(KeePass2::KDF_AES)
- , m_rounds(100000ull)
- , m_seed(QByteArray(32, 0))
-{
-}
-
-quint64 AesKdf::rounds() const
-{
- return m_rounds;
-}
-
-QByteArray AesKdf::seed() const
-{
- return m_seed;
-}
-
-bool AesKdf::setRounds(quint64 rounds)
-{
- m_rounds = rounds;
- return true;
-}
-
-bool AesKdf::setSeed(const QByteArray& seed)
-{
- if (seed.size() != 32) {
- return false;
- }
-
- m_seed = seed;
- return true;
-}
-
-void AesKdf::randomizeTransformSalt()
-{
- setSeed(randomGen()->randomArray(32));
-}
-
QSharedPointer<Kdf> AesKdf::clone() const
{
return QSharedPointer<AesKdf>::create(*this);
@@ -117,17 +84,13 @@ int AesKdf::benchmarkImpl(int msec) const
SymmetricCipher cipher(SymmetricCipher::Aes256, SymmetricCipher::Ecb, SymmetricCipher::Encrypt);
cipher.init(seed, iv);
- int rounds = 0;
+ quint64 rounds = 1000000;
QElapsedTimer timer;
timer.start();
- do {
- if (!cipher.processInPlace(key, 10000)) {
- rounds = -1;
- break;
- }
- rounds += 10000;
+
+ if (!cipher.processInPlace(key, rounds)) {
+ return -1;
}
- while (!timer.hasExpired(msec));
- return rounds;
+ return static_cast<int>(rounds * (static_cast<float>(msec) / timer.elapsed()));
}
diff --git a/src/crypto/kdf/AesKdf.h b/src/crypto/kdf/AesKdf.h
index 28206a8d6..3e2c8ada6 100644
--- a/src/crypto/kdf/AesKdf.h
+++ b/src/crypto/kdf/AesKdf.h
@@ -26,25 +26,15 @@ public:
AesKdf();
bool transform(const QByteArray& raw, QByteArray& result) const override;
- void randomizeTransformSalt() override;
QSharedPointer<Kdf> clone() const override;
- quint64 rounds() const override;
- QByteArray seed() const override;
-
- bool setRounds(quint64 rounds) override;
- bool setSeed(const QByteArray& seed) override;
-
protected:
int benchmarkImpl(int msec) const override;
private:
- quint64 m_rounds;
- QByteArray m_seed;
-
static bool transformKeyRaw(const QByteArray& key,
const QByteArray& seed,
- quint64 rounds,
+ int rounds,
QByteArray* result) Q_REQUIRED_RESULT;
};
diff --git a/src/crypto/kdf/Argon2Kdf.cpp b/src/crypto/kdf/Argon2Kdf.cpp
new file mode 100644
index 000000000..fa410dc93
--- /dev/null
+++ b/src/crypto/kdf/Argon2Kdf.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2017 KeePassXC Team
+ *
+ * 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/>.
+ */
+
+#include "Argon2Kdf.h"
+
+#include <QtConcurrent>
+#include <argon2.h>
+
+#include "format/KeePass2.h"
+#include "crypto/CryptoHash.h"
+
+/**
+ * KeePass' Argon2 implementation supports all parameters that are defined in the official specification,
+ * but only the number of iterations, the memory size and the degree of parallelism can be configured by
+ * the user in the database settings dialog. For the other parameters, KeePass chooses reasonable defaults:
+ * a 256-bit salt is generated each time the database is saved, the tag length is 256 bits, no secret key
+ * or associated data. KeePass uses the latest version of Argon2, v1.3.
+ */
+Argon2Kdf::Argon2Kdf()
+ : Kdf::Kdf(KeePass2::KDF_ARGON2)
+ , m_memory(1<<16)
+ , m_parallelism(2)
+{
+ m_rounds = 1;
+}
+
+quint32 Argon2Kdf::memory() const
+{
+ // Convert to Megabytes
+ return m_memory / (1<<10);
+}
+
+bool Argon2Kdf::setMemory(quint32 memoryMegabytes)
+{
+ // TODO: add bounds check
+ // Convert to Kibibytes
+ m_memory = (1<<10) * memoryMegabytes;
+ return true;
+}
+
+quint32 Argon2Kdf::parallelism() const
+{
+ return m_parallelism;
+}
+
+bool Argon2Kdf::setParallelism(quint32 threads)
+{
+ // TODO: add bounds check
+ m_parallelism = threads;
+ return true;
+}
+
+bool Argon2Kdf::transform(const QByteArray& raw, QByteArray& result) const
+{
+ result.clear();
+ result.resize(32);
+
+ if (!transformKeyRaw(raw, seed(), rounds(), memory(), parallelism(), result)) {
+ return false;
+ }
+
+ result = CryptoHash::hash(result, CryptoHash::Sha256);
+ return true;
+}
+
+bool Argon2Kdf::transformKeyRaw(const QByteArray& key, const QByteArray& seed, int rounds,
+ quint32 memory, quint32 parallelism, QByteArray& result)
+{
+ // Time Cost, Mem Cost, Threads/Lanes, Password, length, Salt, length, out, length
+ int rc = argon2d_hash_raw(rounds, memory, parallelism, key.data(), key.size(),
+ seed.data(), seed.size(), result.data(), result.size());
+ if (rc != ARGON2_OK) {
+ qWarning("Argon2 error: %s", argon2_error_message(rc));
+ return false;
+ }
+
+ return true;
+}
+
+QSharedPointer<Kdf> Argon2Kdf::clone() const
+{
+ return QSharedPointer<Argon2Kdf>::create(*this);
+}
+
+int Argon2Kdf::benchmarkImpl(int msec) const
+{
+ QByteArray key = QByteArray(16, '\x7E');
+ QByteArray seed = QByteArray(32, '\x4B');
+
+ QElapsedTimer timer;
+ timer.start();
+
+ int rounds = 4;
+
+ int rc = argon2d_hash_raw(rounds, m_memory, m_parallelism, key.data(), key.size(), seed.data(), seed.size(), key.data(), key.size());
+ if (rc != ARGON2_OK) {
+ qWarning("Argon2 error: %s", argon2_error_message(rc));
+ return -1;
+ }
+
+ return static_cast<int>(rounds * (static_cast<float>(msec) / timer.elapsed()));
+} \ No newline at end of file
diff --git a/src/crypto/kdf/Argon2Kdf.h b/src/crypto/kdf/Argon2Kdf.h
new file mode 100644
index 000000000..c01698120
--- /dev/null
+++ b/src/crypto/kdf/Argon2Kdf.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 KeePassXC Team
+ *
+ * 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_ARGON2KDF_H
+#define KEEPASSX_ARGON2KDF_H
+
+#include "Kdf.h"
+
+class Argon2Kdf : public Kdf {
+public:
+ Argon2Kdf();
+
+ bool transform(const QByteArray& raw, QByteArray& result) const override;
+ QSharedPointer<Kdf> clone() const override;
+
+ quint32 memory() const;
+ bool setMemory(quint32 memory_kb);
+ quint32 parallelism() const;
+ bool setParallelism(quint32 threads);
+
+protected:
+ int benchmarkImpl(int msec) const override;
+
+ quint32 m_memory;
+ quint32 m_parallelism;
+
+private:
+ static bool transformKeyRaw(const QByteArray& key,
+ const QByteArray& seed,
+ int rounds,
+ quint32 memory,
+ quint32 parallelism,
+ QByteArray& result) Q_REQUIRED_RESULT;
+};
+
+#endif // KEEPASSX_ARGON2KDF_H
diff --git a/src/crypto/kdf/Kdf.cpp b/src/crypto/kdf/Kdf.cpp
index cfc3025c1..5134adc5f 100644
--- a/src/crypto/kdf/Kdf.cpp
+++ b/src/crypto/kdf/Kdf.cpp
@@ -20,8 +20,12 @@
#include <QtConcurrent>
+#include "crypto/Random.h"
+
Kdf::Kdf(Uuid uuid)
- : m_uuid(uuid)
+ : m_rounds(KDF_DEFAULT_ROUNDS)
+ , m_seed(QByteArray(KDF_DEFAULT_SEED_SIZE, 0))
+ , m_uuid(uuid)
{
}
@@ -30,6 +34,37 @@ Uuid Kdf::uuid() const
return m_uuid;
}
+int Kdf::rounds() const
+{
+ return m_rounds;
+}
+
+QByteArray Kdf::seed() const
+{
+ return m_seed;
+}
+
+bool Kdf::setRounds(int rounds)
+{
+ m_rounds = rounds;
+ return true;
+}
+
+bool Kdf::setSeed(const QByteArray& seed)
+{
+ if (seed.size() != m_seed.size()) {
+ return false;
+ }
+
+ m_seed = seed;
+ return true;
+}
+
+void Kdf::randomizeSeed()
+{
+ setSeed(randomGen()->randomArray(m_seed.size()));
+}
+
int Kdf::benchmark(int msec) const
{
BenchmarkThread thread1(msec, this);
@@ -41,7 +76,7 @@ int Kdf::benchmark(int msec) const
thread1.wait();
thread2.wait();
- return qMin(thread1.rounds(), thread2.rounds());
+ return qMax(1, qMin(thread1.rounds(), thread2.rounds()));
}
Kdf::BenchmarkThread::BenchmarkThread(int msec, const Kdf* kdf)
diff --git a/src/crypto/kdf/Kdf.h b/src/crypto/kdf/Kdf.h
index 5330e71d0..cb0bcc364 100644
--- a/src/crypto/kdf/Kdf.h
+++ b/src/crypto/kdf/Kdf.h
@@ -22,6 +22,9 @@
#include "core/Uuid.h"
+#define KDF_DEFAULT_SEED_SIZE 32
+#define KDF_DEFAULT_ROUNDS 100000ull
+
class Kdf
{
public:
@@ -30,12 +33,13 @@ public:
Uuid uuid() const;
- virtual quint64 rounds() const = 0;
- virtual bool setRounds(quint64 rounds) = 0;
- virtual QByteArray seed() const = 0;
- virtual bool setSeed(const QByteArray& seed) = 0;
+ int rounds() const;
+ virtual bool setRounds(int rounds);
+ QByteArray seed() const;
+ virtual bool setSeed(const QByteArray& seed);
+ virtual void randomizeSeed();
+
virtual bool transform(const QByteArray& raw, QByteArray& result) const = 0;
- virtual void randomizeTransformSalt() = 0;
virtual QSharedPointer<Kdf> clone() const = 0;
int benchmark(int msec) const;
@@ -43,6 +47,9 @@ public:
protected:
virtual int benchmarkImpl(int msec) const = 0;
+ int m_rounds;
+ QByteArray m_seed;
+
private:
class BenchmarkThread;
const Uuid m_uuid;