Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 476c6f8

Browse filesBrowse files
richardlauaddaleax
authored andcommitted
crypto: avoid hang when no algorithm available
Avoid an endless loop if no algorithm is available to seed the cryptographically secure pseudorandom number generator (CSPRNG). Co-authored-by: Anna Henningsen <anna@addaleax.net> PR-URL: #46237 Fixes: #46200 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
1 parent 653b108 commit 476c6f8
Copy full SHA for 476c6f8

File tree

Expand file treeCollapse file tree

3 files changed

+64
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

3 files changed

+64
-0
lines changed
Open diff view settings
Collapse file

‎src/crypto/crypto_util.cc‎

Copy file name to clipboardExpand all lines: src/crypto/crypto_util.cc
+14Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ MUST_USE_RESULT CSPRNGResult CSPRNG(void* buffer, size_t length) {
6565
if (1 == RAND_status())
6666
if (1 == RAND_bytes(static_cast<unsigned char*>(buffer), length))
6767
return {true};
68+
#if OPENSSL_VERSION_MAJOR >= 3
69+
const auto code = ERR_peek_last_error();
70+
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
71+
// and RAND_status() but fail in RAND_bytes() if it cannot look up
72+
// a matching algorithm for the CSPRNG.
73+
if (ERR_GET_LIB(code) == ERR_LIB_RAND) {
74+
const auto reason = ERR_GET_REASON(code);
75+
if (reason == RAND_R_ERROR_INSTANTIATING_DRBG ||
76+
reason == RAND_R_UNABLE_TO_FETCH_DRBG ||
77+
reason == RAND_R_UNABLE_TO_CREATE_DRBG) {
78+
return {false};
79+
}
80+
}
81+
#endif
6882
} while (1 == RAND_poll());
6983

7084
return {false};
Collapse file
+12Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
nodejs_conf = nodejs_init
2+
3+
[nodejs_init]
4+
providers = provider_sect
5+
6+
# List of providers to load
7+
[provider_sect]
8+
base = base_sect
9+
10+
[base_sect]
11+
activate = 1
12+
Collapse file
+38Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
7+
if (!common.hasOpenSSL3)
8+
common.skip('this test requires OpenSSL 3.x');
9+
10+
const assert = require('node:assert/strict');
11+
const crypto = require('node:crypto');
12+
13+
if (common.isMainThread) {
14+
// TODO(richardlau): Decide if `crypto.setFips` should error if the
15+
// provider named "fips" is not available.
16+
crypto.setFips(1);
17+
crypto.randomBytes(20, common.mustCall((err) => {
18+
// crypto.randomBytes should either succeed or fail but not hang.
19+
if (err) {
20+
assert.match(err.message, /digital envelope routines::unsupported/);
21+
const expected = /random number generator::unable to fetch drbg/;
22+
assert(err.opensslErrorStack.some((msg) => expected.test(msg)),
23+
`did not find ${expected} in ${err.opensslErrorStack}`);
24+
}
25+
}));
26+
}
27+
28+
{
29+
// Startup test. Should not hang.
30+
const { path } = require('../common/fixtures');
31+
const { spawnSync } = require('node:child_process');
32+
const baseConf = path('openssl3-conf', 'base_only.cnf');
33+
const cp = spawnSync(process.execPath,
34+
[ `--openssl-config=${baseConf}`, '-p', '"hello"' ],
35+
{ encoding: 'utf8' });
36+
assert(common.nodeProcessAborted(cp.status, cp.signal),
37+
`process did not abort, code:${cp.status} signal:${cp.signal}`);
38+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.