diff --git a/.github/workflows/test-shared.yml b/.github/workflows/test-shared.yml
index 3638aa51371f54..24460e9f5bcc97 100644
--- a/.github/workflows/test-shared.yml
+++ b/.github/workflows/test-shared.yml
@@ -247,8 +247,9 @@ jobs:
# the matrix-selected nixpkgs attribute (e.g. `openssl_3_6`). All
# other shared libs (brotli, cares, libuv, …) keep their defaults.
# `permittedInsecurePackages` whitelists just the matrix-selected
- # release (e.g. `openssl-1.1.1w`) so EOL-with-extended-support
- # cycles evaluate without relaxing nixpkgs' meta check globally.
+ # releases so EOL-with-extended-support cycles evaluate without
+ # relaxing nixpkgs' meta check globally. It is empty while every
+ # matrix entry is a supported release.
extra-nix-flags: |
--arg useSeparateDerivationForV8 ${{ needs.build-aarch64-linux-v8.outputs.local-cache && '"$(nix-store --import < libv8-aarch64-linux.nar)"' || 'true' }} \
--arg sharedLibDeps "(import $TAR_DIR/tools/nix/sharedLibDeps.nix {}) // {
diff --git a/BUILDING.md b/BUILDING.md
index 5473f823cafbbf..f05762945f9ad7 100644
--- a/BUILDING.md
+++ b/BUILDING.md
@@ -206,7 +206,7 @@ on your Linux distribution.
#### OpenSSL asm support
-OpenSSL-1.1.1 requires the following assembler version for use of asm
+OpenSSL requires the following assembler version for use of asm
support on x86\_64 and ia32.
For use of AVX-512,
@@ -214,8 +214,6 @@ For use of AVX-512,
* gas (GNU assembler) version 2.26 or higher
* nasm version 2.11.8 or higher in Windows
-AVX-512 is disabled for Skylake-X by OpenSSL-1.1.1.
-
For use of AVX2,
* gas (GNU assembler) version 2.23 or higher
@@ -223,7 +221,7 @@ For use of AVX2,
* llvm version 3.3 or higher
* nasm version 2.10 or higher in Windows
-Please refer to for details.
+Please refer to for details.
If compiling without one of the above, use `configure` with the
`--openssl-no-asm` flag. Otherwise, `configure` will fail.
@@ -1032,7 +1030,7 @@ 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
+variable `OPENSSL_CONF`, or using the command line option `--openssl-config`, 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
@@ -1044,12 +1042,20 @@ configure option:
## Building Node.js with FIPS-compliant OpenSSL
-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.
+Node.js can use an OpenSSL FIPS provider via
+[OpenSSL's provider model](https://docs.openssl.org/master/man7/crypto/#openssl-providers),
+whether OpenSSL is linked statically or dynamically. It is not necessary to
+rebuild Node.js to do so; the provider and the OpenSSL configuration that
+activates it are supplied at runtime.
+
+Node.js does not build a FIPS provider. OpenSSL requires that a FIPS provider
+be built from a release that carries a FIPS certificate, so a provider built
+as part of the Node.js build would have no validation status.
-See [FIPS mode](doc/api/crypto.md#fips-mode) for more information on how to
-enable FIPS support in Node.js.
+`./configure --openssl-is-fips` only records that the OpenSSL being linked is
+FIPS capable, and requires `--shared-openssl`.
+
+See [FIPS mode](doc/api/crypto.md#fips-mode) for how to configure it.
## Building Node.js with Temporal support
@@ -1133,6 +1139,10 @@ A number of `configure` options are provided to support this use case.
provide the ability to set the path to an external JavaScript file
for the dependency to be used at runtime.
+When building with `--shared-openssl`, Node.js requires OpenSSL 3.0 or later.
+Support for building against OpenSSL 1.x was removed in Node.js 27.0.0, and
+`configure` fails if an older version is detected.
+
It is the responsibility of any distribution
shipping with these options to:
diff --git a/configure.py b/configure.py
index def52c6fb22f73..28e7264c5834df 100755
--- a/configure.py
+++ b/configure.py
@@ -268,7 +268,8 @@
action='store_true',
dest='openssl_is_fips',
default=None,
- help='specifies that the OpenSSL library is FIPS compatible')
+ help='specifies that the shared OpenSSL library is FIPS capable '
+ '(requires --shared-openssl)')
parser.add_argument('--openssl-use-def-ca-store',
action='store_true',
@@ -1523,7 +1524,7 @@ def get_openssl_version(o):
return version_number
- except (OSError, ValueError, subprocess.SubprocessError) as e:
+ except (OSError, TypeError, ValueError, subprocess.SubprocessError) as e:
warn(f'Failed to determine OpenSSL version from header: {e}')
return 0
@@ -2275,7 +2276,6 @@ def configure_openssl(o):
variables['node_shared_ngtcp2'] = b(options.shared_ngtcp2)
variables['node_shared_nghttp3'] = b(options.shared_nghttp3)
variables['openssl_is_fips'] = b(options.openssl_is_fips)
- variables['node_fipsinstall'] = b(False)
if options.openssl_no_asm:
variables['openssl_no_asm'] = 1
@@ -2330,17 +2330,25 @@ def without_ssl_error(option):
if options.openssl_no_asm and options.shared_openssl:
error('--openssl-no-asm is incompatible with --shared-openssl')
+ if options.openssl_is_fips and not options.shared_openssl:
+ error('--openssl-is-fips is only available with --shared-openssl')
+
if options.openssl_is_fips:
o['defines'] += ['OPENSSL_FIPS']
- if options.openssl_is_fips and not options.shared_openssl:
- variables['node_fipsinstall'] = b(True)
-
configure_library('openssl', o)
o['variables']['openssl_version'] = get_openssl_version(o)
o['variables']['openssl_is_boringssl'] = get_openssl_is_boringssl(o)
+ # BoringSSL identifies itself as OpenSSL 1.1.1 and is exempt from this check.
+ # A version of 0 means detection failed, which is already warned about in
+ # get_openssl_version() and is caught at compile time by ncrypto.h.
+ openssl_version = o['variables']['openssl_version']
+ if o['variables']['openssl_is_boringssl'] == 'false' and \
+ 0 < openssl_version < 0x30000000:
+ error('OpenSSL 1.x is no longer supported, v3.0.0 or later is required.')
+
def configure_lief(o):
if options.without_lief:
if options.shared_lief:
diff --git a/deps/ncrypto/engine.cc b/deps/ncrypto/engine.cc
index a8e64e25049183..6b9514b8565e39 100644
--- a/deps/ncrypto/engine.cc
+++ b/deps/ncrypto/engine.cc
@@ -1,8 +1,7 @@
#include "ncrypto.h"
-#if !defined(OPENSSL_NO_ENGINE) && \
- ((defined(NCRYPTO_ENGINE_COMPAT) && NCRYPTO_ENGINE_COMPAT) || \
- NCRYPTO_USE_LEGACY_OPENSSL)
+#if !defined(OPENSSL_NO_ENGINE) && defined(NCRYPTO_ENGINE_COMPAT) && \
+ NCRYPTO_ENGINE_COMPAT
#include
#endif
diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc
index bed4d48d118d51..15bd3ec4dfcc81 100644
--- a/deps/ncrypto/ncrypto.cc
+++ b/deps/ncrypto/ncrypto.cc
@@ -17,7 +17,7 @@
#include
#include
#include
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
#include
#include
#include
@@ -59,17 +59,6 @@ constexpr static PQCMapping pqc_mappings[] = {
#endif
-// EVP_PKEY_CTX_set_dsa_paramgen_q_bits was added in OpenSSL 1.1.1e.
-#if OPENSSL_VERSION_NUMBER < 0x1010105fL
-#define EVP_PKEY_CTX_set_dsa_paramgen_q_bits(ctx, qbits) \
- EVP_PKEY_CTX_ctrl((ctx), \
- EVP_PKEY_DSA, \
- EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, \
- (qbits), \
- nullptr)
-#endif
-
namespace ncrypto {
namespace {
using BignumCtxPointer = DeleteFnPtr;
@@ -515,27 +504,26 @@ DataPointer DataPointer::resize(size_t len) {
// ============================================================================
bool isFipsEnabled() {
ClearErrorOnReturn clear_error_on_return;
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
return EVP_default_properties_is_fips_enabled(nullptr) == 1;
#else
return FIPS_mode() == 1;
#endif
}
-bool setFipsEnabled(bool enable, CryptoErrorList* errors) {
- if (isFipsEnabled() == enable) return true;
- ClearErrorOnReturn clearErrorOnReturn(errors);
-#if OPENSSL_VERSION_MAJOR >= 3
- return EVP_default_properties_enable_fips(nullptr, enable ? 1 : 0) == 1 &&
- EVP_default_properties_is_fips_enabled(nullptr);
+bool setFipsEnabled() {
+ if (isFipsEnabled()) return true;
+ ClearErrorOnReturn clearErrorOnReturn;
+#ifndef OPENSSL_IS_BORINGSSL
+ return EVP_default_properties_enable_fips(nullptr, 1) == 1;
#else
- return FIPS_mode_set(enable ? 1 : 0) == 1;
+ return FIPS_mode_set(1) == 1;
#endif
}
bool testFipsEnabled() {
ClearErrorOnReturn clear_error_on_return;
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
OSSL_PROVIDER* fips_provider = nullptr;
if (OSSL_PROVIDER_available(nullptr, "fips")) {
fips_provider = OSSL_PROVIDER_load(nullptr, "fips");
@@ -802,7 +790,7 @@ bool CSPRNG(void* buffer, size_t length) {
auto buf = reinterpret_cast(buffer);
do {
if (1 == RAND_status()) {
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
if (1 == RAND_bytes_ex(nullptr, buf, length, 0)) {
return true;
}
@@ -815,7 +803,7 @@ bool CSPRNG(void* buffer, size_t length) {
return true;
#endif
}
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
const auto code = ERR_peek_last_error();
// A misconfigured OpenSSL 3 installation may report 1 from RAND_poll()
// and RAND_status() but fail in RAND_bytes() if it cannot look up
@@ -1112,7 +1100,7 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
BIO_printf(out.get(), (j == 0) ? "%X" : ":%X", pair);
}
} else {
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
BIO_printf(out.get(), "", ip_len);
#else
BIO_printf(out.get(), "");
@@ -1131,9 +1119,9 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
// awkward, especially when passed to translatePeerCertificate.
bool unicode = true;
const char* prefix = nullptr;
- // OpenSSL 1.1.1 does not support othername in GENERAL_NAME_print and may
+ // BoringSSL does not support othername in GENERAL_NAME_print and may
// not define these NIDs.
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
int nid = OBJ_obj2nid(gen->d.otherName->type_id);
switch (nid) {
case NID_id_on_SmtpUTF8Mailbox:
@@ -1153,7 +1141,7 @@ bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
prefix = "NAIRealm";
break;
}
-#endif // OPENSSL_VERSION_MAJOR >= 3
+#endif // !OPENSSL_IS_BORINGSSL
int val_type = gen->d.otherName->value->type;
if (prefix == nullptr || (unicode && val_type != V_ASN1_UTF8STRING) ||
(!unicode && val_type != V_ASN1_IA5STRING)) {
@@ -1244,7 +1232,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, const X509_EXTENSION* ext) {
}
sk_ACCESS_DESCRIPTION_pop_free(descs, ACCESS_DESCRIPTION_free);
-#if OPENSSL_VERSION_MAJOR < 3
+#ifdef OPENSSL_IS_BORINGSSL
BIO_write(out.get(), "\n", 1);
#endif
@@ -3679,12 +3667,8 @@ Result EVPKeyPointer::writePrivateKey(
cipher,
passphrase);
}
-#else
-#if OPENSSL_VERSION_MAJOR >= 3
- const RSA* rsa = EVP_PKEY_get0_RSA(get());
#else
RSA* rsa = EVP_PKEY_get0_RSA(get());
-#endif
switch (config.format) {
case PKFormatType::PEM: {
err = PEM_write_bio_RSAPrivateKey(
@@ -3754,12 +3738,8 @@ Result EVPKeyPointer::writePrivateKey(
"type-specific",
cipher,
passphrase);
-#else
-#if OPENSSL_VERSION_MAJOR >= 3
- const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get());
#else
EC_KEY* ec = EVP_PKEY_get0_EC_KEY(get());
-#endif
switch (config.format) {
case PKFormatType::PEM: {
err = PEM_write_bio_ECPrivateKey(
@@ -3820,12 +3800,8 @@ Result EVPKeyPointer::writePublicKey(
mark_pop_error_on_return.peekError());
}
return bio;
-#else
-#if OPENSSL_VERSION_MAJOR >= 3
- const RSA* rsa = EVP_PKEY_get0_RSA(get());
#else
RSA* rsa = EVP_PKEY_get0_RSA(get());
-#endif
if (config.format == ncrypto::EVPKeyPointer::PKFormatType::PEM) {
// Encode PKCS#1 as PEM.
if (PEM_write_bio_RSAPublicKey(bio.get(), rsa) != 1) {
@@ -3953,14 +3929,7 @@ EVPKeyPointer::operator Rsa() const {
#if NCRYPTO_USE_OPENSSL3_PROVIDER
return Rsa(get());
#else
- // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL
- // versions older than 1.1.1e via FIPS / dynamic linking.
- OSSL3_CONST RSA* rsa;
- if (OPENSSL_VERSION_NUMBER >= 0x1010105fL) {
- rsa = EVP_PKEY_get0_RSA(get());
- } else {
- rsa = static_cast(EVP_PKEY_get0(get()));
- }
+ OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(get());
if (rsa == nullptr) return {};
return Rsa(rsa);
#endif
@@ -3982,7 +3951,7 @@ EVPKeyPointer::operator Dsa() const {
bool EVPKeyPointer::validateDsaParameters() const {
if (!pkey_) return false;
/* Validate DSA2 parameters from FIPS 186-4 */
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
if (EVP_default_properties_is_fips_enabled(nullptr) && EVP_PKEY_DSA == id()) {
#else
if (FIPS_mode() && EVP_PKEY_DSA == id()) {
@@ -5391,11 +5360,7 @@ EVPKeyPointer EVPKeyCtxPointer::paramgen() const {
bool EVPKeyCtxPointer::publicCheck() const {
if (!ctx_) return false;
#ifndef OPENSSL_IS_BORINGSSL
-#if OPENSSL_VERSION_MAJOR >= 3
return EVP_PKEY_public_check_quick(ctx_.get()) == 1;
-#else
- return EVP_PKEY_public_check(ctx_.get()) == 1;
-#endif
#else // OPENSSL_IS_BORINGSSL
// Boringssl appears not to support this operation.
// TODO(jasnell): Is there an alternative approach that Boringssl does
@@ -5994,7 +5959,7 @@ struct CipherCallbackContext {
void operator()(const char* name) { cb(name); }
};
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
template = 3
+#ifndef OPENSSL_IS_BORINGSSL
array_push_back= 0x3000000f', {
- 'defines!': [ '<@(ncrypto_legacy_openssl_defines)' ],
+ ['openssl_is_boringssl=="false"', {
'defines': [ '<@(ncrypto_strict_defines)' ],
}],
],
},
'sources': [ '<@(ncrypto_sources)' ],
'conditions': [
- ['openssl_is_boringssl=="false" and openssl_version >= 0x3000000f', {
- 'defines!': [ '<@(ncrypto_legacy_openssl_defines)' ],
+ ['openssl_is_boringssl=="false"', {
'defines': [ '<@(ncrypto_strict_defines)' ],
'dependencies': [
'ncrypto_engine',
],
}],
- ['openssl_is_boringssl=="false" and openssl_version < 0x3000000f', {
- 'sources': [ '<@(ncrypto_engine_sources)' ],
- }],
['node_shared_openssl=="false"', {
'dependencies': [
'../openssl/openssl.gyp:openssl'
@@ -63,7 +55,7 @@
},
],
'conditions': [
- ['openssl_is_boringssl=="false" and openssl_version >= 0x3000000f', {
+ ['openssl_is_boringssl=="false"', {
'targets': [
{
'target_name': 'ncrypto_engine',
diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h
index 6fb6b384fd4fa4..a9f59ff4ed0fc5 100644
--- a/deps/ncrypto/ncrypto.h
+++ b/deps/ncrypto/ncrypto.h
@@ -29,6 +29,11 @@
(OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
#endif
+// BoringSSL reports itself as OpenSSL 1.1.1, so it has to be excluded here.
+#if !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_VERSION_PREREQ(3, 0)
+#error "OpenSSL 1.x is no longer supported, v3.0.0 or later is required."
+#endif
+
// BoringSSL declares the EVP_*_do_all* APIs, but their implementation may
// live in libdecrepit. This matches standalone ncrypto's build flag.
#ifndef NCRYPTO_BSSL_LIBDECREPIT_MISSING
@@ -43,31 +48,17 @@
// Backend split:
// - OpenSSL >= 3 uses provider APIs and hides deprecated low-level objects.
-// - BoringSSL has its own API-compatible branch.
-// - OpenSSL < 3 remains the legacy fallback branch.
-#if !defined(OPENSSL_IS_BORINGSSL) && OPENSSL_VERSION_PREREQ(3, 0)
-#define NCRYPTO_USE_OPENSSL3_PROVIDER 1
-#else
-#define NCRYPTO_USE_OPENSSL3_PROVIDER 0
-#endif
-
+// - BoringSSL has its own API-compatible branch and keeps using the legacy
+// low-level key types.
#ifdef OPENSSL_IS_BORINGSSL
#define NCRYPTO_USE_BORINGSSL 1
+#define NCRYPTO_USE_OPENSSL3_PROVIDER 0
#else
#define NCRYPTO_USE_BORINGSSL 0
+#define NCRYPTO_USE_OPENSSL3_PROVIDER 1
#endif
-#if !NCRYPTO_USE_OPENSSL3_PROVIDER && !NCRYPTO_USE_BORINGSSL
-#define NCRYPTO_USE_LEGACY_OPENSSL 1
-#else
-#define NCRYPTO_USE_LEGACY_OPENSSL 0
-#endif
-
-#if NCRYPTO_USE_BORINGSSL || NCRYPTO_USE_LEGACY_OPENSSL
-#define NCRYPTO_USE_LEGACY_KEY_TYPES 1
-#else
-#define NCRYPTO_USE_LEGACY_KEY_TYPES 0
-#endif
+#define NCRYPTO_USE_LEGACY_KEY_TYPES NCRYPTO_USE_BORINGSSL
#if NCRYPTO_USE_OPENSSL3_PROVIDER
#include
@@ -75,13 +66,7 @@
#include
#endif
-// The FIPS-related functions are only available
-// when the OpenSSL itself was compiled with FIPS support.
-#if defined(OPENSSL_FIPS) && !OPENSSL_VERSION_PREREQ(3, 0)
-#include
-#endif // OPENSSL_FIPS
-
-#if OPENSSL_VERSION_PREREQ(3, 0)
+#if !defined(OPENSSL_IS_BORINGSSL)
#define OPENSSL_WITH_AES_OCB 1
#else
#define OPENSSL_WITH_AES_OCB 0
@@ -93,13 +78,9 @@
#define OPENSSL_WITH_ARGON2 0
#endif
-#if OPENSSL_VERSION_PREREQ(3, 0) || defined(OPENSSL_IS_BORINGSSL)
#define OPENSSL_WITH_KEM 1
-#else
-#define OPENSSL_WITH_KEM 0
-#endif
-#if OPENSSL_VERSION_PREREQ(3, 0)
+#if !defined(OPENSSL_IS_BORINGSSL)
#define OPENSSL_WITH_EVP_MAC 1
#else
#define OPENSSL_WITH_EVP_MAC 0
@@ -152,7 +133,7 @@
#define EVP_PKEY_ML_KEM_1024 NID_ML_KEM_1024
#endif
-#if OPENSSL_VERSION_PREREQ(3, 0)
+#if !defined(OPENSSL_IS_BORINGSSL)
#define OSSL3_CONST const
#else
#define OSSL3_CONST
@@ -1842,7 +1823,11 @@ class EnginePointer final {
// FIPS
bool isFipsEnabled();
-bool setFipsEnabled(bool enabled, CryptoErrorList* errors);
+// Restricts the default library context to FIPS-approved implementations.
+// This only narrows the default property query; it neither loads nor
+// activates the FIPS provider. Callers are expected to have established
+// that a FIPS provider is active first, e.g. via testFipsEnabled().
+bool setFipsEnabled();
bool testFipsEnabled();
diff --git a/deps/openssl/openssl.gyp b/deps/openssl/openssl.gyp
index 4e16412a028340..61234b5c6c4d8f 100644
--- a/deps/openssl/openssl.gyp
+++ b/deps/openssl/openssl.gyp
@@ -97,35 +97,6 @@
},
}],
]
- }, {
- # openssl-fipsmodule target
- 'target_name': 'openssl-fipsmodule',
- 'type': 'shared_library',
- 'dependencies': ['openssl-cli'],
- 'includes': ['./openssl_common.gypi'],
- 'include_dirs+': ['openssl/apps/include'],
- 'cflags': [ '-fPIC' ],
- #'ldflags': [ '-o', 'fips.so' ],
- #'ldflags': [ '-Wl,--version-script=providers/fips.ld',],
- 'conditions': [
- [ 'openssl_no_asm==1', {
- 'includes': ['./openssl-fips_no_asm.gypi'],
- }, 'target_arch=="arm64" and OS=="win"', {
- # VC-WIN64-ARM inherits from VC-noCE-common that has no asms.
- 'includes': ['./openssl-fips_no_asm.gypi'],
- }, 'gas_version and v(gas_version) >= v("2.26") or '
- 'nasm_version and v(nasm_version) >= v("2.11.8")', {
- # Require AVX512IFMA supported. See
- # https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_ia32cap.html
- # Currently crypto/poly1305/asm/poly1305-x86_64.pl requires AVX512IFMA.
- 'includes': ['./openssl-fips_asm.gypi'],
- }, {
- 'includes': ['./openssl-fips_asm_avx2.gypi'],
- }],
- ],
- 'direct_dependent_settings': {
- 'include_dirs': [ 'openssl/include', 'openssl/crypto/include']
- }
- },
+ },
]
}
diff --git a/doc/api/cli.md b/doc/api/cli.md
index 5d59844d4cbc72..876f0577a22475 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -1562,15 +1562,6 @@ added: v12.12.0
Disable loading native addons that are not [context-aware][].
-### `--force-fips`
-
-
-
-Force FIPS-compliant crypto on startup. (Cannot be disabled from script code.)
-(Same requirements as `--enable-fips`.)
-
### `--force-node-api-uncaught-exceptions-policy`
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`.
+used to enable FIPS-compliant crypto if Node.js is built against
+FIPS-enabled OpenSSL.
If the [`--openssl-config`][] command-line option is used, the environment
variable is ignored.
diff --git a/doc/api/crypto.md b/doc/api/crypto.md
index 4770e0c36c3948..a1664dca6fa760 100644
--- a/doc/api/crypto.md
+++ b/doc/api/crypto.md
@@ -4190,7 +4190,7 @@ Key decapsulation using a KEM algorithm with a private key.
Supported key types and their KEM algorithms are:
-* `'rsa'`[^openssl30] RSA Secret Value Encapsulation
+* `'rsa'`[^noboringssl] RSA Secret Value Encapsulation
* `'ec'`[^openssl32] DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256)
* `'x25519'`[^openssl32] DHKEM(X25519, HKDF-SHA256)
* `'x448'`[^openssl32] DHKEM(X448, HKDF-SHA512)
@@ -4262,7 +4262,7 @@ Key encapsulation using a KEM algorithm with a public key.
Supported key types and their KEM algorithms are:
-* `'rsa'`[^openssl30] RSA Secret Value Encapsulation
+* `'rsa'`[^noboringssl] RSA Secret Value Encapsulation
* `'ec'`[^openssl32] DHKEM(P-256, HKDF-SHA256), DHKEM(P-384, HKDF-SHA256), DHKEM(P-521, HKDF-SHA256)
* `'x25519'`[^openssl32] DHKEM(X25519, HKDF-SHA256)
* `'x448'`[^openssl32] DHKEM(X448, HKDF-SHA512)
@@ -4275,21 +4275,6 @@ passed to [`crypto.createPublicKey()`][].
If the `callback` function is provided this function uses libuv's threadpool.
-### `crypto.fips`
-
-
-
-> 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.
-
### `crypto.generateKey(type, options, callback)`
-* 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 the default OpenSSL library context restricts
+ algorithm selection to FIPS-approved implementations, `0` otherwise. A future
+ semver-major release may change the return type of this API to a {boolean}.
+
+This reports whether the default property query is `fips=yes`. It is a
+statement of intent, not proof: it does not establish that a FIPS provider is
+loaded, nor that any provider in use is FIPS validated. See [FIPS mode][].
### `crypto.getHashes()`
@@ -6167,17 +6156,6 @@ is a bit field taking one of or a mix of the following flags (defined in
* `crypto.constants.ENGINE_METHOD_ALL`
* `crypto.constants.ENGINE_METHOD_NONE`
-### `crypto.setFips(bool)`
-
-
-
-* `bool` {boolean} `true` to enable FIPS mode.
-
-Enables the FIPS compliant crypto provider in a FIPS-enabled Node.js build.
-Throws an error if FIPS mode is not available.
-
### `crypto.sign(algorithm, data, key[, callback])`
-Type: Runtime
+Type: End-of-Life
-The [`crypto.fips`][] property is deprecated. Please use `crypto.setFips()`
-and `crypto.getFips()` instead.
+The `crypto.fips` property has been removed. Use [`crypto.getFips()`][] to read
+whether the default OpenSSL library context is restricted to FIPS-approved
+implementations. Changing that at runtime is no longer possible; configure the
+FIPS provider through OpenSSL and use [`--enable-fips`][] to require at startup
+that one is active. See [FIPS mode][] for details.
An automated migration is available ([source](https://github.com/nodejs/userland-migrations/tree/main/recipes/crypto-fips-to-getFips)).
@@ -4696,6 +4702,7 @@ successfully before the response closed.
[DEP0142]: #dep0142-repl_builtinlibs
[DEP0156]: #dep0156-aborted-property-and-abort-aborted-event-in-http
+[FIPS mode]: crypto.md#fips-mode
[NIST SP 800-38D]: https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
[RFC 6066]: https://tools.ietf.org/html/rfc6066#section-3
[RFC 8247 Section 2.4]: https://www.rfc-editor.org/rfc/rfc8247#section-2.4
@@ -4703,6 +4710,7 @@ successfully before the response closed.
[WHATWG URL API]: url.md#the-whatwg-url-api
[`"exports"` or `"main"` entry]: packages.md#main-entry-point-export
[`'uncaughtException'`]: process.md#event-uncaughtexception
+[`--enable-fips`]: cli.md#--enable-fips
[`--force-node-api-uncaught-exceptions-policy`]: cli.md#--force-node-api-uncaught-exceptions-policy
[`--pending-deprecation`]: cli.md#--pending-deprecation
[`--throw-deprecation`]: cli.md#--throw-deprecation
@@ -4739,7 +4747,7 @@ successfully before the response closed.
[`crypto.createDecipheriv()`]: crypto.md#cryptocreatedecipherivalgorithm-key-iv-options
[`crypto.createHash()`]: crypto.md#cryptocreatehashalgorithm-options
[`crypto.createHmac()`]: crypto.md#cryptocreatehmacalgorithm-key-options
-[`crypto.fips`]: crypto.md#cryptofips
+[`crypto.getFips()`]: crypto.md#cryptogetfips
[`crypto.pbkdf2()`]: crypto.md#cryptopbkdf2password-salt-iterations-keylen-digest-callback
[`crypto.randomBytes()`]: crypto.md#cryptorandombytessize-callback
[`crypto.scrypt()`]: crypto.md#cryptoscryptpassword-salt-keylen-options-callback
diff --git a/doc/api/errors.md b/doc/api/errors.md
index a7a7e6549f68e6..1b833d9c99c25b 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -911,20 +911,6 @@ key lies outside of the elliptic curve.
An invalid crypto engine identifier was passed to
[`require('node:crypto').setEngine()`][].
-
-
-### `ERR_CRYPTO_FIPS_FORCED`
-
-The [`--force-fips`][] command-line argument was used but there was an attempt
-to enable or disable FIPS mode in the `node:crypto` module.
-
-
-
-### `ERR_CRYPTO_FIPS_UNAVAILABLE`
-
-An attempt was made to enable or disable FIPS mode, but FIPS mode was not
-available.
-
### `ERR_CRYPTO_HASH_FINALIZED`
@@ -3768,6 +3754,28 @@ removed: v15.0.0
The native call from `process.cpuUsage` could not be processed.
+
+
+### `ERR_CRYPTO_FIPS_FORCED`
+
+
+
+The `--force-fips` command-line argument was used but there was an attempt
+to enable or disable FIPS mode in the `node:crypto` module.
+
+
+
+### `ERR_CRYPTO_FIPS_UNAVAILABLE`
+
+
+
+An attempt was made to enable or disable FIPS mode, but FIPS mode was not
+available.
+
### `ERR_CRYPTO_HASH_DIGEST_NO_UTF16`
@@ -4592,7 +4600,6 @@ An error occurred trying to allocate memory. This should never happen.
[`"imports"`]: packages.md#imports
[`'uncaughtException'`]: process.md#event-uncaughtexception
[`--disable-proto=throw`]: cli.md#--disable-protomode
-[`--force-fips`]: cli.md#--force-fips
[`--no-addons`]: cli.md#--no-addons
[`--unhandled-rejections`]: cli.md#--unhandled-rejectionsmode
[`BoundSocket`]: net.md#class-netboundsocket
diff --git a/doc/api/tls.md b/doc/api/tls.md
index ae3de645eaa3b6..5e7bb70587f432 100644
--- a/doc/api/tls.md
+++ b/doc/api/tls.md
@@ -182,8 +182,8 @@ On the client connection, a custom `checkServerIdentity` should be passed
because the default one will fail in the absence of a certificate.
According to the [RFC 4279][], PSK identities up to 128 bytes in length and
-PSKs up to 64 bytes in length must be supported. As of OpenSSL 1.1.0
-maximum identity size is 128 bytes, and maximum PSK length is 256 bytes.
+PSKs up to 64 bytes in length must be supported. In OpenSSL the maximum
+identity size is 128 bytes, and the maximum PSK length is 256 bytes.
The current implementation doesn't support asynchronous PSK callbacks due to the
limitations of the underlying OpenSSL API.
@@ -1195,7 +1195,7 @@ For example, a TLSv1.2 protocol with AES256-SHA cipher:
```
See
-[SSL\_CIPHER\_get\_name](https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_name.html)
+[SSL\_CIPHER\_get\_name](https://www.openssl.org/docs/man3.0/man3/SSL_CIPHER_get_name.html)
for more information.
### `tlsSocket.getEphemeralKeyInfo()`
@@ -1447,7 +1447,7 @@ added: v12.11.0
the client in the order of decreasing preference.
See
-[SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man1.1.1/man3/SSL_get_shared_sigalgs.html)
+[SSL\_get\_shared\_sigalgs](https://www.openssl.org/docs/man3.0/man3/SSL_get_shared_sigalgs.html)
for more information.
### `tlsSocket.getTLSTicket()`
@@ -2034,7 +2034,7 @@ changes:
The list can contain digest algorithms (`SHA256`, `MD5` etc.), public key
algorithms (`RSA-PSS`, `ECDSA` etc.), combination of both (e.g
'RSA+SHA384') or TLS v1.3 scheme names (e.g. `rsa_pss_pss_sha512`).
- See [OpenSSL man pages](https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set1_sigalgs_list.html)
+ See [OpenSSL man pages](https://www.openssl.org/docs/man3.0/man3/SSL_CTX_set1_sigalgs_list.html)
for more info.
* `ciphers` {string} Cipher suite specification, replacing the default. For
more information, see [Modifying the default TLS cipher suite][]. Permitted
@@ -2539,7 +2539,7 @@ added: v0.11.3
[RFC 5077]: https://tools.ietf.org/html/rfc5077
[RFC 5929]: https://tools.ietf.org/html/rfc5929
[RFC 8879]: https://tools.ietf.org/html/rfc8879
-[SSL_METHODS]: https://www.openssl.org/docs/man1.1.1/man7/ssl.html#Dealing-with-Protocol-Methods
+[SSL_METHODS]: https://www.openssl.org/docs/man3.0/man7/ssl.html#Dealing-with-Protocol-Methods
[Session Resumption]: #session-resumption
[Stream]: stream.md#stream
[TLS recommendations]: https://wiki.mozilla.org/Security/Server_Side_TLS
@@ -2556,8 +2556,8 @@ added: v0.11.3
[`Duplex`]: stream.md#class-streamduplex
[`NODE_EXTRA_CA_CERTS`]: cli.md#node_extra_ca_certsfile
[`NODE_OPTIONS`]: cli.md#node_optionsoptions
-[`SSL_export_keying_material`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_export_keying_material.html
-[`SSL_get_version`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_get_version.html
+[`SSL_export_keying_material`]: https://www.openssl.org/docs/man3.0/man3/SSL_export_keying_material.html
+[`SSL_get_version`]: https://www.openssl.org/docs/man3.0/man3/SSL_get_version.html
[`crypto.getCurves()`]: crypto.md#cryptogetcurves
[`import()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
[`net.Server.address()`]: net.md#serveraddress
@@ -2591,6 +2591,6 @@ added: v0.11.3
[`x509.checkHost()`]: crypto.md#x509checkhostname-options
[asn1.js]: https://www.npmjs.com/package/asn1.js
[certificate object]: #certificate-object
-[cipher list format]: https://www.openssl.org/docs/man1.1.1/man1/ciphers.html#CIPHER-LIST-FORMAT
+[cipher list format]: https://www.openssl.org/docs/man3.0/man1/ciphers.html#CIPHER-LIST-FORMAT
[forward secrecy]: https://en.wikipedia.org/wiki/Perfect_forward_secrecy
[perfect forward secrecy]: #perfect-forward-secrecy
diff --git a/doc/api/webcrypto.md b/doc/api/webcrypto.md
index 12d21ae05e73a9..2d11a9b1505c20 100644
--- a/doc/api/webcrypto.md
+++ b/doc/api/webcrypto.md
@@ -119,15 +119,15 @@ WICG proposal:
Algorithms:
-* `'AES-OCB'`[^openssl30]
+* `'AES-OCB'`[^noboringssl]
* `'Argon2d'`[^openssl32]
* `'Argon2i'`[^openssl32]
* `'Argon2id'`[^openssl32]
* `'ChaCha20-Poly1305'`
* `'cSHAKE128'`
* `'cSHAKE256'`
-* `'KMAC128'`[^openssl30]
-* `'KMAC256'`[^openssl30]
+* `'KMAC128'`[^noboringssl]
+* `'KMAC256'`[^noboringssl]
* `'KT128'`
* `'KT256'`
* `'ML-DSA-44'`[^openssl35]
@@ -2715,7 +2715,7 @@ added:
[^modern-algos]: See [Modern Algorithms in the Web Cryptography API][]
-[^openssl30]: Requires OpenSSL >= 3.0
+[^noboringssl]: Not available when Node.js is built against BoringSSL
[^openssl32]: Requires OpenSSL >= 3.2
diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json
index 116f0c28681816..cbb6654f2d90d8 100644
--- a/doc/node-config-schema.json
+++ b/doc/node-config-schema.json
@@ -191,7 +191,7 @@
},
"enable-fips": {
"type": "boolean",
- "description": "enable FIPS crypto at startup"
+ "description": "require an active OpenSSL FIPS provider at startup"
},
"enable-source-maps": {
"type": "boolean",
@@ -284,10 +284,6 @@
"type": "boolean",
"description": "disable loading non-context-aware addons"
},
- "force-fips": {
- "type": "boolean",
- "description": "force FIPS crypto (cannot be disabled)"
- },
"force-node-api-uncaught-exceptions-policy": {
"type": "boolean",
"description": "enforces 'uncaughtException' event on Node API asynchronous callbacks"
diff --git a/doc/node.1 b/doc/node.1
index cc51fde7661ac3..72f4fb62328bbc 100644
--- a/doc/node.1
+++ b/doc/node.1
@@ -834,10 +834,6 @@ if (globalThis.gc) {
.It Fl -force-context-aware
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.)
-.
.It Fl -force-node-api-uncaught-exceptions-policy
Enforces \fBuncaughtException\fR event on Node-API asynchronous callbacks.
To prevent from an existing add-on from crashing the process, this flag is not
@@ -1993,8 +1989,6 @@ one is included in the list below.
.It
\fB--force-context-aware\fR
.It
-\fB--force-fips\fR
-.It
\fB--force-node-api-uncaught-exceptions-policy\fR
.It
\fB--frozen-intrinsics\fR
@@ -2345,8 +2339,8 @@ 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.
+used to enable FIPS-compliant crypto if Node.js is built against
+FIPS-enabled OpenSSL.
If the \fB--openssl-config\fR command-line option is used, the environment
variable is ignored.
.
diff --git a/lib/crypto.js b/lib/crypto.js
index ac4b0a33efb8ab..fd6405740b5a4a 100644
--- a/lib/crypto.js
+++ b/lib/crypto.js
@@ -35,15 +35,10 @@ const {
} = require('internal/util');
assertCrypto();
-const {
- ERR_CRYPTO_FIPS_FORCED,
- ERR_WORKER_UNSUPPORTED_OPERATION,
-} = require('internal/errors').codes;
const constants = internalBinding('constants').crypto;
const { getOptionValue } = require('internal/options');
const {
getFipsCrypto,
- setFipsCrypto,
timingSafeEqual,
} = internalBinding('crypto');
const {
@@ -134,12 +129,6 @@ function lazyWebCrypto() {
return webcrypto;
}
-let ownsProcessState;
-function lazyOwnsProcessState() {
- ownsProcessState ??= require('internal/worker').ownsProcessState;
- return ownsProcessState;
-}
-
// These helper functions are needed because the constructors can
// use new, in which case V8 cannot inline the recursive constructor call
function createHash(algorithm, options) {
@@ -228,7 +217,6 @@ module.exports = {
setEngine,
timingSafeEqual,
getFips,
- setFips,
verify: verifyOneShot,
hash,
encapsulate,
@@ -251,19 +239,7 @@ module.exports = {
};
function getFips() {
- return getOptionValue('--force-fips') ? 1 : getFipsCrypto();
-}
-
-function setFips(val) {
- if (getOptionValue('--force-fips')) {
- if (val) return;
- throw new ERR_CRYPTO_FIPS_FORCED();
- } else {
- if (!lazyOwnsProcessState()) {
- throw new ERR_WORKER_UNSUPPORTED_OPERATION('Calling crypto.setFips()');
- }
- setFipsCrypto(val);
- }
+ return getFipsCrypto();
}
function getRandomValues(array) {
@@ -340,13 +316,6 @@ function getRandomBytesAlias(key) {
}
ObjectDefineProperties(module.exports, {
- fips: {
- __proto__: null,
- get: deprecate(getFips, 'The crypto.fips is deprecated. ' +
- 'Please use crypto.getFips()', 'DEP0093'),
- set: deprecate(setFips, 'The crypto.fips is deprecated. ' +
- 'Please use crypto.setFips()', 'DEP0093'),
- },
constants: {
__proto__: null,
configurable: false,
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 1b5487849169cb..d0e6761b9e355b 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -1175,10 +1175,6 @@ E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s', TypeError);
E('ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
'Public key is not valid for specified curve', Error);
E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found', Error);
-E('ERR_CRYPTO_FIPS_FORCED',
- 'Cannot set FIPS mode, it was forced with --force-fips at startup.', Error);
-E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.',
- Error);
E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error);
E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error);
E('ERR_CRYPTO_INCOMPATIBLE_KEY', 'Incompatible %s: %s', Error);
diff --git a/node.gyp b/node.gyp
index e88bac122b93d4..9a3691388360a1 100644
--- a/node.gyp
+++ b/node.gyp
@@ -790,87 +790,22 @@
]
}],
- ['node_fipsinstall=="true"', {
- 'variables': {
- 'openssl-cli': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)openssl-cli<(EXECUTABLE_SUFFIX)',
- 'provider_name': 'libopenssl-fipsmodule',
- 'opensslconfig': './deps/openssl/nodejs-openssl.cnf',
- 'conditions': [
- ['GENERATOR == "ninja"', {
- 'fipsmodule_internal': '<(PRODUCT_DIR)/lib/<(provider_name).so',
- 'fipsmodule': '<(PRODUCT_DIR)/obj/lib/openssl-modules/fips.so',
- 'fipsconfig': '<(PRODUCT_DIR)/obj/lib/fipsmodule.cnf',
- 'opensslconfig_internal': '<(PRODUCT_DIR)/obj/lib/openssl.cnf',
- }, {
- 'fipsmodule_internal': '<(PRODUCT_DIR)/obj.target/deps/openssl/<(provider_name).so',
- 'fipsmodule': '<(PRODUCT_DIR)/obj.target/deps/openssl/lib/openssl-modules/fips.so',
- 'fipsconfig': '<(PRODUCT_DIR)/obj.target/deps/openssl/fipsmodule.cnf',
- 'opensslconfig_internal': '<(PRODUCT_DIR)/obj.target/deps/openssl/openssl.cnf',
- }],
- ],
- },
- 'actions': [
- {
- 'action_name': 'fipsinstall',
- 'process_outputs_as_sources': 1,
- 'inputs': [
- '<(fipsmodule_internal)',
- ],
- 'outputs': [
- '<(fipsconfig)',
- ],
- 'action': [
- '<(openssl-cli)', 'fipsinstall',
- '-provider_name', '<(provider_name)',
- '-module', '<(fipsmodule_internal)',
- '-out', '<(fipsconfig)',
- #'-quiet',
- ],
- },
- {
- 'action_name': 'copy_fips_module',
- 'inputs': [
- '<(fipsmodule_internal)',
- ],
- 'outputs': [
- '<(fipsmodule)',
- ],
- 'action': [
- '<(python)', 'tools/copyfile.py',
- '<(fipsmodule_internal)',
- '<(fipsmodule)',
- ],
- },
- {
- 'action_name': 'copy_openssl_cnf_and_include_fips_cnf',
- 'inputs': [ '<(opensslconfig)', ],
- 'outputs': [ '<(opensslconfig_internal)', ],
- 'action': [
- '<(python)', 'tools/enable_fips_include.py',
- '<(opensslconfig)',
- '<(opensslconfig_internal)',
- '<(fipsconfig)',
- ],
- },
+ ],
+ 'variables': {
+ 'opensslconfig_internal': '<(obj_dir)/deps/openssl/openssl.cnf',
+ 'opensslconfig': './deps/openssl/nodejs-openssl.cnf',
+ },
+ 'actions': [
+ {
+ 'action_name': 'reset_openssl_cnf',
+ 'inputs': [ '<(opensslconfig)', ],
+ 'outputs': [ '<(opensslconfig_internal)', ],
+ 'action': [
+ '<(python)', 'tools/copyfile.py',
+ '<(opensslconfig)',
+ '<(opensslconfig_internal)',
],
- }, {
- 'variables': {
- 'opensslconfig_internal': '<(obj_dir)/deps/openssl/openssl.cnf',
- 'opensslconfig': './deps/openssl/nodejs-openssl.cnf',
- },
- 'actions': [
- {
- 'action_name': 'reset_openssl_cnf',
- 'inputs': [ '<(opensslconfig)', ],
- 'outputs': [ '<(opensslconfig_internal)', ],
- 'action': [
- '<(python)', 'tools/copyfile.py',
- '<(opensslconfig)',
- '<(opensslconfig_internal)',
- ],
- },
- ],
- }],
+ },
],
}, # node_core_target_name
{
@@ -1053,7 +988,7 @@
],
},
'conditions': [
- ['openssl_is_fips!=""', {
+ ['openssl_is_fips=="true"', {
'variables': { 'mkssldef_flags': ['-DOPENSSL_FIPS'] },
}],
],
diff --git a/src/crypto/README.md b/src/crypto/README.md
index cc5093a385cad3..aae3c3b74080f6 100644
--- a/src/crypto/README.md
+++ b/src/crypto/README.md
@@ -96,8 +96,8 @@ using CipherCtxPointer = DeleteFnPtr;
Examples of these being used are pervasive through the `src/crypto` code.
`HMACCtxPointer` is a dedicated HMAC state wrapper rather than a plain
-`DeleteFnPtr` alias. On OpenSSL 3 and later it owns the provider-backed
-`EVP_MAC`/`EVP_MAC_CTX` state. On OpenSSL 1.1.1 and BoringSSL it owns the
+`DeleteFnPtr` alias. On OpenSSL it owns the provider-backed
+`EVP_MAC`/`EVP_MAC_CTX` state. On BoringSSL it owns the
legacy `HMAC_CTX` state. HMAC call sites should use `HMACCtxPointer::New()`,
`init()`, `update()`, and `digest()`/`digestInto()` so the backend selection
stays contained in ncrypto.
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
index a165e8e3409d6f..759c2dfd883a39 100644
--- a/src/crypto/crypto_cipher.cc
+++ b/src/crypto/crypto_cipher.cc
@@ -719,8 +719,8 @@ bool CipherBase::Final(std::unique_ptr* out) {
static_cast(ctx_.getBlockSize()),
BackingStoreInitializationMode::kUninitialized);
-#if !OPENSSL_VERSION_PREREQ(3, 0)
- // OpenSSL v1.x doesn't verify the presence of the auth tag so do
+#ifdef OPENSSL_IS_BORINGSSL
+ // BoringSSL doesn't verify the presence of the auth tag so do
// it ourselves, see https://github.com/nodejs/node/issues/45874.
if (kind_ == kDecipher && ctx_.isChaCha20Poly1305() &&
auth_tag_state_ != kAuthTagSetByUser) {
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
index 5447de596f98ec..aff44b56f4e5f8 100644
--- a/src/crypto/crypto_context.cc
+++ b/src/crypto/crypto_context.cc
@@ -1645,7 +1645,7 @@ void SecureContext::Init(const FunctionCallbackInfo& args) {
// SSLv3 is disabled because it's susceptible to downgrade attacks (POODLE.)
SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_NO_SSLv2);
SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_NO_SSLv3);
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
SSL_CTX_set_options(sc->ctx_.get(), SSL_OP_ALLOW_CLIENT_RENEGOTIATION);
#endif
@@ -2361,7 +2361,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo& args) {
// TODO(@jasnell): Should this use ThrowCryptoError?
unsigned long err = ERR_get_error(); // NOLINT(runtime/int)
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
if (ERR_GET_REASON(err) == ERR_R_UNSUPPORTED) {
// OpenSSL's "unsupported" error without any context is very
// common and not very helpful, so we override it:
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
index a824e4e0ce90d2..4975dc54228c8c 100644
--- a/src/crypto/crypto_dh.cc
+++ b/src/crypto/crypto_dh.cc
@@ -92,20 +92,14 @@ MaybeLocal DataPointerToBuffer(Environment* env, DataPointer&& data) {
void PutDhError(int reason) {
#ifdef OPENSSL_IS_BORINGSSL
OPENSSL_PUT_ERROR(DH, reason);
-#elif NCRYPTO_USE_OPENSSL3_PROVIDER
- ERR_raise(ERR_LIB_DH, reason);
#else
- ERR_put_error(ERR_LIB_DH, 0, reason, __FILE__, __LINE__);
+ ERR_raise(ERR_LIB_DH, reason);
#endif
}
-#if defined(OPENSSL_IS_BORINGSSL) || !NCRYPTO_USE_OPENSSL3_PROVIDER
-void PutBnError(int reason) {
#ifdef OPENSSL_IS_BORINGSSL
+void PutBnError(int reason) {
OPENSSL_PUT_ERROR(BN, reason);
-#else
- ERR_put_error(ERR_LIB_BN, 0, reason, __FILE__, __LINE__);
-#endif
}
#endif
@@ -134,11 +128,7 @@ void New(const FunctionCallbackInfo& args) {
int32_t bits = args[0].As()->Value();
if (bits < 2) {
#ifndef OPENSSL_IS_BORINGSSL
-#if OPENSSL_VERSION_MAJOR >= 3
PutDhError(DH_R_MODULUS_TOO_SMALL);
-#else
- PutBnError(BN_R_BITS_TOO_SMALL);
-#endif // OPENSSL_VERSION_MAJOR >= 3
#else // OPENSSL_IS_BORINGSSL
PutBnError(BN_R_BITS_TOO_SMALL);
#endif // OPENSSL_IS_BORINGSSL
diff --git a/src/crypto/crypto_hash.cc b/src/crypto/crypto_hash.cc
index aaa3fee58c35b4..8168dd20fccadf 100644
--- a/src/crypto/crypto_hash.cc
+++ b/src/crypto/crypto_hash.cc
@@ -79,7 +79,7 @@ constexpr BoringSSLDigest kBoringSSLDigests[] = {
};
#endif
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
void PushAliases(const char* name, void* data) {
static_cast*>(data)->push_back(name);
}
@@ -155,7 +155,7 @@ void SaveSupportedHashAlgorithms(const EVP_MD* md,
Environment* env = static_cast(arg);
env->supported_hash_algorithms.push_back(from);
}
-#endif // OPENSSL_VERSION_MAJOR >= 3
+#endif // !OPENSSL_IS_BORINGSSL
const std::vector& GetSupportedHashAlgorithms(Environment* env) {
if (env->supported_hash_algorithms.empty()) {
@@ -165,7 +165,7 @@ const std::vector& GetSupportedHashAlgorithms(Environment* env) {
static_cast(digest.get);
env->supported_hash_algorithms.emplace_back(digest.name);
}
-#elif OPENSSL_VERSION_MAJOR >= 3
+#elif !defined(OPENSSL_IS_BORINGSSL)
// Since we'll fetch the EVP_MD*, cache them along the way to speed up
// later lookups instead of throwing them away immediately.
EVP_MD_do_all_sorted(SaveSupportedHashAlgorithmsAndCacheMD, env);
@@ -194,7 +194,7 @@ void Hash::GetCachedAliases(const FunctionCallbackInfo& args) {
size_t size = env->alias_to_md_id_map.size();
LocalVector names(isolate);
LocalVector values(isolate);
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
names.reserve(size);
values.reserve(size);
for (auto& [alias, id] : env->alias_to_md_id_map) {
@@ -218,7 +218,7 @@ const EVP_MD* GetDigestImplementation(Environment* env,
CHECK(cache_id_val->IsInt32());
CHECK(algorithm_cache->IsObject());
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
int32_t cache_id = cache_id_val.As()->Value();
if (cache_id != -1) { // Alias already cached, return the cached EVP_MD*.
return GetCachedMDByID(env, cache_id);
@@ -266,7 +266,7 @@ void MarkInvalidXofLength() {
// version-independent.
#if !OPENSSL_VERSION_PREREQ(3, 4)
bool IsShakeDigest(const EVP_MD* md) {
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
return EVP_MD_is_a(md, "SHAKE128") || EVP_MD_is_a(md, "SHAKE256");
#else
const char* name = OBJ_nid2sn(EVP_MD_type(md));
diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc
index 1404390f4bc8bc..08e63acc3ffde4 100644
--- a/src/crypto/crypto_keys.cc
+++ b/src/crypto/crypto_keys.cc
@@ -1230,7 +1230,7 @@ void KeyObjectHandle::Equals(const FunctionCallbackInfo& args) {
case kKeyTypePrivate: {
EVP_PKEY* pkey = key.GetAsymmetricKey().get();
EVP_PKEY* pkey2 = key2.GetAsymmetricKey().get();
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
int ok = EVP_PKEY_eq(pkey, pkey2);
#else
int ok = EVP_PKEY_cmp(pkey, pkey2);
diff --git a/src/crypto/crypto_tls.cc b/src/crypto/crypto_tls.cc
index ce44ad15fa79d3..d12853b5a5e62a 100644
--- a/src/crypto/crypto_tls.cc
+++ b/src/crypto/crypto_tls.cc
@@ -82,7 +82,7 @@ namespace {
// that the user user Connection::VerifyError after the `secure`
// callback has been made.
int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx) {
- // From https://www.openssl.org/docs/man1.1.1/man3/SSL_verify_cb:
+ // From https://www.openssl.org/docs/man3.0/man3/SSL_verify_cb:
//
// If VerifyCallback returns 1, the verification process is continued. If
// VerifyCallback always returns 1, the TLS/SSL handshake will not be
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
index 711984e5e4f23f..da70d6d8d716e4 100644
--- a/src/crypto/crypto_util.cc
+++ b/src/crypto/crypto_util.cc
@@ -14,7 +14,7 @@
#include "math.h"
-#if OPENSSL_VERSION_MAJOR >= 3
+#ifndef OPENSSL_IS_BORINGSSL
#include "openssl/provider.h"
#endif
@@ -81,20 +81,24 @@ int NoPasswordCallback(char* buf, int size, int rwflag, void* u) {
return 0;
}
-bool ProcessFipsOptions() {
- /* Override FIPS settings in configuration file, if needed. */
- if (per_process::cli_options->enable_fips_crypto ||
- per_process::cli_options->force_fips_crypto) {
-#if OPENSSL_VERSION_MAJOR >= 3
- if (!ncrypto::testFipsEnabled()) return false;
- return ncrypto::setFipsEnabled(true, nullptr);
-#else
- // TODO(@jasnell): Remove this ifdef branch when openssl 1.1.1 is
- // no longer supported.
- if (FIPS_mode() == 0) return FIPS_mode_set(1);
-#endif
+std::optional ProcessFipsOptions() {
+ if (!per_process::cli_options->enable_fips_crypto) return std::nullopt;
+
+ // Whether FIPS-approved implementations are reachable is decided by the
+ // OpenSSL configuration, not by Node.js. Refuse to start rather than
+ // restrict the default property query to a provider that is not there,
+ // which would leave every operation failing as unsupported.
+ if (!ncrypto::testFipsEnabled()) {
+ return "--enable-fips requires an active OpenSSL provider named \"fips\". "
+ "FIPS mode is configured through OpenSSL; see "
+ "https://nodejs.org/api/crypto.html#fips-mode";
}
- return true;
+
+ if (!ncrypto::setFipsEnabled()) {
+ return "OpenSSL error when trying to enable FIPS";
+ }
+
+ return std::nullopt;
}
bool InitCryptoOnce(Isolate* isolate) {
@@ -118,15 +122,6 @@ void InitCryptoOnce() {
#ifndef OPENSSL_IS_BORINGSSL
OPENSSL_INIT_SETTINGS* settings = OPENSSL_INIT_new();
-#if OPENSSL_VERSION_MAJOR < 3
- // --openssl-config=...
- if (!per_process::cli_options->openssl_config.empty()) {
- const char* conf = per_process::cli_options->openssl_config.c_str();
- OPENSSL_INIT_set_config_filename(settings, conf);
- }
-#endif
-
-#if OPENSSL_VERSION_MAJOR >= 3
// --openssl-legacy-provider
if (per_process::cli_options->openssl_legacy_provider) {
OSSL_PROVIDER* legacy_provider = OSSL_PROVIDER_load(nullptr, "legacy");
@@ -134,7 +129,6 @@ void InitCryptoOnce() {
fprintf(stderr, "Unable to load legacy provider.\n");
}
}
-#endif
OPENSSL_init_ssl(0, settings);
@@ -193,24 +187,6 @@ void GetFipsCrypto(const FunctionCallbackInfo& args) {
args.GetReturnValue().Set(ncrypto::isFipsEnabled() ? 1 : 0);
}
-void SetFipsCrypto(const FunctionCallbackInfo& args) {
- Mutex::ScopedLock lock(per_process::cli_options_mutex);
- Mutex::ScopedLock fips_lock(fips_mutex);
-
- CHECK(!per_process::cli_options->force_fips_crypto);
- Environment* env = Environment::GetCurrent(args);
- CHECK(env->owns_process_state());
- bool enable = args[0]->BooleanValue(env->isolate());
-
- CryptoErrorList errors;
- if (!ncrypto::setFipsEnabled(enable, &errors)) {
- Local exception;
- if (cryptoErrorListToException(env, errors).ToLocal(&exception)) {
- env->isolate()->ThrowException(exception);
- }
- }
-}
-
void TestFipsCrypto(const v8::FunctionCallbackInfo& args) {
Mutex::ScopedLock lock(per_process::cli_options_mutex);
Mutex::ScopedLock fips_lock(fips_mutex);
@@ -857,7 +833,6 @@ void Initialize(Environment* env, Local