Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: move crypto related common utilities in common/crypto #56714

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions test/addons/openssl-providers/providers.cjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
'use strict';

const common = require('../../common');
if (!common.hasCrypto)
if (!common.hasCrypto) {
common.skip('missing crypto');
}
const { hasOpenSSL3 } = require('../../common/crypto');

if (!common.hasOpenSSL3)
if (!hasOpenSSL3) {
common.skip('this test requires OpenSSL 3.x');
}
const assert = require('node:assert');
const { createHash, getCiphers, getHashes } = require('node:crypto');
const { debuglog } = require('node:util');
Expand Down
5 changes: 4 additions & 1 deletion test/benchmark/test-benchmark-crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');

if (common.hasFipsCrypto)
const { getFips } = require('crypto');

if (getFips()) {
common.skip('some benchmarks are FIPS-incompatible');
}

const runBenchmark = require('../common/benchmark');

Expand Down
17 changes: 0 additions & 17 deletions test/common/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,6 @@ The TTY file descriptor is assumed to be capable of being writable.

Indicates whether OpenSSL is available.

### `hasFipsCrypto`

* [\<boolean>][<boolean>]

Indicates that Node.js has been linked with a FIPS compatible OpenSSL library,
and that FIPS as been enabled using `--enable-fips`.

To only detect if the OpenSSL library is FIPS compatible, regardless if it has
been enabled or not, then `process.config.variables.openssl_is_fips` can be
used to determine that situation.

### `hasIntl`

* [\<boolean>][<boolean>]
Expand Down Expand Up @@ -417,12 +406,6 @@ Returns `true` if the exit code `exitCode` and/or signal name `signal` represent
the exit code and/or signal name of a node process that aborted, `false`
otherwise.

### `opensslCli`

* [\<boolean>][<boolean>]

Indicates whether 'opensslCli' is supported.

### `platformTimeout(ms)`

* `ms` [\<number>][<number>] | [\<bigint>][<bigint>]
Expand Down
52 changes: 51 additions & 1 deletion test/common/crypto.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
'use strict';

const common = require('../common');
if (!common.hasCrypto)
if (!common.hasCrypto) {
common.skip('missing crypto');
}

const assert = require('assert');
const crypto = require('crypto');
Expand Down Expand Up @@ -98,6 +99,27 @@ const pkcs8EncExp = getRegExpForPEM('ENCRYPTED PRIVATE KEY');
const sec1Exp = getRegExpForPEM('EC PRIVATE KEY');
const sec1EncExp = (cipher) => getRegExpForPEM('EC PRIVATE KEY', cipher);

// Synthesize OPENSSL_VERSION_NUMBER format with the layout 0xMNN00PPSL
const opensslVersionNumber = (major = 0, minor = 0, patch = 0) => {
assert(major >= 0 && major <= 0xf);
assert(minor >= 0 && minor <= 0xff);
assert(patch >= 0 && patch <= 0xff);
return (major << 28) | (minor << 20) | (patch << 4);
};

let OPENSSL_VERSION_NUMBER;
const hasOpenSSL = (major = 0, minor = 0, patch = 0) => {
if (!common.hasCrypto) return false;
if (OPENSSL_VERSION_NUMBER === undefined) {
const regexp = /(?<m>\d+)\.(?<n>\d+)\.(?<p>\d+)/;
const { m, n, p } = process.versions.openssl.match(regexp).groups;
OPENSSL_VERSION_NUMBER = opensslVersionNumber(m, n, p);
}
return OPENSSL_VERSION_NUMBER >= opensslVersionNumber(major, minor, patch);
};

let opensslCli = null;

module.exports = {
modp2buf,
assertApproximateSize,
Expand All @@ -111,4 +133,32 @@ module.exports = {
pkcs8EncExp, // used once
sec1Exp,
sec1EncExp,
hasOpenSSL,
get hasOpenSSL3() {
return hasOpenSSL(3);
},
// opensslCli defined lazily to reduce overhead of spawnSync
get opensslCli() {
if (opensslCli !== null) return opensslCli;

if (process.config.variables.node_shared_openssl) {
// Use external command
opensslCli = 'openssl';
} else {
const path = require('path');
// Use command built from sources included in Node.js repository
opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
}

if (exports.isWindows) opensslCli += '.exe';

const { spawnSync } = require('child_process');

const opensslCmd = spawnSync(opensslCli, ['version']);
if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) {
// OpenSSL command cannot be executed
opensslCli = false;
}
return opensslCli;
},
};
52 changes: 0 additions & 52 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

/* eslint-disable node-core/crypto-check */
'use strict';
const process = global.process; // Some tests tamper with the process global.

Expand Down Expand Up @@ -57,25 +56,6 @@ const noop = () => {};
const hasCrypto = Boolean(process.versions.openssl) &&
!process.env.NODE_SKIP_CRYPTO;

// Synthesize OPENSSL_VERSION_NUMBER format with the layout 0xMNN00PPSL
const opensslVersionNumber = (major = 0, minor = 0, patch = 0) => {
assert(major >= 0 && major <= 0xf);
assert(minor >= 0 && minor <= 0xff);
assert(patch >= 0 && patch <= 0xff);
return (major << 28) | (minor << 20) | (patch << 4);
};

let OPENSSL_VERSION_NUMBER;
const hasOpenSSL = (major = 0, minor = 0, patch = 0) => {
if (!hasCrypto) return false;
if (OPENSSL_VERSION_NUMBER === undefined) {
const regexp = /(?<m>\d+)\.(?<n>\d+)\.(?<p>\d+)/;
const { m, n, p } = process.versions.openssl.match(regexp).groups;
OPENSSL_VERSION_NUMBER = opensslVersionNumber(m, n, p);
}
return OPENSSL_VERSION_NUMBER >= opensslVersionNumber(major, minor, patch);
};

const hasQuic = hasCrypto && !!process.config.variables.openssl_quic;

function parseTestFlags(filename = process.argv[1]) {
Expand Down Expand Up @@ -220,7 +200,6 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) {
}).enable();
}

let opensslCli = null;
let inFreeBSDJail = null;
let localhostIPv4 = null;

Expand Down Expand Up @@ -985,7 +964,6 @@ const common = {
getTTYfd,
hasIntl,
hasCrypto,
hasOpenSSL,
hasQuic,
hasMultiLocalhost,
invalidArgTypeHelper,
Expand Down Expand Up @@ -1027,10 +1005,6 @@ const common = {
return require('os').totalmem() > 0x70000000; /* 1.75 Gb */
},

get hasFipsCrypto() {
return hasCrypto && require('crypto').getFips();
},

get hasIPv6() {
const iFaces = require('os').networkInterfaces();
let re;
Expand All @@ -1047,10 +1021,6 @@ const common = {
});
},

get hasOpenSSL3() {
return hasOpenSSL(3);
},

get inFreeBSDJail() {
if (inFreeBSDJail !== null) return inFreeBSDJail;

Expand Down Expand Up @@ -1100,28 +1070,6 @@ const common = {
return localhostIPv4;
},

// opensslCli defined lazily to reduce overhead of spawnSync
get opensslCli() {
if (opensslCli !== null) return opensslCli;

if (process.config.variables.node_shared_openssl) {
// Use external command
opensslCli = 'openssl';
} else {
// Use command built from sources included in Node.js repository
opensslCli = path.join(path.dirname(process.execPath), 'openssl-cli');
}

if (exports.isWindows) opensslCli += '.exe';

const opensslCmd = spawnSync(opensslCli, ['version']);
if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) {
// OpenSSL command cannot be executed
opensslCli = false;
}
return opensslCli;
},

get PORT() {
if (+process.env.TEST_PARALLEL) {
throw new Error('common.PORT cannot be used in a parallelized test');
Expand Down
2 changes: 0 additions & 2 deletions test/common/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ const {
mustNotMutateObjectDeep,
mustSucceed,
nodeProcessAborted,
opensslCli,
parseTestFlags,
PIPE,
platformTimeout,
Expand Down Expand Up @@ -97,7 +96,6 @@ export {
mustNotMutateObjectDeep,
mustSucceed,
nodeProcessAborted,
opensslCli,
parseTestFlags,
PIPE,
platformTimeout,
Expand Down
3 changes: 2 additions & 1 deletion test/parallel/test-cli-node-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const { Worker } = require('worker_threads');

const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { hasOpenSSL3 } = require('../common/crypto');
tmpdir.refresh();

const printA = path.relative(tmpdir.path, fixtures.path('printA.js'));
Expand Down Expand Up @@ -64,7 +65,7 @@ if (common.isLinux) {
if (common.hasCrypto) {
expectNoWorker('--use-openssl-ca', 'B\n');
expectNoWorker('--use-bundled-ca', 'B\n');
if (!common.hasOpenSSL3)
if (!hasOpenSSL3)
expectNoWorker('--openssl-config=_ossl_cfg', 'B\n');
}

Expand Down
20 changes: 12 additions & 8 deletions test/parallel/test-crypto-authenticated.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@
// Flags: --no-warnings
'use strict';
const common = require('../common');
if (!common.hasCrypto)
if (!common.hasCrypto) {
common.skip('missing crypto');
}

const assert = require('assert');
const crypto = require('crypto');
const { inspect } = require('util');
const fixtures = require('../common/fixtures');
const { hasOpenSSL3 } = require('../common/crypto');

const isFipsEnabled = crypto.getFips();

//
// Test authenticated encryption modes.
Expand All @@ -53,7 +57,7 @@ for (const test of TEST_CASES) {
continue;
}

if (common.hasFipsCrypto && test.iv.length < 24) {
if (isFipsEnabled && test.iv.length < 24) {
common.printSkipMessage('IV len < 12 bytes unsupported in FIPS mode');
continue;
}
Expand Down Expand Up @@ -95,7 +99,7 @@ for (const test of TEST_CASES) {
}

{
if (isCCM && common.hasFipsCrypto) {
if (isCCM && isFipsEnabled) {
assert.throws(() => {
crypto.createDecipheriv(test.algo,
Buffer.from(test.key, 'hex'),
Expand Down Expand Up @@ -286,7 +290,7 @@ for (const test of TEST_CASES) {
});
}, errMessages.authTagLength);

if (!common.hasFipsCrypto) {
if (!isFipsEnabled) {
assert.throws(() => {
crypto.createDecipheriv('aes-256-ccm',
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
Expand All @@ -312,7 +316,7 @@ for (const test of TEST_CASES) {
});

// CCM decryption and create(De|C)ipher are unsupported in FIPS mode.
if (!common.hasFipsCrypto) {
if (!isFipsEnabled) {
assert.throws(() => {
crypto.createDecipheriv(`aes-256-${mode}`,
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
Expand Down Expand Up @@ -388,7 +392,7 @@ for (const test of TEST_CASES) {
cipher.setAAD(Buffer.from('0123456789', 'hex'));
}, /options\.plaintextLength required for CCM mode with AAD/);

if (!common.hasFipsCrypto) {
if (!isFipsEnabled) {
assert.throws(() => {
const cipher = crypto.createDecipheriv('aes-256-ccm',
'FxLKsqdmv0E9xrQhp0b1ZgI0K7JFZJM8',
Expand All @@ -403,7 +407,7 @@ for (const test of TEST_CASES) {

// Test that final() throws in CCM mode when no authentication tag is provided.
{
if (!common.hasFipsCrypto) {
if (!isFipsEnabled) {
const key = Buffer.from('1ed2233fa2223ef5d7df08546049406c', 'hex');
const iv = Buffer.from('7305220bca40d4c90e1791e9', 'hex');
const ct = Buffer.from('8beba09d4d4d861f957d51c0794f4abf8030848e', 'hex');
Expand Down Expand Up @@ -562,7 +566,7 @@ for (const test of TEST_CASES) {
]) {
assert.throws(() => {
cipher.final();
}, common.hasOpenSSL3 ? {
}, hasOpenSSL3 ? {
code: 'ERR_OSSL_TAG_NOT_SET'
} : {
message: /Unsupported state/
Expand Down
10 changes: 6 additions & 4 deletions test/parallel/test-crypto-cipheriv-decipheriv.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ if (!common.hasCrypto)

const assert = require('assert');
const crypto = require('crypto');
const { hasOpenSSL3 } = require('../common/crypto');
const isFipsEnabled = crypto.getFips();

function testCipher1(key, iv) {
// Test encryption and decryption with explicit key and iv
Expand Down Expand Up @@ -150,7 +152,7 @@ testCipher1(Buffer.from('0123456789abcd0123456789'), '12345678');
testCipher1(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));
testCipher2(Buffer.from('0123456789abcd0123456789'), Buffer.from('12345678'));

if (!common.hasFipsCrypto) {
if (!isFipsEnabled) {
testCipher3(Buffer.from('000102030405060708090A0B0C0D0E0F', 'hex'),
Buffer.from('A6A6A6A6A6A6A6A6', 'hex'));
}
Expand Down Expand Up @@ -193,10 +195,10 @@ assert.throws(
errMessage);

// But all other IV lengths should be accepted.
const minIvLength = common.hasOpenSSL3 ? 8 : 1;
const maxIvLength = common.hasOpenSSL3 ? 64 : 256;
const minIvLength = hasOpenSSL3 ? 8 : 1;
const maxIvLength = hasOpenSSL3 ? 64 : 256;
for (let n = minIvLength; n < maxIvLength; n += 1) {
if (common.hasFipsCrypto && n < 12) continue;
if (isFipsEnabled && n < 12) continue;
crypto.createCipheriv('aes-128-gcm', Buffer.alloc(16), Buffer.alloc(n));
}

Expand Down
Loading
Loading