mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
crypto,https,tls: end OpenSSL engine support
OpenSSL removed support for engines in version 4. Remove the Node.js APIs, constants, native bindings, and implementation that depend on ENGINE. Keep recognizing the former TLS and HTTPS engine options so their use fails explicitly instead of appearing to work while being ignored. Move DEP0183 directly from Documentation-only to End-of-Life after reverting its unreleased Runtime deprecation. Signed-off-by: Filip Skokan <panva.ip@gmail.com> Assisted-by: Codex PR-URL: https://github.com/nodejs/node/pull/64777 Fixes: https://github.com/nodejs/node/issues/56733 Refs: https://github.com/nodejs/node/pull/64211 Refs: https://github.com/nodejs/node/pull/63966 Refs: https://github.com/nodejs/node/pull/53329 Refs: https://github.com/nodejs/node/pull/48950 Refs: https://github.com/nodejs/node/issues/45465 Refs: https://github.com/nodejs/node/issues/42827 Refs: https://github.com/nodejs/node/issues/47076 Refs: https://github.com/nodejs/node/pull/62862 Refs: https://github.com/nodejs/node/pull/38512 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
This commit is contained in:
41 files changed
+174
-1290
No files matched your search
Vendored
-105
@@ -1,105 +0,0 @@
|
|||||||
#include "ncrypto.h"
|
|
||||||
|
|
||||||
#if !defined(OPENSSL_NO_ENGINE) && defined(NCRYPTO_ENGINE_COMPAT) && \
|
|
||||||
NCRYPTO_ENGINE_COMPAT
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ncrypto {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// Engine
|
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
EnginePointer::EnginePointer(void* engine_, bool finish_on_exit_)
|
|
||||||
: engine(engine_), finish_on_exit(finish_on_exit_) {}
|
|
||||||
|
|
||||||
EnginePointer::EnginePointer(EnginePointer&& other) noexcept
|
|
||||||
: engine(other.engine), finish_on_exit(other.finish_on_exit) {
|
|
||||||
other.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
EnginePointer::~EnginePointer() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
EnginePointer& EnginePointer::operator=(EnginePointer&& other) noexcept {
|
|
||||||
if (this == &other) return *this;
|
|
||||||
this->~EnginePointer();
|
|
||||||
return *new (this) EnginePointer(std::move(other));
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnginePointer::reset(void* engine_, bool finish_on_exit_) {
|
|
||||||
if (engine != nullptr) {
|
|
||||||
ENGINE* current = static_cast<ENGINE*>(engine);
|
|
||||||
if (finish_on_exit) {
|
|
||||||
// This also does the equivalent of ENGINE_free.
|
|
||||||
ENGINE_finish(current);
|
|
||||||
} else {
|
|
||||||
ENGINE_free(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
engine = engine_;
|
|
||||||
finish_on_exit = finish_on_exit_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* EnginePointer::release() {
|
|
||||||
void* ret = engine;
|
|
||||||
engine = nullptr;
|
|
||||||
finish_on_exit = false;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
EnginePointer EnginePointer::getEngineByName(const char* name,
|
|
||||||
CryptoErrorList* errors) {
|
|
||||||
MarkPopErrorOnReturn mark_pop_error_on_return(errors);
|
|
||||||
EnginePointer engine(ENGINE_by_id(name));
|
|
||||||
if (!engine) {
|
|
||||||
// Engine not found, try loading dynamically.
|
|
||||||
engine = EnginePointer(ENGINE_by_id("dynamic"));
|
|
||||||
if (engine) {
|
|
||||||
ENGINE* current = static_cast<ENGINE*>(engine.engine);
|
|
||||||
if (!ENGINE_ctrl_cmd_string(current, "SO_PATH", name, 0) ||
|
|
||||||
!ENGINE_ctrl_cmd_string(current, "LOAD", nullptr, 0)) {
|
|
||||||
engine.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EnginePointer::setAsDefault(uint32_t flags, CryptoErrorList* errors) {
|
|
||||||
if (engine == nullptr) return false;
|
|
||||||
ClearErrorOnReturn clear_error_on_return(errors);
|
|
||||||
return ENGINE_set_default(static_cast<ENGINE*>(engine), flags) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EnginePointer::init(bool finish_on_exit) {
|
|
||||||
if (engine == nullptr) return false;
|
|
||||||
if (finish_on_exit) setFinishOnExit();
|
|
||||||
return ENGINE_init(static_cast<ENGINE*>(engine)) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
EVPKeyPointer EnginePointer::loadPrivateKey(const char* key_name) {
|
|
||||||
if (engine == nullptr) return EVPKeyPointer();
|
|
||||||
return EVPKeyPointer(ENGINE_load_private_key(
|
|
||||||
static_cast<ENGINE*>(engine), key_name, nullptr, nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EnginePointer::setClientCertEngine(SSL_CTX* ctx) {
|
|
||||||
if (engine == nullptr || ctx == nullptr) return false;
|
|
||||||
return SSL_CTX_set_client_cert_engine(ctx, static_cast<ENGINE*>(engine)) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EnginePointer::initEnginesOnce() {
|
|
||||||
static bool initialized = false;
|
|
||||||
if (!initialized) {
|
|
||||||
ENGINE_load_builtin_engines();
|
|
||||||
ENGINE_register_all_complete();
|
|
||||||
initialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
} // namespace ncrypto
|
|
||||||
Vendored
-35
@@ -5,10 +5,6 @@
|
|||||||
'ncrypto.cc',
|
'ncrypto.cc',
|
||||||
'ncrypto.h',
|
'ncrypto.h',
|
||||||
],
|
],
|
||||||
'ncrypto_engine_sources': [
|
|
||||||
'engine.cc',
|
|
||||||
'ncrypto.h',
|
|
||||||
],
|
|
||||||
# OpenSSL may be configured with --api below 3.0. Keep 3.0 deprecation
|
# OpenSSL may be configured with --api below 3.0. Keep 3.0 deprecation
|
||||||
# checks where supported without exceeding its configured API level.
|
# checks where supported without exceeding its configured API level.
|
||||||
'ncrypto_openssl3_api_compat':
|
'ncrypto_openssl3_api_compat':
|
||||||
@@ -17,11 +13,6 @@
|
|||||||
'OPENSSL_API_COMPAT=<(ncrypto_openssl3_api_compat)',
|
'OPENSSL_API_COMPAT=<(ncrypto_openssl3_api_compat)',
|
||||||
'OPENSSL_NO_DEPRECATED',
|
'OPENSSL_NO_DEPRECATED',
|
||||||
],
|
],
|
||||||
'ncrypto_engine_defines': [
|
|
||||||
'OPENSSL_API_COMPAT=<(ncrypto_openssl3_api_compat)',
|
|
||||||
'OPENSSL_SUPPRESS_DEPRECATED',
|
|
||||||
'NCRYPTO_ENGINE_COMPAT=1',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
'targets': [
|
'targets': [
|
||||||
{
|
{
|
||||||
@@ -46,9 +37,6 @@
|
|||||||
'conditions': [
|
'conditions': [
|
||||||
['openssl_is_boringssl=="false"', {
|
['openssl_is_boringssl=="false"', {
|
||||||
'defines': [ '<@(ncrypto_strict_defines)' ],
|
'defines': [ '<@(ncrypto_strict_defines)' ],
|
||||||
'dependencies': [
|
|
||||||
'ncrypto_engine',
|
|
||||||
],
|
|
||||||
}],
|
}],
|
||||||
['node_shared_openssl=="false"', {
|
['node_shared_openssl=="false"', {
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
@@ -58,27 +46,4 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'conditions': [
|
|
||||||
['openssl_is_boringssl=="false"', {
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'ncrypto_engine',
|
|
||||||
'type': 'static_library',
|
|
||||||
'include_dirs': ['.'],
|
|
||||||
'defines': [
|
|
||||||
'NCRYPTO_BSSL_LIBDECREPIT_MISSING=<(ncrypto_bssl_libdecrepit_missing)',
|
|
||||||
'<@(ncrypto_engine_defines)',
|
|
||||||
],
|
|
||||||
'sources': [ '<@(ncrypto_engine_sources)' ],
|
|
||||||
'conditions': [
|
|
||||||
['node_shared_openssl=="false"', {
|
|
||||||
'dependencies': [
|
|
||||||
'../openssl/openssl.gyp:openssl'
|
|
||||||
]
|
|
||||||
}],
|
|
||||||
]
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
Vendored
-43
@@ -23,11 +23,6 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#if defined(NCRYPTO_ENGINE_COMPAT) && NCRYPTO_ENGINE_COMPAT && \
|
|
||||||
!defined(OPENSSL_NO_ENGINE)
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#endif // NCRYPTO_ENGINE_COMPAT && !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
#ifndef OPENSSL_VERSION_PREREQ
|
#ifndef OPENSSL_VERSION_PREREQ
|
||||||
#define OPENSSL_VERSION_PREREQ(maj, min) \
|
#define OPENSSL_VERSION_PREREQ(maj, min) \
|
||||||
(OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
|
(OPENSSL_VERSION_NUMBER >= (((maj) << 28) | ((min) << 20)))
|
||||||
@@ -2109,44 +2104,6 @@ class MacCache final {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
class EnginePointer final {
|
|
||||||
public:
|
|
||||||
EnginePointer() = default;
|
|
||||||
|
|
||||||
explicit EnginePointer(void* engine_, bool finish_on_exit = false);
|
|
||||||
EnginePointer(EnginePointer&& other) noexcept;
|
|
||||||
EnginePointer& operator=(EnginePointer&& other) noexcept;
|
|
||||||
NCRYPTO_DISALLOW_COPY(EnginePointer)
|
|
||||||
~EnginePointer();
|
|
||||||
|
|
||||||
inline operator bool() const { return engine != nullptr; }
|
|
||||||
inline void setFinishOnExit() { finish_on_exit = true; }
|
|
||||||
|
|
||||||
void reset(void* engine_ = nullptr, bool finish_on_exit_ = false);
|
|
||||||
|
|
||||||
bool setAsDefault(uint32_t flags, CryptoErrorList* errors = nullptr);
|
|
||||||
bool init(bool finish_on_exit = false);
|
|
||||||
EVPKeyPointer loadPrivateKey(const char* key_name);
|
|
||||||
bool setClientCertEngine(SSL_CTX* ctx);
|
|
||||||
|
|
||||||
void* release();
|
|
||||||
|
|
||||||
// Retrieve an OpenSSL Engine instance by name. If the name does not
|
|
||||||
// identify a valid named engine, the returned EnginePointer will be
|
|
||||||
// empty.
|
|
||||||
static EnginePointer getEngineByName(const char* name,
|
|
||||||
CryptoErrorList* errors = nullptr);
|
|
||||||
|
|
||||||
// Call once when initializing OpenSSL at startup for the process.
|
|
||||||
static void initEnginesOnce();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void* engine = nullptr;
|
|
||||||
bool finish_on_exit = false;
|
|
||||||
};
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// FIPS
|
// FIPS
|
||||||
bool isFipsEnabled();
|
bool isFipsEnabled();
|
||||||
|
|||||||
Vendored
+1
-5
@@ -26,11 +26,7 @@ template("ncrypto_gn_build") {
|
|||||||
source_set(target_name) {
|
source_set(target_name) {
|
||||||
forward_variables_from(invoker, "*")
|
forward_variables_from(invoker, "*")
|
||||||
public_configs = [ ":ncrypto_config" ]
|
public_configs = [ ":ncrypto_config" ]
|
||||||
defines = [
|
sources = gypi_values.ncrypto_sources
|
||||||
"NCRYPTO_ENGINE_COMPAT=1",
|
|
||||||
"OPENSSL_SUPPRESS_DEPRECATED",
|
|
||||||
]
|
|
||||||
sources = gypi_values.ncrypto_sources + gypi_values.ncrypto_engine_sources
|
|
||||||
deps = [ "$node_openssl_path" ]
|
deps = [ "$node_openssl_path" ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6601,42 +6601,6 @@ added: v15.6.0
|
|||||||
* `utilization` {number} The calculated ratio of `used` to `total`
|
* `utilization` {number} The calculated ratio of `used` to `total`
|
||||||
allocated bytes.
|
allocated bytes.
|
||||||
|
|
||||||
### `crypto.setEngine(engine[, flags])`
|
|
||||||
|
|
||||||
<!-- YAML
|
|
||||||
added: v0.11.11
|
|
||||||
changes:
|
|
||||||
- version:
|
|
||||||
- v22.4.0
|
|
||||||
- v20.16.0
|
|
||||||
pr-url: https://github.com/nodejs/node/pull/53329
|
|
||||||
description: Custom engine support in OpenSSL 3 is deprecated.
|
|
||||||
-->
|
|
||||||
|
|
||||||
* `engine` {string}
|
|
||||||
* `flags` {crypto.constants} **Default:** `crypto.constants.ENGINE_METHOD_ALL`
|
|
||||||
|
|
||||||
Load and set the `engine` for some or all OpenSSL functions (selected by flags).
|
|
||||||
Support for custom engines in OpenSSL is deprecated from OpenSSL 3.
|
|
||||||
|
|
||||||
`engine` could be either an id or a path to the engine's shared library.
|
|
||||||
|
|
||||||
The optional `flags` argument uses `ENGINE_METHOD_ALL` by default. The `flags`
|
|
||||||
is a bit field taking one of or a mix of the following flags (defined in
|
|
||||||
`crypto.constants`):
|
|
||||||
|
|
||||||
* `crypto.constants.ENGINE_METHOD_RSA`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_DSA`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_DH`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_RAND`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_EC`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_CIPHERS`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_DIGESTS`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_PKEY_METHS`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_PKEY_ASN1_METHS`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_ALL`
|
|
||||||
* `crypto.constants.ENGINE_METHOD_NONE`
|
|
||||||
|
|
||||||
### `crypto.setFips(bool)`
|
### `crypto.setFips(bool)`
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
@@ -7463,59 +7427,6 @@ See the [list of SSL OP Flags][] for details.
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### OpenSSL engine constants
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>Constant</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_RSA</code></td>
|
|
||||||
<td>Limit engine usage to RSA</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_DSA</code></td>
|
|
||||||
<td>Limit engine usage to DSA</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_DH</code></td>
|
|
||||||
<td>Limit engine usage to DH</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_RAND</code></td>
|
|
||||||
<td>Limit engine usage to RAND</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_EC</code></td>
|
|
||||||
<td>Limit engine usage to EC</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_CIPHERS</code></td>
|
|
||||||
<td>Limit engine usage to CIPHERS</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_DIGESTS</code></td>
|
|
||||||
<td>Limit engine usage to DIGESTS</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_PKEY_METHS</code></td>
|
|
||||||
<td>Limit engine usage to PKEY_METHS</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_PKEY_ASN1_METHS</code></td>
|
|
||||||
<td>Limit engine usage to PKEY_ASN1_METHS</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_ALL</code></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ENGINE_METHOD_NONE</code></td>
|
|
||||||
<td></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Other OpenSSL constants
|
### Other OpenSSL constants
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
+11
-7
@@ -4111,6 +4111,9 @@ that are shorter than the default authentication tag length (i.e., shorter than
|
|||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/64777
|
||||||
|
description: End-of-Life.
|
||||||
- version:
|
- version:
|
||||||
- v22.4.0
|
- v22.4.0
|
||||||
- v20.16.0
|
- v20.16.0
|
||||||
@@ -4118,13 +4121,15 @@ changes:
|
|||||||
description: Documentation-only deprecation.
|
description: Documentation-only deprecation.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
Type: Documentation-only
|
Type: End-of-Life
|
||||||
|
|
||||||
OpenSSL 3 has deprecated support for custom engines with a recommendation to
|
The `crypto.setEngine()` API and the `crypto.constants.ENGINE_METHOD_*`
|
||||||
switch to its new provider model. The `clientCertEngine` option for
|
constants have been removed. The `clientCertEngine` option for
|
||||||
`https.request()`, [`tls.createSecureContext()`][], and [`tls.createServer()`][];
|
[`https.request()`][], [`tls.createSecureContext()`][], and
|
||||||
the `privateKeyEngine` and `privateKeyIdentifier` for [`tls.createSecureContext()`][];
|
[`tls.createServer()`][] and the `privateKeyEngine` and `privateKeyIdentifier`
|
||||||
and [`crypto.setEngine()`][] all depend on this functionality from OpenSSL.
|
options for [`tls.createSecureContext()`][] now throw
|
||||||
|
`ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED` when used. There is no direct
|
||||||
|
replacement API in Node.js. OpenSSL's provider model replaces engines upstream.
|
||||||
|
|
||||||
### DEP0184: Instantiating `node:zlib` classes without `new`
|
### DEP0184: Instantiating `node:zlib` classes without `new`
|
||||||
|
|
||||||
@@ -4887,7 +4892,6 @@ Type: Documentation-only
|
|||||||
[`crypto.pbkdf2()`]: crypto.md#cryptopbkdf2password-salt-iterations-keylen-digest-callback
|
[`crypto.pbkdf2()`]: crypto.md#cryptopbkdf2password-salt-iterations-keylen-digest-callback
|
||||||
[`crypto.randomBytes()`]: crypto.md#cryptorandombytessize-callback
|
[`crypto.randomBytes()`]: crypto.md#cryptorandombytessize-callback
|
||||||
[`crypto.scrypt()`]: crypto.md#cryptoscryptpassword-salt-keylen-options-callback
|
[`crypto.scrypt()`]: crypto.md#cryptoscryptpassword-salt-keylen-options-callback
|
||||||
[`crypto.setEngine()`]: crypto.md#cryptosetengineengine-flags
|
|
||||||
[`decipher.final()`]: crypto.md#decipherfinaloutputencoding
|
[`decipher.final()`]: crypto.md#decipherfinaloutputencoding
|
||||||
[`decipher.setAuthTag()`]: crypto.md#deciphersetauthtagbuffer-encoding
|
[`decipher.setAuthTag()`]: crypto.md#deciphersetauthtagbuffer-encoding
|
||||||
[`dirent.parentPath`]: fs.md#direntparentpath
|
[`dirent.parentPath`]: fs.md#direntparentpath
|
||||||
|
|||||||
+13
-11
@@ -911,9 +911,8 @@ Argon2 is not supported by the current version of OpenSSL being used.
|
|||||||
|
|
||||||
### `ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED`
|
### `ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED`
|
||||||
|
|
||||||
An OpenSSL engine was requested (for example, through the `clientCertEngine` or
|
An OpenSSL engine-based TLS or HTTPS option was used after support for custom
|
||||||
`privateKeyEngine` TLS options) that is not supported by the version of OpenSSL
|
engines reached End-of-Life in Node.js.
|
||||||
being used, likely due to the compile-time flag `OPENSSL_NO_ENGINE`.
|
|
||||||
|
|
||||||
<a id="ERR_CRYPTO_ECDH_INVALID_FORMAT"></a>
|
<a id="ERR_CRYPTO_ECDH_INVALID_FORMAT"></a>
|
||||||
|
|
||||||
@@ -930,13 +929,6 @@ An invalid value for the `key` argument has been passed to the
|
|||||||
`crypto.ECDH()` class `computeSecret()` method. It means that the public
|
`crypto.ECDH()` class `computeSecret()` method. It means that the public
|
||||||
key lies outside of the elliptic curve.
|
key lies outside of the elliptic curve.
|
||||||
|
|
||||||
<a id="ERR_CRYPTO_ENGINE_UNKNOWN"></a>
|
|
||||||
|
|
||||||
### `ERR_CRYPTO_ENGINE_UNKNOWN`
|
|
||||||
|
|
||||||
An invalid crypto engine identifier was passed to
|
|
||||||
[`require('node:crypto').setEngine()`][].
|
|
||||||
|
|
||||||
<a id="ERR_CRYPTO_FIPS_FORCED"></a>
|
<a id="ERR_CRYPTO_FIPS_FORCED"></a>
|
||||||
|
|
||||||
### `ERR_CRYPTO_FIPS_FORCED`
|
### `ERR_CRYPTO_FIPS_FORCED`
|
||||||
@@ -3945,6 +3937,17 @@ removed: v15.0.0
|
|||||||
|
|
||||||
The native call from `process.cpuUsage` could not be processed.
|
The native call from `process.cpuUsage` could not be processed.
|
||||||
|
|
||||||
|
<a id="ERR_CRYPTO_ENGINE_UNKNOWN"></a>
|
||||||
|
|
||||||
|
### `ERR_CRYPTO_ENGINE_UNKNOWN`
|
||||||
|
|
||||||
|
<!-- YAML
|
||||||
|
removed: REPLACEME
|
||||||
|
-->
|
||||||
|
|
||||||
|
An invalid crypto engine identifier was passed to
|
||||||
|
`require('node:crypto').setEngine()`.
|
||||||
|
|
||||||
<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`
|
||||||
@@ -4840,7 +4843,6 @@ An error occurred trying to allocate memory. This should never happen.
|
|||||||
[`process.send()`]: process.md#processsendmessage-sendhandle-options-callback
|
[`process.send()`]: process.md#processsendmessage-sendhandle-options-callback
|
||||||
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
|
[`process.setUncaughtExceptionCaptureCallback()`]: process.md#processsetuncaughtexceptioncapturecallbackfn
|
||||||
[`readable._read()`]: stream.md#readable_readsize
|
[`readable._read()`]: stream.md#readable_readsize
|
||||||
[`require('node:crypto').setEngine()`]: crypto.md#cryptosetengineengine-flags
|
|
||||||
[`require()`]: modules.md#requireid
|
[`require()`]: modules.md#requireid
|
||||||
[`server.close()`]: net.md#serverclosecallback
|
[`server.close()`]: net.md#serverclosecallback
|
||||||
[`server.listen()`]: net.md#serverlisten
|
[`server.listen()`]: net.md#serverlisten
|
||||||
|
|||||||
+7
-4
@@ -427,6 +427,10 @@ a `timeout` of 5 seconds.
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.3.6
|
added: v0.3.6
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/64777
|
||||||
|
description: Using the `clientCertEngine` option now throws
|
||||||
|
`ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED`.
|
||||||
- version:
|
- version:
|
||||||
- v22.4.0
|
- v22.4.0
|
||||||
- v20.16.0
|
- v20.16.0
|
||||||
@@ -468,10 +472,9 @@ changes:
|
|||||||
Makes a request to a secure web server.
|
Makes a request to a secure web server.
|
||||||
|
|
||||||
The following additional `options` from [`tls.connect()`][] are also accepted:
|
The following additional `options` from [`tls.connect()`][] are also accepted:
|
||||||
`ca`, `cert`, `ciphers`, `clientCertEngine` (deprecated), `crl`, `dhparam`, `ecdhCurve`,
|
`ca`, `cert`, `ciphers`, `crl`, `dhparam`, `ecdhCurve`, `honorCipherOrder`,
|
||||||
`honorCipherOrder`, `key`, `passphrase`, `pfx`, `rejectUnauthorized`,
|
`key`, `passphrase`, `pfx`, `rejectUnauthorized`, `secureOptions`,
|
||||||
`secureOptions`, `secureProtocol`, `servername`, `sessionIdContext`,
|
`secureProtocol`, `servername`, `sessionIdContext`, `highWaterMark`.
|
||||||
`highWaterMark`.
|
|
||||||
|
|
||||||
`options` can be an object, a string, or a [`URL`][] object. If `options` is a
|
`options` can be an object, a string, or a [`URL`][] object. If `options` is a
|
||||||
string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][]
|
string, it is automatically parsed with [`new URL()`][]. If it is a [`URL`][]
|
||||||
|
|||||||
@@ -503,8 +503,6 @@ There are constraints you need to know before using this system:
|
|||||||
expanded path is not covered by `--allow-fs-write`. Because the location is
|
expanded path is not covered by `--allow-fs-write`. Because the location is
|
||||||
chosen by the operator, gaps like this are treated as regular bugs rather
|
chosen by the operator, gaps like this are treated as regular bugs rather
|
||||||
than vulnerabilities. Please report them through the regular issue tracker.
|
than vulnerabilities. Please report them through the regular issue tracker.
|
||||||
* OpenSSL engines cannot be requested at runtime when the Permission
|
|
||||||
Model is enabled, affecting the built-in crypto, https, and tls modules.
|
|
||||||
* Run-Time Loadable Extensions cannot be loaded when the Permission Model is
|
* Run-Time Loadable Extensions cannot be loaded when the Permission Model is
|
||||||
enabled, affecting the sqlite module.
|
enabled, affecting the sqlite module.
|
||||||
* Using existing file descriptors via the `node:fs` module bypasses the
|
* Using existing file descriptors via the `node:fs` module bypasses the
|
||||||
|
|||||||
+9
-10
@@ -1988,6 +1988,11 @@ argument.
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.11.13
|
added: v0.11.13
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/64777
|
||||||
|
description: Using the `clientCertEngine`, `privateKeyEngine`, or
|
||||||
|
`privateKeyIdentifier` option now throws
|
||||||
|
`ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED`.
|
||||||
- version:
|
- version:
|
||||||
- v26.4.0
|
- v26.4.0
|
||||||
- v24.19.0
|
- v24.19.0
|
||||||
@@ -2102,8 +2107,6 @@ changes:
|
|||||||
more information, see [Modifying the default TLS cipher suite][]. Permitted
|
more information, see [Modifying the default TLS cipher suite][]. Permitted
|
||||||
ciphers can be obtained via [`tls.getCiphers()`][]. Cipher names must be
|
ciphers can be obtained via [`tls.getCiphers()`][]. Cipher names must be
|
||||||
uppercased in order for OpenSSL to accept them.
|
uppercased in order for OpenSSL to accept them.
|
||||||
* `clientCertEngine` {string} Name of an OpenSSL engine which can provide the
|
|
||||||
client certificate. **Deprecated.**
|
|
||||||
* `crl` {string|string\[]|Buffer|Buffer\[]} PEM formatted CRLs (Certificate
|
* `crl` {string|string\[]|Buffer|Buffer\[]} PEM formatted CRLs (Certificate
|
||||||
Revocation Lists).
|
Revocation Lists).
|
||||||
* `dhparam` {string|Buffer} `'auto'` or custom Diffie-Hellman parameters,
|
* `dhparam` {string|Buffer} `'auto'` or custom Diffie-Hellman parameters,
|
||||||
@@ -2134,12 +2137,6 @@ changes:
|
|||||||
occur in an array. `object.passphrase` is optional. Encrypted keys will be
|
occur in an array. `object.passphrase` is optional. Encrypted keys will be
|
||||||
decrypted with `object.passphrase` if provided, or `options.passphrase` if
|
decrypted with `object.passphrase` if provided, or `options.passphrase` if
|
||||||
it is not.
|
it is not.
|
||||||
* `privateKeyEngine` {string} Name of an OpenSSL engine to get private key
|
|
||||||
from. Should be used together with `privateKeyIdentifier`. **Deprecated.**
|
|
||||||
* `privateKeyIdentifier` {string} Identifier of a private key managed by
|
|
||||||
an OpenSSL engine. Should be used together with `privateKeyEngine`.
|
|
||||||
Should not be set together with `key`, because both options define a
|
|
||||||
private key in different ways. **Deprecated.**
|
|
||||||
* `maxVersion` {string} Optionally set the maximum TLS version to allow. One
|
* `maxVersion` {string} Optionally set the maximum TLS version to allow. One
|
||||||
of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified
|
of `'TLSv1.3'`, `'TLSv1.2'`, `'TLSv1.1'`, or `'TLSv1'`. Cannot be specified
|
||||||
along with the `secureProtocol` option; use one or the other.
|
along with the `secureProtocol` option; use one or the other.
|
||||||
@@ -2212,6 +2209,10 @@ permissible, use 2048 bits or larger for stronger security.
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.3.2
|
added: v0.3.2
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/64777
|
||||||
|
description: Using the `clientCertEngine` option now throws
|
||||||
|
`ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED`.
|
||||||
- version:
|
- version:
|
||||||
- v22.4.0
|
- v22.4.0
|
||||||
- v20.16.0
|
- v20.16.0
|
||||||
@@ -2262,8 +2263,6 @@ changes:
|
|||||||
If a string is returned that does not match one of the client's ALPN
|
If a string is returned that does not match one of the client's ALPN
|
||||||
protocols, an error will be thrown. This option cannot be used with the
|
protocols, an error will be thrown. This option cannot be used with the
|
||||||
`ALPNProtocols` option, and setting both options will throw an error.
|
`ALPNProtocols` option, and setting both options will throw an error.
|
||||||
* `clientCertEngine` {string} Name of an OpenSSL engine which can provide the
|
|
||||||
client certificate. **Deprecated.**
|
|
||||||
* `enableTrace` {boolean} If `true`, [`tls.TLSSocket.enableTrace()`][] will be
|
* `enableTrace` {boolean} If `true`, [`tls.TLSSocket.enableTrace()`][] will be
|
||||||
called on new connections. Tracing can be enabled after the secure
|
called on new connections. Tracing can be enabled after the secure
|
||||||
connection is established, but this option must be used to trace the secure
|
connection is established, but this option must be used to trace the secure
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ const {
|
|||||||
getCurves,
|
getCurves,
|
||||||
getHashes,
|
getHashes,
|
||||||
getMacs,
|
getMacs,
|
||||||
setEngine,
|
|
||||||
secureHeapUsed,
|
secureHeapUsed,
|
||||||
} = require('internal/crypto/util');
|
} = require('internal/crypto/util');
|
||||||
const Certificate = require('internal/crypto/certificate');
|
const Certificate = require('internal/crypto/certificate');
|
||||||
@@ -237,7 +236,6 @@ module.exports = {
|
|||||||
scrypt,
|
scrypt,
|
||||||
scryptSync,
|
scryptSync,
|
||||||
sign: signOneShot,
|
sign: signOneShot,
|
||||||
setEngine,
|
|
||||||
timingSafeEqual,
|
timingSafeEqual,
|
||||||
getFips,
|
getFips,
|
||||||
setFips,
|
setFips,
|
||||||
|
|||||||
+6
-12
@@ -49,6 +49,9 @@ const { ERR_PROXY_TUNNEL } = require('internal/errors').codes;
|
|||||||
assertCrypto();
|
assertCrypto();
|
||||||
|
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
|
const {
|
||||||
|
validateOpenSSLEngineOptions,
|
||||||
|
} = require('internal/tls/secure-context');
|
||||||
const kPerRequestCheckServerIdentity = Symbol('per-request checkServerIdentity');
|
const kPerRequestCheckServerIdentity = Symbol('per-request checkServerIdentity');
|
||||||
let perRequestCheckServerIdentityIndex = 0;
|
let perRequestCheckServerIdentityIndex = 0;
|
||||||
const {
|
const {
|
||||||
@@ -487,6 +490,7 @@ function Agent(options) {
|
|||||||
return new Agent(options);
|
return new Agent(options);
|
||||||
|
|
||||||
options = { __proto__: null, ...options };
|
options = { __proto__: null, ...options };
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
options.defaultPort ??= 443;
|
options.defaultPort ??= 443;
|
||||||
options.protocol ??= 'https:';
|
options.protocol ??= 'https:';
|
||||||
FunctionPrototypeCall(HttpAgent, this, options);
|
FunctionPrototypeCall(HttpAgent, this, options);
|
||||||
@@ -535,6 +539,7 @@ function getPfxAgentKey(pfx, passphrase) {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
Agent.prototype.getName = function getName(options = kEmptyObject) {
|
Agent.prototype.getName = function getName(options = kEmptyObject) {
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
let name = FunctionPrototypeCall(HttpAgent.prototype.getName, this, options);
|
let name = FunctionPrototypeCall(HttpAgent.prototype.getName, this, options);
|
||||||
|
|
||||||
name += ':';
|
name += ':';
|
||||||
@@ -545,10 +550,6 @@ Agent.prototype.getName = function getName(options = kEmptyObject) {
|
|||||||
if (options.cert)
|
if (options.cert)
|
||||||
name += options.cert;
|
name += options.cert;
|
||||||
|
|
||||||
name += ':';
|
|
||||||
if (options.clientCertEngine)
|
|
||||||
name += options.clientCertEngine;
|
|
||||||
|
|
||||||
name += ':';
|
name += ':';
|
||||||
if (options.ciphers)
|
if (options.ciphers)
|
||||||
name += options.ciphers;
|
name += options.ciphers;
|
||||||
@@ -609,14 +610,6 @@ Agent.prototype.getName = function getName(options = kEmptyObject) {
|
|||||||
if (options.sigalgs)
|
if (options.sigalgs)
|
||||||
name += JSONStringify(options.sigalgs);
|
name += JSONStringify(options.sigalgs);
|
||||||
|
|
||||||
name += ':';
|
|
||||||
if (options.privateKeyIdentifier)
|
|
||||||
name += options.privateKeyIdentifier;
|
|
||||||
|
|
||||||
name += ':';
|
|
||||||
if (options.privateKeyEngine)
|
|
||||||
name += options.privateKeyEngine;
|
|
||||||
|
|
||||||
if (options[kPerRequestCheckServerIdentity])
|
if (options[kPerRequestCheckServerIdentity])
|
||||||
name += `:${options[kPerRequestCheckServerIdentity]}`;
|
name += `:${options[kPerRequestCheckServerIdentity]}`;
|
||||||
|
|
||||||
@@ -692,6 +685,7 @@ function request(...args) {
|
|||||||
if (args[0] && typeof args[0] !== 'function') {
|
if (args[0] && typeof args[0] !== 'function') {
|
||||||
ObjectAssign(options, ArrayPrototypeShift(args));
|
ObjectAssign(options, ArrayPrototypeShift(args));
|
||||||
}
|
}
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
|
|
||||||
if (options.checkServerIdentity !== undefined &&
|
if (options.checkServerIdentity !== undefined &&
|
||||||
options.checkServerIdentity !== tls.checkServerIdentity &&
|
options.checkServerIdentity !== tls.checkServerIdentity &&
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ const {
|
|||||||
getCurves: _getCurves,
|
getCurves: _getCurves,
|
||||||
getHashes: _getHashes,
|
getHashes: _getHashes,
|
||||||
getMacs: _getMacs,
|
getMacs: _getMacs,
|
||||||
setEngine: _setEngine,
|
|
||||||
secureHeapUsed: _secureHeapUsed,
|
secureHeapUsed: _secureHeapUsed,
|
||||||
getCachedAliases,
|
getCachedAliases,
|
||||||
getCachedMacAliases,
|
getCachedMacAliases,
|
||||||
@@ -68,18 +67,10 @@ function isFips() {
|
|||||||
|
|
||||||
const { getOptionValue } = require('internal/options');
|
const { getOptionValue } = require('internal/options');
|
||||||
|
|
||||||
const {
|
|
||||||
crypto: {
|
|
||||||
ENGINE_METHOD_ALL,
|
|
||||||
},
|
|
||||||
} = internalBinding('constants');
|
|
||||||
|
|
||||||
const normalizeHashName = require('internal/crypto/hashnames');
|
const normalizeHashName = require('internal/crypto/hashnames');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
codes: {
|
codes: {
|
||||||
ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED,
|
|
||||||
ERR_CRYPTO_ENGINE_UNKNOWN,
|
|
||||||
ERR_INVALID_ARG_TYPE,
|
ERR_INVALID_ARG_TYPE,
|
||||||
},
|
},
|
||||||
hideStackFrames,
|
hideStackFrames,
|
||||||
@@ -87,7 +78,6 @@ const {
|
|||||||
|
|
||||||
const {
|
const {
|
||||||
validateArray,
|
validateArray,
|
||||||
validateNumber,
|
|
||||||
validateString,
|
validateString,
|
||||||
} = require('internal/validators');
|
} = require('internal/validators');
|
||||||
|
|
||||||
@@ -212,22 +202,6 @@ const getMacs = cachedArrayByFipsGeneration(
|
|||||||
const getCurves = cachedArrayByFipsGeneration(
|
const getCurves = cachedArrayByFipsGeneration(
|
||||||
() => filterDuplicateStrings(_getCurves()));
|
() => filterDuplicateStrings(_getCurves()));
|
||||||
|
|
||||||
function setEngine(id, flags) {
|
|
||||||
validateString(id, 'id');
|
|
||||||
if (flags)
|
|
||||||
validateNumber(flags, 'flags');
|
|
||||||
flags = flags >>> 0;
|
|
||||||
|
|
||||||
// Use provided engine for everything by default
|
|
||||||
if (flags === 0)
|
|
||||||
flags = ENGINE_METHOD_ALL;
|
|
||||||
|
|
||||||
if (typeof _setEngine !== 'function')
|
|
||||||
throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED();
|
|
||||||
if (!_setEngine(id, flags))
|
|
||||||
throw new ERR_CRYPTO_ENGINE_UNKNOWN(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const getArrayBufferOrView = hideStackFrames((buffer, name, encoding) => {
|
const getArrayBufferOrView = hideStackFrames((buffer, name, encoding) => {
|
||||||
if (isAnyArrayBuffer(buffer))
|
if (isAnyArrayBuffer(buffer))
|
||||||
return buffer;
|
return buffer;
|
||||||
@@ -1279,7 +1253,6 @@ module.exports = {
|
|||||||
getMacs,
|
getMacs,
|
||||||
getOptionalByteLength,
|
getOptionalByteLength,
|
||||||
kHandle,
|
kHandle,
|
||||||
setEngine,
|
|
||||||
toBuf,
|
toBuf,
|
||||||
|
|
||||||
kNamedCurveAliases,
|
kNamedCurveAliases,
|
||||||
|
|||||||
@@ -1175,11 +1175,10 @@ E('ERR_CONSTRUCT_CALL_REQUIRED', 'Class constructor %s cannot be invoked without
|
|||||||
E('ERR_CONTEXT_NOT_INITIALIZED', 'context used is not initialized', Error);
|
E('ERR_CONTEXT_NOT_INITIALIZED', 'context used is not initialized', Error);
|
||||||
E('ERR_CRYPTO_ARGON2_NOT_SUPPORTED', 'Argon2 algorithm not supported', Error);
|
E('ERR_CRYPTO_ARGON2_NOT_SUPPORTED', 'Argon2 algorithm not supported', Error);
|
||||||
E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
||||||
'Custom engines not supported by this OpenSSL', Error);
|
'Custom engines not supported by this version of Node.js', Error);
|
||||||
E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s', TypeError);
|
E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s', TypeError);
|
||||||
E('ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
|
E('ERR_CRYPTO_ECDH_INVALID_PUBLIC_KEY',
|
||||||
'Public key is not valid for specified curve', Error);
|
'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',
|
E('ERR_CRYPTO_FIPS_FORCED',
|
||||||
'Cannot set FIPS mode, it was forced with --force-fips at startup.', Error);
|
'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.',
|
E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.',
|
||||||
|
|||||||
@@ -127,8 +127,26 @@ function processCiphers(ciphers, name) {
|
|||||||
return { cipherList, cipherSuites };
|
return { cipherList, cipherSuites };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateOpenSSLEngineOptions(options) {
|
||||||
|
const {
|
||||||
|
clientCertEngine,
|
||||||
|
privateKeyEngine,
|
||||||
|
privateKeyIdentifier,
|
||||||
|
} = options;
|
||||||
|
|
||||||
|
// OpenSSL engine support moves directly from Documentation-only to
|
||||||
|
// End-of-Life. Keep recognizing these options so users cannot assume engines
|
||||||
|
// still work: their use must throw instead of being silently ignored.
|
||||||
|
if (clientCertEngine != null ||
|
||||||
|
privateKeyEngine != null ||
|
||||||
|
privateKeyIdentifier != null) {
|
||||||
|
throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function configSecureContext(context, options = kEmptyObject, name = 'options') {
|
function configSecureContext(context, options = kEmptyObject, name = 'options') {
|
||||||
validateObject(options, name);
|
validateObject(options, name);
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
allowPartialTrustChain,
|
allowPartialTrustChain,
|
||||||
@@ -136,15 +154,12 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
|
|||||||
cert,
|
cert,
|
||||||
certificateCompression,
|
certificateCompression,
|
||||||
ciphers = getDefaultCiphers(),
|
ciphers = getDefaultCiphers(),
|
||||||
clientCertEngine,
|
|
||||||
crl,
|
crl,
|
||||||
dhparam,
|
dhparam,
|
||||||
ecdhCurve = getDefaultEcdhCurve(),
|
ecdhCurve = getDefaultEcdhCurve(),
|
||||||
key,
|
key,
|
||||||
passphrase,
|
passphrase,
|
||||||
pfx,
|
pfx,
|
||||||
privateKeyIdentifier,
|
|
||||||
privateKeyEngine,
|
|
||||||
sessionIdContext,
|
sessionIdContext,
|
||||||
sessionTimeout,
|
sessionTimeout,
|
||||||
sigalgs,
|
sigalgs,
|
||||||
@@ -255,35 +270,6 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
|
|||||||
context.setSigalgs(sigalgs);
|
context.setSigalgs(sigalgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (privateKeyIdentifier !== undefined && privateKeyIdentifier !== null) {
|
|
||||||
if (privateKeyEngine === undefined || privateKeyEngine === null) {
|
|
||||||
// Engine is required when privateKeyIdentifier is present
|
|
||||||
throw new ERR_INVALID_ARG_VALUE(`${name}.privateKeyEngine`,
|
|
||||||
privateKeyEngine);
|
|
||||||
}
|
|
||||||
if (key) {
|
|
||||||
// Both data key and engine key can't be set at the same time
|
|
||||||
throw new ERR_INVALID_ARG_VALUE(`${name}.privateKeyIdentifier`,
|
|
||||||
privateKeyIdentifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof privateKeyIdentifier === 'string' &&
|
|
||||||
typeof privateKeyEngine === 'string') {
|
|
||||||
if (context.setEngineKey)
|
|
||||||
context.setEngineKey(privateKeyIdentifier, privateKeyEngine);
|
|
||||||
else
|
|
||||||
throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED();
|
|
||||||
} else if (typeof privateKeyIdentifier !== 'string') {
|
|
||||||
throw new ERR_INVALID_ARG_TYPE(`${name}.privateKeyIdentifier`,
|
|
||||||
['string', 'null', 'undefined'],
|
|
||||||
privateKeyIdentifier);
|
|
||||||
} else {
|
|
||||||
throw new ERR_INVALID_ARG_TYPE(`${name}.privateKeyEngine`,
|
|
||||||
['string', 'null', 'undefined'],
|
|
||||||
privateKeyEngine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
validateString(ecdhCurve, `${name}.ecdhCurve`);
|
validateString(ecdhCurve, `${name}.ecdhCurve`);
|
||||||
context.setECDHCurve(ecdhCurve);
|
context.setECDHCurve(ecdhCurve);
|
||||||
|
|
||||||
@@ -329,17 +315,6 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof clientCertEngine === 'string') {
|
|
||||||
if (typeof context.setClientCertEngine !== 'function')
|
|
||||||
throw new ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED();
|
|
||||||
else
|
|
||||||
context.setClientCertEngine(clientCertEngine);
|
|
||||||
} else if (clientCertEngine !== undefined && clientCertEngine !== null) {
|
|
||||||
throw new ERR_INVALID_ARG_TYPE(`${name}.clientCertEngine`,
|
|
||||||
['string', 'null', 'undefined'],
|
|
||||||
clientCertEngine);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ticketKeys !== undefined && ticketKeys !== null) {
|
if (ticketKeys !== undefined && ticketKeys !== null) {
|
||||||
validateBuffer(ticketKeys, `${name}.ticketKeys`);
|
validateBuffer(ticketKeys, `${name}.ticketKeys`);
|
||||||
if (ticketKeys.byteLength !== 48) {
|
if (ticketKeys.byteLength !== 48) {
|
||||||
@@ -359,4 +334,5 @@ function configSecureContext(context, options = kEmptyObject, name = 'options')
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
configSecureContext,
|
configSecureContext,
|
||||||
|
validateOpenSSLEngineOptions,
|
||||||
};
|
};
|
||||||
@@ -48,6 +48,9 @@ const EE = require('events');
|
|||||||
const net = require('net');
|
const net = require('net');
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
const common = require('internal/tls/common');
|
const common = require('internal/tls/common');
|
||||||
|
const {
|
||||||
|
validateOpenSSLEngineOptions,
|
||||||
|
} = require('internal/tls/secure-context');
|
||||||
const { kReinitializeHandle } = require('internal/net');
|
const { kReinitializeHandle } = require('internal/net');
|
||||||
const JSStreamSocket = require('internal/js_stream_socket');
|
const JSStreamSocket = require('internal/js_stream_socket');
|
||||||
const { Buffer } = require('buffer');
|
const { Buffer } = require('buffer');
|
||||||
@@ -623,6 +626,7 @@ function initRead(tlsSocket, socket) {
|
|||||||
|
|
||||||
function TLSSocket(socket, opts) {
|
function TLSSocket(socket, opts) {
|
||||||
const tlsOptions = { ...opts };
|
const tlsOptions = { ...opts };
|
||||||
|
validateOpenSSLEngineOptions(tlsOptions);
|
||||||
let enableTrace = tlsOptions.enableTrace;
|
let enableTrace = tlsOptions.enableTrace;
|
||||||
|
|
||||||
if (enableTrace == null) {
|
if (enableTrace == null) {
|
||||||
@@ -1458,7 +1462,6 @@ function tlsConnectionListener(rawSocket) {
|
|||||||
// - rejectUnauthorized. Boolean, default to true.
|
// - rejectUnauthorized. Boolean, default to true.
|
||||||
// - key. string.
|
// - key. string.
|
||||||
// - cert: string.
|
// - cert: string.
|
||||||
// - clientCertEngine: string.
|
|
||||||
// - ca: string or array of strings.
|
// - ca: string or array of strings.
|
||||||
// - sessionTimeout: integer.
|
// - sessionTimeout: integer.
|
||||||
//
|
//
|
||||||
@@ -1550,6 +1553,7 @@ exports.createServer = function createServer(options, listener) {
|
|||||||
|
|
||||||
Server.prototype.setSecureContext = function(options) {
|
Server.prototype.setSecureContext = function(options) {
|
||||||
validateObject(options, 'options');
|
validateObject(options, 'options');
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
|
|
||||||
if (options.pfx)
|
if (options.pfx)
|
||||||
this.pfx = options.pfx;
|
this.pfx = options.pfx;
|
||||||
@@ -1571,11 +1575,6 @@ Server.prototype.setSecureContext = function(options) {
|
|||||||
else
|
else
|
||||||
this.cert = undefined;
|
this.cert = undefined;
|
||||||
|
|
||||||
if (options.clientCertEngine)
|
|
||||||
this.clientCertEngine = options.clientCertEngine;
|
|
||||||
else
|
|
||||||
this.clientCertEngine = undefined;
|
|
||||||
|
|
||||||
if (options.ca)
|
if (options.ca)
|
||||||
this.ca = options.ca;
|
this.ca = options.ca;
|
||||||
else
|
else
|
||||||
@@ -1642,8 +1641,6 @@ Server.prototype.setSecureContext = function(options) {
|
|||||||
if (options.ticketKeys)
|
if (options.ticketKeys)
|
||||||
this.ticketKeys = options.ticketKeys;
|
this.ticketKeys = options.ticketKeys;
|
||||||
|
|
||||||
this.privateKeyIdentifier = options.privateKeyIdentifier;
|
|
||||||
this.privateKeyEngine = options.privateKeyEngine;
|
|
||||||
this.certificateCompression = options.certificateCompression;
|
this.certificateCompression = options.certificateCompression;
|
||||||
|
|
||||||
this._sharedCreds = tls.createSecureContext({
|
this._sharedCreds = tls.createSecureContext({
|
||||||
@@ -1651,7 +1648,6 @@ Server.prototype.setSecureContext = function(options) {
|
|||||||
key: this.key,
|
key: this.key,
|
||||||
passphrase: this.passphrase,
|
passphrase: this.passphrase,
|
||||||
cert: this.cert,
|
cert: this.cert,
|
||||||
clientCertEngine: this.clientCertEngine,
|
|
||||||
ca: this.ca,
|
ca: this.ca,
|
||||||
ciphers: this.ciphers,
|
ciphers: this.ciphers,
|
||||||
sigalgs: this.sigalgs,
|
sigalgs: this.sigalgs,
|
||||||
@@ -1666,8 +1662,6 @@ Server.prototype.setSecureContext = function(options) {
|
|||||||
sessionIdContext: this.sessionIdContext,
|
sessionIdContext: this.sessionIdContext,
|
||||||
ticketKeys: this.ticketKeys,
|
ticketKeys: this.ticketKeys,
|
||||||
sessionTimeout: this.sessionTimeout,
|
sessionTimeout: this.sessionTimeout,
|
||||||
privateKeyIdentifier: this.privateKeyIdentifier,
|
|
||||||
privateKeyEngine: this.privateKeyEngine,
|
|
||||||
certificateCompression: this.certificateCompression,
|
certificateCompression: this.certificateCompression,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -1865,6 +1859,7 @@ exports.connect = function connect(...args) {
|
|||||||
minDHSize: 1024,
|
minDHSize: 1024,
|
||||||
...options,
|
...options,
|
||||||
};
|
};
|
||||||
|
validateOpenSSLEngineOptions(options);
|
||||||
|
|
||||||
if (!options.keepAlive)
|
if (!options.keepAlive)
|
||||||
options.singleUse = true;
|
options.singleUse = true;
|
||||||
|
|||||||
@@ -40,12 +40,8 @@ namespace node {
|
|||||||
using ncrypto::BIOPointer;
|
using ncrypto::BIOPointer;
|
||||||
using ncrypto::Cipher;
|
using ncrypto::Cipher;
|
||||||
using ncrypto::ClearErrorOnReturn;
|
using ncrypto::ClearErrorOnReturn;
|
||||||
using ncrypto::CryptoErrorList;
|
|
||||||
using ncrypto::DHPointer;
|
using ncrypto::DHPointer;
|
||||||
using ncrypto::Digest;
|
using ncrypto::Digest;
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
using ncrypto::EnginePointer;
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
using ncrypto::EVPKeyPointer;
|
using ncrypto::EVPKeyPointer;
|
||||||
using ncrypto::KeyAlgorithm;
|
using ncrypto::KeyAlgorithm;
|
||||||
using ncrypto::MarkPopErrorOnReturn;
|
using ncrypto::MarkPopErrorOnReturn;
|
||||||
@@ -1350,11 +1346,6 @@ Local<FunctionTemplate> SecureContext::GetConstructorTemplate(
|
|||||||
SetProtoMethodNoSideEffect(
|
SetProtoMethodNoSideEffect(
|
||||||
isolate, tmpl, "getIssuer", GetCertificate<false>);
|
isolate, tmpl, "getIssuer", GetCertificate<false>);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
SetProtoMethod(isolate, tmpl, "setEngineKey", SetEngineKey);
|
|
||||||
SetProtoMethod(isolate, tmpl, "setClientCertEngine", SetClientCertEngine);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
#define SET_INTEGER_CONSTANTS(name, value) \
|
#define SET_INTEGER_CONSTANTS(name, value) \
|
||||||
tmpl->Set(FIXED_ONE_BYTE_STRING(isolate, name), \
|
tmpl->Set(FIXED_ONE_BYTE_STRING(isolate, name), \
|
||||||
Integer::NewFromUnsigned(isolate, value));
|
Integer::NewFromUnsigned(isolate, value));
|
||||||
@@ -1689,11 +1680,6 @@ void SecureContext::RegisterExternalReferences(
|
|||||||
registry->Register(GetCertificate<true>);
|
registry->Register(GetCertificate<true>);
|
||||||
registry->Register(GetCertificate<false>);
|
registry->Register(GetCertificate<false>);
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
registry->Register(SetEngineKey);
|
|
||||||
registry->Register(SetClientCertEngine);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
registry->Register(CtxGetter);
|
registry->Register(CtxGetter);
|
||||||
|
|
||||||
registry->Register(GetBundledRootCertificates);
|
registry->Register(GetBundledRootCertificates);
|
||||||
@@ -1968,54 +1954,6 @@ void SecureContext::SetSigalgs(const FunctionCallbackInfo<Value>& args) {
|
|||||||
return ThrowCryptoError(env, ERR_get_error());
|
return ThrowCryptoError(env, ERR_get_error());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
void SecureContext::SetEngineKey(const FunctionCallbackInfo<Value>& args) {
|
|
||||||
Environment* env = Environment::GetCurrent(args);
|
|
||||||
|
|
||||||
SecureContext* sc;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
|
|
||||||
|
|
||||||
CHECK_EQ(args.Length(), 2);
|
|
||||||
|
|
||||||
if (env->permission()->enabled()) [[unlikely]] {
|
|
||||||
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
|
|
||||||
env,
|
|
||||||
"Programmatic selection of OpenSSL engines is unsupported while the "
|
|
||||||
"experimental permission model is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoErrorList errors;
|
|
||||||
Utf8Value engine_id(env->isolate(), args[1]);
|
|
||||||
auto engine = EnginePointer::getEngineByName(*engine_id, &errors);
|
|
||||||
if (!engine) {
|
|
||||||
Local<Value> exception;
|
|
||||||
if (errors.empty()) {
|
|
||||||
errors.add(getNodeCryptoErrorString(NodeCryptoError::ENGINE_NOT_FOUND,
|
|
||||||
*engine_id));
|
|
||||||
}
|
|
||||||
if (cryptoErrorListToException(env, errors).ToLocal(&exception))
|
|
||||||
env->isolate()->ThrowException(exception);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!engine.init(true /* finish on exit*/)) {
|
|
||||||
return THROW_ERR_CRYPTO_OPERATION_FAILED(
|
|
||||||
env, "Failure to initialize engine");
|
|
||||||
}
|
|
||||||
|
|
||||||
Utf8Value key_name(env->isolate(), args[0]);
|
|
||||||
auto key = engine.loadPrivateKey(*key_name);
|
|
||||||
|
|
||||||
if (!key)
|
|
||||||
return ThrowCryptoError(env, ERR_get_error(), "ENGINE_load_private_key");
|
|
||||||
|
|
||||||
if (!SSL_CTX_use_PrivateKey(sc->ctx_.get(), key.get()))
|
|
||||||
return ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
|
|
||||||
|
|
||||||
sc->private_key_engine_ = std::move(engine);
|
|
||||||
}
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
Maybe<void> SecureContext::AddCert(Environment* env, BIOPointer&& bio) {
|
Maybe<void> SecureContext::AddCert(Environment* env, BIOPointer&& bio) {
|
||||||
ClearErrorOnReturn clear_error_on_return;
|
ClearErrorOnReturn clear_error_on_return;
|
||||||
// TODO(tniessen): this should be checked by the caller and not treated as ok
|
// TODO(tniessen): this should be checked by the caller and not treated as ok
|
||||||
@@ -2534,53 +2472,6 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
void SecureContext::SetClientCertEngine(
|
|
||||||
const FunctionCallbackInfo<Value>& args) {
|
|
||||||
Environment* env = Environment::GetCurrent(args);
|
|
||||||
CHECK_EQ(args.Length(), 1);
|
|
||||||
CHECK(args[0]->IsString());
|
|
||||||
|
|
||||||
SecureContext* sc;
|
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&sc, args.This());
|
|
||||||
|
|
||||||
MarkPopErrorOnReturn mark_pop_error_on_return;
|
|
||||||
|
|
||||||
// SSL_CTX_set_client_cert_engine does not itself support multiple
|
|
||||||
// calls by cleaning up before overwriting the client_cert_engine
|
|
||||||
// internal context variable.
|
|
||||||
// Instead of trying to fix up this problem we in turn also do not
|
|
||||||
// support multiple calls to SetClientCertEngine.
|
|
||||||
CHECK(!sc->client_cert_engine_provided_);
|
|
||||||
|
|
||||||
if (env->permission()->enabled()) [[unlikely]] {
|
|
||||||
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
|
|
||||||
env,
|
|
||||||
"Programmatic selection of OpenSSL engines is unsupported while the "
|
|
||||||
"experimental permission model is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoErrorList errors;
|
|
||||||
const Utf8Value engine_id(env->isolate(), args[0]);
|
|
||||||
auto engine = EnginePointer::getEngineByName(*engine_id, &errors);
|
|
||||||
if (!engine) {
|
|
||||||
Local<Value> exception;
|
|
||||||
if (errors.empty()) {
|
|
||||||
errors.add(getNodeCryptoErrorString(NodeCryptoError::ENGINE_NOT_FOUND,
|
|
||||||
*engine_id));
|
|
||||||
}
|
|
||||||
if (cryptoErrorListToException(env, errors).ToLocal(&exception))
|
|
||||||
env->isolate()->ThrowException(exception);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note that this takes another reference to `engine`.
|
|
||||||
if (!engine.setClientCertEngine(sc->ctx_.get()))
|
|
||||||
return ThrowCryptoError(env, ERR_get_error());
|
|
||||||
sc->client_cert_engine_provided_ = true;
|
|
||||||
}
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) {
|
void SecureContext::GetTicketKeys(const FunctionCallbackInfo<Value>& args) {
|
||||||
SecureContext* wrap;
|
SecureContext* wrap;
|
||||||
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
|
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.This());
|
||||||
|
|||||||
@@ -118,9 +118,6 @@ class SecureContext final : public BaseObject {
|
|||||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
static void SetEngineKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
static void SetCert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void SetCert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void AddCACert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void AddCACert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void SetAllowPartialTrustChain(
|
static void SetAllowPartialTrustChain(
|
||||||
@@ -147,10 +144,6 @@ class SecureContext final : public BaseObject {
|
|||||||
static void GetMaxProto(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void GetMaxProto(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void LoadPKCS12(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void LoadPKCS12(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
static void SetClientCertEngine(
|
|
||||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void GetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
static void SetTicketKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||||
static void EnableTicketKeyCallback(
|
static void EnableTicketKeyCallback(
|
||||||
@@ -200,10 +193,6 @@ class SecureContext final : public BaseObject {
|
|||||||
ncrypto::X509Pointer issuer_;
|
ncrypto::X509Pointer issuer_;
|
||||||
// Non-owning cache for SSL_CTX_get_cert_store(ctx_.get())
|
// Non-owning cache for SSL_CTX_get_cert_store(ctx_.get())
|
||||||
X509_STORE* own_cert_store_cache_ = nullptr;
|
X509_STORE* own_cert_store_cache_ = nullptr;
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
bool client_cert_engine_provided_ = false;
|
|
||||||
ncrypto::EnginePointer private_key_engine_;
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
unsigned char ticket_key_name_[16];
|
unsigned char ticket_key_name_[16];
|
||||||
unsigned char ticket_key_aes_[16];
|
unsigned char ticket_key_aes_[16];
|
||||||
|
|||||||
@@ -38,9 +38,6 @@ using ncrypto::BignumPointer;
|
|||||||
using ncrypto::BIOPointer;
|
using ncrypto::BIOPointer;
|
||||||
using ncrypto::CryptoErrorList;
|
using ncrypto::CryptoErrorList;
|
||||||
using ncrypto::DataPointer;
|
using ncrypto::DataPointer;
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
using ncrypto::EnginePointer;
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
using ncrypto::SSLPointer;
|
using ncrypto::SSLPointer;
|
||||||
using v8::Array;
|
using v8::Array;
|
||||||
using v8::ArrayBuffer;
|
using v8::ArrayBuffer;
|
||||||
@@ -544,10 +541,6 @@ void InitCryptoOnce() {
|
|||||||
// Turn off compression. Saves memory and protects against CRIME attacks.
|
// Turn off compression. Saves memory and protects against CRIME attacks.
|
||||||
// No-op with OPENSSL_NO_COMP builds of OpenSSL.
|
// No-op with OPENSSL_NO_COMP builds of OpenSSL.
|
||||||
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
EnginePointer::initEnginesOnce();
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
|
void GetFipsCrypto(const FunctionCallbackInfo<Value>& args) {
|
||||||
@@ -1030,28 +1023,6 @@ void ThrowCryptoError(Environment* env,
|
|||||||
env->isolate()->ThrowException(exception);
|
env->isolate()->ThrowException(exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
void SetEngine(const FunctionCallbackInfo<Value>& args) {
|
|
||||||
Environment* env = Environment::GetCurrent(args);
|
|
||||||
if (env->permission()->enabled()) [[unlikely]] {
|
|
||||||
return THROW_ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED(
|
|
||||||
env,
|
|
||||||
"Programmatic selection of OpenSSL engines is unsupported while the "
|
|
||||||
"experimental permission model is enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(args.Length() >= 2 && args[0]->IsString());
|
|
||||||
uint32_t flags;
|
|
||||||
if (!args[1]->Uint32Value(env->context()).To(&flags)) return;
|
|
||||||
|
|
||||||
const node::Utf8Value engine_id(env->isolate(), args[0]);
|
|
||||||
// If the engine name is not known, calling setAsDefault on the
|
|
||||||
// empty engine pointer will be non-op that always returns false.
|
|
||||||
args.GetReturnValue().Set(
|
|
||||||
EnginePointer::getEngineByName(*engine_id).setAsDefault(flags));
|
|
||||||
}
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
MaybeLocal<Value> EncodeBignum(Environment* env, const BIGNUM* bn, int size) {
|
MaybeLocal<Value> EncodeBignum(Environment* env, const BIGNUM* bn, int size) {
|
||||||
EscapableHandleScope scope(env->isolate());
|
EscapableHandleScope scope(env->isolate());
|
||||||
auto buf = BignumPointer::EncodePadded(bn, size);
|
auto buf = BignumPointer::EncodePadded(bn, size);
|
||||||
@@ -1191,10 +1162,6 @@ void SecureHeapUsed(const FunctionCallbackInfo<Value>& args) {
|
|||||||
namespace Util {
|
namespace Util {
|
||||||
void Initialize(Environment* env, Local<Object> target) {
|
void Initialize(Environment* env, Local<Object> target) {
|
||||||
Local<Context> context = env->context();
|
Local<Context> context = env->context();
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
SetMethod(context, target, "setEngine", SetEngine);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
SetMethodNoSideEffect(context, target, "getFipsCrypto", GetFipsCrypto);
|
SetMethodNoSideEffect(context, target, "getFipsCrypto", GetFipsCrypto);
|
||||||
SetMethodNoSideEffect(
|
SetMethodNoSideEffect(
|
||||||
context, target, "getFipsCryptoGeneration", GetFipsCryptoGeneration);
|
context, target, "getFipsCryptoGeneration", GetFipsCryptoGeneration);
|
||||||
@@ -1214,10 +1181,6 @@ void Initialize(Environment* env, Local<Object> target) {
|
|||||||
context, target, "getOpenSSLSecLevelCrypto", GetOpenSSLSecLevelCrypto);
|
context, target, "getOpenSSLSecLevelCrypto", GetOpenSSLSecLevelCrypto);
|
||||||
}
|
}
|
||||||
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
registry->Register(SetEngine);
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
registry->Register(GetFipsCrypto);
|
registry->Register(GetFipsCrypto);
|
||||||
registry->Register(GetFipsCryptoGeneration);
|
registry->Register(GetFipsCryptoGeneration);
|
||||||
registry->Register(SetupFipsIndicatorChannel);
|
registry->Register(SetupFipsIndicatorChannel);
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ void Decode(const v8::FunctionCallbackInfo<v8::Value>& args,
|
|||||||
V(DERIVING_BITS_FAILED, "Deriving bits failed") \
|
V(DERIVING_BITS_FAILED, "Deriving bits failed") \
|
||||||
V(ECDH_FAILED, "ECDH key agreement failed") \
|
V(ECDH_FAILED, "ECDH key agreement failed") \
|
||||||
V(ENCAPSULATION_FAILED, "Encapsulation failed") \
|
V(ENCAPSULATION_FAILED, "Encapsulation failed") \
|
||||||
V(ENGINE_NOT_FOUND, "Engine \"%s\" was not found") \
|
|
||||||
V(HKDF_FAILED, "HKDF derivation failed") \
|
V(HKDF_FAILED, "HKDF derivation failed") \
|
||||||
V(INVALID_KEY_TYPE, "Invalid key type") \
|
V(INVALID_KEY_TYPE, "Invalid key type") \
|
||||||
V(KEY_GENERATION_JOB_FAILED, "Key generation job failed") \
|
V(KEY_GENERATION_JOB_FAILED, "Key generation job failed") \
|
||||||
|
|||||||
@@ -86,25 +86,6 @@
|
|||||||
#define DH_NOT_SUITABLE_GENERATOR 0x08
|
#define DH_NOT_SUITABLE_GENERATOR 0x08
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef OPENSSL_NO_ENGINE
|
|
||||||
#ifndef OPENSSL_IS_BORINGSSL
|
|
||||||
// Engine constants remain public API while engine implementation lives in the
|
|
||||||
// dedicated compatibility target.
|
|
||||||
#define ENGINE_METHOD_RSA (unsigned int)0x0001
|
|
||||||
#define ENGINE_METHOD_DSA (unsigned int)0x0002
|
|
||||||
#define ENGINE_METHOD_DH (unsigned int)0x0004
|
|
||||||
#define ENGINE_METHOD_RAND (unsigned int)0x0008
|
|
||||||
#define ENGINE_METHOD_CIPHERS (unsigned int)0x0040
|
|
||||||
#define ENGINE_METHOD_DIGESTS (unsigned int)0x0080
|
|
||||||
#define ENGINE_METHOD_PKEY_METHS (unsigned int)0x0200
|
|
||||||
#define ENGINE_METHOD_PKEY_ASN1_METHS (unsigned int)0x0400
|
|
||||||
#define ENGINE_METHOD_EC (unsigned int)0x0800
|
|
||||||
#define ENGINE_METHOD_ALL (unsigned int)0xFFFF
|
|
||||||
#define ENGINE_METHOD_NONE (unsigned int)0x0000
|
|
||||||
#else
|
|
||||||
#include <openssl/engine.h>
|
|
||||||
#endif
|
|
||||||
#endif // !OPENSSL_NO_ENGINE
|
|
||||||
#endif // HAVE_OPENSSL
|
#endif // HAVE_OPENSSL
|
||||||
|
|
||||||
#if defined(__POSIX__)
|
#if defined(__POSIX__)
|
||||||
@@ -972,54 +953,6 @@ void DefineCryptoConstants(Local<Object> target) {
|
|||||||
NODE_DEFINE_CONSTANT(target, SSL_OP_TLS_ROLLBACK_BUG);
|
NODE_DEFINE_CONSTANT(target, SSL_OP_TLS_ROLLBACK_BUG);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_RSA
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_RSA);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_DSA
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DSA);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_DH
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DH);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_RAND
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_RAND);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_EC
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_EC);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_CIPHERS
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_CIPHERS);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_DIGESTS
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_DIGESTS);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_PKEY_METHS
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_METHS);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_PKEY_ASN1_METHS
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_PKEY_ASN1_METHS);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_ALL
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_ALL);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# ifdef ENGINE_METHOD_NONE
|
|
||||||
NODE_DEFINE_CONSTANT(target, ENGINE_METHOD_NONE);
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# endif // !OPENSSL_NO_ENGINE
|
|
||||||
|
|
||||||
#ifdef DH_CHECK_P_NOT_SAFE_PRIME
|
#ifdef DH_CHECK_P_NOT_SAFE_PRIME
|
||||||
NODE_DEFINE_CONSTANT(target, DH_CHECK_P_NOT_SAFE_PRIME);
|
NODE_DEFINE_CONSTANT(target, DH_CHECK_P_NOT_SAFE_PRIME);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ void OOMErrorHandler(const char* location, const v8::OOMDetails& details);
|
|||||||
V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \
|
V(ERR_CONSTRUCT_CALL_INVALID, TypeError) \
|
||||||
V(ERR_CPU_PROFILE_NOT_STARTED, Error) \
|
V(ERR_CPU_PROFILE_NOT_STARTED, Error) \
|
||||||
V(ERR_CPU_PROFILE_TOO_MANY, Error) \
|
V(ERR_CPU_PROFILE_TOO_MANY, Error) \
|
||||||
V(ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED, Error) \
|
|
||||||
V(ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS, Error) \
|
V(ERR_CRYPTO_INCOMPATIBLE_KEY_OPTIONS, Error) \
|
||||||
V(ERR_CRYPTO_INITIALIZATION_FAILED, Error) \
|
V(ERR_CRYPTO_INITIALIZATION_FAILED, Error) \
|
||||||
V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError) \
|
V(ERR_CRYPTO_INVALID_AUTH_TAG, TypeError) \
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'testengine',
|
|
||||||
'type': 'none',
|
|
||||||
'includes': ['../common.gypi'],
|
|
||||||
'conditions': [
|
|
||||||
['OS=="mac" and '
|
|
||||||
'node_use_openssl=="true" and '
|
|
||||||
'node_shared=="false" and '
|
|
||||||
'node_shared_openssl=="false"', {
|
|
||||||
'type': 'shared_library',
|
|
||||||
'sources': [ 'testengine.cc' ],
|
|
||||||
'product_extension': 'engine',
|
|
||||||
'include_dirs': ['../../../deps/openssl/openssl/include'],
|
|
||||||
'xcode_settings': {
|
|
||||||
'OTHER_LDFLAGS': ['-undefined', 'dynamic_lookup'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const common = require('../../common');
|
|
||||||
const fixture = require('../../common/fixtures');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const { hasOpenSSL } = require('../../common/crypto');
|
|
||||||
|
|
||||||
if (hasOpenSSL(4))
|
|
||||||
common.skip('OpenSSL 4 does not support engines');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const engine = path.join(__dirname,
|
|
||||||
`/build/${common.buildType}/testengine.engine`);
|
|
||||||
|
|
||||||
if (!fs.existsSync(engine))
|
|
||||||
common.skip('no client cert engine');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const https = require('https');
|
|
||||||
|
|
||||||
const agentKey = fs.readFileSync(fixture.path('/keys/agent1-key.pem'));
|
|
||||||
const agentCert = fs.readFileSync(fixture.path('/keys/agent1-cert.pem'));
|
|
||||||
const agentCa = fs.readFileSync(fixture.path('/keys/ca1-cert.pem'));
|
|
||||||
|
|
||||||
const serverOptions = {
|
|
||||||
key: agentKey,
|
|
||||||
cert: agentCert,
|
|
||||||
ca: agentCa,
|
|
||||||
requestCert: true,
|
|
||||||
rejectUnauthorized: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const server = https.createServer(serverOptions, common.mustCall((req, res) => {
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end('hello world');
|
|
||||||
})).listen(0, common.localhostIPv4, common.mustCall(() => {
|
|
||||||
const clientOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
host: common.localhostIPv4,
|
|
||||||
port: server.address().port,
|
|
||||||
path: '/test',
|
|
||||||
clientCertEngine: engine, // `engine` will provide key+cert
|
|
||||||
rejectUnauthorized: false, // Prevent failing on self-signed certificates
|
|
||||||
headers: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = https.request(clientOptions, common.mustCall((response) => {
|
|
||||||
let body = '';
|
|
||||||
response.setEncoding('utf8');
|
|
||||||
response.on('data', (chunk) => {
|
|
||||||
body += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
response.on('end', common.mustCall(() => {
|
|
||||||
assert.strictEqual(body, 'hello world');
|
|
||||||
server.close();
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
|
|
||||||
req.end();
|
|
||||||
}));
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifndef ENGINE_CMD_BASE
|
|
||||||
# error did not get engine.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TEST_ENGINE_ID "testengine"
|
|
||||||
#define TEST_ENGINE_NAME "dummy test engine"
|
|
||||||
|
|
||||||
#define AGENT_KEY "test/fixtures/keys/agent1-key.pem"
|
|
||||||
#define AGENT_CERT "test/fixtures/keys/agent1-cert.pem"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define DEFAULT_VISIBILITY __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
# define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
int EngineInit(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineFinish(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineDestroy(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LoadFile(const char* filename) {
|
|
||||||
std::ifstream file(filename);
|
|
||||||
return std::string(std::istreambuf_iterator<char>(file),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int EngineLoadSSLClientCert(ENGINE* engine,
|
|
||||||
SSL* ssl,
|
|
||||||
STACK_OF(X509_NAME)* ca_dn,
|
|
||||||
X509** ppcert,
|
|
||||||
EVP_PKEY** ppkey,
|
|
||||||
STACK_OF(X509)** pother,
|
|
||||||
UI_METHOD* ui_method,
|
|
||||||
void* callback_data) {
|
|
||||||
if (ppcert != nullptr) {
|
|
||||||
std::string cert = LoadFile(AGENT_CERT);
|
|
||||||
if (cert.empty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BIO* bio = BIO_new_mem_buf(cert.data(), cert.size());
|
|
||||||
*ppcert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr);
|
|
||||||
BIO_vfree(bio);
|
|
||||||
if (*ppcert == nullptr) {
|
|
||||||
printf("Could not read certificate\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ppkey != nullptr) {
|
|
||||||
std::string key = LoadFile(AGENT_KEY);
|
|
||||||
if (key.empty()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
BIO* bio = BIO_new_mem_buf(key.data(), key.size());
|
|
||||||
*ppkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
|
|
||||||
BIO_vfree(bio);
|
|
||||||
if (*ppkey == nullptr) {
|
|
||||||
printf("Could not read private key\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bind_fn(ENGINE* engine, const char* id) {
|
|
||||||
ENGINE_set_id(engine, TEST_ENGINE_ID);
|
|
||||||
ENGINE_set_name(engine, TEST_ENGINE_NAME);
|
|
||||||
ENGINE_set_init_function(engine, EngineInit);
|
|
||||||
ENGINE_set_finish_function(engine, EngineFinish);
|
|
||||||
ENGINE_set_destroy_function(engine, EngineDestroy);
|
|
||||||
ENGINE_set_load_ssl_client_cert_function(engine, EngineLoadSSLClientCert);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_CHECK_FN();
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'testkeyengine',
|
|
||||||
'type': 'none',
|
|
||||||
'includes': ['../common.gypi'],
|
|
||||||
'conditions': [
|
|
||||||
['OS=="mac" and '
|
|
||||||
'node_use_openssl=="true" and '
|
|
||||||
'node_shared=="false" and '
|
|
||||||
'node_shared_openssl=="false"', {
|
|
||||||
'type': 'shared_library',
|
|
||||||
'sources': [ 'testkeyengine.cc' ],
|
|
||||||
'product_extension': 'engine',
|
|
||||||
'include_dirs': ['../../../deps/openssl/openssl/include'],
|
|
||||||
'xcode_settings': {
|
|
||||||
'OTHER_LDFLAGS': ['-undefined', 'dynamic_lookup'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const common = require('../../common');
|
|
||||||
const fixture = require('../../common/fixtures');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const { hasOpenSSL } = require('../../common/crypto');
|
|
||||||
|
|
||||||
if (hasOpenSSL(4))
|
|
||||||
common.skip('OpenSSL 4 does not support engines');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const engine = path.join(__dirname,
|
|
||||||
`/build/${common.buildType}/testkeyengine.engine`);
|
|
||||||
|
|
||||||
if (!fs.existsSync(engine))
|
|
||||||
common.skip('no client cert engine');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const https = require('https');
|
|
||||||
|
|
||||||
const agentKey = fs.readFileSync(fixture.path('/keys/agent1-key.pem'));
|
|
||||||
const agentCert = fs.readFileSync(fixture.path('/keys/agent1-cert.pem'));
|
|
||||||
const agentCa = fs.readFileSync(fixture.path('/keys/ca1-cert.pem'));
|
|
||||||
|
|
||||||
const serverOptions = {
|
|
||||||
key: agentKey,
|
|
||||||
cert: agentCert,
|
|
||||||
ca: agentCa,
|
|
||||||
requestCert: true,
|
|
||||||
rejectUnauthorized: true,
|
|
||||||
};
|
|
||||||
|
|
||||||
const server = https.createServer(serverOptions, common.mustCall((req, res) => {
|
|
||||||
res.writeHead(200);
|
|
||||||
res.end('hello world');
|
|
||||||
})).listen(0, common.localhostIPv4, common.mustCall(() => {
|
|
||||||
const clientOptions = {
|
|
||||||
method: 'GET',
|
|
||||||
host: common.localhostIPv4,
|
|
||||||
port: server.address().port,
|
|
||||||
path: '/test',
|
|
||||||
privateKeyEngine: engine,
|
|
||||||
privateKeyIdentifier: 'dummykey',
|
|
||||||
cert: agentCert,
|
|
||||||
rejectUnauthorized: false, // Prevent failing on self-signed certificates
|
|
||||||
headers: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = https.request(clientOptions, common.mustCall((response) => {
|
|
||||||
let body = '';
|
|
||||||
response.setEncoding('utf8');
|
|
||||||
response.on('data', (chunk) => {
|
|
||||||
body += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
response.on('end', common.mustCall(() => {
|
|
||||||
assert.strictEqual(body, 'hello world');
|
|
||||||
server.close();
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
|
|
||||||
req.end();
|
|
||||||
}));
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#include <openssl/engine.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iterator>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifndef ENGINE_CMD_BASE
|
|
||||||
# error did not get engine.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TEST_ENGINE_ID "testkeyengine"
|
|
||||||
#define TEST_ENGINE_NAME "dummy test key engine"
|
|
||||||
|
|
||||||
#define PRIVATE_KEY "test/fixtures/keys/agent1-key.pem"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define DEFAULT_VISIBILITY __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
# define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
int EngineInit(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineFinish(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineDestroy(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LoadFile(const char* filename) {
|
|
||||||
std::ifstream file(filename);
|
|
||||||
return std::string(std::istreambuf_iterator<char>(file),
|
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
}
|
|
||||||
|
|
||||||
static EVP_PKEY* EngineLoadPrivkey(ENGINE* engine, const char* name,
|
|
||||||
UI_METHOD* ui_method, void* callback_data) {
|
|
||||||
if (strcmp(name, "dummykey") == 0) {
|
|
||||||
std::string key = LoadFile(PRIVATE_KEY);
|
|
||||||
BIO* bio = BIO_new_mem_buf(key.data(), key.size());
|
|
||||||
EVP_PKEY* ret = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr);
|
|
||||||
|
|
||||||
BIO_vfree(bio);
|
|
||||||
if (ret != nullptr) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bind_fn(ENGINE* engine, const char* id) {
|
|
||||||
ENGINE_set_id(engine, TEST_ENGINE_ID);
|
|
||||||
ENGINE_set_name(engine, TEST_ENGINE_NAME);
|
|
||||||
ENGINE_set_init_function(engine, EngineInit);
|
|
||||||
ENGINE_set_finish_function(engine, EngineFinish);
|
|
||||||
ENGINE_set_destroy_function(engine, EngineDestroy);
|
|
||||||
ENGINE_set_load_privkey_function(engine, EngineLoadPrivkey);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_CHECK_FN();
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
'targets': [
|
|
||||||
{
|
|
||||||
'target_name': 'testsetengine',
|
|
||||||
'type': 'none',
|
|
||||||
'includes': ['../common.gypi'],
|
|
||||||
'conditions': [
|
|
||||||
['(OS=="mac" or OS=="linux") and '
|
|
||||||
'node_use_openssl=="true" and '
|
|
||||||
'node_shared=="false" and '
|
|
||||||
'node_shared_openssl=="false"', {
|
|
||||||
'type': 'shared_library',
|
|
||||||
'sources': [ 'testsetengine.cc' ],
|
|
||||||
'product_extension': 'engine',
|
|
||||||
'include_dirs': ['../../../deps/openssl/openssl/include'],
|
|
||||||
'conditions': [
|
|
||||||
['OS=="mac"', {
|
|
||||||
'xcode_settings': {
|
|
||||||
'OTHER_CFLAGS': ['-Wno-deprecated-declarations'],
|
|
||||||
'OTHER_LDFLAGS': ['-undefined', 'dynamic_lookup'],
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
['OS=="linux"', {
|
|
||||||
'cflags': [
|
|
||||||
'-Wno-deprecated-declarations',
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}],
|
|
||||||
],
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const common = require('../../common');
|
|
||||||
|
|
||||||
// This tests crypto.setEngine().
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const crypto = require('crypto');
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
// Engine support in OpenSSL is checked later on.
|
|
||||||
let hasEngineSupport = true;
|
|
||||||
|
|
||||||
assert.throws(() => crypto.setEngine(true), /ERR_INVALID_ARG_TYPE|ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED/);
|
|
||||||
assert.throws(() => crypto.setEngine('/path/to/engine', 'notANumber'),
|
|
||||||
/ERR_INVALID_ARG_TYPE/);
|
|
||||||
|
|
||||||
{
|
|
||||||
const invalidEngineName = 'xxx';
|
|
||||||
assert.throws(() => crypto.setEngine(invalidEngineName),
|
|
||||||
/ERR_CRYPTO_ENGINE_UNKNOWN|ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED/);
|
|
||||||
assert.throws(() => crypto.setEngine(invalidEngineName,
|
|
||||||
crypto.constants.ENGINE_METHOD_RSA),
|
|
||||||
/ERR_CRYPTO_ENGINE_UNKNOWN|ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED/);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
crypto.setEngine('dynamic');
|
|
||||||
crypto.setEngine('dynamic');
|
|
||||||
|
|
||||||
crypto.setEngine('dynamic', crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
crypto.setEngine('dynamic', crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
} catch (err) {
|
|
||||||
assert.strictEqual(err.code, 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED');
|
|
||||||
hasEngineSupport = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasEngineSupport) {
|
|
||||||
const engine = path.join(__dirname,
|
|
||||||
`/build/${common.buildType}/testsetengine.engine`);
|
|
||||||
|
|
||||||
if (!fs.existsSync(engine))
|
|
||||||
common.skip('no engine');
|
|
||||||
|
|
||||||
{
|
|
||||||
const engineId = path.parse(engine).name;
|
|
||||||
const execDir = path.parse(engine).dir;
|
|
||||||
|
|
||||||
crypto.setEngine(engine);
|
|
||||||
// OpenSSL 3.0.1 and 1.1.1m now throw errors if an engine is loaded again
|
|
||||||
// with a duplicate absolute path.
|
|
||||||
// TODO(richardlau): figure out why this fails on macOS but not Linux.
|
|
||||||
// crypto.setEngine(engine);
|
|
||||||
|
|
||||||
// crypto.setEngine(engine, crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
// crypto.setEngine(engine, crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
|
|
||||||
process.env.OPENSSL_ENGINES = execDir;
|
|
||||||
|
|
||||||
crypto.setEngine(engineId);
|
|
||||||
crypto.setEngine(engineId);
|
|
||||||
|
|
||||||
crypto.setEngine(engineId, crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
crypto.setEngine(engineId, crypto.constants.ENGINE_METHOD_RSA);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#include <openssl/engine.h>
|
|
||||||
|
|
||||||
#ifndef ENGINE_CMD_BASE
|
|
||||||
# error did not get engine.h
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TEST_ENGINE_ID "testsetengine"
|
|
||||||
#define TEST_ENGINE_NAME "dummy test engine"
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
# define DEFAULT_VISIBILITY __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
# define DEFAULT_VISIBILITY __attribute__((visibility("default")))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
int EngineInit(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineFinish(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EngineDestroy(ENGINE* engine) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int bind_fn(ENGINE* engine, const char* id) {
|
|
||||||
ENGINE_set_id(engine, TEST_ENGINE_ID);
|
|
||||||
ENGINE_set_name(engine, TEST_ENGINE_NAME);
|
|
||||||
ENGINE_set_init_function(engine, EngineInit);
|
|
||||||
ENGINE_set_finish_function(engine, EngineFinish);
|
|
||||||
ENGINE_set_destroy_function(engine, EngineDestroy);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_CHECK_FN();
|
|
||||||
DEFAULT_VISIBILITY IMPLEMENT_DYNAMIC_BIND_FN(bind_fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // anonymous namespace
|
|
||||||
@@ -159,4 +159,4 @@ for await (const dirent of await fs.opendir(new URL('../../out/doc/api/', import
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.strictEqual(numberOfDeprecatedSections, 48); // Increase this number every time a new API is deprecated.
|
assert.strictEqual(numberOfDeprecatedSections, 48); // Increase this number every time a new API is deprecated.
|
||||||
assert.strictEqual(numberOfRemovedAPIs, 46); // Increase this number every time a section is marked as removed.
|
assert.strictEqual(numberOfRemovedAPIs, 47); // Increase this number every time a section is marked as removed.
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
// Flags: --expose-internals
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const common = require('../common');
|
||||||
|
if (!common.hasCrypto)
|
||||||
|
common.skip('missing crypto');
|
||||||
|
|
||||||
|
const assert = require('assert');
|
||||||
|
const crypto = require('crypto');
|
||||||
|
const https = require('https');
|
||||||
|
const tls = require('tls');
|
||||||
|
const { internalBinding } = require('internal/test/binding');
|
||||||
|
|
||||||
|
process.on('warning', (warning) => {
|
||||||
|
if (warning.code === 'DEP0183')
|
||||||
|
throw warning;
|
||||||
|
});
|
||||||
|
|
||||||
|
// DEP0183: OpenSSL engine-based APIs have reached End-of-Life.
|
||||||
|
assert.strictEqual(Object.hasOwn(crypto, 'setEngine'), false);
|
||||||
|
import('node:crypto').then(common.mustCall((esmCrypto) => {
|
||||||
|
assert.strictEqual(Object.hasOwn(esmCrypto, 'setEngine'), false);
|
||||||
|
}));
|
||||||
|
|
||||||
|
for (const name of [
|
||||||
|
'ENGINE_METHOD_RSA',
|
||||||
|
'ENGINE_METHOD_DSA',
|
||||||
|
'ENGINE_METHOD_DH',
|
||||||
|
'ENGINE_METHOD_RAND',
|
||||||
|
'ENGINE_METHOD_CIPHERS',
|
||||||
|
'ENGINE_METHOD_DIGESTS',
|
||||||
|
'ENGINE_METHOD_PKEY_METHS',
|
||||||
|
'ENGINE_METHOD_PKEY_ASN1_METHS',
|
||||||
|
'ENGINE_METHOD_EC',
|
||||||
|
'ENGINE_METHOD_ALL',
|
||||||
|
'ENGINE_METHOD_NONE',
|
||||||
|
]) {
|
||||||
|
assert.strictEqual(Object.hasOwn(crypto.constants, name), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const binding = internalBinding('crypto');
|
||||||
|
assert.strictEqual(Object.hasOwn(binding, 'setEngine'), false);
|
||||||
|
const secureContext = new binding.SecureContext();
|
||||||
|
assert.strictEqual('setEngineKey' in secureContext, false);
|
||||||
|
assert.strictEqual('setClientCertEngine' in secureContext, false);
|
||||||
|
|
||||||
|
const engineError = {
|
||||||
|
code: 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
||||||
|
message: 'Custom engines not supported by this version of Node.js',
|
||||||
|
};
|
||||||
|
const engineOptions = [
|
||||||
|
{ clientCertEngine: 'engine' },
|
||||||
|
{ clientCertEngine: 0 },
|
||||||
|
{ privateKeyEngine: 'engine' },
|
||||||
|
{ privateKeyEngine: false },
|
||||||
|
{ privateKeyIdentifier: 'key' },
|
||||||
|
{ privateKeyIdentifier: '' },
|
||||||
|
{ privateKeyIdentifier: 'key', privateKeyEngine: 'engine' },
|
||||||
|
];
|
||||||
|
const existingContext = tls.createSecureContext();
|
||||||
|
|
||||||
|
// The removed TLS options remain recognized so they cannot appear to work.
|
||||||
|
for (const options of engineOptions) {
|
||||||
|
assert.throws(() => tls.createSecureContext(options), engineError);
|
||||||
|
assert.throws(() => tls.createServer(options), engineError);
|
||||||
|
assert.throws(
|
||||||
|
() => tls.connect({ port: 443, secureContext: existingContext, ...options }),
|
||||||
|
engineError,
|
||||||
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => new tls.TLSSocket(undefined, { secureContext: existingContext, ...options }),
|
||||||
|
engineError,
|
||||||
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => https.request({ host: 'localhost', port: 443, agent: false, ...options }),
|
||||||
|
engineError,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTPS rejects the options before a pooled socket could hide their use.
|
||||||
|
const agent = new https.Agent();
|
||||||
|
const options = { host: 'example.com', port: 443 };
|
||||||
|
for (const removedOption of [
|
||||||
|
'clientCertEngine',
|
||||||
|
'privateKeyEngine',
|
||||||
|
'privateKeyIdentifier',
|
||||||
|
]) {
|
||||||
|
assert.throws(
|
||||||
|
() => new https.Agent({ [removedOption]: 'engine' }),
|
||||||
|
engineError,
|
||||||
|
);
|
||||||
|
assert.throws(
|
||||||
|
() => agent.getName({ ...options, [removedOption]: 'engine' }),
|
||||||
|
engineError,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -13,13 +13,13 @@ const agent = new https.Agent();
|
|||||||
// empty argument
|
// empty argument
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
agent.getName(),
|
agent.getName(),
|
||||||
'localhost::::::::::::::::::::::'
|
'localhost:::::::::::::::::::'
|
||||||
);
|
);
|
||||||
|
|
||||||
// empty options
|
// empty options
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
agent.getName({}),
|
agent.getName({}),
|
||||||
'localhost::::::::::::::::::::::'
|
'localhost:::::::::::::::::::'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Pass all options arguments
|
// Pass all options arguments
|
||||||
@@ -29,7 +29,6 @@ const options = {
|
|||||||
localAddress: '192.168.1.1',
|
localAddress: '192.168.1.1',
|
||||||
ca: 'ca',
|
ca: 'ca',
|
||||||
cert: 'cert',
|
cert: 'cert',
|
||||||
clientCertEngine: 'dynamic',
|
|
||||||
ciphers: 'ciphers',
|
ciphers: 'ciphers',
|
||||||
crl: [Buffer.from('c'), Buffer.from('r'), Buffer.from('l')],
|
crl: [Buffer.from('c'), Buffer.from('r'), Buffer.from('l')],
|
||||||
dhparam: 'dhparam',
|
dhparam: 'dhparam',
|
||||||
@@ -43,15 +42,13 @@ const options = {
|
|||||||
servername: 'localhost',
|
servername: 'localhost',
|
||||||
sessionIdContext: 'sessionIdContext',
|
sessionIdContext: 'sessionIdContext',
|
||||||
sigalgs: 'sigalgs',
|
sigalgs: 'sigalgs',
|
||||||
privateKeyIdentifier: 'privateKeyIdentifier',
|
|
||||||
privateKeyEngine: 'privateKeyEngine',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
assert.strictEqual(
|
assert.strictEqual(
|
||||||
agent.getName(options),
|
agent.getName(options),
|
||||||
'0.0.0.0:443:192.168.1.1:ca:cert:dynamic:ciphers:key:pfx:false:localhost:' +
|
'0.0.0.0:443:192.168.1.1:ca:cert:ciphers:key:pfx:false:localhost:' +
|
||||||
'::secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext:' +
|
'::secureProtocol:c,r,l:false:ecdhCurve:dhparam:0:sessionIdContext:' +
|
||||||
'"sigalgs":privateKeyIdentifier:privateKeyEngine'
|
'"sigalgs"'
|
||||||
);
|
);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const common = require('../common');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const tls = require('tls');
|
|
||||||
|
|
||||||
{
|
|
||||||
assert.throws(
|
|
||||||
() => { tls.createSecureContext({ clientCertEngine: 0 }); },
|
|
||||||
{ code: 'ERR_INVALID_ARG_TYPE',
|
|
||||||
message: / Received type number \(0\)/ });
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// Flags: --expose-internals
|
|
||||||
'use strict';
|
|
||||||
const common = require('../common');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
// Monkey-patch SecureContext
|
|
||||||
const { internalBinding } = require('internal/test/binding');
|
|
||||||
const binding = internalBinding('crypto');
|
|
||||||
const NativeSecureContext = binding.SecureContext;
|
|
||||||
|
|
||||||
binding.SecureContext = function() {
|
|
||||||
const rv = new NativeSecureContext();
|
|
||||||
rv.setClientCertEngine = undefined;
|
|
||||||
return rv;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tls = require('tls');
|
|
||||||
|
|
||||||
{
|
|
||||||
assert.throws(
|
|
||||||
() => { tls.createSecureContext({ clientCertEngine: 'Cannonmouth' }); },
|
|
||||||
{
|
|
||||||
code: 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
|
||||||
message: 'Custom engines not supported by this OpenSSL'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
// This tests that the crypto error stack can be correctly converted.
|
|
||||||
const common = require('../common');
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const tls = require('tls');
|
|
||||||
|
|
||||||
assert.throws(() => {
|
|
||||||
tls.createSecureContext({ clientCertEngine: 'x' });
|
|
||||||
}, (err) => {
|
|
||||||
if (err.code === 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED')
|
|
||||||
common.skip('OpenSSL dropped engine support');
|
|
||||||
|
|
||||||
return err.name === 'Error' &&
|
|
||||||
/could not load the shared library/.test(err.message) &&
|
|
||||||
Array.isArray(err.opensslErrorStack) &&
|
|
||||||
err.opensslErrorStack.length > 0;
|
|
||||||
});
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
const common = require('../common');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
const tls = require('tls');
|
|
||||||
|
|
||||||
assert.throws(
|
|
||||||
() => {
|
|
||||||
tls.createSecureContext({ privateKeyEngine: 0,
|
|
||||||
privateKeyIdentifier: 'key' });
|
|
||||||
},
|
|
||||||
{ code: 'ERR_INVALID_ARG_TYPE',
|
|
||||||
message: / Received type number \(0\)$/ });
|
|
||||||
|
|
||||||
assert.throws(
|
|
||||||
() => {
|
|
||||||
tls.createSecureContext({ privateKeyEngine: 'engine',
|
|
||||||
privateKeyIdentifier: 0 });
|
|
||||||
},
|
|
||||||
{ code: 'ERR_INVALID_ARG_TYPE',
|
|
||||||
message: / Received type number \(0\)$/ });
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
// Flags: --expose-internals
|
|
||||||
'use strict';
|
|
||||||
const common = require('../common');
|
|
||||||
|
|
||||||
if (!common.hasCrypto)
|
|
||||||
common.skip('missing crypto');
|
|
||||||
|
|
||||||
const assert = require('assert');
|
|
||||||
// Monkey-patch SecureContext
|
|
||||||
const { internalBinding } = require('internal/test/binding');
|
|
||||||
const binding = internalBinding('crypto');
|
|
||||||
const NativeSecureContext = binding.SecureContext;
|
|
||||||
|
|
||||||
binding.SecureContext = function() {
|
|
||||||
const rv = new NativeSecureContext();
|
|
||||||
rv.setEngineKey = undefined;
|
|
||||||
return rv;
|
|
||||||
};
|
|
||||||
|
|
||||||
const tls = require('tls');
|
|
||||||
|
|
||||||
{
|
|
||||||
assert.throws(
|
|
||||||
() => {
|
|
||||||
tls.createSecureContext({
|
|
||||||
privateKeyEngine: 'engine',
|
|
||||||
privateKeyIdentifier: 'key'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{
|
|
||||||
code: 'ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED',
|
|
||||||
message: 'Custom engines not supported by this OpenSSL'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
-11
@@ -217,17 +217,6 @@ export interface ConstantsBinding {
|
|||||||
SSL_OP_NO_TLSv1_3: 536870912;
|
SSL_OP_NO_TLSv1_3: 536870912;
|
||||||
SSL_OP_PRIORITIZE_CHACHA: 2097152;
|
SSL_OP_PRIORITIZE_CHACHA: 2097152;
|
||||||
SSL_OP_TLS_ROLLBACK_BUG: 8388608;
|
SSL_OP_TLS_ROLLBACK_BUG: 8388608;
|
||||||
ENGINE_METHOD_RSA: 1;
|
|
||||||
ENGINE_METHOD_DSA: 2;
|
|
||||||
ENGINE_METHOD_DH: 4;
|
|
||||||
ENGINE_METHOD_RAND: 8;
|
|
||||||
ENGINE_METHOD_EC: 2048;
|
|
||||||
ENGINE_METHOD_CIPHERS: 64;
|
|
||||||
ENGINE_METHOD_DIGESTS: 128;
|
|
||||||
ENGINE_METHOD_PKEY_METHS: 512;
|
|
||||||
ENGINE_METHOD_PKEY_ASN1_METHS: 1024;
|
|
||||||
ENGINE_METHOD_ALL: 65535;
|
|
||||||
ENGINE_METHOD_NONE: 0;
|
|
||||||
DH_CHECK_P_NOT_SAFE_PRIME: 2;
|
DH_CHECK_P_NOT_SAFE_PRIME: 2;
|
||||||
DH_CHECK_P_NOT_PRIME: 1;
|
DH_CHECK_P_NOT_PRIME: 1;
|
||||||
DH_UNABLE_TO_CHECK_GENERATOR: 4;
|
DH_UNABLE_TO_CHECK_GENERATOR: 4;
|
||||||
|
|||||||
Vendored
-3
@@ -697,7 +697,6 @@ declare namespace InternalCryptoBinding {
|
|||||||
init(secureProtocol: string | undefined, minVersion: number, maxVersion: number): void;
|
init(secureProtocol: string | undefined, minVersion: number, maxVersion: number): void;
|
||||||
setKey(key: ByteSource, passphrase?: ByteSource): void;
|
setKey(key: ByteSource, passphrase?: ByteSource): void;
|
||||||
setSigalgs(sigalgs: string): void;
|
setSigalgs(sigalgs: string): void;
|
||||||
setEngineKey?(privateKeyIdentifier: string, privateKeyEngine: string): void;
|
|
||||||
setCert(cert: ByteSource): void;
|
setCert(cert: ByteSource): void;
|
||||||
setAllowPartialTrustChain(): void;
|
setAllowPartialTrustChain(): void;
|
||||||
addCACert(cert: ByteSource): void;
|
addCACert(cert: ByteSource): void;
|
||||||
@@ -717,7 +716,6 @@ declare namespace InternalCryptoBinding {
|
|||||||
setCertificateCompression(algorithms: number): void;
|
setCertificateCompression(algorithms: number): void;
|
||||||
close(): void;
|
close(): void;
|
||||||
loadPKCS12(pfx: ByteSource, passphrase?: ByteSource): void;
|
loadPKCS12(pfx: ByteSource, passphrase?: ByteSource): void;
|
||||||
setClientCertEngine(clientCertEngine: string): void;
|
|
||||||
getTicketKeys(): Buffer;
|
getTicketKeys(): Buffer;
|
||||||
setTicketKeys(keys: ByteSource): void;
|
setTicketKeys(keys: ByteSource): void;
|
||||||
enableTicketKeyCallback(): void;
|
enableTicketKeyCallback(): void;
|
||||||
@@ -1006,7 +1004,6 @@ export interface CryptoBinding {
|
|||||||
resetRootCertStore(): void;
|
resetRootCertStore(): void;
|
||||||
secureBuffer(length: number): Uint8Array | undefined;
|
secureBuffer(length: number): Uint8Array | undefined;
|
||||||
secureHeapUsed(): bigint | undefined;
|
secureHeapUsed(): bigint | undefined;
|
||||||
setEngine?(engine: string, flags: number): void;
|
|
||||||
setupFipsIndicatorChannel(): void;
|
setupFipsIndicatorChannel(): void;
|
||||||
setFipsCrypto(fips: boolean | number): void;
|
setFipsCrypto(fips: boolean | number): void;
|
||||||
startLoadingCertificatesOffThread(): void;
|
startLoadingCertificatesOffThread(): void;
|
||||||
|
|||||||
Reference in new issue
Block a user