diff --git a/src/node_crypto.cc b/src/node_crypto.cc index d878cbe5265b78..f27bdf5aaa85a1 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -416,29 +416,18 @@ void SecureContext::Init(const FunctionCallbackInfo& args) { // Takes a string or buffer and loads it into a BIO. // Caller responsible for BIO_free_all-ing the returned object. static BIO* LoadBIO(Environment* env, Local v) { - BIO* bio = NodeBIO::New(); - if (!bio) - return nullptr; - HandleScope scope(env->isolate()); - int r = -1; - if (v->IsString()) { const node::Utf8Value s(env->isolate(), v); - r = BIO_write(bio, *s, s.length()); - } else if (Buffer::HasInstance(v)) { - char* buffer_data = Buffer::Data(v); - size_t buffer_length = Buffer::Length(v); - r = BIO_write(bio, buffer_data, buffer_length); + return NodeBIO::NewFixed(*s, s.length()); } - if (r <= 0) { - BIO_free_all(bio); - return nullptr; + if (Buffer::HasInstance(v)) { + return NodeBIO::NewFixed(Buffer::Data(v), Buffer::Length(v)); } - return bio; + return nullptr; } @@ -761,15 +750,12 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { root_cert_store = X509_STORE_new(); for (size_t i = 0; i < ARRAY_SIZE(root_certs); i++) { - BIO* bp = NodeBIO::New(); - - if (!BIO_write(bp, root_certs[i], strlen(root_certs[i]))) { - BIO_free_all(bp); + BIO* bp = NodeBIO::NewFixed(root_certs[i], strlen(root_certs[i])); + if (bp == nullptr) { return; } X509 *x509 = PEM_read_bio_X509(bp, nullptr, CryptoPemCallback, nullptr); - if (x509 == nullptr) { BIO_free_all(bp); return; diff --git a/src/node_crypto_bio.cc b/src/node_crypto_bio.cc index ca0d0ba97ecfef..d155eaf79a6f9c 100644 --- a/src/node_crypto_bio.cc +++ b/src/node_crypto_bio.cc @@ -2,6 +2,7 @@ #include "openssl/bio.h" #include "util.h" #include "util-inl.h" +#include #include namespace node { @@ -27,6 +28,21 @@ BIO* NodeBIO::New() { } +BIO* NodeBIO::NewFixed(const char* data, size_t len) { + BIO* bio = New(); + + if (bio == nullptr || + len > INT_MAX || + BIO_write(bio, data, len) != static_cast(len) || + BIO_set_mem_eof_return(bio, 0) != 1) { + BIO_free(bio); + return nullptr; + } + + return bio; +} + + void NodeBIO::AssignEnvironment(Environment* env) { env_ = env; } diff --git a/src/node_crypto_bio.h b/src/node_crypto_bio.h index c4f2923675e9e2..eb247b7f51ace7 100644 --- a/src/node_crypto_bio.h +++ b/src/node_crypto_bio.h @@ -23,6 +23,10 @@ class NodeBIO { static BIO* New(); + // NewFixed takes a copy of `len` bytes from `data` and returns a BIO that, + // when read from, returns those bytes followed by EOF. + static BIO* NewFixed(const char* data, size_t len); + void AssignEnvironment(Environment* env); // Move read head to next buffer if needed