mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
This separates the native crypto backend paths for OpenSSL >= 3, BoringSSL, and legacy OpenSSL. The OpenSSL >= 3 path now builds with `OPENSSL_API_COMPAT=30000` and `OPENSSL_NO_DEPRECATED`, moving normal crypto/TLS code away from APIs that OpenSSL 3.0.0 marks deprecated. BoringSSL remains on its own branch, and OpenSSL < 3 remains the legacy fallback. The exception is ENGINE support. ENGINE APIs are isolated into a dedicated compatibility target so they can remain available while the JS-facing engine APIs are runtime-deprecated in 27.x. That gives us a clear removal point for 28.x, without letting ENGINE usage leak back into the strict OpenSSL 3 path. The split also makes the eventual OpenSSL 1.1.1 removal easier to reason about. Once support for OpenSSL < 3 is dropped, the legacy branch can be removed in a focused follow-up, possibly targeting 27.x, instead of untangling mixed version guards throughout the crypto implementation. No public crypto or TLS API behavior is intentionally changed. Assisted-by: Codex:gpt-5 Signed-off-by: Filip Skokan <panva.ip@gmail.com> PR-URL: https://github.com/nodejs/node/pull/64211 Refs: https://github.com/nodejs/node/issues/56733 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Richard Lau <richard.lau@ibm.com> Reviewed-By: James M Snell <jasnell@gmail.com>
107 lines
3.1 KiB
C++
107 lines
3.1 KiB
C++
#include "ncrypto.h"
|
|
|
|
#if !defined(OPENSSL_NO_ENGINE) && \
|
|
((defined(NCRYPTO_ENGINE_COMPAT) && NCRYPTO_ENGINE_COMPAT) || \
|
|
NCRYPTO_USE_LEGACY_OPENSSL)
|
|
#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
|