Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Adjust tests for always-available FIPS options
- The fipsMode constant (defined at compile time)
  was replaced by the new `TestFipsCrypto()`/`testFipsCrypto()` functions,
  which rely on the OpenSSL function `FIPS_selftest()`.

  This results in the FIPS mode being always checked on runtime
  and being informed purely by the OpenSSL implementation in use.
  • Loading branch information
khardix committed Feb 9, 2021
commit eb4ff0b438fa522ed98ea233b4ed97709b4b986c
8 changes: 4 additions & 4 deletions doc/api/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ code from strings throw an exception instead. This does not affect the Node.js
added: v6.0.0
-->

Enable FIPS-compliant crypto at startup. (Requires Node.js to be built with
`./configure --openssl-fips`.)
Enable FIPS-compliant crypto at startup. (Requires Node.js to be built
against FIPS-compatible OpenSSL.)

### `--enable-source-maps`
<!-- YAML
Expand Down Expand Up @@ -606,8 +606,8 @@ added: v6.9.0
-->

Load an OpenSSL configuration file on startup. Among other uses, this can be
used to enable FIPS-compliant crypto if Node.js is built with
`./configure --openssl-fips`.
used to enable FIPS-compliant crypto if Node.js is built
with against FIPS-enabled OpenSSL.
Comment thread
mhdawson marked this conversation as resolved.
Outdated

### `--pending-deprecation`
<!-- YAML
Expand Down
22 changes: 4 additions & 18 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,10 @@ assertCrypto();

const {
ERR_CRYPTO_FIPS_FORCED,
ERR_CRYPTO_FIPS_UNAVAILABLE
} = require('internal/errors').codes;
const constants = internalBinding('constants').crypto;
const { getOptionValue } = require('internal/options');
const pendingDeprecation = getOptionValue('--pending-deprecation');
const { fipsMode } = internalBinding('config');
const fipsForced = getOptionValue('--force-fips');
const {
getFipsCrypto,
Expand Down Expand Up @@ -218,10 +216,8 @@ module.exports = {
sign: signOneShot,
setEngine,
timingSafeEqual,
getFips: !fipsMode ? getFipsDisabled :
fipsForced ? getFipsForced : getFipsCrypto,
setFips: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto,
getFips: fipsForced ? getFipsForced : getFipsCrypto,
setFips: fipsForced ? setFipsForced : setFipsCrypto,
verify: verifyOneShot,

// Classes
Expand All @@ -242,19 +238,11 @@ module.exports = {
secureHeapUsed,
};

function setFipsDisabled() {
throw new ERR_CRYPTO_FIPS_UNAVAILABLE();
}

function setFipsForced(val) {
if (val) return;
throw new ERR_CRYPTO_FIPS_FORCED();
}

function getFipsDisabled() {
return 0;
}

function getFipsForced() {
return 1;
}
Expand All @@ -276,10 +264,8 @@ ObjectDefineProperties(module.exports, {
},
// crypto.fips is deprecated. DEP0093. Use crypto.getFips()/crypto.setFips()
fips: {
get: !fipsMode ? getFipsDisabled :
fipsForced ? getFipsForced : getFipsCrypto,
set: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto
get: fipsForced ? getFipsForced : getFipsCrypto,
set: fipsForced ? setFipsForced : setFipsCrypto
},
DEFAULT_ENCODING: {
enumerable: false,
Expand Down
71 changes: 32 additions & 39 deletions test/parallel/test-crypto-fips.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,20 @@ const spawnSync = require('child_process').spawnSync;
const path = require('path');
const fixtures = require('../common/fixtures');
const { internalBinding } = require('internal/test/binding');
const { fipsMode } = internalBinding('config');
const { testFipsCrypto } = internalBinding('crypto');

const FIPS_ENABLED = 1;
const FIPS_DISABLED = 0;
const FIPS_ERROR_STRING =
'Error [ERR_CRYPTO_FIPS_UNAVAILABLE]: Cannot set FIPS mode in a ' +
'non-FIPS build.';
const FIPS_ERROR_STRING2 =
'Error [ERR_CRYPTO_FIPS_FORCED]: Cannot set FIPS mode, it was forced with ' +
'--force-fips at startup.';
const OPTION_ERROR_STRING = 'bad option';
const FIPS_UNSUPPORTED_ERROR_STRING = 'fips mode not supported';
Comment thread
khardix marked this conversation as resolved.
Outdated

const CNF_FIPS_ON = fixtures.path('openssl_fips_enabled.cnf');
const CNF_FIPS_OFF = fixtures.path('openssl_fips_disabled.cnf');

let num_children_ok = 0;

function compiledWithFips() {
return fipsMode ? true : false;
}

function sharedOpenSSL() {
return process.config.variables.node_shared_openssl;
}
Expand Down Expand Up @@ -75,17 +68,17 @@ testHelper(

// --enable-fips should turn FIPS mode on
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
process.env);

// --force-fips should turn FIPS mode on
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
process.env);

Expand All @@ -106,23 +99,23 @@ if (!sharedOpenSSL()) {
testHelper(
'stdout',
[`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED,
testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()',
process.env);

// OPENSSL_CONF should be able to turn on FIPS mode
testHelper(
'stdout',
[],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED,
testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_ON }));

// --openssl-config option should override OPENSSL_CONF
testHelper(
'stdout',
[`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED,
testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));
}
Expand All @@ -136,78 +129,78 @@ testHelper(

// --enable-fips should take precedence over OpenSSL config file
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips', `--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
process.env);

// OPENSSL_CONF should _not_ make a difference to --enable-fips
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));

// --force-fips should take precedence over OpenSSL config file
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips', `--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
process.env);

// Using OPENSSL_CONF should not make a difference to --force-fips
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));

// setFipsCrypto should be able to turn FIPS mode on
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
[],
compiledWithFips() ? FIPS_ENABLED : FIPS_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' +
'require("crypto").getFips())',
process.env);

// setFipsCrypto should be able to turn FIPS mode on and off
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
[],
compiledWithFips() ? FIPS_DISABLED : FIPS_ERROR_STRING,
testFipsCrypto() ? FIPS_DISABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' +
'require("crypto").setFips(false),' +
'require("crypto").getFips())',
process.env);

// setFipsCrypto takes precedence over OpenSSL config file, FIPS on
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
[`--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' +
'require("crypto").getFips())',
process.env);

// setFipsCrypto takes precedence over OpenSSL config file, FIPS off
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
'stdout',
[`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_DISABLED : FIPS_ERROR_STRING,
FIPS_DISABLED,
'(require("crypto").setFips(false),' +
'require("crypto").getFips())',
process.env);

// --enable-fips does not prevent use of setFipsCrypto API
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'],
compiledWithFips() ? FIPS_DISABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_DISABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(false),' +
'require("crypto").getFips())',
process.env);
Expand All @@ -216,15 +209,15 @@ testHelper(
testHelper(
'stderr',
['--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)',
process.env);

// --force-fips makes setFipsCrypto enable a no-op (FIPS stays on)
testHelper(
compiledWithFips() ? 'stdout' : 'stderr',
testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' +
'require("crypto").getFips())',
process.env);
Expand All @@ -233,14 +226,14 @@ testHelper(
testHelper(
'stderr',
['--force-fips', '--enable-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)',
process.env);

// --enable-fips and --force-fips order does not matter
testHelper(
'stderr',
['--enable-fips', '--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)',
process.env);
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,6 @@ const conditionalOpts = [
'--secure-heap-min',
].includes(opt);
}
}, {
// We are using openssl_is_fips from the configuration because it could be
// the case that OpenSSL is FIPS compatible but fips has not been enabled
// (starting node with --enable-fips). If we use common.hasFipsCrypto
// that would only tells us if fips has been enabled, but in this case we
// want to check options which will be available regardless of whether fips
// is enabled at runtime or not.
include: process.config.variables.openssl_is_fips,
filter: (opt) => opt.includes('-fips')
Comment thread
khardix marked this conversation as resolved.
}, {
include: common.hasIntl,
filter: (opt) => opt === '--icu-data-dir'
Expand Down