Skip to content

Commit 3cd1576

Browse files
panvaaduh95
authored andcommitted
crypto: preserve OpenSSL errors from KDF failures
The ncrypto KDF helpers cleared the OpenSSL error queue on return, and the traits insert their own message, which makes DeriveBitsJob skip errors->Capture(). Argon2, HKDF, PBKDF2 and scrypt failures were therefore bare Errors with no code and no opensslErrorStack. Drop the guard, which DeriveBitsJob already provides, and capture before inserting since Capture() clears the store. Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: #64776 Backport-PR-URL: #65087 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 74b3023 commit 3cd1576

3 files changed

Lines changed: 35 additions & 16 deletions

File tree

deps/ncrypto/ncrypto.cc

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2642,8 +2642,6 @@ DataPointer hkdf(const Digest& md,
26422642
const Buffer<const unsigned char>& info,
26432643
const Buffer<const unsigned char>& salt,
26442644
size_t length) {
2645-
ClearErrorOnReturn clearErrorOnReturn;
2646-
26472645
if (!checkHkdfLength(md, length) || info.len > INT_MAX ||
26482646
salt.len > INT_MAX) {
26492647
return {};
@@ -2714,8 +2712,6 @@ DataPointer scrypt(const Buffer<const char>& pass,
27142712
uint64_t p,
27152713
uint64_t maxmem,
27162714
size_t length) {
2717-
ClearErrorOnReturn clearErrorOnReturn;
2718-
27192715
if (pass.len > INT_MAX || salt.len > INT_MAX) {
27202716
return {};
27212717
}
@@ -2742,8 +2738,6 @@ DataPointer pbkdf2(const Digest& md,
27422738
const Buffer<const unsigned char>& salt,
27432739
uint32_t iterations,
27442740
size_t length) {
2745-
ClearErrorOnReturn clearErrorOnReturn;
2746-
27472741
if (pass.len > INT_MAX || salt.len > INT_MAX || length > INT_MAX) {
27482742
return {};
27492743
}
@@ -2775,8 +2769,6 @@ DataPointer argon2(const Buffer<const char>& pass,
27752769
const Buffer<const unsigned char>& secret,
27762770
const Buffer<const unsigned char>& ad,
27772771
Argon2Type type) {
2778-
ClearErrorOnReturn clearErrorOnReturn;
2779-
27802772
std::string_view algorithm;
27812773
switch (type) {
27822774
case Argon2Type::ARGON2I:

test/parallel/test-crypto-argon2-job.js

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,30 @@ const empty = Buffer.alloc(0);
2929

3030
// Parameters that OpenSSL's Argon2 KDF rejects.
3131
const badParams = [
32-
{ lanes: 0, keylen: 32, memcost: 16, iter: 1 }, // lanes < 1
33-
{ lanes: 1, keylen: 32, memcost: 0, iter: 1 }, // memcost == 0
34-
{ lanes: 1, keylen: 32, memcost: 16, iter: 0 }, // iter == 0
32+
{ lanes: 0, keylen: 32, memcost: 16, iter: 1,
33+
reason: /invalid thread pool size/ },
34+
{ lanes: 1, keylen: 32, memcost: 0, iter: 1,
35+
reason: /invalid memory size/ },
36+
{ lanes: 1, keylen: 32, memcost: 16, iter: 0,
37+
reason: /invalid iteration count/ },
3538
];
3639

37-
for (const { lanes, keylen, memcost, iter } of badParams) {
40+
function assertError(err, { reason }) {
41+
assert.ok(err);
42+
const details = [err.message, ...(err.opensslErrorStack ?? [])];
43+
assert.ok(details.some((msg) => reason.test(msg)),
44+
`did not find ${reason} in ${details}`);
45+
}
46+
47+
for (const params of badParams) {
48+
const { lanes, keylen, memcost, iter } = params;
49+
3850
{
3951
const job = new Argon2Job(
4052
kCryptoJobSync, pass, salt, lanes, keylen, memcost, iter,
4153
empty, empty, kTypeArgon2id);
4254
const { 0: err, 1: result } = job.run();
43-
assert.ok(err);
44-
assert.match(err.message, /Deriving bits failed/);
55+
assertError(err, params);
4556
assert.strictEqual(result, undefined);
4657
}
4758

@@ -50,8 +61,7 @@ for (const { lanes, keylen, memcost, iter } of badParams) {
5061
kCryptoJobAsync, pass, salt, lanes, keylen, memcost, iter,
5162
empty, empty, kTypeArgon2id);
5263
job.ondone = common.mustCall((err, result) => {
53-
assert.ok(err);
54-
assert.match(err.message, /Deriving bits failed/);
64+
assertError(err, params);
5565
assert.strictEqual(result, undefined);
5666
});
5767
job.run();

test/parallel/test-crypto-no-algorithm.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,23 @@ if (isMainThread) {
2626
`did not find ${expected} in ${err.opensslErrorStack}`);
2727
}
2828
}));
29+
30+
const derivations = [
31+
['HKDF', () => crypto.hkdfSync('sha256', Buffer.alloc(32), Buffer.alloc(8),
32+
Buffer.alloc(0), 32)],
33+
['PBKDF2', () => crypto.pbkdf2Sync('secret', Buffer.alloc(16), 1000, 32,
34+
'sha256')],
35+
];
36+
for (const { 0: name, 1: derive } of derivations) {
37+
try {
38+
derive();
39+
} catch (err) {
40+
const expected = /digital envelope routines::unsupported/;
41+
const details = [err.message, ...(err.opensslErrorStack ?? [])];
42+
assert(details.some((msg) => expected.test(msg)),
43+
`${name}: did not find ${expected} in ${details}`);
44+
}
45+
}
2946
}
3047

3148
{

0 commit comments

Comments
 (0)