diff --git a/doc/api/errors.md b/doc/api/errors.md
index 753f84f7c5..fcc39ab2ac 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -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()`][].
+
+### 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.
+
+
+### ERR_CRYPTO_FIPS_UNAVAILABLE
+
+Used when trying to enable or disable FIPS mode when FIPS is not available.
+
### ERR_CRYPTO_HASH_DIGEST_NO_UTF16
@@ -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
diff --git a/lib/crypto.js b/lib/crypto.js
index 0082172c5c..d7c59f553e 100644
--- a/lib/crypto.js
+++ b/lib/crypto.js
@@ -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,
@@ -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,
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index f539cdc955..6b647ee522 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -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');
diff --git a/src/node_config.cc b/src/node_config.cc
index 38ce2a47bb..8af3472b0f 100644
--- a/src/node_config.cc
+++ b/src/node_config.cc
@@ -44,6 +44,12 @@ static void InitConfig(Local