mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Delete test-crypto-ecb.js, which can no longer run anywhere: Blowfish is available only from OpenSSL's legacy provider and is absent from BoringSSL. The addon and cctest version guards become OPENSSL_IS_BORINGSSL checks. Remove legacy digest-alias coverage and unreachable OpenSSL 1.x branches. JavaScript test and benchmark gates, skip reasons, and TLS error expectations that distinguished OpenSSL 1.x from provider-backed OpenSSL now distinguish BoringSSL, including PKCS12 parsing, named DH groups, private-key serialization, RSA-PSS parameters, consolidated provider caches, FIPS availability, and empty KMAC output. Keep the CCM alternate finalization error only for BoringSSL. Provider-only test skips use version-neutral terminology or state the actual minimum OpenSSL version. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/64777 Fixes: https://github.com/nodejs/node/issues/56733 Refs: https://github.com/nodejs/node/pull/64211 Refs: https://github.com/nodejs/node/pull/63966 Refs: https://github.com/nodejs/node/pull/53329 Refs: https://github.com/nodejs/node/pull/48950 Refs: https://github.com/nodejs/node/issues/45465 Refs: https://github.com/nodejs/node/issues/42827 Refs: https://github.com/nodejs/node/issues/47076 Refs: https://github.com/nodejs/node/pull/62862 Refs: https://github.com/nodejs/node/pull/38512 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
185 lines
5.5 KiB
JavaScript
185 lines
5.5 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
|
|
if (!common.hasCrypto) {
|
|
common.skip('missing crypto');
|
|
}
|
|
|
|
const assert = require('node:assert');
|
|
const diagnosticsChannel = require('node:diagnostics_channel');
|
|
const { once } = require('node:events');
|
|
const { Worker } = require('node:worker_threads');
|
|
const {
|
|
spawnSyncAndExitWithoutError,
|
|
} = require('../common/child_process');
|
|
const { hasFIPS, hasOpenSSL } = require('../common/crypto');
|
|
const {
|
|
createHmac,
|
|
generateKeyPairSync,
|
|
sign,
|
|
subtle,
|
|
} = require('node:crypto');
|
|
|
|
const channelName = 'crypto.fips.indicator';
|
|
|
|
if (!hasOpenSSL(3, 4)) {
|
|
common.skip('OpenSSL 3.4 or later is required');
|
|
} else if (!hasFIPS(3, 4)) {
|
|
common.skip('an active OpenSSL FIPS provider is required');
|
|
} else if (!process.execArgv.includes('--enable-fips-indicator-events')) {
|
|
spawnSyncAndExitWithoutError(
|
|
process.execPath,
|
|
['--enable-fips-indicator-events', __filename],
|
|
);
|
|
} else {
|
|
run().then(common.mustCall());
|
|
}
|
|
|
|
function nextIndicator() {
|
|
const keepAlive = setInterval(common.mustNotCall(), 10_000);
|
|
const { promise, resolve } = Promise.withResolvers();
|
|
const subscriber = common.mustCall((event, name) => {
|
|
assert.strictEqual(name, channelName);
|
|
clearInterval(keepAlive);
|
|
assert.strictEqual(
|
|
diagnosticsChannel.unsubscribe(channelName, subscriber), true);
|
|
resolve(event);
|
|
});
|
|
diagnosticsChannel.subscribe(channelName, subscriber);
|
|
return promise;
|
|
}
|
|
|
|
function testUnsubscribeDuringDrain(key, privateKey) {
|
|
const keepAlive = setInterval(common.mustNotCall(), 10_000);
|
|
const { promise, resolve } = Promise.withResolvers();
|
|
const subscriber = common.mustCall(() => {
|
|
clearInterval(keepAlive);
|
|
assert.strictEqual(
|
|
diagnosticsChannel.unsubscribe(channelName, subscriber), true);
|
|
setImmediate(common.mustCall(resolve));
|
|
});
|
|
diagnosticsChannel.subscribe(channelName, subscriber);
|
|
createHmac('sha256', key).digest();
|
|
sign('sha1', Buffer.alloc(0), privateKey);
|
|
return promise;
|
|
}
|
|
|
|
async function testNoStaleIndicator(key) {
|
|
createHmac('sha256', key).digest();
|
|
const subscriber = common.mustNotCall();
|
|
diagnosticsChannel.subscribe(channelName, subscriber);
|
|
await new Promise((resolve) => setImmediate(resolve));
|
|
assert.strictEqual(
|
|
diagnosticsChannel.unsubscribe(channelName, subscriber), true);
|
|
}
|
|
|
|
async function run() {
|
|
const key = Buffer.alloc(13);
|
|
|
|
const keepAlive = setInterval(common.mustNotCall(), 10_000);
|
|
const { promise, resolve: resolveProbe } = Promise.withResolvers();
|
|
const probeSubscriber = (event) => {
|
|
clearInterval(keepAlive);
|
|
diagnosticsChannel.unsubscribe(channelName, probeSubscriber);
|
|
resolveProbe(event);
|
|
};
|
|
diagnosticsChannel.subscribe(channelName, probeSubscriber);
|
|
|
|
let output;
|
|
try {
|
|
output = createHmac('sha256', key).digest();
|
|
} catch (error) {
|
|
clearInterval(keepAlive);
|
|
diagnosticsChannel.unsubscribe(channelName, probeSubscriber);
|
|
assert.match(error.code, /^ERR_OSSL_/);
|
|
common.printSkipMessage(
|
|
'the FIPS provider rejects unapproved operations before signaling');
|
|
return;
|
|
}
|
|
|
|
assert.strictEqual(output.byteLength, 32);
|
|
assert.deepStrictEqual(await promise, {
|
|
operation: 'HMAC',
|
|
reason: 'keysize',
|
|
blocked: false,
|
|
count: 1,
|
|
dropped: 0,
|
|
});
|
|
|
|
await testNoStaleIndicator(key);
|
|
|
|
let eventPromise = nextIndicator();
|
|
createHmac('sha256', key).digest();
|
|
createHmac('sha256', key).digest();
|
|
assert.deepStrictEqual(await eventPromise, {
|
|
operation: 'HMAC',
|
|
reason: 'keysize',
|
|
blocked: false,
|
|
count: 2,
|
|
dropped: 0,
|
|
});
|
|
|
|
const secondSubscriber = common.mustCall();
|
|
diagnosticsChannel.subscribe(channelName, secondSubscriber);
|
|
eventPromise = nextIndicator();
|
|
createHmac('sha256', key).digest();
|
|
await eventPromise;
|
|
assert.strictEqual(
|
|
diagnosticsChannel.unsubscribe(channelName, secondSubscriber), true);
|
|
|
|
const { privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
|
|
await testUnsubscribeDuringDrain(key, privateKey);
|
|
|
|
const hmacKey = await subtle.importKey(
|
|
'raw', Buffer.alloc(13), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
eventPromise = nextIndicator();
|
|
const [signature, hmacEvent] = await Promise.all([
|
|
subtle.sign('HMAC', hmacKey, Buffer.alloc(0)),
|
|
eventPromise,
|
|
]);
|
|
assert.strictEqual(signature.byteLength, 32);
|
|
assert.strictEqual(hmacEvent.operation, 'HMAC');
|
|
assert.strictEqual(hmacEvent.reason, 'keysize');
|
|
assert.strictEqual(hmacEvent.blocked, false);
|
|
|
|
eventPromise = nextIndicator();
|
|
const worker = new Worker(`
|
|
'use strict';
|
|
const diagnosticsChannel = require('node:diagnostics_channel');
|
|
const { parentPort, workerData } = require('node:worker_threads');
|
|
const { createHmac } = require('node:crypto');
|
|
|
|
let indicatorCount = 0;
|
|
diagnosticsChannel.subscribe('crypto.fips.indicator', () => {
|
|
indicatorCount++;
|
|
});
|
|
const result = createHmac('sha256', workerData.key).digest();
|
|
setImmediate(() => {
|
|
parentPort.postMessage({
|
|
indicatorCount,
|
|
length: result.byteLength,
|
|
});
|
|
});
|
|
`, {
|
|
eval: true,
|
|
workerData: { key },
|
|
});
|
|
worker.on('error', common.mustNotCall());
|
|
const exitPromise = once(worker, 'exit');
|
|
const [[message], workerEvent] = await Promise.all([
|
|
once(worker, 'message'),
|
|
eventPromise,
|
|
]);
|
|
assert.deepStrictEqual(message, { indicatorCount: 0, length: 32 });
|
|
assert.deepStrictEqual(workerEvent, {
|
|
operation: 'HMAC',
|
|
reason: 'keysize',
|
|
blocked: false,
|
|
count: 1,
|
|
dropped: 0,
|
|
});
|
|
const [exitCode] = await exitPromise;
|
|
assert.strictEqual(exitCode, 0);
|
|
}
|