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

crypto: migrate setFipsCrypto to internal/errors #16428

Closed
wants to merge 1 commit into from
Closed
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
13 changes: 13 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,17 @@ Used when an invalid value for the `format` argument has been passed to the
Used when an invalid crypto engine identifier is passed to
[`require('crypto').setEngine()`][].

<a id="ERR_CRYPTO_FIPS_FORCED"></a>
### ERR_CRYPTO_FIPS_FORCED

Used when trying to enable or disable FIPS mode in the crypto module and
the [`--force-fips`][] command-line argument is used.

<a id="ERR_CRYPTO_FIPS_UNAVAILABLE"></a>
### ERR_CRYPTO_FIPS_UNAVAILABLE

Used when trying to enable or disable FIPS mode when FIPS is not available.

<a id="ERR_CRYPTO_HASH_DIGEST_NO_UTF16"></a>
### ERR_CRYPTO_HASH_DIGEST_NO_UTF16

Expand Down Expand Up @@ -1440,6 +1451,7 @@ Used when a given value is out of the accepted range.
Used when an attempt is made to use a `zlib` object after it has already been
closed.

[`--force-fips`]: cli.html#cli_force_fips
[`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b
[`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback
[`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE
Expand All @@ -1463,6 +1475,7 @@ closed.
[`require('crypto').setEngine()`]: crypto.html#crypto_crypto_setengine_engine_flags
[`server.listen()`]: net.html#net_server_listen
[ES6 module]: esm.html
[`require('crypto').fips`]: crypto.html#crypto_crypto_fips
[Node.js Error Codes]: #nodejs-error-codes
[V8's stack trace API]: https://github.com/v8/v8/wiki/Stack-Trace-API
[WHATWG URL API]: url.html#url_the_whatwg_url_api
Expand Down
28 changes: 26 additions & 2 deletions lib/crypto.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ const {
} = require('internal/util');
assertCrypto();

const errors = require('internal/errors');
const constants = process.binding('constants').crypto;
const {
fipsMode,
fipsForced
} = process.binding('config');
const {
getFipsCrypto,
setFipsCrypto,
Expand Down Expand Up @@ -173,10 +178,29 @@ module.exports = exports = {
Verify
};

function setFipsDisabled() {
throw new errors.Error('ERR_CRYPTO_FIPS_UNAVAILABLE');
}

function setFipsForced(val) {
if (val) return;
throw new errors.Error('ERR_CRYPTO_FIPS_FORCED');
}

function getFipsDisabled() {
return 0;
}

function getFipsForced() {
return 1;
}

Object.defineProperties(exports, {
fips: {
get: getFipsCrypto,
set: setFipsCrypto
get: !fipsMode ? getFipsDisabled :
fipsForced ? getFipsForced : getFipsCrypto,
set: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto
},
DEFAULT_ENCODING: {
enumerable: true,
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ E('ERR_CONSOLE_WRITABLE_STREAM',
E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s');
E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s');
E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found');
E('ERR_CRYPTO_FIPS_FORCED',
'Cannot set FIPS mode, it was forced with --force-fips at startup.');
E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.');
E('ERR_CRYPTO_HASH_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16');
E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called');
E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed');
Expand Down
6 changes: 6 additions & 0 deletions src/node_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ static void InitConfig(Local<Object> target,
Environment* env = Environment::GetCurrent(context);
Isolate* isolate = env->isolate();

#ifdef NODE_FIPS_MODE
READONLY_BOOLEAN_PROPERTY("fipsMode");
if (force_fips_crypto)
READONLY_BOOLEAN_PROPERTY("fipsForced");
#endif

#ifdef NODE_HAVE_I18N_SUPPORT

READONLY_BOOLEAN_PROPERTY("hasIntl");
Expand Down
22 changes: 9 additions & 13 deletions src/node_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5946,32 +5946,24 @@ void SetEngine(const FunctionCallbackInfo<Value>& args) {
}
#endif // !OPENSSL_NO_ENGINE

#ifdef NODE_FIPS_MODE
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
if (FIPS_mode()) {
args.GetReturnValue().Set(1);
} else {
args.GetReturnValue().Set(0);
}
args.GetReturnValue().Set(FIPS_mode() ? 1 : 0);
}

void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
CHECK(!force_fips_crypto);
Environment* env = Environment::GetCurrent(args);
#ifdef NODE_FIPS_MODE
const bool enabled = FIPS_mode();
const bool enable = args[0]->BooleanValue();
if (enable == enabled)
return; // No action needed.
if (force_fips_crypto) {
return env->ThrowError(
"Cannot set FIPS mode, it was forced with --force-fips at startup.");
} else if (!FIPS_mode_set(enable)) {
if (!FIPS_mode_set(enable)) {
unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
return ThrowCryptoError(env, err);
}
#else
return env->ThrowError("Cannot set FIPS mode in a non-FIPS build.");
#endif /* NODE_FIPS_MODE */
}
#endif /* NODE_FIPS_MODE */

void InitCrypto(Local<Object> target,
Local<Value> unused,
Expand All @@ -5997,8 +5989,12 @@ void InitCrypto(Local<Object> target,
#ifndef OPENSSL_NO_ENGINE
env->SetMethod(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE

#ifdef NODE_FIPS_MODE
env->SetMethod(target, "getFipsCrypto", GetFipsCrypto);
env->SetMethod(target, "setFipsCrypto", SetFipsCrypto);
#endif

env->SetMethod(target, "PBKDF2", PBKDF2);
env->SetMethod(target, "randomBytes", RandomBytes);
env->SetMethod(target, "randomFill", RandomBytesBuffer);
Expand Down
13 changes: 9 additions & 4 deletions test/parallel/test-crypto-fips.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ const fixtures = require('../common/fixtures');

const FIPS_ENABLED = 1;
const FIPS_DISABLED = 0;
const FIPS_ERROR_STRING = 'Error: Cannot set FIPS mode';
const FIPS_ERROR_STRING =
'Error [ERR_CRYPTO_FIPS_UNAVAILABLE]: Cannot set FIPS mode in a ' +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be two flavors of this string, the tests below needs update

'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 CNF_FIPS_ON = fixtures.path('openssl_fips_enabled.cnf');
Expand Down Expand Up @@ -208,7 +213,7 @@ testHelper(
testHelper(
'stderr',
['--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING : OPTION_ERROR_STRING,
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
'require("crypto").fips = false',
process.env);

Expand All @@ -225,14 +230,14 @@ testHelper(
testHelper(
'stderr',
['--force-fips', '--enable-fips'],
compiledWithFips() ? FIPS_ERROR_STRING : OPTION_ERROR_STRING,
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
'require("crypto").fips = false',
process.env);

//--enable-fips and --force-fips order does not matter
testHelper(
'stderr',
['--enable-fips', '--force-fips'],
compiledWithFips() ? FIPS_ERROR_STRING : OPTION_ERROR_STRING,
compiledWithFips() ? FIPS_ERROR_STRING2 : OPTION_ERROR_STRING,
'require("crypto").fips = false',
process.env);