diff --git a/BUILDING.md b/BUILDING.md index df66fa9a6af25f..76b6738097bdc1 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -792,246 +792,12 @@ $ ./configure --openssl-conf-name= ## Building Node.js with FIPS-compliant OpenSSL -The current version of Node.js supports FIPS when statically and -dynamically linking with OpenSSL 3.0.0 by using the configuration flag -`--openssl-is-fips`. +Node.js supports FIPS when statically or dynamically linked with OpenSSL 3 via +[OpenSSL's provider model](https://www.openssl.org/docs/man3.0/man7/crypto.html#OPENSSL-PROVIDERS). +It is not necessary to rebuild Node.js to enable support for FIPS. -### FIPS support when statically linking OpenSSL - -FIPS can be supported by specifying the configuration flag `--openssl-is-fips`: - -```console -$ ./configure --openssl-is-fips -$ make -j8 -``` - -The above command will build and install the FIPS module into the out directory. -This includes building fips.so, running the `installfips` command that generates -the FIPS configuration file (fipsmodule.cnf), copying and updating openssl.cnf -to include the correct path to fipsmodule.cnf and finally uncomment the fips -section. - -We can then run node specifying `--enable-fips`: - -```console -$ ./node --enable-fips -p 'crypto.getFips()' -1 -``` - -The above will use the Node.js default locations for OpenSSL 3.0: - -```console -$ ./out/Release/openssl-cli version -m -d -OPENSSLDIR: "/nodejs/openssl/out/Release/obj.target/deps/openssl" -MODULESDIR: "/nodejs/openssl/out/Release/obj.target/deps/openssl/lib/openssl-modules" -``` - -The OpenSSL configuration files will be found in `OPENSSLDIR` directory above: - -```console -$ ls -w 1 out/Release/obj.target/deps/openssl/*.cnf -out/Release/obj.target/deps/openssl/fipsmodule.cnf -out/Release/obj.target/deps/openssl/openssl.cnf -``` - -And the FIPS module will be located in the `MODULESDIR` directory: - -```console -$ ls out/Release/obj.target/deps/openssl/lib/openssl-modules/ -fips.so -``` - -Running `configure` without `--openssl-is-fips` flag and rebuilding will reset -the FIPS configuration. - -### FIPS support when dynamically linking OpenSSL - -For quictls/openssl 3.0 it is possible to enable FIPS when dynamically linking. -If you want to build Node.js using openssl-3.0.0+quic, you can follow these -steps: - -**clone OpenSSL source and prepare build** - -```bash -git clone git@github.com:quictls/openssl.git - -cd openssl - -./config \ - --prefix=/path/to/install/dir/ \ - shared \ - enable-fips \ - linux-x86_64 -``` - -The `/path/to/install/dir` is the path in which the `make install` instructions -will publish the OpenSSL libraries and such. We will also use this path -(and sub-paths) later when compiling Node.js. - -**compile and install OpenSSL** - -```console -make -j8 -make install -make install_ssldirs -make install_fips -``` - -After the OpenSSL (including FIPS) modules have been compiled and installed -(into the `/path/to/install/dir`) by the above instructions we also need to -update the OpenSSL configuration file located under -`/path/to/install/dir/ssl/openssl.cnf`. Right next to this file, you should -find the `fipsmodule.cnf` file - let's add the following to the end of the -`openssl.cnf` file. - -**alter openssl.cnf** - -```text -.include /absolute/path/to/fipsmodule.cnf - -# List of providers to load -[provider_sect] -default = default_sect -# The fips section name should match the section name inside the -# included /path/to/install/dir/ssl/fipsmodule.cnf. -fips = fips_sect - -[default_sect] -activate = 1 -``` - -You can e.g. accomplish this by running the following command - be sure to -replace `/path/to/install/dir/` with the path you have selected. Please make -sure that you specify an absolute path for the `.include fipsmodule.cnf` line - -using relative paths did not work on my system! - -**alter openssl.cnf using a script** - -```console -cat <> /path/to/install/dir/ssl/openssl.cnf -.include /path/to/install/dir/ssl/fipsmodule.cnf - -# List of providers to load -[provider_sect] -default = default_sect -# The fips section name should match the section name inside the -# included /path/to/install/dir/ssl/fipsmodule.cnf. -fips = fips_sect - -[default_sect] -activate = 1 -EOT -``` - -As you might have picked a non-custom path for your OpenSSL install dir, we -have to export the following two environment variables in order for Node.js to -find our OpenSSL modules we built beforehand: - -```console -export OPENSSL_CONF=/path/to/install/dir/ssl/openssl.cnf -export OPENSSL_MODULES=/path/to/install/dir/lib/ossl-modules -``` - -**build Node.js** - -```console -./configure \ - --shared-openssl \ - --shared-openssl-libpath=/path/to/install/dir/lib \ - --shared-openssl-includes=/path/to/install/dir/include \ - --shared-openssl-libname=crypto,ssl \ - --openssl-is-fips - -export LD_LIBRARY_PATH=/path/to/install/dir/lib - -make -j8 -``` - -**verify the produced executable** - -```console -ldd ./node - linux-vdso.so.1 (0x00007ffd7917b000) - libcrypto.so.81.3 => /path/to/install/dir/lib/libcrypto.so.81.3 (0x00007fd911321000) - libssl.so.81.3 => /path/to/install/dir/lib/libssl.so.81.3 (0x00007fd91125e000) - libdl.so.2 => /usr/lib64/libdl.so.2 (0x00007fd911232000) - libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fd911039000) - libm.so.6 => /usr/lib64/libm.so.6 (0x00007fd910ef3000) - libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fd910ed9000) - libpthread.so.0 => /usr/lib64/libpthread.so.0 (0x00007fd910eb5000) - libc.so.6 => /usr/lib64/libc.so.6 (0x00007fd910cec000) - /lib64/ld-linux-x86-64.so.2 (0x00007fd9117f2000) -``` - -If the `ldd` command says that `libcrypto` cannot be found one needs to set -`LD_LIBRARY_PATH` to point to the directory used above for -`--shared-openssl-libpath` (see previous step). - -**verify the OpenSSL version** - -```console -./node -p process.versions.openssl -3.0.0-alpha16+quic -``` - -**verify that FIPS is available** - -```console -./node -p 'process.config.variables.openssl_is_fips' -true - -./node --enable-fips -p 'crypto.getFips()' -1 -``` - -FIPS support can then be enable via the OpenSSL configuration file or -using `--enable-fips` or `--force-fips` command line options to the Node.js -executable. See sections -[Enabling FIPS using Node.js options](#enabling-fips-using-node.js-options) and -[Enabling FIPS using OpenSSL config](#enabling-fips-using-openssl-config) below. - -### Enabling FIPS using Node.js options - -This is done using one of the Node.js options `--enable-fips` or -`--force-fips`, for example: - -```console -$ node --enable-fips -p 'crypto.getFips()' -``` - -### Enabling FIPS using OpenSSL config - -This example show that using OpenSSL's configuration file, FIPS can be enabled -without specifying the `--enable-fips` or `--force-fips` options by setting -`default_properties = fips=yes` in the FIPS configuration file. See -[link](https://github.com/openssl/openssl/blob/master/README-FIPS.md#loading-the-fips-module-at-the-same-time-as-other-providers) -for details. - -For this to work the OpenSSL configuration file (default openssl.cnf) needs to -be updated. The following shows an example: - -```console -openssl_conf = openssl_init - -.include /path/to/install/dir/ssl/fipsmodule.cnf - -[openssl_init] -providers = prov -alg_section = algorithm_sect - -[prov] -fips = fips_sect -default = default_sect - -[default_sect] -activate = 1 - -[algorithm_sect] -default_properties = fips=yes -``` - -After this change Node.js can be run without the `--enable-fips` or `--force-fips` -options. +See [FIPS mode](./doc/api/crypto.md#fips-mode) for more information on how to +enable FIPS support in Node.js. ## Building Node.js with external core modules diff --git a/doc/api/crypto.md b/doc/api/crypto.md index e495c9ca6508a6..17a50f4b25d333 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -5736,6 +5736,86 @@ try { 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][]. + +For FIPS support in Node.js you will need: + +* 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. + +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. + +```text +nodejs_conf = nodejs_init + +.include //fipsmodule.cnf + +[nodejs_init] +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 + +[default_sect] +activate = 1 + +[algorithm_sect] +default_properties = fips=yes +``` + ## Crypto constants The following constants exported by `crypto.constants` apply to various uses of @@ -6015,12 +6095,15 @@ 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 [HTML 5.2]: https://www.w3.org/TR/html52/changes.html#features-removed [JWK]: https://tools.ietf.org/html/rfc7517 [NIST SP 800-131A]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.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 [Nonce-Disrespecting Adversaries]: https://github.com/nonce-disrespect/nonce-disrespect +[OpenSSL's FIPS README file]: https://github.com/openssl/openssl/blob/openssl-3.0/README-FIPS.md [OpenSSL's SPKAC implementation]: https://www.openssl.org/docs/man3.0/man1/openssl-spkac.html [RFC 1421]: https://www.rfc-editor.org/rfc/rfc1421.txt [RFC 2409]: https://www.rfc-editor.org/rfc/rfc2409.txt