Skip to content

Commit 561bc87

Browse files
committed
src: move more crypto code to ncrypto
PR-URL: #54320 Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent 746e287 commit 561bc87

File tree

9 files changed

+147
-50
lines changed

9 files changed

+147
-50
lines changed

deps/ncrypto/ncrypto.cc

+53
Original file line numberDiff line numberDiff line change
@@ -963,4 +963,57 @@ X509Pointer X509Pointer::IssuerFrom(const SSL_CTX* ctx, const X509View& cert) {
963963
X509Pointer X509Pointer::PeerFrom(const SSLPointer& ssl) {
964964
return X509Pointer(SSL_get_peer_certificate(ssl.get()));
965965
}
966+
// ============================================================================
967+
// BIOPointer
968+
969+
BIOPointer::BIOPointer(BIO* bio) : bio_(bio) {}
970+
971+
BIOPointer::BIOPointer(BIOPointer&& other) noexcept : bio_(other.release()) {}
972+
973+
BIOPointer& BIOPointer::operator=(BIOPointer&& other) noexcept {
974+
if (this == &other) return *this;
975+
this->~BIOPointer();
976+
return *new (this) BIOPointer(std::move(other));
977+
}
978+
979+
BIOPointer::~BIOPointer() { reset(); }
980+
981+
void BIOPointer::reset(BIO* bio) { bio_.reset(bio); }
982+
983+
BIO* BIOPointer::release() { return bio_.release(); }
984+
985+
bool BIOPointer::resetBio() const {
986+
if (!bio_) return 0;
987+
return BIO_reset(bio_.get()) == 1;
988+
}
989+
990+
BIOPointer BIOPointer::NewMem() {
991+
return BIOPointer(BIO_new(BIO_s_mem()));
992+
}
993+
994+
BIOPointer BIOPointer::NewSecMem() {
995+
return BIOPointer(BIO_new(BIO_s_secmem()));
996+
}
997+
998+
BIOPointer BIOPointer::New(const BIO_METHOD* method) {
999+
return BIOPointer(BIO_new(method));
1000+
}
1001+
1002+
BIOPointer BIOPointer::New(const void* data, size_t len) {
1003+
return BIOPointer(BIO_new_mem_buf(data, len));
1004+
}
1005+
1006+
BIOPointer BIOPointer::NewFile(std::string_view filename, std::string_view mode) {
1007+
return BIOPointer(BIO_new_file(filename.data(), mode.data()));
1008+
}
1009+
1010+
BIOPointer BIOPointer::NewFp(FILE* fd, int close_flag) {
1011+
return BIOPointer(BIO_new_fp(fd, close_flag));
1012+
}
1013+
1014+
int BIOPointer::Write(BIOPointer* bio, std::string_view message) {
1015+
if (bio == nullptr || !*bio) return 0;
1016+
return BIO_write(bio->get(), message.data(), message.size());
1017+
}
1018+
9661019
} // namespace ncrypto

deps/ncrypto/ncrypto.h

+49-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#include <optional>
77
#include <string>
88
#include <string_view>
9+
#include <openssl/bio.h>
910
#include <openssl/bn.h>
10-
#include <openssl/x509.h>
1111
#include <openssl/dh.h>
1212
#include <openssl/dsa.h>
1313
#include <openssl/ec.h>
@@ -17,6 +17,7 @@
1717
#include <openssl/kdf.h>
1818
#include <openssl/rsa.h>
1919
#include <openssl/ssl.h>
20+
#include <openssl/x509.h>
2021
#ifndef OPENSSL_NO_ENGINE
2122
# include <openssl/engine.h>
2223
#endif // !OPENSSL_NO_ENGINE
@@ -192,7 +193,6 @@ template <typename T, void (*function)(T*)>
192193
using DeleteFnPtr = typename FunctionDeleter<T, function>::Pointer;
193194

194195
using BignumCtxPointer = DeleteFnPtr<BN_CTX, BN_CTX_free>;
195-
using BIOPointer = DeleteFnPtr<BIO, BIO_free_all>;
196196
using CipherCtxPointer = DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
197197
using DHPointer = DeleteFnPtr<DH, DH_free>;
198198
using DSAPointer = DeleteFnPtr<DSA, DSA_free>;
@@ -265,6 +265,53 @@ class DataPointer final {
265265
size_t len_ = 0;
266266
};
267267

268+
class BIOPointer final {
269+
public:
270+
static BIOPointer NewMem();
271+
static BIOPointer NewSecMem();
272+
static BIOPointer New(const BIO_METHOD* method);
273+
static BIOPointer New(const void* data, size_t len);
274+
static BIOPointer NewFile(std::string_view filename, std::string_view mode);
275+
static BIOPointer NewFp(FILE* fd, int flags);
276+
277+
BIOPointer() = default;
278+
BIOPointer(std::nullptr_t) : bio_(nullptr) {}
279+
explicit BIOPointer(BIO* bio);
280+
BIOPointer(BIOPointer&& other) noexcept;
281+
BIOPointer& operator=(BIOPointer&& other) noexcept;
282+
NCRYPTO_DISALLOW_COPY(BIOPointer)
283+
~BIOPointer();
284+
285+
inline bool operator==(std::nullptr_t) noexcept { return bio_ == nullptr; }
286+
inline operator bool() const { return bio_ != nullptr; }
287+
inline BIO* get() const noexcept { return bio_.get(); }
288+
289+
inline operator BUF_MEM*() const {
290+
BUF_MEM* mem = nullptr;
291+
if (!bio_) return mem;
292+
BIO_get_mem_ptr(bio_.get(), &mem);
293+
return mem;
294+
}
295+
296+
inline operator BIO*() const { return bio_.get(); }
297+
298+
void reset(BIO* bio = nullptr);
299+
BIO* release();
300+
301+
bool resetBio() const;
302+
303+
static int Write(BIOPointer* bio, std::string_view message);
304+
305+
template <typename...Args>
306+
static void Printf(BIOPointer* bio, const char* format, Args...args) {
307+
if (bio == nullptr || !*bio) return;
308+
BIO_printf(bio->get(), format, std::forward<Args...>(args...));
309+
}
310+
311+
private:
312+
mutable DeleteFnPtr<BIO, BIO_free_all> bio_;
313+
};
314+
268315
class BignumPointer final {
269316
public:
270317
BignumPointer() = default;

src/crypto/crypto_bio.cc

+4-4
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ namespace node {
3333
namespace crypto {
3434

3535
BIOPointer NodeBIO::New(Environment* env) {
36-
BIOPointer bio(BIO_new(GetMethod()));
36+
auto bio = BIOPointer::New(GetMethod());
3737
if (bio && env != nullptr)
3838
NodeBIO::FromBIO(bio.get())->env_ = env;
3939
return bio;
@@ -43,9 +43,9 @@ BIOPointer NodeBIO::New(Environment* env) {
4343
BIOPointer NodeBIO::NewFixed(const char* data, size_t len, Environment* env) {
4444
BIOPointer bio = New(env);
4545

46-
if (!bio ||
47-
len > INT_MAX ||
48-
BIO_write(bio.get(), data, len) != static_cast<int>(len) ||
46+
if (!bio || len > INT_MAX ||
47+
BIOPointer::Write(&bio, std::string_view(data, len)) !=
48+
static_cast<int>(len) ||
4949
BIO_set_mem_eof_return(bio.get(), 0) != 1) {
5050
return BIOPointer();
5151
}

src/crypto/crypto_context.cc

+11-11
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,17 @@ X509_STORE* GetOrCreateRootCertStore() {
6464
// Caller responsible for BIO_free_all-ing the returned object.
6565
BIOPointer LoadBIO(Environment* env, Local<Value> v) {
6666
if (v->IsString() || v->IsArrayBufferView()) {
67-
BIOPointer bio(BIO_new(BIO_s_secmem()));
68-
if (!bio) return nullptr;
67+
auto bio = BIOPointer::NewSecMem();
68+
if (!bio) return {};
6969
ByteSource bsrc = ByteSource::FromStringOrBuffer(env, v);
70-
if (bsrc.size() > INT_MAX) return nullptr;
71-
int written = BIO_write(bio.get(), bsrc.data<char>(), bsrc.size());
72-
if (written < 0) return nullptr;
73-
if (static_cast<size_t>(written) != bsrc.size()) return nullptr;
70+
if (bsrc.size() > INT_MAX) return {};
71+
int written = BIOPointer::Write(
72+
&bio, std::string_view(bsrc.data<char>(), bsrc.size()));
73+
if (written < 0) return {};
74+
if (static_cast<size_t>(written) != bsrc.size()) return {};
7475
return bio;
7576
}
76-
return nullptr;
77+
return {};
7778
}
7879

7980
namespace {
@@ -202,7 +203,7 @@ unsigned long LoadCertsFromFile( // NOLINT(runtime/int)
202203
const char* file) {
203204
MarkPopErrorOnReturn mark_pop_error_on_return;
204205

205-
BIOPointer bio(BIO_new_file(file, "r"));
206+
auto bio = BIOPointer::NewFile(file, "r");
206207
if (!bio) return ERR_get_error();
207208

208209
while (X509* x509 = PEM_read_bio_X509(
@@ -1012,16 +1013,15 @@ void SecureContext::SetSessionIdContext(
10121013
if (SSL_CTX_set_session_id_context(sc->ctx_.get(), sid_ctx, sid_ctx_len) == 1)
10131014
return;
10141015

1015-
BUF_MEM* mem;
10161016
Local<String> message;
10171017

1018-
BIOPointer bio(BIO_new(BIO_s_mem()));
1018+
auto bio = BIOPointer::NewMem();
10191019
if (!bio) {
10201020
message = FIXED_ONE_BYTE_STRING(env->isolate(),
10211021
"SSL_CTX_set_session_id_context error");
10221022
} else {
10231023
ERR_print_errors(bio.get());
1024-
BIO_get_mem_ptr(bio.get(), &mem);
1024+
BUF_MEM* mem = bio;
10251025
message = OneByteString(env->isolate(), mem->data, mem->length);
10261026
}
10271027

src/crypto/crypto_ec.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ WebCryptoKeyExportStatus ECKeyExportTraits::DoExport(
736736
CHECK_EQ(1, EC_KEY_set_public_key(ec.get(), uncompressed.get()));
737737
EVPKeyPointer pkey(EVP_PKEY_new());
738738
CHECK_EQ(1, EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get()));
739-
BIOPointer bio(BIO_new(BIO_s_mem()));
739+
auto bio = BIOPointer::NewMem();
740740
CHECK(bio);
741741
if (!i2d_PUBKEY_bio(bio.get(), pkey.get()))
742742
return WebCryptoKeyExportStatus::FAILED;

src/crypto/crypto_keys.cc

+15-17
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ ParseKeyResult TryParsePublicKey(EVPKeyPointer* pkey,
104104
ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
105105
const char* key_pem,
106106
int key_pem_len) {
107-
BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
107+
auto bp = BIOPointer::New(key_pem, key_pem_len);
108108
if (!bp)
109109
return ParseKeyResult::kParseKeyFailed;
110110

@@ -119,7 +119,7 @@ ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
119119
return ret;
120120

121121
// Maybe it is PKCS#1.
122-
CHECK(BIO_reset(bp.get()));
122+
CHECK(bp.resetBio());
123123
ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY",
124124
[](const unsigned char** p, long l) { // NOLINT(runtime/int)
125125
return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
@@ -128,7 +128,7 @@ ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
128128
return ret;
129129

130130
// X.509 fallback.
131-
CHECK(BIO_reset(bp.get()));
131+
CHECK(bp.resetBio());
132132
return TryParsePublicKey(pkey, bp, "CERTIFICATE",
133133
[](const unsigned char** p, long l) { // NOLINT(runtime/int)
134134
X509Pointer x509(d2i_X509(nullptr, p, l));
@@ -218,7 +218,7 @@ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
218218
const ByteSource* passphrase = config.passphrase_.get();
219219

220220
if (config.format_ == kKeyFormatPEM) {
221-
BIOPointer bio(BIO_new_mem_buf(key, key_len));
221+
auto bio = BIOPointer::New(key, key_len);
222222
if (!bio)
223223
return ParseKeyResult::kParseKeyFailed;
224224

@@ -233,7 +233,7 @@ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
233233
const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
234234
pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
235235
} else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
236-
BIOPointer bio(BIO_new_mem_buf(key, key_len));
236+
auto bio = BIOPointer::New(key, key_len);
237237
if (!bio)
238238
return ParseKeyResult::kParseKeyFailed;
239239

@@ -270,12 +270,10 @@ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
270270
return ParseKeyResult::kParseKeyFailed;
271271
}
272272

273-
MaybeLocal<Value> BIOToStringOrBuffer(
274-
Environment* env,
275-
BIO* bio,
276-
PKFormatType format) {
277-
BUF_MEM* bptr;
278-
BIO_get_mem_ptr(bio, &bptr);
273+
MaybeLocal<Value> BIOToStringOrBuffer(Environment* env,
274+
const BIOPointer& bio,
275+
PKFormatType format) {
276+
BUF_MEM* bptr = bio;
279277
if (format == kKeyFormatPEM) {
280278
// PEM is an ASCII format, so we will return it as a string.
281279
return String::NewFromUtf8(env->isolate(), bptr->data,
@@ -292,7 +290,7 @@ MaybeLocal<Value> BIOToStringOrBuffer(
292290
MaybeLocal<Value> WritePrivateKey(Environment* env,
293291
OSSL3_CONST EVP_PKEY* pkey,
294292
const PrivateKeyEncodingConfig& config) {
295-
BIOPointer bio(BIO_new(BIO_s_mem()));
293+
auto bio = BIOPointer::NewMem();
296294
CHECK(bio);
297295

298296
// If an empty string was passed as the passphrase, the ByteSource might
@@ -388,7 +386,7 @@ MaybeLocal<Value> WritePrivateKey(Environment* env,
388386
ThrowCryptoError(env, ERR_get_error(), "Failed to encode private key");
389387
return MaybeLocal<Value>();
390388
}
391-
return BIOToStringOrBuffer(env, bio.get(), config.format_);
389+
return BIOToStringOrBuffer(env, bio, config.format_);
392390
}
393391

394392
bool WritePublicKeyInner(OSSL3_CONST EVP_PKEY* pkey,
@@ -422,14 +420,14 @@ bool WritePublicKeyInner(OSSL3_CONST EVP_PKEY* pkey,
422420
MaybeLocal<Value> WritePublicKey(Environment* env,
423421
OSSL3_CONST EVP_PKEY* pkey,
424422
const PublicKeyEncodingConfig& config) {
425-
BIOPointer bio(BIO_new(BIO_s_mem()));
423+
auto bio = BIOPointer::NewMem();
426424
CHECK(bio);
427425

428426
if (!WritePublicKeyInner(pkey, bio, config)) {
429427
ThrowCryptoError(env, ERR_get_error(), "Failed to encode public key");
430428
return MaybeLocal<Value>();
431429
}
432-
return BIOToStringOrBuffer(env, bio.get(), config.format_);
430+
return BIOToStringOrBuffer(env, bio, config.format_);
433431
}
434432

435433
Maybe<void> ExportJWKSecretKey(Environment* env,
@@ -1448,7 +1446,7 @@ WebCryptoKeyExportStatus PKEY_SPKI_Export(
14481446
CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
14491447
ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
14501448
Mutex::ScopedLock lock(*m_pkey.mutex());
1451-
BIOPointer bio(BIO_new(BIO_s_mem()));
1449+
auto bio = BIOPointer::NewMem();
14521450
CHECK(bio);
14531451
if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
14541452
return WebCryptoKeyExportStatus::FAILED;
@@ -1464,7 +1462,7 @@ WebCryptoKeyExportStatus PKEY_PKCS8_Export(
14641462
ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
14651463
Mutex::ScopedLock lock(*m_pkey.mutex());
14661464

1467-
BIOPointer bio(BIO_new(BIO_s_mem()));
1465+
auto bio = BIOPointer::NewMem();
14681466
CHECK(bio);
14691467
PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
14701468
if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))

src/crypto/crypto_tls.cc

+6-5
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@
2020
// USE OR OTHER DEALINGS IN THE SOFTWARE.
2121

2222
#include "crypto/crypto_tls.h"
23-
#include "crypto/crypto_context.h"
24-
#include "crypto/crypto_common.h"
25-
#include "crypto/crypto_util.h"
23+
#include <cstdio>
24+
#include "async_wrap-inl.h"
2625
#include "crypto/crypto_bio.h"
2726
#include "crypto/crypto_clienthello-inl.h"
28-
#include "async_wrap-inl.h"
27+
#include "crypto/crypto_common.h"
28+
#include "crypto/crypto_context.h"
29+
#include "crypto/crypto_util.h"
2930
#include "debug_utils-inl.h"
3031
#include "memory_tracker-inl.h"
3132
#include "node_buffer.h"
@@ -1244,7 +1245,7 @@ void TLSWrap::EnableTrace(const FunctionCallbackInfo<Value>& args) {
12441245

12451246
#if HAVE_SSL_TRACE
12461247
if (wrap->ssl_) {
1247-
wrap->bio_trace_.reset(BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT));
1248+
wrap->bio_trace_ = BIOPointer::NewFp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
12481249
SSL_set_msg_callback(wrap->ssl_.get(), [](int write_p, int version, int
12491250
content_type, const void* buf, size_t len, SSL* ssl, void* arg)
12501251
-> void {

src/crypto/crypto_util.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -355,8 +355,7 @@ MaybeLocal<Uint8Array> ByteSource::ToBuffer(Environment* env) {
355355

356356
ByteSource ByteSource::FromBIO(const BIOPointer& bio) {
357357
CHECK(bio);
358-
BUF_MEM* bptr;
359-
BIO_get_mem_ptr(bio.get(), &bptr);
358+
BUF_MEM* bptr = bio;
360359
ByteSource::Builder out(bptr->length);
361360
memcpy(out.data<void>(), bptr->data, bptr->length);
362361
return std::move(out).release();

0 commit comments

Comments
 (0)