Skip to content

Commit

Permalink
crypto: migrate setFipsCrypto to internal/errors
Browse files Browse the repository at this point in the history
With the exception of ThrowCryptoError, use internal/errors
to report fips unavailable or forced

PR-URL: #16428
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
  • Loading branch information
jasnell committed Oct 27, 2017
1 parent a0f7ae6 commit ee76f31
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 19 deletions.
12 changes: 12 additions & 0 deletions doc/api/errors.md
Original file line number Original file line 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 Used when an invalid crypto engine identifier is passed to
[`require('crypto').setEngine()`][]. [`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> <a id="ERR_CRYPTO_HASH_DIGEST_NO_UTF16"></a>
### ERR_CRYPTO_HASH_DIGEST_NO_UTF16 ### 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 Used when an attempt is made to use a `zlib` object after it has already been
closed. closed.


[`--force-fips`]: cli.html#cli_force_fips
[`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b [`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b
[`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback [`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback
[`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE [`ERR_INVALID_ARG_TYPE`]: #ERR_INVALID_ARG_TYPE
Expand Down
28 changes: 26 additions & 2 deletions lib/crypto.js
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ const {
} = require('internal/util'); } = require('internal/util');
assertCrypto(); assertCrypto();


const errors = require('internal/errors');
const constants = process.binding('constants').crypto; const constants = process.binding('constants').crypto;
const {
fipsMode,
fipsForced
} = process.binding('config');
const { const {
getFipsCrypto, getFipsCrypto,
setFipsCrypto, setFipsCrypto,
Expand Down Expand Up @@ -173,10 +178,29 @@ module.exports = exports = {
Verify 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, { Object.defineProperties(exports, {
fips: { fips: {
get: getFipsCrypto, get: !fipsMode ? getFipsDisabled :
set: setFipsCrypto fipsForced ? getFipsForced : getFipsCrypto,
set: !fipsMode ? setFipsDisabled :
fipsForced ? setFipsForced : setFipsCrypto
}, },
DEFAULT_ENCODING: { DEFAULT_ENCODING: {
enumerable: true, enumerable: true,
Expand Down
3 changes: 3 additions & 0 deletions lib/internal/errors.js
Original file line number Original file line 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_CPU_USAGE', 'Unable to obtain cpu usage %s');
E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s'); E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s');
E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found'); 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_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16');
E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called'); E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called');
E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed'); 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 Original file line Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ static void InitConfig(Local<Object> target,
Environment* env = Environment::GetCurrent(context); Environment* env = Environment::GetCurrent(context);
Isolate* isolate = env->isolate(); 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 #ifdef NODE_HAVE_I18N_SUPPORT


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


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


void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) { void SetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
CHECK(!force_fips_crypto);
Environment* env = Environment::GetCurrent(args); Environment* env = Environment::GetCurrent(args);
#ifdef NODE_FIPS_MODE
const bool enabled = FIPS_mode(); const bool enabled = FIPS_mode();
const bool enable = args[0]->BooleanValue(); const bool enable = args[0]->BooleanValue();
if (enable == enabled) if (enable == enabled)
return; // No action needed. return; // No action needed.
if (force_fips_crypto) { if (!FIPS_mode_set(enable)) {
return env->ThrowError(
"Cannot set FIPS mode, it was forced with --force-fips at startup.");
} else if (!FIPS_mode_set(enable)) {
unsigned long err = ERR_get_error(); // NOLINT(runtime/int) unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
return ThrowCryptoError(env, err); 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, void InitCrypto(Local<Object> target,
Local<Value> unused, Local<Value> unused,
Expand All @@ -5997,8 +5989,12 @@ void InitCrypto(Local<Object> target,
#ifndef OPENSSL_NO_ENGINE #ifndef OPENSSL_NO_ENGINE
env->SetMethod(target, "setEngine", SetEngine); env->SetMethod(target, "setEngine", SetEngine);
#endif // !OPENSSL_NO_ENGINE #endif // !OPENSSL_NO_ENGINE

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

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


const FIPS_ENABLED = 1; const FIPS_ENABLED = 1;
const FIPS_DISABLED = 0; 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 ' +
'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 OPTION_ERROR_STRING = 'bad option';


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


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


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

0 comments on commit ee76f31

Please sign in to comment.