Skip to content

Commit 39bc0cc

Browse files
jasnellnpaun
authored andcommitted
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: nodejs/node#57300 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
1 parent 3a40e0d commit 39bc0cc

File tree

2 files changed

+86
-40
lines changed

2 files changed

+86
-40
lines changed

include/ncrypto.h

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,21 @@ class Cipher final {
338338
std::string_view getModeLabel() const;
339339
const char* getName() const;
340340

341+
bool isGcmMode() const;
342+
bool isWrapMode() const;
343+
bool isCtrMode() const;
344+
bool isCcmMode() const;
345+
bool isOcbMode() const;
346+
bool isStreamMode() const;
347+
bool isChaCha20Poly1305() const;
348+
341349
bool isSupportedAuthenticatedMode() const;
342350

351+
int bytesToKey(const Digest& digest,
352+
const Buffer<const unsigned char>& input,
353+
unsigned char* key,
354+
unsigned char* iv) const;
355+
343356
static const Cipher FromName(const char* name);
344357
static const Cipher FromNid(int nid);
345358
static const Cipher FromCtx(const CipherCtxPointer& ctx);
@@ -375,7 +388,7 @@ class Cipher final {
375388

376389
struct CipherParams {
377390
int padding;
378-
const EVP_MD* digest;
391+
Digest digest;
379392
const Buffer<const void> label;
380393
};
381394

@@ -728,7 +741,8 @@ class CipherCtxPointer final {
728741
void reset(EVP_CIPHER_CTX* ctx = nullptr);
729742
EVP_CIPHER_CTX* release();
730743

731-
void setFlags(int flags);
744+
void setAllowWrap();
745+
732746
bool setKeyLength(size_t length);
733747
bool setIvLength(size_t length);
734748
bool setAeadTag(const Buffer<const char>& tag);
@@ -784,13 +798,13 @@ class EVPKeyCtxPointer final {
784798
bool setDsaParameters(uint32_t bits, std::optional<int> q_bits);
785799
bool setEcParameters(int curve, int encoding);
786800

787-
bool setRsaOaepMd(const EVP_MD* md);
788-
bool setRsaMgf1Md(const EVP_MD* md);
801+
bool setRsaOaepMd(const Digest& md);
802+
bool setRsaMgf1Md(const Digest& md);
789803
bool setRsaPadding(int padding);
790804
bool setRsaKeygenPubExp(BignumPointer&& e);
791805
bool setRsaKeygenBits(int bits);
792-
bool setRsaPssKeygenMd(const EVP_MD* md);
793-
bool setRsaPssKeygenMgf1Md(const EVP_MD* md);
806+
bool setRsaPssKeygenMd(const Digest& md);
807+
bool setRsaPssKeygenMgf1Md(const Digest& md);
794808
bool setRsaPssSaltlen(int salt_len);
795809
bool setRsaImplicitRejection();
796810
bool setRsaOaepLabel(DataPointer&& data);
@@ -1207,7 +1221,7 @@ class X509View final {
12071221
bool checkPrivateKey(const EVPKeyPointer& pkey) const;
12081222
bool checkPublicKey(const EVPKeyPointer& pkey) const;
12091223

1210-
std::optional<std::string> getFingerprint(const EVP_MD* method) const;
1224+
std::optional<std::string> getFingerprint(const Digest& method) const;
12111225

12121226
X509Pointer clone() const;
12131227

@@ -1403,16 +1417,25 @@ class EVPMDCtxPointer final {
14031417
void reset(EVP_MD_CTX* ctx = nullptr);
14041418
EVP_MD_CTX* release();
14051419

1406-
bool digestInit(const EVP_MD* digest);
1420+
bool digestInit(const Digest& digest);
14071421
bool digestUpdate(const Buffer<const void>& in);
14081422
DataPointer digestFinal(size_t length);
14091423
bool digestFinalInto(Buffer<void>* buf);
14101424
size_t getExpectedSize();
14111425

14121426
std::optional<EVP_PKEY_CTX*> signInit(const EVPKeyPointer& key,
1413-
const EVP_MD* digest);
1427+
const Digest& digest);
14141428
std::optional<EVP_PKEY_CTX*> verifyInit(const EVPKeyPointer& key,
1415-
const EVP_MD* digest);
1429+
const Digest& digest);
1430+
1431+
std::optional<EVP_PKEY_CTX*> signInitWithContext(
1432+
const EVPKeyPointer& key,
1433+
const Digest& digest,
1434+
const Buffer<const unsigned char>& context_string);
1435+
std::optional<EVP_PKEY_CTX*> verifyInitWithContext(
1436+
const EVPKeyPointer& key,
1437+
const Digest& digest,
1438+
const Buffer<const unsigned char>& context_string);
14161439

14171440
std::optional<EVP_PKEY_CTX*> signInitWithContext(
14181441
const EVPKeyPointer& key,
@@ -1456,7 +1479,7 @@ class HMACCtxPointer final {
14561479
void reset(HMAC_CTX* ctx = nullptr);
14571480
HMAC_CTX* release();
14581481

1459-
bool init(const Buffer<const void>& buf, const EVP_MD* md);
1482+
bool init(const Buffer<const void>& buf, const Digest& md);
14601483
bool update(const Buffer<const void>& buf);
14611484
DataPointer digest();
14621485
bool digestInto(Buffer<void>* buf);
@@ -1607,7 +1630,7 @@ const EVP_CIPHER* getCipherByName(const char* name);
16071630
// Verify that the specified HKDF output length is valid for the given digest.
16081631
// The maximum length for HKDF output for a given digest is 255 times the
16091632
// hash size for the given digest algorithm.
1610-
bool checkHkdfLength(const EVP_MD* md, size_t length);
1633+
bool checkHkdfLength(const Digest& digest, size_t length);
16111634

16121635
bool extractP1363(const Buffer<const unsigned char>& buf,
16131636
unsigned char* dest,
@@ -1620,7 +1643,7 @@ bool hkdfInfo(const EVP_MD* md,
16201643
size_t length,
16211644
Buffer<unsigned char>* out);
16221645

1623-
DataPointer hkdf(const EVP_MD* md,
1646+
DataPointer hkdf(const Digest& md,
16241647
const Buffer<const unsigned char>& key,
16251648
const Buffer<const unsigned char>& info,
16261649
const Buffer<const unsigned char>& salt,
@@ -1652,7 +1675,7 @@ bool pbkdf2Into(const EVP_MD* md,
16521675
size_t length,
16531676
Buffer<unsigned char>* out);
16541677

1655-
DataPointer pbkdf2(const EVP_MD* md,
1678+
DataPointer pbkdf2(const Digest& md,
16561679
const Buffer<const char>& pass,
16571680
const Buffer<const unsigned char>& salt,
16581681
uint32_t iterations,

src/ncrypto.cpp

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,7 +1343,7 @@ X509View X509View::From(const SSLCtxPointer& ctx) {
13431343
}
13441344

13451345
std::optional<std::string> X509View::getFingerprint(
1346-
const EVP_MD* method) const {
1346+
const Digest& method) const {
13471347
unsigned int md_size;
13481348
unsigned char md[EVP_MAX_MD_SIZE];
13491349
static constexpr char hex[] = "0123456789ABCDEF";
@@ -1859,17 +1859,17 @@ const EVP_CIPHER* getCipherByName(const char* name) {
18591859
return EVP_get_cipherbyname(name);
18601860
}
18611861

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

1872-
bool hkdfInfo(const EVP_MD* md,
1872+
bool hkdfInfo(const Digest& md,
18731873
const Buffer<const unsigned char>& key,
18741874
const Buffer<const unsigned char>& info,
18751875
const Buffer<const unsigned char>& salt,
@@ -1887,7 +1887,15 @@ bool hkdfInfo(const EVP_MD* md,
18871887
if (salt.len > 0) {
18881888
actual_salt = {reinterpret_cast<const char*>(salt.data), salt.len};
18891889
} else {
1890-
actual_salt = {default_salt, static_cast<unsigned>(EVP_MD_size(md))};
1890+
actual_salt = {default_salt, static_cast<unsigned>(md.size())};
1891+
}
1892+
1893+
#ifndef NCRYPTO_NO_KDF_H
1894+
auto ctx = EVPKeyCtxPointer::NewFromID(EVP_PKEY_HKDF);
1895+
if (!ctx || !EVP_PKEY_derive_init(ctx.get()) ||
1896+
!EVP_PKEY_CTX_set_hkdf_md(ctx.get(), md) ||
1897+
!EVP_PKEY_CTX_add1_hkdf_info(ctx.get(), info.data, info.len)) {
1898+
return false;
18911899
}
18921900

18931901
#ifndef NCRYPTO_NO_KDF_H
@@ -2003,7 +2011,7 @@ DataPointer scrypt(const Buffer<const char>& pass,
20032011
return {};
20042012
}
20052013

2006-
bool pbkdf2Into(const EVP_MD* md,
2014+
bool pbkdf2Into(const Digest& md,
20072015
const Buffer<const char>& pass,
20082016
const Buffer<const unsigned char>& salt,
20092017
uint32_t iterations,
@@ -2016,12 +2024,13 @@ bool pbkdf2Into(const EVP_MD* md,
20162024
return false;
20172025
}
20182026

2027+
const EVP_MD* md_ptr = md;
20192028
if (PKCS5_PBKDF2_HMAC(pass.data,
20202029
pass.len,
20212030
salt.data,
20222031
salt.len,
20232032
iterations,
2024-
md,
2033+
md_ptr,
20252034
length,
20262035
out->data)) {
20272036
return true;
@@ -3358,6 +3367,14 @@ bool Cipher::isSupportedAuthenticatedMode() const {
33583367
}
33593368
}
33603369

3370+
int Cipher::bytesToKey(const Digest& digest,
3371+
const Buffer<const unsigned char>& input,
3372+
unsigned char* key,
3373+
unsigned char* iv) const {
3374+
return EVP_BytesToKey(
3375+
*this, Digest::MD5, nullptr, input.data, input.len, 1, key, iv);
3376+
}
3377+
33613378
// ============================================================================
33623379

33633380
CipherCtxPointer CipherCtxPointer::New() {
@@ -3391,9 +3408,9 @@ EVP_CIPHER_CTX* CipherCtxPointer::release() {
33913408
return ctx_.release();
33923409
}
33933410

3394-
void CipherCtxPointer::setFlags(int flags) {
3411+
void CipherCtxPointer::setAllowWrap() {
33953412
if (!ctx_) return;
3396-
EVP_CIPHER_CTX_set_flags(ctx_.get(), flags);
3413+
EVP_CIPHER_CTX_set_flags(ctx_.get(), EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
33973414
}
33983415

33993416
bool CipherCtxPointer::setKeyLength(size_t length) {
@@ -3832,14 +3849,16 @@ bool EVPKeyCtxPointer::setEcParameters(int curve, int encoding) {
38323849
EVP_PKEY_CTX_set_ec_param_enc(ctx_.get(), encoding) == 1;
38333850
}
38343851

3835-
bool EVPKeyCtxPointer::setRsaOaepMd(const EVP_MD* md) {
3836-
if (md == nullptr || !ctx_) return false;
3837-
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md) > 0;
3852+
bool EVPKeyCtxPointer::setRsaOaepMd(const Digest& md) {
3853+
if (!md || !ctx_) return false;
3854+
const EVP_MD* md_ptr = md;
3855+
return EVP_PKEY_CTX_set_rsa_oaep_md(ctx_.get(), md_ptr) > 0;
38383856
}
38393857

3840-
bool EVPKeyCtxPointer::setRsaMgf1Md(const EVP_MD* md) {
3841-
if (md == nullptr || !ctx_) return false;
3842-
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md) > 0;
3858+
bool EVPKeyCtxPointer::setRsaMgf1Md(const Digest& md) {
3859+
if (!md || !ctx_) return false;
3860+
const EVP_MD* md_ptr = md;
3861+
return EVP_PKEY_CTX_set_rsa_mgf1_md(ctx_.get(), md_ptr) > 0;
38433862
}
38443863

38453864
bool EVPKeyCtxPointer::setRsaPadding(int padding) {
@@ -3874,14 +3893,17 @@ bool EVPKeyCtxPointer::setRsaKeygenPubExp(BignumPointer&& e) {
38743893
return false;
38753894
}
38763895

3877-
bool EVPKeyCtxPointer::setRsaPssKeygenMd(const EVP_MD* md) {
3878-
if (md == nullptr || !ctx_) return false;
3879-
return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md) > 0;
3896+
bool EVPKeyCtxPointer::setRsaPssKeygenMd(const Digest& md) {
3897+
if (!md || !ctx_) return false;
3898+
// OpenSSL < 3 accepts a void* for the md parameter.
3899+
const EVP_MD* md_ptr = md;
3900+
return EVP_PKEY_CTX_set_rsa_pss_keygen_md(ctx_.get(), md_ptr) > 0;
38803901
}
38813902

3882-
bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const EVP_MD* md) {
3883-
if (md == nullptr || !ctx_) return false;
3884-
return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md) > 0;
3903+
bool EVPKeyCtxPointer::setRsaPssKeygenMgf1Md(const Digest& md) {
3904+
if (!md || !ctx_) return false;
3905+
const EVP_MD* md_ptr = md;
3906+
return EVP_PKEY_CTX_set_rsa_pss_keygen_mgf1_md(ctx_.get(), md_ptr) > 0;
38853907
}
38863908

38873909
bool EVPKeyCtxPointer::setRsaPssSaltlen(int salt_len) {
@@ -4400,7 +4422,7 @@ EVP_MD_CTX* EVPMDCtxPointer::release() {
44004422
return ctx_.release();
44014423
}
44024424

4403-
bool EVPMDCtxPointer::digestInit(const EVP_MD* digest) {
4425+
bool EVPMDCtxPointer::digestInit(const Digest& digest) {
44044426
if (!ctx_) return false;
44054427
return EVP_DigestInit_ex(ctx_.get(), digest, nullptr) > 0;
44064428
}
@@ -4466,7 +4488,7 @@ bool EVPMDCtxPointer::copyTo(const EVPMDCtxPointer& other) const {
44664488
}
44674489

44684490
std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit(const EVPKeyPointer& key,
4469-
const EVP_MD* digest) {
4491+
const Digest& digest) {
44704492
EVP_PKEY_CTX* ctx = nullptr;
44714493
if (!EVP_DigestSignInit(ctx_.get(), &ctx, digest, nullptr, key.get())) {
44724494
return std::nullopt;
@@ -4475,7 +4497,7 @@ std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::signInit(const EVPKeyPointer& key,
44754497
}
44764498

44774499
std::optional<EVP_PKEY_CTX*> EVPMDCtxPointer::verifyInit(
4478-
const EVPKeyPointer& key, const EVP_MD* digest) {
4500+
const EVPKeyPointer& key, const Digest& digest) {
44794501
EVP_PKEY_CTX* ctx = nullptr;
44804502
if (!EVP_DigestVerifyInit(ctx_.get(), &ctx, digest, nullptr, key.get())) {
44814503
return std::nullopt;
@@ -4620,9 +4642,10 @@ HMAC_CTX* HMACCtxPointer::release() {
46204642
return ctx_.release();
46214643
}
46224644

4623-
bool HMACCtxPointer::init(const Buffer<const void>& buf, const EVP_MD* md) {
4645+
bool HMACCtxPointer::init(const Buffer<const void>& buf, const Digest& md) {
46244646
if (!ctx_) return false;
4625-
return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md, nullptr) == 1;
4647+
const EVP_MD* md_ptr = md;
4648+
return HMAC_Init_ex(ctx_.get(), buf.data, buf.len, md_ptr, nullptr) == 1;
46264649
}
46274650

46284651
bool HMACCtxPointer::update(const Buffer<const void>& buf) {

0 commit comments

Comments
 (0)