Skip to content

Commit

Permalink
Revert back to Argon2 reference library
Browse files Browse the repository at this point in the history
* Fix keepassxreboot#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
  • Loading branch information
droidmonkey committed Mar 6, 2022
1 parent 93624c3 commit e5a2958
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 20 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,10 @@ if(BOTAN2_VERSION VERSION_LESS "2.11.0")
message(FATAL_ERROR "Botan2 2.11.0 or higher is required")
endif()
include_directories(SYSTEM ${BOTAN2_INCLUDE_DIR})
# Find Argon2 -- Botan 2.18 and below does not support threaded Argon2
find_library(ARGON2_LIBRARIES NAMES argon2)
find_path(ARGON2_INCLUDE_DIR NAMES argon2.h PATH_SUFFIXES local/include)
include_directories(SYSTEM ${ARGON2_INCLUDE_DIR})

# Find zlib
find_package(ZLIB REQUIRED)
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ target_link_libraries(keepassx_core
${PCSC_LIBRARIES}
${ZXCVBN_LIBRARIES}
${ZLIB_LIBRARIES}
${ARGON2_LIBRARIES}
${thirdparty_LIBRARIES}
)

Expand Down
51 changes: 31 additions & 20 deletions src/crypto/kdf/Argon2Kdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@

#include "Argon2Kdf.h"

#include <QElapsedTimer>
#include <QThread>
#include <botan/pwdhash.h>

#include <argon2.h>

#include "format/KeePass2.h"

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/gui/dbsettings/DatabaseSettingsWidgetEncryption.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
}
Expand Down
37 changes: 37 additions & 0 deletions utils/vcpkg_ports/argon2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.8)
project(argon2 C)

set(PROJECT_VERSION 20190702)

if(MSVC)
add_compile_options(/W3)
endif()

include_directories(include src)

set(SRC
src/argon2.c
src/core.c
src/encoding.c
src/ref.c
src/thread.c
src/opt.c
src/blake2/blake2b.c
)

set(HEADERS
include/argon2.h
)

add_library(argon2 ${SRC})

install(
TARGETS argon2
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)

if(NOT DISABLE_INSTALL_HEADERS)
install(FILES ${HEADERS} DESTINATION include)
endif()
25 changes: 25 additions & 0 deletions utils/vcpkg_ports/argon2/portfile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
vcpkg_check_linkage(ONLY_STATIC_LIBRARY)

vcpkg_from_github(
OUT_SOURCE_PATH SOURCE_PATH
REPO P-H-C/phc-winner-argon2
REF 20190702
SHA512 0a4cb89e8e63399f7df069e2862ccd05308b7652bf4ab74372842f66bcc60776399e0eaf979a7b7e31436b5e6913fe5b0a6949549d8c82ebd06e0629b106e85f
HEAD_REF master
)

configure_file(${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt ${SOURCE_PATH}/CMakeLists.txt COPYONLY)

vcpkg_configure_cmake(
SOURCE_PATH ${SOURCE_PATH}
PREFER_NINJA
OPTIONS
${FEATURE_OPTIONS}
OPTIONS_DEBUG
-DDISABLE_INSTALL_HEADERS=ON
)

vcpkg_install_cmake()
vcpkg_copy_pdbs()

file(INSTALL ${SOURCE_PATH}/LICENSE DESTINATION ${CURRENT_PACKAGES_DIR}/share/${PORT} RENAME copyright)
7 changes: 7 additions & 0 deletions utils/vcpkg_ports/argon2/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "argon2",
"version-string": "20190702",
"port-version": 1,
"description": "Reference C implementation of Argon2, the password-hashing function that won the Password Hashing Competition (PHC).",
"homepage": "https://github.com/P-H-C/phc-winner-argon2"
}

0 comments on commit e5a2958

Please sign in to comment.