crypto: make FIPS related options always awailable

There is no reason to hide FIPS functionality behind build flags.
OpenSSL always provide the information about FIPS availability via
`FIPS_mode()` function.

This makes the user experience more consistent, because the OpenSSL
library is always queried and the `crypto.getFips()` always returns
OpenSSL settings.

Fixes #34903

PR-URL: https://github.com/nodejs/node/pull/36341
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
This commit is contained in:
Vít Ondruch 2020-08-25 14:04:54 +02:00 committed by Michael Dawson
parent 148bc33347
commit f392ac0bbe
15 changed files with 77 additions and 108 deletions

View file

@ -186,8 +186,8 @@ code from strings throw an exception instead. This does not affect the Node.js
added: v6.0.0 added: v6.0.0
--> -->
Enable FIPS-compliant crypto at startup. (Requires Node.js to be built with Enable FIPS-compliant crypto at startup. (Requires Node.js to be built
`./configure --openssl-fips`.) against FIPS-compatible OpenSSL.)
### `--enable-source-maps` ### `--enable-source-maps`
<!-- YAML <!-- YAML
@ -613,8 +613,8 @@ added: v6.9.0
--> -->
Load an OpenSSL configuration file on startup. Among other uses, this can be 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 used to enable FIPS-compliant crypto if Node.js is built
`./configure --openssl-fips`. against FIPS-enabled OpenSSL.
### `--pending-deprecation` ### `--pending-deprecation`
<!-- YAML <!-- YAML

View file

@ -37,12 +37,10 @@ assertCrypto();
const { const {
ERR_CRYPTO_FIPS_FORCED, ERR_CRYPTO_FIPS_FORCED,
ERR_CRYPTO_FIPS_UNAVAILABLE
} = require('internal/errors').codes; } = require('internal/errors').codes;
const constants = internalBinding('constants').crypto; const constants = internalBinding('constants').crypto;
const { getOptionValue } = require('internal/options'); const { getOptionValue } = require('internal/options');
const pendingDeprecation = getOptionValue('--pending-deprecation'); const pendingDeprecation = getOptionValue('--pending-deprecation');
const { fipsMode } = internalBinding('config');
const fipsForced = getOptionValue('--force-fips'); const fipsForced = getOptionValue('--force-fips');
const { const {
getFipsCrypto, getFipsCrypto,
@ -218,10 +216,8 @@ module.exports = {
sign: signOneShot, sign: signOneShot,
setEngine, setEngine,
timingSafeEqual, timingSafeEqual,
getFips: !fipsMode ? getFipsDisabled : getFips: fipsForced ? getFipsForced : getFipsCrypto,
fipsForced ? getFipsForced : getFipsCrypto, setFips: fipsForced ? setFipsForced : setFipsCrypto,
setFips: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto,
verify: verifyOneShot, verify: verifyOneShot,
// Classes // Classes
@ -242,19 +238,11 @@ module.exports = {
secureHeapUsed, secureHeapUsed,
}; };
function setFipsDisabled() {
throw new ERR_CRYPTO_FIPS_UNAVAILABLE();
}
function setFipsForced(val) { function setFipsForced(val) {
if (val) return; if (val) return;
throw new ERR_CRYPTO_FIPS_FORCED(); throw new ERR_CRYPTO_FIPS_FORCED();
} }
function getFipsDisabled() {
return 0;
}
function getFipsForced() { function getFipsForced() {
return 1; return 1;
} }
@ -276,10 +264,8 @@ ObjectDefineProperties(module.exports, {
}, },
// crypto.fips is deprecated. DEP0093. Use crypto.getFips()/crypto.setFips() // crypto.fips is deprecated. DEP0093. Use crypto.getFips()/crypto.setFips()
fips: { fips: {
get: !fipsMode ? getFipsDisabled : get: fipsForced ? getFipsForced : getFipsCrypto,
fipsForced ? getFipsForced : getFipsCrypto, set: fipsForced ? setFipsForced : setFipsCrypto
set: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto
}, },
DEFAULT_ENCODING: { DEFAULT_ENCODING: {
enumerable: false, enumerable: false,

View file

@ -319,9 +319,6 @@
[ 'node_use_openssl=="true"', { [ 'node_use_openssl=="true"', {
'defines': [ 'HAVE_OPENSSL=1' ], 'defines': [ 'HAVE_OPENSSL=1' ],
'conditions': [ 'conditions': [
['openssl_fips != "" or openssl_is_fips=="true"', {
'defines': [ 'NODE_FIPS_MODE' ],
}],
[ 'node_shared_openssl=="false"', { [ 'node_shared_openssl=="false"', {
'dependencies': [ 'dependencies': [
'./deps/openssl/openssl.gyp:openssl', './deps/openssl/openssl.gyp:openssl',

View file

@ -343,12 +343,10 @@ void CipherBase::Init(const char* cipher_type,
HandleScope scope(env()->isolate()); HandleScope scope(env()->isolate());
MarkPopErrorOnReturn mark_pop_error_on_return; MarkPopErrorOnReturn mark_pop_error_on_return;
#ifdef NODE_FIPS_MODE
if (FIPS_mode()) { if (FIPS_mode()) {
return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(), return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(),
"crypto.createCipher() is not supported in FIPS mode."); "crypto.createCipher() is not supported in FIPS mode.");
} }
#endif // NODE_FIPS_MODE
const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type); const EVP_CIPHER* const cipher = EVP_get_cipherbyname(cipher_type);
if (cipher == nullptr) if (cipher == nullptr)
@ -528,14 +526,12 @@ bool CipherBase::InitAuthenticated(
return false; return false;
} }
#ifdef NODE_FIPS_MODE
// TODO(tniessen) Support CCM decryption in FIPS mode // TODO(tniessen) Support CCM decryption in FIPS mode
if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher && FIPS_mode()) { if (mode == EVP_CIPH_CCM_MODE && kind_ == kDecipher && FIPS_mode()) {
THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(), THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env(),
"CCM encryption not supported in FIPS mode"); "CCM encryption not supported in FIPS mode");
return false; return false;
} }
#endif
// Tell OpenSSL about the desired length. // Tell OpenSSL about the desired length.
if (!EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, auth_tag_len, if (!EVP_CIPHER_CTX_ctrl(ctx_.get(), EVP_CTRL_AEAD_SET_TAG, auth_tag_len,

View file

@ -27,7 +27,6 @@ using v8::Value;
namespace crypto { namespace crypto {
namespace { namespace {
bool ValidateDSAParameters(EVP_PKEY* key) { bool ValidateDSAParameters(EVP_PKEY* key) {
#ifdef NODE_FIPS_MODE
/* Validate DSA2 parameters from FIPS 186-4 */ /* Validate DSA2 parameters from FIPS 186-4 */
if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) { if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) {
DSA* dsa = EVP_PKEY_get0_DSA(key); DSA* dsa = EVP_PKEY_get0_DSA(key);
@ -43,7 +42,6 @@ bool ValidateDSAParameters(EVP_PKEY* key) {
(L == 2048 && N == 256) || (L == 2048 && N == 256) ||
(L == 3072 && N == 256); (L == 3072 && N == 256);
} }
#endif // NODE_FIPS_MODE
return true; return true;
} }

View file

@ -133,7 +133,6 @@ void InitCryptoOnce() {
} }
#endif #endif
#ifdef NODE_FIPS_MODE
/* Override FIPS settings in cnf file, if needed. */ /* Override FIPS settings in cnf file, if needed. */
unsigned long err = 0; // NOLINT(runtime/int) unsigned long err = 0; // NOLINT(runtime/int)
if (per_process::cli_options->enable_fips_crypto || if (per_process::cli_options->enable_fips_crypto ||
@ -143,12 +142,10 @@ void InitCryptoOnce() {
} }
} }
if (0 != err) { if (0 != err) {
fprintf(stderr, auto* isolate = Isolate::GetCurrent();
"openssl fips failed: %s\n", auto* env = Environment::GetCurrent(isolate);
ERR_error_string(err, nullptr)); return ThrowCryptoError(env, err);
UNREACHABLE();
} }
#endif // NODE_FIPS_MODE
// Turn off compression. Saves memory and protects against CRIME attacks. // Turn off compression. Saves memory and protects against CRIME attacks.
// No-op with OPENSSL_NO_COMP builds of OpenSSL. // No-op with OPENSSL_NO_COMP builds of OpenSSL.
@ -162,7 +159,6 @@ void InitCryptoOnce() {
NodeBIO::GetMethod(); NodeBIO::GetMethod();
} }
#ifdef NODE_FIPS_MODE
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) { void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(FIPS_mode() ? 1 : 0); args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
} }
@ -180,7 +176,16 @@ void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
return ThrowCryptoError(env, err); return ThrowCryptoError(env, err);
} }
} }
#endif /* NODE_FIPS_MODE */
void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args) {
#ifdef OPENSSL_FIPS
const auto enabled = FIPS_selftest() ? 1 : 0;
#else // OPENSSL_FIPS
const auto enabled = 0;
#endif // OPENSSL_FIPS
args.GetReturnValue().Set(enabled);
}
void CryptoErrorVector::Capture() { void CryptoErrorVector::Capture() {
clear(); clear();
@ -652,10 +657,9 @@ void Initialize(Environment* env, Local<Object> target) {
env->SetMethod(target, "setEngine", SetEngine); env->SetMethod(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE #endif // !OPENSSL_NO_ENGINE
#ifdef NODE_FIPS_MODE
env->SetMethodNoSideEffect(target, "getFipsCrypto", GetFipsCrypto); env->SetMethodNoSideEffect(target, "getFipsCrypto", GetFipsCrypto);
env->SetMethod(target, "setFipsCrypto", SetFipsCrypto); env->SetMethod(target, "setFipsCrypto", SetFipsCrypto);
#endif env->SetMethodNoSideEffect(target, "testFipsCrypto", TestFipsCrypto);
NODE_DEFINE_CONSTANT(target, kCryptoJobAsync); NODE_DEFINE_CONSTANT(target, kCryptoJobAsync);
NODE_DEFINE_CONSTANT(target, kCryptoJobSync); NODE_DEFINE_CONSTANT(target, kCryptoJobSync);

View file

@ -22,6 +22,11 @@
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h> # include <openssl/engine.h>
#endif // !OPENSSL_NO_ENGINE #endif // !OPENSSL_NO_ENGINE
// The FIPS-related functions are only available
// when the OpenSSL itself was compiled with FIPS support.
#ifdef OPENSSL_FIPS
# include <openssl/fips.h>
#endif // OPENSSL_FIPS
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
@ -510,11 +515,11 @@ bool SetEngine(
void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args); void SetEngine(const v8::FunctionCallbackInfo<v8::Value>& args);
#endif // !OPENSSL_NO_ENGINE #endif // !OPENSSL_NO_ENGINE
#ifdef NODE_FIPS_MODE
void GetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args); void GetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
void SetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args); void SetFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
#endif /* NODE_FIPS_MODE */
void TestFipsCrypto(const v8::FunctionCallbackInfo<v8::Value>& args);
class CipherPushContext { class CipherPushContext {
public: public:

View file

@ -1013,11 +1013,11 @@ InitializationResult InitializeOncePerProcess(int argc, char** argv) {
if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs)) if (credentials::SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs))
crypto::UseExtraCaCerts(extra_ca_certs); crypto::UseExtraCaCerts(extra_ca_certs);
} }
#ifdef NODE_FIPS_MODE
// In the case of FIPS builds we should make sure // In the case of FIPS builds we should make sure
// the random source is properly initialized first. // the random source is properly initialized first.
OPENSSL_init(); if (FIPS_mode()) {
#endif // NODE_FIPS_MODE OPENSSL_init();
}
// V8 on Windows doesn't have a good source of entropy. Seed it from // V8 on Windows doesn't have a good source of entropy. Seed it from
// OpenSSL's pool. // OpenSSL's pool.
V8::SetEntropySource(crypto::EntropySource); V8::SetEntropySource(crypto::EntropySource);

View file

@ -42,9 +42,7 @@ static void Initialize(Local<Object> target,
READONLY_FALSE_PROPERTY(target, "hasOpenSSL"); READONLY_FALSE_PROPERTY(target, "hasOpenSSL");
#endif // HAVE_OPENSSL #endif // HAVE_OPENSSL
#ifdef NODE_FIPS_MODE
READONLY_TRUE_PROPERTY(target, "fipsMode"); READONLY_TRUE_PROPERTY(target, "fipsMode");
#endif
#ifdef NODE_HAVE_I18N_SUPPORT #ifdef NODE_HAVE_I18N_SUPPORT

View file

@ -31,6 +31,7 @@ namespace node {
using v8::Context; using v8::Context;
using v8::Local; using v8::Local;
using v8::Object; using v8::Object;
using v8::TryCatch;
using v8::Value; using v8::Value;
namespace crypto { namespace crypto {
@ -39,11 +40,16 @@ void Initialize(Local<Object> target,
Local<Value> unused, Local<Value> unused,
Local<Context> context, Local<Context> context,
void* priv) { void* priv) {
static uv_once_t init_once = UV_ONCE_INIT;
uv_once(&init_once, InitCryptoOnce);
Environment* env = Environment::GetCurrent(context); Environment* env = Environment::GetCurrent(context);
static uv_once_t init_once = UV_ONCE_INIT;
TryCatch try_catch{env->isolate()};
uv_once(&init_once, InitCryptoOnce);
if (try_catch.HasCaught() && !try_catch.HasTerminated()) {
try_catch.ReThrow();
return;
}
AES::Initialize(env, target); AES::Initialize(env, target);
CipherBase::Initialize(env, target); CipherBase::Initialize(env, target);
DiffieHellman::Initialize(env, target); DiffieHellman::Initialize(env, target);

View file

@ -766,7 +766,6 @@ PerProcessOptionsParser::PerProcessOptionsParser(
&PerProcessOptions::ssl_openssl_cert_store); &PerProcessOptions::ssl_openssl_cert_store);
Implies("--use-openssl-ca", "[ssl_openssl_cert_store]"); Implies("--use-openssl-ca", "[ssl_openssl_cert_store]");
ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]"); ImpliesNot("--use-bundled-ca", "[ssl_openssl_cert_store]");
#if NODE_FIPS_MODE
AddOption("--enable-fips", AddOption("--enable-fips",
"enable FIPS crypto at startup", "enable FIPS crypto at startup",
&PerProcessOptions::enable_fips_crypto, &PerProcessOptions::enable_fips_crypto,
@ -775,7 +774,6 @@ PerProcessOptionsParser::PerProcessOptionsParser(
"force FIPS crypto (cannot be disabled)", "force FIPS crypto (cannot be disabled)",
&PerProcessOptions::force_fips_crypto, &PerProcessOptions::force_fips_crypto,
kAllowedInEnvironment); kAllowedInEnvironment);
#endif
AddOption("--secure-heap", AddOption("--secure-heap",
"total size of the OpenSSL secure heap", "total size of the OpenSSL secure heap",
&PerProcessOptions::secure_heap, &PerProcessOptions::secure_heap,

View file

@ -245,10 +245,8 @@ class PerProcessOptions : public Options {
#endif #endif
bool use_openssl_ca = false; bool use_openssl_ca = false;
bool use_bundled_ca = false; bool use_bundled_ca = false;
#if NODE_FIPS_MODE
bool enable_fips_crypto = false; bool enable_fips_crypto = false;
bool force_fips_crypto = false; bool force_fips_crypto = false;
#endif
#endif #endif
// Per-process because reports can be triggered outside a known V8 context. // Per-process because reports can be triggered outside a known V8 context.

View file

@ -8,8 +8,6 @@ const common = require('../common');
const assert = require('assert'); const assert = require('assert');
const { exec } = require('child_process'); const { exec } = require('child_process');
const { internalBinding } = require('internal/test/binding');
const { fipsMode } = internalBinding('config');
let stdOut; let stdOut;
@ -28,9 +26,8 @@ function validateNodePrintHelp() {
const cliHelpOptions = [ const cliHelpOptions = [
{ compileConstant: HAVE_OPENSSL, { compileConstant: HAVE_OPENSSL,
flags: [ '--openssl-config=...', '--tls-cipher-list=...', flags: [ '--openssl-config=...', '--tls-cipher-list=...',
'--use-bundled-ca', '--use-openssl-ca' ] }, '--use-bundled-ca', '--use-openssl-ca',
{ compileConstant: fipsMode, '--enable-fips', '--force-fips' ] },
flags: [ '--enable-fips', '--force-fips' ] },
{ compileConstant: NODE_HAVE_I18N_SUPPORT, { compileConstant: NODE_HAVE_I18N_SUPPORT,
flags: [ '--icu-data-dir=...', 'NODE_ICU_DATA' ] }, flags: [ '--icu-data-dir=...', 'NODE_ICU_DATA' ] },
{ compileConstant: HAVE_INSPECTOR, { compileConstant: HAVE_INSPECTOR,

View file

@ -9,27 +9,20 @@ const spawnSync = require('child_process').spawnSync;
const path = require('path'); const path = require('path');
const fixtures = require('../common/fixtures'); const fixtures = require('../common/fixtures');
const { internalBinding } = require('internal/test/binding'); const { internalBinding } = require('internal/test/binding');
const { fipsMode } = internalBinding('config'); const { testFipsCrypto } = internalBinding('crypto');
const FIPS_ENABLED = 1; const FIPS_ENABLED = 1;
const FIPS_DISABLED = 0; 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 = const FIPS_ERROR_STRING2 =
'Error [ERR_CRYPTO_FIPS_FORCED]: Cannot set FIPS mode, it was forced with ' + 'Error [ERR_CRYPTO_FIPS_FORCED]: Cannot set FIPS mode, it was forced with ' +
'--force-fips at startup.'; '--force-fips at startup.';
const OPTION_ERROR_STRING = 'bad option'; const FIPS_UNSUPPORTED_ERROR_STRING = 'fips mode not supported';
const CNF_FIPS_ON = fixtures.path('openssl_fips_enabled.cnf'); const CNF_FIPS_ON = fixtures.path('openssl_fips_enabled.cnf');
const CNF_FIPS_OFF = fixtures.path('openssl_fips_disabled.cnf'); const CNF_FIPS_OFF = fixtures.path('openssl_fips_disabled.cnf');
let num_children_ok = 0; let num_children_ok = 0;
function compiledWithFips() {
return fipsMode ? true : false;
}
function sharedOpenSSL() { function sharedOpenSSL() {
return process.config.variables.node_shared_openssl; return process.config.variables.node_shared_openssl;
} }
@ -75,17 +68,17 @@ testHelper(
// --enable-fips should turn FIPS mode on // --enable-fips should turn FIPS mode on
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'], ['--enable-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
process.env); process.env);
// --force-fips should turn FIPS mode on // --force-fips should turn FIPS mode on
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'], ['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
process.env); process.env);
@ -106,7 +99,7 @@ if (!sharedOpenSSL()) {
testHelper( testHelper(
'stdout', 'stdout',
[`--openssl-config=${CNF_FIPS_ON}`], [`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()', 'require("crypto").getFips()',
process.env); process.env);
@ -114,7 +107,7 @@ if (!sharedOpenSSL()) {
testHelper( testHelper(
'stdout', 'stdout',
[], [],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()', 'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_ON })); Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_ON }));
@ -122,7 +115,7 @@ if (!sharedOpenSSL()) {
testHelper( testHelper(
'stdout', 'stdout',
[`--openssl-config=${CNF_FIPS_ON}`], [`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, testFipsCrypto() ? FIPS_ENABLED : FIPS_DISABLED,
'require("crypto").getFips()', 'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));
} }
@ -136,50 +129,50 @@ testHelper(
// --enable-fips should take precedence over OpenSSL config file // --enable-fips should take precedence over OpenSSL config file
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips', `--openssl-config=${CNF_FIPS_OFF}`], ['--enable-fips', `--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
process.env); process.env);
// OPENSSL_CONF should _not_ make a difference to --enable-fips // OPENSSL_CONF should _not_ make a difference to --enable-fips
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'], ['--enable-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));
// --force-fips should take precedence over OpenSSL config file // --force-fips should take precedence over OpenSSL config file
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips', `--openssl-config=${CNF_FIPS_OFF}`], ['--force-fips', `--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
process.env); process.env);
// Using OPENSSL_CONF should not make a difference to --force-fips // Using OPENSSL_CONF should not make a difference to --force-fips
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'], ['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").getFips()', 'require("crypto").getFips()',
Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF })); Object.assign({}, process.env, { 'OPENSSL_CONF': CNF_FIPS_OFF }));
// setFipsCrypto should be able to turn FIPS mode on // setFipsCrypto should be able to turn FIPS mode on
testHelper( 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").setFips(true),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
process.env); process.env);
// setFipsCrypto should be able to turn FIPS mode on and off // setFipsCrypto should be able to turn FIPS mode on and off
testHelper( 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(true),' +
'require("crypto").setFips(false),' + 'require("crypto").setFips(false),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
@ -187,27 +180,27 @@ testHelper(
// setFipsCrypto takes precedence over OpenSSL config file, FIPS on // setFipsCrypto takes precedence over OpenSSL config file, FIPS on
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
[`--openssl-config=${CNF_FIPS_OFF}`], [`--openssl-config=${CNF_FIPS_OFF}`],
compiledWithFips() ? FIPS_ENABLED : FIPS_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' + '(require("crypto").setFips(true),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
process.env); process.env);
// setFipsCrypto takes precedence over OpenSSL config file, FIPS off // setFipsCrypto takes precedence over OpenSSL config file, FIPS off
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', 'stdout',
[`--openssl-config=${CNF_FIPS_ON}`], [`--openssl-config=${CNF_FIPS_ON}`],
compiledWithFips() ? FIPS_DISABLED : FIPS_ERROR_STRING, FIPS_DISABLED,
'(require("crypto").setFips(false),' + '(require("crypto").setFips(false),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
process.env); process.env);
// --enable-fips does not prevent use of setFipsCrypto API // --enable-fips does not prevent use of setFipsCrypto API
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--enable-fips'], ['--enable-fips'],
compiledWithFips() ? FIPS_DISABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_DISABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(false),' + '(require("crypto").setFips(false),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
process.env); process.env);
@ -216,15 +209,15 @@ testHelper(
testHelper( testHelper(
'stderr', 'stderr',
['--force-fips'], ['--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)', 'require("crypto").setFips(false)',
process.env); process.env);
// --force-fips makes setFipsCrypto enable a no-op (FIPS stays on) // --force-fips makes setFipsCrypto enable a no-op (FIPS stays on)
testHelper( testHelper(
compiledWithFips() ? 'stdout' : 'stderr', testFipsCrypto() ? 'stdout' : 'stderr',
['--force-fips'], ['--force-fips'],
compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ENABLED : FIPS_UNSUPPORTED_ERROR_STRING,
'(require("crypto").setFips(true),' + '(require("crypto").setFips(true),' +
'require("crypto").getFips())', 'require("crypto").getFips())',
process.env); process.env);
@ -233,7 +226,7 @@ testHelper(
testHelper( testHelper(
'stderr', 'stderr',
['--force-fips', '--enable-fips'], ['--force-fips', '--enable-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)', 'require("crypto").setFips(false)',
process.env); process.env);
@ -241,6 +234,6 @@ testHelper(
testHelper( testHelper(
'stderr', 'stderr',
['--enable-fips', '--force-fips'], ['--enable-fips', '--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING, testFipsCrypto() ? FIPS_ERROR_STRING2 : FIPS_UNSUPPORTED_ERROR_STRING,
'require("crypto").setFips(false)', 'require("crypto").setFips(false)',
process.env); process.env);

View file

@ -51,17 +51,10 @@ const conditionalOpts = [
'--use-openssl-ca', '--use-openssl-ca',
'--secure-heap', '--secure-heap',
'--secure-heap-min', '--secure-heap-min',
'--enable-fips',
'--force-fips',
].includes(opt); ].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')
}, { }, {
include: common.hasIntl, include: common.hasIntl,
filter: (opt) => opt === '--icu-data-dir' filter: (opt) => opt === '--icu-data-dir'