Revert back to Argon2 reference library

* Fix #7487 - Botan does not use threads when calculating Argon2 KDF leading to very poor performance for a parallelism value > 1.
* Include port file for vcpkg backed builds
This commit is contained in:
Jonathan White
2022-03-05 10:45:57 -05:00
parent 93624c3700
commit e5a2958458
7 changed files with 107 additions and 20 deletions

View File

@@ -336,6 +336,7 @@ target_link_libraries(keepassx_core
${PCSC_LIBRARIES}
${ZXCVBN_LIBRARIES}
${ZLIB_LIBRARIES}
${ARGON2_LIBRARIES}
${thirdparty_LIBRARIES}
)

View File

@@ -17,8 +17,10 @@
#include "Argon2Kdf.h"
#include <QElapsedTimer>
#include <QThread>
#include <botan/pwdhash.h>
#include <argon2.h>
#include "format/KeePass2.h"
@@ -163,20 +165,27 @@ bool Argon2Kdf::transform(const QByteArray& raw, QByteArray& result) const
{
result.clear();
result.resize(32);
try {
auto algo = type() == Type::Argon2d ? "Argon2d" : "Argon2id";
auto pwhash = Botan::PasswordHashFamily::create_or_throw(algo)->from_params(memory(), rounds(), parallelism());
pwhash->derive_key(reinterpret_cast<uint8_t*>(result.data()),
result.size(),
raw.constData(),
raw.size(),
reinterpret_cast<const uint8_t*>(seed().constData()),
seed().size());
return true;
} catch (std::exception& e) {
qWarning("Argon2 error: %s", e.what());
// Time Cost, Mem Cost, Threads/Lanes, Password, length, Salt, length, out, length
int rc = argon2_hash(rounds(),
memory(),
parallelism(),
raw.data(),
raw.size(),
seed().data(),
seed().size(),
result.data(),
result.size(),
nullptr,
0,
type() == Type::Argon2d ? Argon2_d : Argon2_id,
version());
if (rc != ARGON2_OK) {
qWarning("Argon2 error: %s", argon2_error_message(rc));
return false;
}
return true;
}
QSharedPointer<Kdf> Argon2Kdf::clone() const
@@ -186,14 +195,16 @@ QSharedPointer<Kdf> Argon2Kdf::clone() const
int Argon2Kdf::benchmark(int msec) const
{
try {
auto algo = type() == Type::Argon2d ? "Argon2d" : "Argon2id";
auto pwhash = Botan::PasswordHashFamily::create_or_throw(algo)->tune(
32, std::chrono::milliseconds(msec), memory() / 1024);
return qMax(static_cast<size_t>(1), pwhash->iterations());
} catch (std::exception& e) {
return 1;
QByteArray key = QByteArray(16, '\x7E');
QElapsedTimer timer;
timer.start();
if (transform(key, key)) {
return static_cast<int>(rounds() * (static_cast<float>(msec) / timer.elapsed()));
}
return 1;
}
QString Argon2Kdf::toString() const

View File

@@ -325,6 +325,8 @@ void DatabaseSettingsWidgetEncryption::benchmarkTransformRounds(int millisecs)
kdf->setRounds(m_ui->transformRoundsSpinBox->value());
if (IS_ARGON2(kdf->uuid())) {
auto argon2Kdf = kdf.staticCast<Argon2Kdf>();
// Set a small static number of rounds for the benchmark
argon2Kdf->setRounds(4);
if (!argon2Kdf->setMemory(static_cast<quint64>(m_ui->memorySpinBox->value()) * (1 << 10))) {
m_ui->memorySpinBox->setValue(static_cast<int>(argon2Kdf->memory() / (1 << 10)));
}