Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
1f7b08a
win,test: disable test case failing with ClangCL
StefanStojanovic Mar 12, 2025
3cff7f8
src: suggest --use-system-ca when a certificate error occurs
Aditi-1400 Mar 12, 2025
f694d7d
assert: improve partialDeepStrictEqual
BridgeAR Mar 7, 2025
e4cc54a
benchmark: add assert partialDeepStrictEqual benchmark
BridgeAR Mar 8, 2025
7592cf4
benchmark: skip running some assert benchmarks by default
BridgeAR Mar 8, 2025
d52a71f
benchmark: adjust assert runtimes
BridgeAR Mar 8, 2025
80d9d56
assert,util: improve performance
BridgeAR Mar 8, 2025
64b0867
assert: implement partial error comparison
BridgeAR Mar 10, 2025
097d992
doc: add note about sync nodejs-private branches
RafaelGSS Mar 12, 2025
f8f81c8
timers: remove unused parameter from insertGuarded
gurgunday Mar 12, 2025
3687390
doc: fix small typo in `process.md`
Mar 13, 2025
c4fdb27
tls: remove unnecessary type check on normalize
anonrig Mar 13, 2025
ca67145
doc: add missing `deprecated` badges in `fs.md`
y-hsgw Mar 13, 2025
6a13319
src: cleanup aliased_buffer.h
VoltrexKeyva Mar 13, 2025
5be80b1
src: refine ncrypto more
jasnell Mar 3, 2025
27f183a
doc: update maintaining-openssl.md for openssl
richardlau Mar 13, 2025
0ca362f
meta: move ovflowd to emeritus
ovflowd Mar 14, 2025
573467c
deps: update acorn to 8.14.1
nodejs-github-bot Mar 14, 2025
30e5658
deps: update googletest to 0bdccf4
nodejs-github-bot Mar 14, 2025
d5a26f6
lib: make getCallSites sourceMap option truly optional
jasnell Mar 9, 2025
4ab3c16
src: cleanup crypto more
jasnell Mar 4, 2025
8cb3441
doc: explicit mention arbitrary code execution as a vuln
RafaelGSS Mar 14, 2025
99f93af
deps: update ada to v3.2.1
anonrig Mar 14, 2025
ee4e855
doc: fix typo in sqlite.md
tniessen Mar 14, 2025
9adaaeb
doc: remove typo YAML snippet from tls.getCACertificates doc
RaisinTen Mar 15, 2025
17ccf92
doc: add history info for --use-system-ca
RaisinTen Mar 15, 2025
2a5fcb2
doc: fix typo in `url.md`
mureinik Mar 15, 2025
053cef7
crypto: add optional callback to crypto.diffieHellman
panva Mar 15, 2025
f0c9f50
tools: bump @babel/helpers from 7.26.9 to 7.26.10 in /tools/eslint
dependabot[bot] Mar 15, 2025
de48407
build: fix update-wpt workflow
JonasBa Mar 15, 2025
6ee15c6
src: define urlpattern components using a macro
JonasBa Mar 14, 2025
5006627
fs: apply exclude function to root path
Trott Mar 16, 2025
91a824e
doc: add review guidelines for collaborator nominations
aduh95 Mar 16, 2025
43bea6b
deps: V8: cherry-pick c172ffc5bf54
tunz Mar 6, 2025
0583c3d
http: coerce content-length to number
marco-ippolito Mar 16, 2025
f8acf2d
src: make minor cleanups in compile_cache.cc
jasnell Mar 13, 2025
b9d9ee4
src: make minor cleanups in encoding_binding.cc
jasnell Mar 13, 2025
e5e3987
doc: fixed the incorrect splitting of multiple words
letianpailove Mar 14, 2025
cc42ee8
crypto: ensure expected JWK alg in SubtleCrypto.importKey RSA imports
panva Mar 16, 2025
52cd095
cli: clarify --cpu-prof-name allowed values
cecia234 Mar 13, 2025
27b01ed
test: update parallel/test-tls-dhe for OpenSSL 3.5
richardlau Mar 17, 2025
db9c37f
doc: prefer to sign commits under nodejs repository
RafaelGSS Mar 17, 2025
a40ff1f
url: fix constructor error message for URLPattern
jakecastelli Mar 17, 2025
4729649
doc: replace NOTEs that do not render properly
cjihrig Mar 17, 2025
4b04c92
sqlite: add StatementSync.prototype.columns()
cjihrig Mar 18, 2025
fda56b9
lib: limit split function calls to prevent excessive array length
gurgunday Mar 18, 2025
5c976f1
sqlite: add DatabaseSync.prototype[Symbol.dispose]()
cjihrig Mar 18, 2025
e28c723
doc: add node.js streams references to Web Streams doc
dario-piotrowicz Mar 18, 2025
1f08864
debugger: fix behavior of plain object exec in debugger repl
dario-piotrowicz Mar 18, 2025
273607e
doc: add new writing-docs contributing md
dario-piotrowicz Mar 18, 2025
9d5be4b
doc: run license-builder
github-actions[bot] Mar 19, 2025
5c05ba1
doc: remove some inconsistencies in `deprecations.md`
aduh95 Mar 19, 2025
176d951
doc: deprecate passing `args` to `spawn` and `execFile`
aduh95 Mar 19, 2025
3ddc5cd
src: cache urlpattern properties
JonasBa Mar 14, 2025
5652da6
sqlite: add DatabaseSync.prototype.isOpen
cjihrig Mar 19, 2025
a9a93f3
meta: edit collaborator nomination process
aduh95 Mar 19, 2025
7b72396
assert: improve partialDeepStrictEqual performance
BridgeAR Mar 19, 2025
1b8d1d3
util: expose diff function used by the assertion errors
Mar 19, 2025
706b646
doc: remove mention of visa fees from onboarding doc
RaisinTen Mar 20, 2025
ee60254
doc: recommend watching the collaborators repo in the onboarding doc
RaisinTen Mar 20, 2025
d4abd9d
timers: remove unnecessary allocation of _onTimeout
gurgunday Mar 20, 2025
d637763
doc: remove mertcanaltin from Triagers
mertcanaltin Mar 20, 2025
d0c96c4
meta: remove collaborator self-nomination
Trott Mar 20, 2025
9611980
src: improve error handling in multiple files
jasnell Mar 16, 2025
87e0dda
doc: mark multiple experimental APIS as stable
jasnell Mar 16, 2025
f36bee4
util: avoid run debug when enabled is false
fengmk2 Mar 21, 2025
c21068b
doc: remove deprecated pattern in `child_process.md`
aduh95 Mar 21, 2025
c45894f
doc: add history entry for DEP0190 in `child_process.md`
aduh95 Mar 21, 2025
2a580b9
lib: add warning when binding inspector to public IP
DemianParkhomenko Nov 5, 2024
7f5e316
src: ensure primordials are initialized exactly once
legendecas Mar 21, 2025
f8aff90
process: add execve
ShogunPanda Jan 7, 2025
e8d4a31
sqlite: add support for unknown named parameters
cjihrig Mar 22, 2025
2c4f894
doc: module resolution pseudocode corrections
laverdet Mar 22, 2025
481ea66
test: add more number cases for buffer.indexOf
nektro Mar 22, 2025
e3bb26d
tools: update sccache to support GH cache changes
targos Mar 23, 2025
b4576a6
doc: remove cryptoStream API reference
JonasBa Mar 23, 2025
717c44d
doc: make stability labels more consistent
aduh95 Mar 23, 2025
3d372ad
test: update WPT for urlpattern to 6ceca69d26
nodejs-github-bot Mar 23, 2025
3742d2a
doc: update support channels
ovflowd Mar 23, 2025
595e9e5
doc: add bjohansebas as triager
bjohansebas Mar 23, 2025
8f7debc
timers: optimize timer functions with improved argument handling
gurgunday Mar 24, 2025
00a5b18
meta: add some clarification to the nomination process
jasnell Mar 16, 2025
ee1c78a
doc: add section stating that very stale PRs should be closed
dario-piotrowicz Mar 25, 2025
162b282
deps: update undici to 6.21.2
mcollina Mar 13, 2025
8c76b29
doc: mention reports should align with Node.js CoC
RafaelGSS Mar 26, 2025
7faa482
tools: remove stalled label on unstalled issues and PRs
Trott Mar 26, 2025
99dbd8b
doc: remove mention of `--require` not supporting ES modules
JLHwung Mar 28, 2025
921041b
doc: remove Corepack documentation
aduh95 Mar 28, 2025
4ed1a09
doc: clarify behaviour of node-api adjust function
mhdawson Mar 28, 2025
affeaac
doc: add gurgunday as triager
gurgunday Mar 29, 2025
ad5dcc5
tools: fix WPT update cron string
aduh95 Mar 30, 2025
7611fc1
crypto: fix output of privateDecrypt with zero-length data
panva Apr 1, 2025
9ad070e
2025-04-01, Version 23.11.0 (Current)
aduh95 Apr 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
src: refine ncrypto more
An eventual goal for ncrypto is to completely abstract away
details of working directly with openssl in order to make it
easier to work with multiple different openssl/boringssl versions.
As part of that we want to move away from direct reliance on
specific openssl APIs in the runtime and instead go through
the ncrypto abstractions. Not only does this help other
runtimes trying to be compatible with Node.js, but it helps
Node.js also by reducing the complexity of the crypto code
in Node.js itself.

PR-URL: #57300
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
  • Loading branch information
jasnell authored and aduh95 committed Mar 18, 2025
commit 5be80b1748f3d722ffc6f255034f5160e55cd8c7
237 changes: 210 additions & 27 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1164,7 +1164,7 @@ X509View X509View::From(const SSLCtxPointer& ctx) {
}

std::optional<std::string> X509View::getFingerprint(
const EVP_MD* method) const {
const Digest& method) const {
unsigned int md_size;
unsigned char md[EVP_MAX_MD_SIZE];
static constexpr char hex[] = "0123456789ABCDEF";
Expand Down Expand Up @@ -1669,17 +1669,17 @@ const EVP_CIPHER* getCipherByName(const std::string_view name) {
return EVP_get_cipherbyname(name.data());
}

bool checkHkdfLength(const EVP_MD* md, size_t length) {
bool checkHkdfLength(const Digest& md, size_t length) {
// HKDF-Expand computes up to 255 HMAC blocks, each having as many bits as
// the output of the hash function. 255 is a hard limit because HKDF appends
// an 8-bit counter to each HMAC'd message, starting at 1.
static constexpr size_t kMaxDigestMultiplier = 255;
size_t max_length = EVP_MD_size(md) * kMaxDigestMultiplier;
size_t max_length = md.size() * kMaxDigestMultiplier;
if (length > max_length) return false;
return true;
}

DataPointer hkdf(const EVP_MD* md,
DataPointer hkdf(const Digest& md,
const Buffer<const unsigned char>& key,
const Buffer<const unsigned char>& info,
const Buffer<const unsigned char>& salt,
Expand All @@ -1692,8 +1692,11 @@ DataPointer hkdf(const EVP_MD* md,
}

auto ctx = EVPKeyCtxPointer::NewFromID(EVP_PKEY_HKDF);
// OpenSSL < 3.0.0 accepted only a void* as the argument of
// EVP_PKEY_CTX_set_hkdf_md.
const EVP_MD* md_ptr = md;
if (!ctx || !EVP_PKEY_derive_init(ctx.get()) ||
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md) ||
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md_ptr) ||
!EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data, info.len)) {
return {};
}
Expand All @@ -1703,7 +1706,7 @@ DataPointer hkdf(const EVP_MD* md,
if (salt.len > 0) {
actual_salt = {reinterpret_cast<const char*>(salt.data), salt.len};
} else {
actual_salt = {default_salt, static_cast<unsigned>(EVP_MD_size(md))};
actual_salt = {default_salt, static_cast<unsigned>(md.size())};
}

// We do not use EVP_PKEY_HKDF_MODE_EXTRACT_AND_EXPAND because and instead
Expand Down Expand Up @@ -1776,7 +1779,7 @@ DataPointer scrypt(const Buffer<const char>& pass,
return {};
}

DataPointer pbkdf2(const EVP_MD* md,
DataPointer pbkdf2(const Digest& md,
const Buffer<const char>& pass,
const Buffer<const unsigned char>& salt,
uint32_t iterations,
Expand All @@ -1788,12 +1791,13 @@ DataPointer pbkdf2(const EVP_MD* md,
}

auto dp = DataPointer::Alloc(length);
const EVP_MD* md_ptr = md;
if (dp && PKCS5_PBKDF2_HMAC(pass.data,
pass.len,
salt.data,
salt.len,
iterations,
md,
md_ptr,
length,
reinterpret_cast<unsigned char*>(dp.get()))) {
return dp;
Expand Down Expand Up @@ -2728,6 +2732,17 @@ bool SSLCtxPointer::setGroups(const char* groups) {
return SSL_CTX_set1_groups_list(get(), groups) == 1;
}

bool SSLCtxPointer::setCipherSuites(std::string_view ciphers) {
#ifndef OPENSSL_IS_BORINGSSL
if (!ctx_) return false;
return SSL_CTX_set_ciphersuites(ctx_.get(), ciphers.data());
#else
// BoringSSL does not allow API config of TLS 1.3 cipher suites.
// We treat this as a non-op.
return true;
#endif
}

// ============================================================================

const Cipher Cipher::FromName(std::string_view name) {
Expand All @@ -2742,6 +2757,55 @@ const Cipher Cipher::FromCtx(const CipherCtxPointer& ctx) {
return Cipher(EVP_CIPHER_CTX_cipher(ctx.get()));
}

const Cipher Cipher::EMPTY = Cipher();
const Cipher Cipher::AES_128_CBC = Cipher::FromNid(NID_aes_128_cbc);
const Cipher Cipher::AES_192_CBC = Cipher::FromNid(NID_aes_192_cbc);
const Cipher Cipher::AES_256_CBC = Cipher::FromNid(NID_aes_256_cbc);
const Cipher Cipher::AES_128_CTR = Cipher::FromNid(NID_aes_128_ctr);
const Cipher Cipher::AES_192_CTR = Cipher::FromNid(NID_aes_192_ctr);
const Cipher Cipher::AES_256_CTR = Cipher::FromNid(NID_aes_256_ctr);
const Cipher Cipher::AES_128_GCM = Cipher::FromNid(NID_aes_128_gcm);
const Cipher Cipher::AES_192_GCM = Cipher::FromNid(NID_aes_192_gcm);
const Cipher Cipher::AES_256_GCM = Cipher::FromNid(NID_aes_256_gcm);
const Cipher Cipher::AES_128_KW = Cipher::FromNid(NID_id_aes128_wrap);
const Cipher Cipher::AES_192_KW = Cipher::FromNid(NID_id_aes192_wrap);
const Cipher Cipher::AES_256_KW = Cipher::FromNid(NID_id_aes256_wrap);

bool Cipher::isGcmMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_GCM_MODE;
}

bool Cipher::isWrapMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_WRAP_MODE;
}

bool Cipher::isCtrMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_CTR_MODE;
}

bool Cipher::isCcmMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_CCM_MODE;
}

bool Cipher::isOcbMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_OCB_MODE;
}

bool Cipher::isStreamMode() const {
if (!cipher_) return false;
return getMode() == EVP_CIPH_STREAM_CIPHER;
}

bool Cipher::isChaCha20Poly1305() const {
if (!cipher_) return false;
return getNid() == NID_chacha20_poly1305;
}

int Cipher::getMode() const {
if (!cipher_) return 0;
return EVP_CIPHER_mode(cipher_);
Expand Down Expand Up @@ -2818,6 +2882,14 @@ bool Cipher::isSupportedAuthenticatedMode() const {
}
}

int Cipher::bytesToKey(const Digest& digest,
const Buffer<const unsigned char>& input,
unsigned char* key,
unsigned char* iv) const {
return EVP_BytesToKey(
*this, Digest::MD5, nullptr, input.data, input.len, 1, key, iv);
}

// ============================================================================

CipherCtxPointer CipherCtxPointer::New() {
Expand Down Expand Up @@ -2851,9 +2923,9 @@ EVP_CIPHER_CTX* CipherCtxPointer::release() {
return ctx_.release();
}

void CipherCtxPointer::setFlags(int flags) {
void CipherCtxPointer::setAllowWrap() {
if (!ctx_) return;
EVP_CIPHER_CTX_set_flags(ctx_.get(), flags);
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
}

bool CipherCtxPointer::setKeyLength(size_t length) {
Expand Down Expand Up @@ -2894,6 +2966,26 @@ int CipherCtxPointer::getMode() const {
return EVP_CIPHER_CTX_mode(ctx_.get());
}

bool CipherCtxPointer::isGcmMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_GCM_MODE;
}

bool CipherCtxPointer::isCcmMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_CCM_MODE;
}

bool CipherCtxPointer::isWrapMode() const {
if (!ctx_) return false;
return getMode() == EVP_CIPH_WRAP_MODE;
}

bool CipherCtxPointer::isChaCha20Poly1305() const {
if (!ctx_) return false;
return getNid() == NID_chacha20_poly1305;
}

int CipherCtxPointer::getNid() const {
if (!ctx_) return 0;
return EVP_CIPHER_CTX_nid(ctx_.get());
Expand Down Expand Up @@ -3258,14 +3350,16 @@ bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) {
EVP_PKEY_CTX_set_ec_param_enc(ctx_.get(), encoding) == 1;
}

bool EVPKeyCtxPointer::setRsaOaepMd(const EVP_MD* md) {
if (md == nullptr || !ctx_) return false;
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md) > 0;
bool EVPKeyCtxPointer::setRsaOaepMd(const Digest& md) {
if (!md || !ctx_) return false;
const EVP_MD* md_ptr = md;
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md_ptr) > 0;
}

bool EVPKeyCtxPointer::setRsaMgf1Md(const EVP_MD* md) {
if (md == nullptr || !ctx_) return false;
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md) > 0;
bool EVPKeyCtxPointer::setRsaMgf1Md(const Digest& md) {
if (!md || !ctx_) return false;
const EVP_MD* md_ptr = md;
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md_ptr) > 0;
}

bool EVPKeyCtxPointer::setRsaPadding(int padding) {
Expand Down Expand Up @@ -3300,14 +3394,17 @@ bool EVPKeyCtxPointer::setRsaKeygenPubExp(BignumPointer&& e) {
return false;
}

bool EVPKeyCtxPointer::setRsaPssKeygenMd(const EVP_MD* md) {
if (md == nullptr || !ctx_) return false;
return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md) > 0;
bool EVPKeyCtxPointer::setRsaPssKeygenMd(const Digest& md) {
if (!md || !ctx_) return false;
// OpenSSL < 3 accepts a void* for the md parameter.
const EVP_MD* md_ptr = md;
return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md_ptr) > 0;
}

bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const EVP_MD* md) {
if (md == nullptr || !ctx_) return false;
return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md) > 0;
bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const Digest& md) {
if (!md || !ctx_) return false;
const EVP_MD* md_ptr = md;
return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md_ptr) > 0;
}

bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) {
Expand Down Expand Up @@ -3673,6 +3770,74 @@ DataPointer Cipher::recover(const EVPKeyPointer& key,
key, params, in);
}

namespace {
struct CipherCallbackContext {
Cipher::CipherNameCallback cb;
void operator()(std::string_view name) { cb(name); }
};

#if OPENSSL_VERSION_MAJOR >= 3
template <class TypeName,
TypeName* fetch_type(OSSL_LIB_CTX*, const char*, const char*),
void free_type(TypeName*),
const TypeName* getbyname(const char*),
const char* getname(const TypeName*)>
void array_push_back(const TypeName* evp_ref,
const char* from,
const char* to,
void* arg) {
if (from == nullptr) return;

const TypeName* real_instance = getbyname(from);
if (!real_instance) return;

const char* real_name = getname(real_instance);
if (!real_name) return;

// EVP_*_fetch() does not support alias names, so we need to pass it the
// real/original algorithm name.
// We use EVP_*_fetch() as a filter here because it will only return an
// instance if the algorithm is supported by the public OpenSSL APIs (some
// algorithms are used internally by OpenSSL and are also passed to this
// callback).
TypeName* fetched = fetch_type(nullptr, real_name, nullptr);
if (fetched == nullptr) return;

free_type(fetched);
auto& cb = *(static_cast<CipherCallbackContext*>(arg));
cb(from);
}
#else
template <class TypeName>
void array_push_back(const TypeName* evp_ref,
const char* from,
const char* to,
void* arg) {
if (!from) return;
auto& cb = *(static_cast<CipherCallbackContext*>(arg));
cb(from);
}
#endif
} // namespace

void Cipher::ForEach(Cipher::CipherNameCallback callback) {
ClearErrorOnReturn clearErrorOnReturn;
CipherCallbackContext context;
context.cb = std::move(callback);

EVP_CIPHER_do_all_sorted(
#if OPENSSL_VERSION_MAJOR >= 3
array_push_back<EVP_CIPHER,
EVP_CIPHER_fetch,
EVP_CIPHER_free,
EVP_get_cipherbyname,
EVP_CIPHER_get0_name>,
#else
array_push_back<EVP_CIPHER>,
#endif
&context);
}

// ============================================================================

Ec::Ec() : ec_(nullptr) {}
Expand Down Expand Up @@ -3713,7 +3878,7 @@ EVP_MD_CTX* EVPMDCtxPointer::release() {
return ctx_.release();
}

bool EVPMDCtxPointer::digestInit(const EVP_MD* digest) {
bool EVPMDCtxPointer::digestInit(const Digest& digest) {
if (!ctx_) return false;
return EVP_DigestInit_ex(ctx_.get(), digest, nullptr) > 0;
}
Expand Down Expand Up @@ -3779,7 +3944,7 @@ bool EVPMDCtxPointer::copyTo(const EVPMDCtxPointer& other) const {
}

std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit(const EVPKeyPointer& key,
const EVP_MD* digest) {
const Digest& digest) {
EVP_PKEY_CTX* ctx = nullptr;
if (!EVP_DigestSignInit(ctx_.get(), &ctx, digest, nullptr, key.get())) {
return std::nullopt;
Expand All @@ -3788,7 +3953,7 @@ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit(const EVPKeyPointer& key,
}

std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::verifyInit(
const EVPKeyPointer& key, const EVP_MD* digest) {
const EVPKeyPointer& key, const Digest& digest) {
EVP_PKEY_CTX* ctx = nullptr;
if (!EVP_DigestVerifyInit(ctx_.get(), &ctx, digest, nullptr, key.get())) {
return std::nullopt;
Expand Down Expand Up @@ -3885,9 +4050,10 @@ HMAC_CTX* HMACCtxPointer::release() {
return ctx_.release();
}

bool HMACCtxPointer::init(const Buffer<const void>& buf, const EVP_MD* md) {
bool HMACCtxPointer::init(const Buffer<const void>& buf, const Digest& md) {
if (!ctx_) return false;
return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md, nullptr) == 1;
const EVP_MD* md_ptr = md;
return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md_ptr, nullptr) == 1;
}

bool HMACCtxPointer::update(const Buffer<const void>& buf) {
Expand Down Expand Up @@ -4029,4 +4195,21 @@ size_t Dsa::getDivisorLength() const {
return BignumPointer::GetBitCount(getQ());
}

// ============================================================================

size_t Digest::size() const {
if (md_ == nullptr) return 0;
return EVP_MD_size(md_);
}

const Digest Digest::MD5 = Digest(EVP_md5());
const Digest Digest::SHA1 = Digest(EVP_sha1());
const Digest Digest::SHA256 = Digest(EVP_sha256());
const Digest Digest::SHA384 = Digest(EVP_sha384());
const Digest Digest::SHA512 = Digest(EVP_sha512());

const Digest Digest::FromName(std::string_view name) {
return ncrypto::getDigestByName(name);
}

} // namespace ncrypto
Loading