diff --git a/BUILDING.md b/BUILDING.md index 02ea54c2f8a..e477d46863f 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -1032,11 +1032,11 @@ as `deps/icu` (You'll have: `deps/icu/source/...`) ### Configure OpenSSL appname Node.js can use an OpenSSL configuration file by specifying the environment -variable `OPENSSL_CONF`, or using the command line option `--openssl-conf`, and -if none of those are specified will default to reading the default OpenSSL -configuration file `openssl.cnf`. Node.js will only read a section that is by -default named `nodejs_conf`, but this name can be overridden using the following -configure option: +variable `OPENSSL_CONF`, or using the command line option `--openssl-config`, +which takes precedence. If neither is specified, Node.js defaults to reading the +default OpenSSL configuration file `openssl.cnf`. Node.js will only read a +section that is by default named `nodejs_conf`, but this name can be overridden +using the following configure option: ```bash ./configure --openssl-conf-name= @@ -1048,6 +1048,8 @@ Node.js supports FIPS when statically or dynamically linked with OpenSSL 3 via [OpenSSL's provider model](https://docs.openssl.org/3.0/man7/crypto/#OPENSSL-PROVIDERS). It is not necessary to rebuild Node.js to enable support for FIPS. +When using OpenSSL 1.1.1, Node.js must be built against a FIPS-capable OpenSSL. + See [FIPS mode](doc/api/crypto.md#fips-mode) for more information on how to enable FIPS support in Node.js. diff --git a/doc/api/cli.md b/doc/api/cli.md index e0d13b406df..2052f010f4b 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -882,8 +882,9 @@ priority than `--dns-result-order`. added: v6.0.0 --> -Enable FIPS-compliant crypto at startup. (Requires Node.js to be built -against FIPS-compatible OpenSSL.) +Enable [FIPS mode][] at startup. With OpenSSL 3, a configured provider named +`fips` must be available and initialize successfully. With OpenSSL 1.1.1, +Node.js must be built against a FIPS-capable OpenSSL. ### `--enable-source-maps` @@ -1582,8 +1583,8 @@ Disable loading native addons that are not [context-aware][]. added: v6.0.0 --> -Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.) -(Same requirements as `--enable-fips`.) +Enable [FIPS mode][] at startup and prevent it from being disabled from script +code. The same OpenSSL requirements as [`--enable-fips`][] apply. ### `--force-node-api-uncaught-exceptions-policy` @@ -2273,9 +2274,11 @@ usually only useful for developers debugging Node.js itself. 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 -against FIPS-enabled OpenSSL. +Load an OpenSSL configuration file on startup. The file can activate an +OpenSSL 3 FIPS provider or configure a FIPS-capable OpenSSL 1.1.1 build. See +[FIPS mode][]. + +This option takes precedence over the `OPENSSL_CONF` environment variable. ### `--openssl-legacy-provider` @@ -4256,9 +4259,8 @@ environment variable is arbitrary. added: v6.11.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`. +Load an OpenSSL configuration file on startup. The file can be used as part of +a [FIPS mode][] configuration. If the [`--openssl-config`][] command-line option is used, the environment variable is ignored. @@ -4465,6 +4467,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 [ECMAScript module]: esm.md#modules-ecmascript-modules [EventSource Web API]: https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events [ExperimentalWarning: `vm.measureMemory` is an experimental feature]: vm.md#vmmeasurememoryoptions +[FIPS mode]: crypto.md#fips-mode [File System Permissions]: permissions.md#file-system-permissions [Loading ECMAScript modules using `require()`]: modules.md#loading-ecmascript-modules-using-require [Module resolution and loading]: packages.md#module-resolution-and-loading @@ -4494,6 +4497,7 @@ node --stack-trace-limit=12 -p -e "Error.stackTraceLimit" # prints 12 [`--cpu-prof-dir`]: #--cpu-prof-dir [`--diagnostic-dir`]: #--diagnostic-dirdirectory [`--disable-sigusr1`]: #--disable-sigusr1 +[`--enable-fips`]: #--enable-fips [`--env-file-if-exists`]: #--env-file-if-existsfile [`--env-file`]: #--env-filefile [`--experimental-sea-config`]: single-executable-applications.md#1-generating-single-executable-preparation-blobs diff --git a/doc/api/crypto.md b/doc/api/crypto.md index f83e9430c33..dcef80701f1 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -4337,11 +4337,8 @@ deprecated: v10.0.0 > Stability: 0 - Deprecated -Property for checking and controlling whether a FIPS compliant crypto provider -is currently in use. Setting to true requires a FIPS build of Node.js. - -This property is deprecated. Please use `crypto.setFips()` and -`crypto.getFips()` instead. +Deprecated property for checking and controlling [FIPS mode][]. Use +[`crypto.getFips()`][] and [`crypto.setFips()`][] instead. ### `crypto.generateKey(type, options, callback)` @@ -4932,9 +4929,14 @@ console.log(aliceSecret === bobSecret); added: v10.0.0 --> -* Returns: {number} `1` if and only if a FIPS compliant crypto provider is - currently in use, `0` otherwise. A future semver-major release may change - the return type of this API to a {boolean}. +* Returns: {number} `1` if FIPS mode is enabled, `0` otherwise. A future + semver-major release may change the return type of this API to a {boolean}. + +With OpenSSL 3, this reports whether the default property query includes +`fips=yes`. It does not establish that a FIPS provider is loaded or validated. +It can return `1` even when a requested cryptographic implementation cannot be +fetched because no loaded provider supplies a match for `fips=yes`. See [FIPS +mode][]. ### `crypto.getHashes()` @@ -6231,10 +6233,33 @@ is a bit field taking one of or a mix of the following flags (defined in added: v10.0.0 --> -* `bool` {boolean} `true` to enable FIPS mode. +* `bool` {boolean} `true` to enable FIPS mode, `false` to disable it. -Enables the FIPS compliant crypto provider in a FIPS-enabled Node.js build. -Throws an error if FIPS mode is not available. +Changes [FIPS mode][]. With OpenSSL 3, this only adds or removes `fips=yes` in +the default property query. It does not install, load, initialize, or validate +a FIPS provider. For a usable FIPS configuration, install the provider and +configure OpenSSL to load it when Node.js starts, as described in [FIPS +mode][]. + +If no loaded provider supplies a requested cryptographic implementation +matching `fips=yes`, the call can still succeed and `crypto.getFips()` can still +return `1`, but fetching that implementation fails. Affected `node:crypto` +operations typically fail with `ERR_OSSL_EVP_UNSUPPORTED`. Operations that do +not require a new fetch, including those using previously fetched +implementations or initialized operation contexts, may still succeed. Call this +method during application initialization, before application code uses other +OpenSSL-backed APIs. + +This method only affects subsequent algorithm fetches. Node.js initializes some +OpenSSL state before application code runs. When the property query must be +active from process startup, set `default_properties = fips=yes` in the OpenSSL +configuration or use [`--enable-fips`][] or [`--force-fips`][]. The command-line +flags additionally require a configured provider named `fips` to initialize and +pass its self-test; Node.js fails to start otherwise. + +Throws an error if OpenSSL cannot change the state. FIPS mode cannot be +disabled when Node.js was started with `--force-fips`. With OpenSSL 1.1.1, +enabling FIPS mode requires a FIPS-capable OpenSSL build. ### `crypto.sign(algorithm, data, key[, callback])` @@ -6679,64 +6704,32 @@ console.log(receivedPlaintext); ### FIPS mode -When using OpenSSL 3, Node.js supports FIPS 140-2 when used with an appropriate -OpenSSL 3 provider, such as the [FIPS provider from OpenSSL 3][] which can be -installed by following the instructions in [OpenSSL's FIPS README file][]. +Node.js exposes the FIPS support provided by the linked OpenSSL library. Node.js +is not itself FIPS validated. Validation belongs to a specific OpenSSL module or +provider and only applies when it is deployed according to its security policy. +Vendor-provided Node.js or OpenSSL builds can require a different configuration; +follow the vendor's documentation for those builds. -For FIPS support in Node.js you will need: +With OpenSSL 1.1.1, Node.js must be built against a FIPS-capable OpenSSL library. + +With OpenSSL 3, FIPS support uses the provider model described in the +[OpenSSL FIPS module guide][]. Using FIPS-approved implementations requires: * A correctly installed OpenSSL 3 FIPS provider. * An OpenSSL 3 [FIPS module configuration file][]. -* An OpenSSL 3 configuration file that references the FIPS module - configuration file. +* The FIPS provider to be loaded into the OpenSSL library context used by + Node.js, normally by activating it in an OpenSSL configuration file when + Node.js starts. +* The default property query to include `fips=yes` when cryptographic + implementations are fetched. This can be set from process startup by the + OpenSSL configuration, [`--enable-fips`][], or [`--force-fips`][], or for + subsequent fetches by `crypto.setFips(true)`. -Node.js will need to be configured with an OpenSSL configuration file that -points to the FIPS provider. An example configuration file looks like this: - -```text -nodejs_conf = nodejs_init - -.include //fipsmodule.cnf - -[nodejs_init] -providers = provider_sect - -[provider_sect] -default = default_sect -# The fips section name should match the section name inside the -# included fipsmodule.cnf. -fips = fips_sect - -[default_sect] -activate = 1 -``` - -where `fipsmodule.cnf` is the FIPS module configuration file generated from the -FIPS provider installation step: - -```bash -openssl fipsinstall -``` - -Set the `OPENSSL_CONF` environment variable to point to -your configuration file and `OPENSSL_MODULES` to the location of the FIPS -provider dynamic library. e.g. - -```bash -export OPENSSL_CONF=//nodejs.cnf -export OPENSSL_MODULES=//ossl-modules -``` - -FIPS mode can then be enabled in Node.js either by: - -* Starting Node.js with `--enable-fips` or `--force-fips` command line flags. -* Programmatically calling `crypto.setFips(true)`. - -Optionally FIPS mode can be enabled in Node.js via the OpenSSL configuration -file. e.g. +An example OpenSSL 3 configuration file looks like this: ```text nodejs_conf = nodejs_init +config_diagnostics = 1 .include //fipsmodule.cnf @@ -6745,18 +6738,87 @@ providers = provider_sect alg_section = algorithm_sect [provider_sect] -default = default_sect # The fips section name should match the section name inside the # included fipsmodule.cnf. fips = fips_sect +base = base_sect -[default_sect] +[base_sect] activate = 1 [algorithm_sect] default_properties = fips=yes ``` +The `fipsmodule.cnf` file is generated as part of the FIPS provider installation +and contains module integrity and self-test information. The exact command and +arguments are installation-specific; see [OpenSSL FIPS configuration][] and the +[OpenSSL FIPS module guide][]. The installation uses `openssl fipsinstall`. + +The example activates the provider and enables the `fips=yes` property query +when Node.js starts. To activate the provider at startup but enable the property +query later with `crypto.setFips(true)`, omit `alg_section = algorithm_sect` and +the `[algorithm_sect]` block. The provider must still be loaded; when using this +startup configuration, keep its activation enabled. `crypto.setFips(true)` +should be called before application code uses other OpenSSL-backed APIs. It is +not equivalent to enabling the property query from process startup because +Node.js initializes some OpenSSL state before application code runs. Use the +example as written, [`--enable-fips`][], or [`--force-fips`][] when the property +query must be active from process startup. + +`config_diagnostics` causes configuration errors to prevent startup instead of +being ignored. The `base` provider supplies non-cryptographic supporting +algorithms, such as encoders and decoders, that are commonly needed alongside +the FIPS provider. `default_properties = fips=yes` restricts OpenSSL's default +algorithm selection to implementations that match `fips=yes`. + +Set `OPENSSL_CONF` to the OpenSSL configuration file. For a dynamically loaded +provider, `OPENSSL_MODULES` can set the directory containing the provider module. +For example: + +```bash +export OPENSSL_CONF=//nodejs.cnf +export OPENSSL_MODULES=//ossl-modules +``` + +The [`--openssl-config`][] command-line option selects the configuration file and +takes precedence over `OPENSSL_CONF`. If neither is set, OpenSSL's default +configuration file is used. + +By default, Node.js reads the `nodejs_conf` section instead of OpenSSL's usual +`openssl_conf` section. Use [`--openssl-shared-config`][] to read `openssl_conf`, +or build Node.js with `./configure --openssl-conf-name=` to change the +default section name. + +On OpenSSL 3, the configuration above enables the `fips=yes` property query at +startup. The following controls are also available: + +* [`--enable-fips`][] and [`--force-fips`][] enable the property query and + additionally require the configured provider named `fips` to initialize and + pass its self-test. Node.js exits if that check fails. `--force-fips` also + prevents FIPS mode from being disabled from script code. +* [`crypto.setFips()`][] changes the FIPS/property-query state. On OpenSSL 3, it + does not install, load, initialize, or validate a provider. Implementations + fetched before the call are not changed. +* [`crypto.getFips()`][] reports the FIPS/property-query state. On OpenSSL 3, a + return value of `1` does not prove that a FIPS provider is loaded or validated. + +With OpenSSL 1.1.1, these controls use the library's FIPS mode support and +require a FIPS-capable OpenSSL build. + +Only algorithms available under the active FIPS settings can be used. With +OpenSSL 3, if no loaded provider supplies a requested cryptographic +implementation matching `fips=yes`, fetching it fails, typically with +`ERR_OSSL_EVP_UNSUPPORTED`. The same error can occur for algorithms that +Node.js supports when FIPS mode is disabled but that are unavailable under the +active FIPS settings. + +OpenSSL documents that the same FIPS provider cannot be used by multiple copies +of `libcrypto` in one process. This can affect native addons that load another +copy of `libcrypto`; OpenSSL's documented workaround is to use a separate copy +of the provider for each `libcrypto` instance. See [OpenSSL FIPS provider +limitations][]. + ## Crypto constants The following constants exported by `crypto.constants` apply to various uses of @@ -7038,15 +7100,17 @@ See the [list of SSL OP Flags][] for details. [CVE-2021-44532]: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44532 [Caveats]: #support-for-weak-or-compromised-algorithms [Crypto constants]: #crypto-constants -[FIPS module configuration file]: https://www.openssl.org/docs/man3.0/man5/fips_config.html -[FIPS provider from OpenSSL 3]: https://www.openssl.org/docs/man3.0/man7/crypto.html#FIPS-provider +[FIPS mode]: #fips-mode +[FIPS module configuration file]: https://docs.openssl.org/3.0/man5/fips_config/ [HTML 5.2]: https://www.w3.org/TR/html52/changes.html#features-removed [JWK]: https://tools.ietf.org/html/rfc7517 [Key usages]: webcrypto.md#cryptokeyusages [NIST SP 800-131A]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf [NIST SP 800-132]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-132.pdf [NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf -[OpenSSL's FIPS README file]: https://github.com/openssl/openssl/blob/openssl-3.0/README-FIPS.md +[OpenSSL FIPS configuration]: https://docs.openssl.org/3.0/man5/fips_config/ +[OpenSSL FIPS module guide]: https://docs.openssl.org/master/man7/fips_module/ +[OpenSSL FIPS provider limitations]: https://docs.openssl.org/3.6/man7/OSSL_PROVIDER-FIPS/ [OpenSSL's SPKAC implementation]: https://www.openssl.org/docs/man3.0/man1/openssl-spkac.html [Permission Model]: permissions.md#permission-model [RFC 1421]: https://www.rfc-editor.org/rfc/rfc1421.txt @@ -7063,6 +7127,10 @@ See the [list of SSL OP Flags][] for details. [RFC 9562]: https://www.rfc-editor.org/rfc/rfc9562.txt [Web Crypto API documentation]: webcrypto.md [`--allow-openssl-store`]: cli.md#--allow-openssl-store +[`--enable-fips`]: cli.md#--enable-fips +[`--force-fips`]: cli.md#--force-fips +[`--openssl-config`]: cli.md#--openssl-configfile +[`--openssl-shared-config`]: cli.md#--openssl-shared-config [`BN_is_prime_ex`]: https://www.openssl.org/docs/man1.1.1/man3/BN_is_prime_ex.html [`Buffer`]: buffer.md [`DH_generate_key()`]: https://www.openssl.org/docs/man3.0/man3/DH_generate_key.html @@ -7089,6 +7157,7 @@ See the [list of SSL OP Flags][] for details. [`crypto.generateKeyPair()`]: #cryptogeneratekeypairtype-options-callback [`crypto.getCurves()`]: #cryptogetcurves [`crypto.getDiffieHellman()`]: #cryptogetdiffiehellmangroupname +[`crypto.getFips()`]: #cryptogetfips [`crypto.getHashes()`]: #cryptogethashes [`crypto.hash()`]: #cryptohashalgorithm-data-options [`crypto.privateDecrypt()`]: #cryptoprivatedecryptprivatekey-buffer @@ -7097,6 +7166,7 @@ See the [list of SSL OP Flags][] for details. [`crypto.publicEncrypt()`]: #cryptopublicencryptkey-buffer [`crypto.randomBytes()`]: #cryptorandombytessize-callback [`crypto.randomFill()`]: #cryptorandomfillbuffer-offset-size-callback +[`crypto.setFips()`]: #cryptosetfipsbool [`crypto.sign()`]: #cryptosignalgorithm-data-key-callback [`crypto.verify()`]: #cryptoverifyalgorithm-data-key-signature-callback [`crypto.webcrypto.getRandomValues()`]: webcrypto.md#cryptogetrandomvaluestypedarray diff --git a/doc/node.1 b/doc/node.1 index 6aede253510..6114455ebe0 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -513,8 +513,9 @@ The default is \fBverbatim\fR and \fBdns.setDefaultResultOrder()\fR have higher priority than \fB--dns-result-order\fR. . .It Fl -enable-fips -Enable FIPS-compliant crypto at startup. (Requires Node.js to be built -against FIPS-compatible OpenSSL.) +Enable FIPS mode at startup. With OpenSSL 3, a configured provider named +\fBfips\fR must be available and initialize successfully. With OpenSSL 1.1.1, +Node.js must be built against a FIPS-capable OpenSSL. . .It Fl -enable-source-maps Enable Source Map support for stack traces. @@ -846,8 +847,8 @@ if (globalThis.gc) { Disable loading native addons that are not context-aware. . .It Fl -force-fips -Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.) -(Same requirements as \fB--enable-fips\fR.) +Enable FIPS mode at startup and prevent it from being disabled from script +code. The same OpenSSL requirements as \fB--enable-fips\fR apply. . .It Fl -force-node-api-uncaught-exceptions-policy Enforces \fBuncaughtException\fR event on Node-API asynchronous callbacks. @@ -1147,9 +1148,10 @@ Enable extra debug checks for memory leaks in Node.js internals. This is usually only useful for developers debugging Node.js itself. . .It Fl -openssl-config Ns = Ns Ar file -Load an OpenSSL configuration file on startup. Among other uses, this can be -used to enable FIPS-compliant crypto if Node.js is built -against FIPS-enabled OpenSSL. +Load an OpenSSL configuration file on startup. The file can activate an +OpenSSL 3 FIPS provider or configure a FIPS-capable OpenSSL 1.1.1 build. See +FIPS mode. +This option takes precedence over the \fBOPENSSL_CONF\fR environment variable. . .It Fl -openssl-legacy-provider Enable OpenSSL 3.0 legacy provider. For more information please see @@ -2379,9 +2381,8 @@ propagation. environment variable is arbitrary. . .It Ev OPENSSL_CONF Ar file -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 -\fB./configure --openssl-fips\fR. +Load an OpenSSL configuration file on startup. The file can be used as part of +a FIPS mode configuration. If the \fB--openssl-config\fR command-line option is used, the environment variable is ignored. .