Commit 6511fb8e340 for nodejs
commit 6511fb8e34010ad6ea0f73003542373111660fe7
Author: Filip Skokan <panva.ip@gmail.com>
Date: Wed Oct 21 18:24:04 2026 +0200
Revert "src: seed V8 from the OS CSPRNG instead of OpenSSL's DRBG"
This reverts commit 43d3fe95581cb599611dc8e1aae9a79a900998b8.
PR-URL: https://github.com/nodejs/node/pull/66903
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
diff --git a/src/node.cc b/src/node.cc
index e2efaad8a20..f7a19747bed 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -50,9 +50,6 @@
#if HAVE_OPENSSL
#include "ncrypto.h"
-#if OPENSSL_VERSION_MAJOR >= 3
-#include <openssl/provider.h>
-#endif
#include "node_crypto.h"
#if OPENSSL_VERSION_MAJOR >= 3 && !defined(CONF_MFLAGS_IGNORE_MISSING_FILE)
// OpenSSL hides this deprecated macro under OPENSSL_NO_DEPRECATED, but the
@@ -1393,36 +1390,15 @@ InitializeOncePerProcessInternal(
}
crypto::InstallFipsIndicatorCallback();
- // Activating the default provider here keeps --openssl-legacy-provider
- // working. Its explicit load disables OpenSSL's fallback, and the eager
- // CSPRNG check used to activate the provider as a side effect. Only
- // check the seeding when that provider is missing or FIPS is on, so a
- // configuration without a DRBG still aborts at startup instead of
- // hanging at the first crypto call. Otherwise the DRBG is instantiated
- // on first use.
-#if OPENSSL_VERSION_MAJOR >= 3
- const bool check_csprng = ncrypto::isFipsEnabled() ||
- !OSSL_PROVIDER_available(nullptr, "default");
-#else
- const bool check_csprng = true;
-#endif
- if (check_csprng) {
- CHECK(ncrypto::CSPRNG(nullptr, 0));
- }
+ // Ensure CSPRNG is properly seeded.
+ CHECK(ncrypto::CSPRNG(nullptr, 0));
- // V8 uses the entropy for hash seeds, ASLR and Math.random(), none of
- // it cryptographic. Going through OpenSSL would instantiate the DRBG
- // and build the default provider's algorithm tables on every startup.
- // V8 falls back to very weak entropy when the source fails, so abort
- // instead.
V8::SetEntropySource([](unsigned char* buffer, size_t length) {
-#ifdef _AIX
- // uv_random() reads /dev/random on AIX, which blocks. OpenSSL seeds
- // from /dev/urandom there.
+ // V8 falls back to very weak entropy when this function fails
+ // and /dev/urandom isn't available. That wouldn't be so bad if
+ // the entropy was only used for Math.random() but it's also used for
+ // hash table and address space layout randomization. Better to abort.
CHECK(ncrypto::CSPRNG(buffer, length));
-#else
- CHECK_EQ(uv_random(nullptr, nullptr, buffer, length, 0, nullptr), 0);
-#endif
return true;
});
#endif // !defined(OPENSSL_IS_BORINGSSL)
diff --git a/test/addons/openssl-providers/test-legacy-provider-option.js b/test/addons/openssl-providers/test-legacy-provider-option.js
index 1f01ce55a8f..5ad60dac9b8 100644
--- a/test/addons/openssl-providers/test-legacy-provider-option.js
+++ b/test/addons/openssl-providers/test-legacy-provider-option.js
@@ -22,6 +22,3 @@ if (getFips()) {
common.skip('this test cannot be run in FIPS mode');
}
providers.testProviderPresent('legacy');
-// The explicit legacy load disables OpenSSL's provider fallback, so the
-// default provider has to be active before it runs.
-providers.testProviderPresent('default');
diff --git a/test/fixtures/openssl3-conf/random_unavailable.cnf b/test/fixtures/openssl3-conf/random_unavailable.cnf
deleted file mode 100644
index a2dc8d2c9ff..00000000000
--- a/test/fixtures/openssl3-conf/random_unavailable.cnf
+++ /dev/null
@@ -1,7 +0,0 @@
-nodejs_conf = nodejs_init
-
-[nodejs_init]
-random = random_sect
-
-[random_sect]
-random = NO-SUCH-DRBG
diff --git a/test/parallel/test-crypto-no-algorithm.js b/test/parallel/test-crypto-no-algorithm.js
index 0354aad8b0b..06aab7614ff 100644
--- a/test/parallel/test-crypto-no-algorithm.js
+++ b/test/parallel/test-crypto-no-algorithm.js
@@ -57,21 +57,3 @@ if (isMainThread) {
assert(common.nodeProcessAborted(cp.status, cp.signal),
`process did not abort, code:${cp.status} signal:${cp.signal}`);
}
-
-// AIX keeps OpenSSL as V8's entropy source, so a DRBG that cannot be
-// fetched still aborts at startup there.
-if (!common.isAIX) {
- // A configuration whose random section names a DRBG that cannot be
- // fetched starts normally; the first crypto call fails, without a hang.
- const fixtures = require('../common/fixtures');
- const { spawnSync } = require('node:child_process');
- const randomConf = fixtures.path('openssl3-conf', 'random_unavailable.cnf');
- const cp = spawnSync(process.execPath,
- [ `--openssl-config=${randomConf}`, '-e',
- 'require("node:crypto").randomBytes(8)' ],
- { encoding: 'utf8' });
- assert(!common.nodeProcessAborted(cp.status, cp.signal),
- `process aborted, code:${cp.status} signal:${cp.signal}`);
- assert.strictEqual(cp.status, 1);
- assert.match(cp.stderr, /unable to fetch drbg/);
-}
diff --git a/test/parallel/test-crypto-secure-heap.js b/test/parallel/test-crypto-secure-heap.js
index 3c79d1bb8a6..22f90b6be99 100644
--- a/test/parallel/test-crypto-secure-heap.js
+++ b/test/parallel/test-crypto-secure-heap.js
@@ -70,28 +70,6 @@ if (process.argv[2] === 'child') {
return;
}
-if (process.argv[2] === 'workers') {
- // Eight Workers held alive at once. A 1 KiB secure heap has room for a
- // few DRBGs only, so an isolate setup that drew its entropy through
- // OpenSSL would fail for the later Workers and abort the process.
- const { Worker } = require('worker_threads');
- const i32 = new Int32Array(new SharedArrayBuffer(4));
- let online = 0;
- for (let i = 0; i < 8; i++) {
- const worker = new Worker(
- 'const { workerData } = require("worker_threads");' +
- 'Atomics.wait(workerData.i32, 0, 0);',
- { eval: true, workerData: { i32 } });
- worker.on('online', () => {
- if (++online === 8) {
- Atomics.store(i32, 0, 1);
- Atomics.notify(i32, 0);
- }
- });
- }
- return;
-}
-
const child = fork(
process.argv[1],
['child'],
@@ -101,19 +79,6 @@ child.on('exit', common.mustCall((code) => {
assert.strictEqual(code, 0);
}));
-// AIX keeps OpenSSL as V8's entropy source, so a Worker's isolate setup
-// still draws on the secure heap there.
-if (!common.isAIX) {
- const child = fork(
- process.argv[1],
- ['workers'],
- { execArgv: ['--secure-heap=1024', '--secure-heap-min=4'] });
- child.on('exit', common.mustCall((code, signal) => {
- assert.strictEqual(signal, null);
- assert.strictEqual(code, 0);
- }));
-}
-
{
const child = fork(fixtures.path('a.js'), {
execArgv: ['--secure-heap=3', '--secure-heap-min=3'],