Skip to content

Commit bcfc7dd

Browse files
ranisaltpanvajasnell
authored andcommitted
crypto: add argon2() and argon2Sync() methods
Co-authored-by: Filip Skokan <[email protected]> Co-authored-by: James M Snell <[email protected]> PR-URL: nodejs/node#50353 Reviewed-By: Ethan Arrowood <[email protected]> Reviewed-By: Filip Skokan <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent 150696e commit bcfc7dd

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
@@ -1608,6 +1608,23 @@ DataPointer pbkdf2(const Digest& md,
16081608
uint32_t iterations,
16091609
size_t length);
16101610

1611+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
1612+
#ifndef OPENSSL_NO_ARGON2
1613+
enum class Argon2Type { ARGON2D, ARGON2I, ARGON2ID };
1614+
1615+
DataPointer argon2(const Buffer<const char>& pass,
1616+
const Buffer<const unsigned char>& salt,
1617+
uint32_t lanes,
1618+
size_t length,
1619+
uint32_t memcost,
1620+
uint32_t iter,
1621+
uint32_t version,
1622+
const Buffer<const unsigned char>& secret,
1623+
const Buffer<const unsigned char>& ad,
1624+
Argon2Type type);
1625+
#endif
1626+
#endif
1627+
16111628
// ============================================================================
16121629
// Version metadata
16131630
#define NCRYPTO_VERSION "0.0.1"

src/ncrypto.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@
1818
#include <algorithm>
1919
#include <cstring>
2020
#if OPENSSL_VERSION_MAJOR >= 3
21+
#include <openssl/core_names.h>
22+
#include <openssl/params.h>
2123
#include <openssl/provider.h>
24+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
25+
#include <openssl/thread.h>
26+
#endif
2227
#endif
2328
#if OPENSSL_WITH_PQC
2429
struct PQCMapping {
@@ -2006,6 +2011,102 @@ DataPointer pbkdf2(const Digest& md,
20062011
return {};
20072012
}
20082013

2014+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L
2015+
#ifndef OPENSSL_NO_ARGON2
2016+
DataPointer argon2(const Buffer<const char>& pass,
2017+
const Buffer<const unsigned char>& salt,
2018+
uint32_t lanes,
2019+
size_t length,
2020+
uint32_t memcost,
2021+
uint32_t iter,
2022+
uint32_t version,
2023+
const Buffer<const unsigned char>& secret,
2024+
const Buffer<const unsigned char>& ad,
2025+
Argon2Type type) {
2026+
ClearErrorOnReturn clearErrorOnReturn;
2027+
2028+
std::string_view algorithm;
2029+
switch (type) {
2030+
case Argon2Type::ARGON2I:
2031+
algorithm = "ARGON2I";
2032+
break;
2033+
case Argon2Type::ARGON2D:
2034+
algorithm = "ARGON2D";
2035+
break;
2036+
case Argon2Type::ARGON2ID:
2037+
algorithm = "ARGON2ID";
2038+
break;
2039+
default:
2040+
// Invalid Argon2 type
2041+
return {};
2042+
}
2043+
2044+
// creates a new library context to avoid locking when running concurrently
2045+
auto ctx = DeleteFnPtr<OSSL_LIB_CTX, OSSL_LIB_CTX_free>{OSSL_LIB_CTX_new()};
2046+
if (!ctx) {
2047+
return {};
2048+
}
2049+
2050+
// required if threads > 1
2051+
if (lanes > 1 && OSSL_set_max_threads(ctx.get(), lanes) != 1) {
2052+
return {};
2053+
}
2054+
2055+
auto kdf = DeleteFnPtr<EVP_KDF, EVP_KDF_free>{
2056+
EVP_KDF_fetch(ctx.get(), algorithm.data(), nullptr)};
2057+
if (!kdf) {
2058+
return {};
2059+
}
2060+
2061+
auto kctx =
2062+
DeleteFnPtr<EVP_KDF_CTX, EVP_KDF_CTX_free>{EVP_KDF_CTX_new(kdf.get())};
2063+
if (!kctx) {
2064+
return {};
2065+
}
2066+
2067+
std::vector<OSSL_PARAM> params;
2068+
params.reserve(9);
2069+
2070+
params.push_back(OSSL_PARAM_construct_octet_string(
2071+
OSSL_KDF_PARAM_PASSWORD,
2072+
const_cast<char*>(pass.len > 0 ? pass.data : ""),
2073+
pass.len));
2074+
params.push_back(OSSL_PARAM_construct_octet_string(
2075+
OSSL_KDF_PARAM_SALT, const_cast<unsigned char*>(salt.data), salt.len));
2076+
params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_THREADS, &lanes));
2077+
params.push_back(
2078+
OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES, &lanes));
2079+
params.push_back(
2080+
OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, &memcost));
2081+
params.push_back(OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ITER, &iter));
2082+
2083+
if (ad.len != 0) {
2084+
params.push_back(OSSL_PARAM_construct_octet_string(
2085+
OSSL_KDF_PARAM_ARGON2_AD, const_cast<unsigned char*>(ad.data), ad.len));
2086+
}
2087+
2088+
if (secret.len != 0) {
2089+
params.push_back(OSSL_PARAM_construct_octet_string(
2090+
OSSL_KDF_PARAM_SECRET,
2091+
const_cast<unsigned char*>(secret.data),
2092+
secret.len));
2093+
}
2094+
2095+
params.push_back(OSSL_PARAM_construct_end());
2096+
2097+
auto dp = DataPointer::Alloc(length);
2098+
if (dp && EVP_KDF_derive(kctx.get(),
2099+
reinterpret_cast<unsigned char*>(dp.get()),
2100+
length,
2101+
params.data()) == 1) {
2102+
return dp;
2103+
}
2104+
2105+
return {};
2106+
}
2107+
#endif
2108+
#endif
2109+
20092110
// ============================================================================
20102111

20112112
EVPKeyPointer::PrivateKeyEncodingConfig::PrivateKeyEncodingConfig(

0 commit comments

Comments
 (0)