Skip to content

Commit 5871455

Browse files
ranisaltpanvajasnell
authored andcommitted
crypto: add argon2() and argon2Sync() methods
Co-authored-by: Filip Skokan <panva.ip@gmail.com> Co-authored-by: James M Snell <jasnell@gmail.com> PR-URL: nodejs/node#50353 Reviewed-By: Ethan Arrowood <ethan@arrowood.dev> Reviewed-By: Filip Skokan <panva.ip@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 7bd0798 commit 5871455

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

include/ncrypto.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,23 @@ DataPointer pbkdf2(const EVP_MD* md,
14821482
uint32_t iterations,
14831483
size_t length);
14841484

1485+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
1486+
#ifndef OPENSSL_NO_ARGON2
1487+
enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID };
1488+
1489+
DataPointer argon2(const Buffer<const char>& pass,
1490+
const Buffer<const unsigned char>& salt,
1491+
uint32_t lanes,
1492+
size_t length,
1493+
uint32_t memcost,
1494+
uint32_t iter,
1495+
uint32_t version,
1496+
const Buffer<const unsigned char>& secret,
1497+
const Buffer<const unsigned char>& ad,
1498+
Argon2Type type);
1499+
#endif
1500+
#endif
1501+
14851502
// ============================================================================
14861503
// Version metadata
14871504
#define NCRYPTO_VERSION "0.0.1"

src/ncrypto.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
#include <algorithm>
2020
#include <cstring>
2121
#if OPENSSL_VERSION_MAJOR >= 3
22+
#include <openssl/core_names.h>
23+
#include <openssl/params.h>
2224
#include <openssl/provider.h>
25+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
26+
#include <openssl/thread.h>
27+
#endif
2328
#endif
2429
#if OPENSSL_WITH_PQC
2530
struct PQCMapping {
@@ -1954,6 +1959,102 @@ DataPointer pbkdf2(const EVP_MD* md,
19541959
return {};
19551960
}
19561961

1962+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
1963+
#ifndef OPENSSL_NO_ARGON2
1964+
DataPointer argon2(const Buffer<const char>& pass,
1965+
const Buffer<const unsigned char>& salt,
1966+
uint32_t lanes,
1967+
size_t length,
1968+
uint32_t memcost,
1969+
uint32_t iter,
1970+
uint32_t version,
1971+
const Buffer<const unsigned char>& secret,
1972+
const Buffer<const unsigned char>& ad,
1973+
Argon2Type type) {
1974+
ClearErrorOnReturn clearErrorOnReturn;
1975+
1976+
std::string_view algorithm;
1977+
switch (type) {
1978+
case Argon2Type::ARGON2I:
1979+
algorithm = "ARGON2I";
1980+
break;
1981+
case Argon2Type::ARGON2D:
1982+
algorithm = "ARGON2D";
1983+
break;
1984+
case Argon2Type::ARGON2ID:
1985+
algorithm = "ARGON2ID";
1986+
break;
1987+
default:
1988+
// Invalid Argon2 type
1989+
return {};
1990+
}
1991+
1992+
// creates a new library context to avoid locking when running concurrently
1993+
auto ctx = DeleteFnPtr<OSSL_LIB_CTX, OSSL_LIB_CTX_free>{OSSL_LIB_CTX_new()};
1994+
if (!ctx) {
1995+
return {};
1996+
}
1997+
1998+
// required if threads > 1
1999+
if (lanes > 1 && OSSL_set_max_threads(ctx.get(), lanes) != 1) {
2000+
return {};
2001+
}
2002+
2003+
auto kdf = DeleteFnPtr<EVP_KDF, EVP_KDF_free>{
2004+
EVP_KDF_fetch(ctx.get(), algorithm.data(), nullptr)};
2005+
if (!kdf) {
2006+
return {};
2007+
}
2008+
2009+
auto kctx =
2010+
DeleteFnPtr<EVP_KDF_CTX, EVP_KDF_CTX_free>{EVP_KDF_CTX_new(kdf.get())};
2011+
if (!kctx) {
2012+
return {};
2013+
}
2014+
2015+
std::vector<OSSL_PARAM> params;
2016+
params.reserve(9);
2017+
2018+
params.push_back(OSSL_PARAM_construct_octet_string(
2019+
OSSL_KDF_PARAM_PASSWORD,
2020+
const_cast<char*>(pass.len > 0 ? pass.data : ""),
2021+
pass.len));
2022+
params.push_back(OSSL_PARAM_construct_octet_string(
2023+
OSSL_KDF_PARAM_SALT, const_cast<unsigned char*>(salt.data), salt.len));
2024+
params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_THREADS, &lanes));
2025+
params.push_back(
2026+
OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &lanes));
2027+
params.push_back(
2028+
OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memcost));
2029+
params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ITER, &iter));
2030+
2031+
if (ad.len != 0) {
2032+
params.push_back(OSSL_PARAM_construct_octet_string(
2033+
OSSL_KDF_PARAM_ARGON2_AD, const_cast<unsigned char*>(ad.data), ad.len));
2034+
}
2035+
2036+
if (secret.len != 0) {
2037+
params.push_back(OSSL_PARAM_construct_octet_string(
2038+
OSSL_KDF_PARAM_SECRET,
2039+
const_cast<unsigned char*>(secret.data),
2040+
secret.len));
2041+
}
2042+
2043+
params.push_back(OSSL_PARAM_construct_end());
2044+
2045+
auto dp = DataPointer::Alloc(length);
2046+
if (dp && EVP_KDF_derive(kctx.get(),
2047+
reinterpret_cast<unsigned char*>(dp.get()),
2048+
length,
2049+
params.data()) == 1) {
2050+
return dp;
2051+
}
2052+
2053+
return {};
2054+
}
2055+
#endif
2056+
#endif
2057+
19572058
// ============================================================================
19582059

19592060
EVPKeyPointer::PrivateKeyEncodingConfig::PrivateKeyEncodingConfig(

0 commit comments

Comments
 (0)