Skip to content

Commit 3aef68d

Browse files
jasnelldanielleadams
authored andcommitted
src: add additional utilities to crypto::SecureContext
In preparation for use by the QUIC implementation. PR-URL: #45912 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 92fdb24 commit 3aef68d

File tree

2 files changed

+98
-49
lines changed

2 files changed

+98
-49
lines changed

src/crypto/crypto_context.cc

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@ using v8::HandleScope;
3232
using v8::Int32;
3333
using v8::Integer;
3434
using v8::Isolate;
35+
using v8::Just;
3536
using v8::Local;
37+
using v8::Maybe;
38+
using v8::Nothing;
3639
using v8::Object;
3740
using v8::PropertyAttribute;
3841
using v8::ReadOnly;
@@ -574,6 +577,22 @@ void SecureContext::SetKeylogCallback(KeylogCb cb) {
574577
SSL_CTX_set_keylog_callback(ctx_.get(), cb);
575578
}
576579

580+
Maybe<bool> SecureContext::UseKey(Environment* env,
581+
std::shared_ptr<KeyObjectData> key) {
582+
if (key->GetKeyType() != KeyType::kKeyTypePrivate) {
583+
THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
584+
return Nothing<bool>();
585+
}
586+
587+
ClearErrorOnReturn clear_error_on_return;
588+
if (!SSL_CTX_use_PrivateKey(ctx_.get(), key->GetAsymmetricKey().get())) {
589+
ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
590+
return Nothing<bool>();
591+
}
592+
593+
return Just(true);
594+
}
595+
577596
void SecureContext::SetKey(const FunctionCallbackInfo<Value>& args) {
578597
Environment* env = Environment::GetCurrent(args);
579598

@@ -662,97 +681,112 @@ void SecureContext::SetEngineKey(const FunctionCallbackInfo<Value>& args) {
662681
}
663682
#endif // !OPENSSL_NO_ENGINE
664683

665-
void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
666-
Environment* env = Environment::GetCurrent(args);
667-
668-
SecureContext* sc;
669-
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
670-
671-
CHECK_GE(args.Length(), 1); // Certificate argument is mandator
672-
673-
BIOPointer bio(LoadBIO(env, args[0]));
674-
if (!bio)
675-
return;
676-
677-
sc->cert_.reset();
678-
sc->issuer_.reset();
684+
Maybe<bool> SecureContext::AddCert(Environment* env, BIOPointer&& bio) {
685+
ClearErrorOnReturn clear_error_on_return;
686+
if (!bio) return Just(false);
687+
cert_.reset();
688+
issuer_.reset();
679689

680-
if (!SSL_CTX_use_certificate_chain(
681-
sc->ctx_.get(),
682-
std::move(bio),
683-
&sc->cert_,
684-
&sc->issuer_)) {
685-
return ThrowCryptoError(
686-
env,
687-
ERR_get_error(),
688-
"SSL_CTX_use_certificate_chain");
690+
// The SSL_CTX_use_certificate_chain call here is not from openssl, this is
691+
// the method implemented elsewhere in this file. The naming is a bit
692+
// confusing, unfortunately.
693+
if (SSL_CTX_use_certificate_chain(
694+
ctx_.get(), std::move(bio), &cert_, &issuer_) == 0) {
695+
ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_certificate_chain");
696+
return Nothing<bool>();
689697
}
698+
return Just(true);
690699
}
691700

692-
void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
701+
void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
693702
Environment* env = Environment::GetCurrent(args);
694703

695704
SecureContext* sc;
696705
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
697-
ClearErrorOnReturn clear_error_on_return;
698706

699-
CHECK_GE(args.Length(), 1); // CA certificate argument is mandatory
707+
CHECK_GE(args.Length(), 1); // Certificate argument is mandatory
700708

701709
BIOPointer bio(LoadBIO(env, args[0]));
702-
if (!bio)
703-
return;
710+
USE(sc->AddCert(env, std::move(bio)));
711+
}
704712

705-
X509_STORE* cert_store = SSL_CTX_get_cert_store(sc->ctx_.get());
713+
void SecureContext::SetCACert(const BIOPointer& bio) {
714+
ClearErrorOnReturn clear_error_on_return;
715+
if (!bio) return;
716+
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
706717
while (X509Pointer x509 = X509Pointer(PEM_read_bio_X509_AUX(
707718
bio.get(), nullptr, NoPasswordCallback, nullptr))) {
708719
if (cert_store == GetOrCreateRootCertStore()) {
709720
cert_store = NewRootCertStore();
710-
SSL_CTX_set_cert_store(sc->ctx_.get(), cert_store);
721+
SSL_CTX_set_cert_store(ctx_.get(), cert_store);
711722
}
712-
X509_STORE_add_cert(cert_store, x509.get());
713-
SSL_CTX_add_client_CA(sc->ctx_.get(), x509.get());
723+
CHECK_EQ(1, X509_STORE_add_cert(cert_store, x509.get()));
724+
CHECK_EQ(1, SSL_CTX_add_client_CA(ctx_.get(), x509.get()));
714725
}
715726
}
716727

717-
void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
728+
void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
718729
Environment* env = Environment::GetCurrent(args);
719730

720731
SecureContext* sc;
721732
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
722733

723-
CHECK_GE(args.Length(), 1); // CRL argument is mandatory
724-
725-
ClearErrorOnReturn clear_error_on_return;
734+
CHECK_GE(args.Length(), 1); // CA certificate argument is mandatory
726735

727736
BIOPointer bio(LoadBIO(env, args[0]));
728-
if (!bio)
729-
return;
737+
sc->SetCACert(bio);
738+
}
739+
740+
Maybe<bool> SecureContext::SetCRL(Environment* env, const BIOPointer& bio) {
741+
ClearErrorOnReturn clear_error_on_return;
742+
if (!bio) return Just(false);
730743

731744
DeleteFnPtr<X509_CRL, X509_CRL_free> crl(
732745
PEM_read_bio_X509_CRL(bio.get(), nullptr, NoPasswordCallback, nullptr));
733746

734-
if (!crl)
735-
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to parse CRL");
747+
if (!crl) {
748+
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to parse CRL");
749+
return Nothing<bool>();
750+
}
736751

737-
X509_STORE* cert_store = SSL_CTX_get_cert_store(sc->ctx_.get());
752+
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
738753
if (cert_store == GetOrCreateRootCertStore()) {
739754
cert_store = NewRootCertStore();
740-
SSL_CTX_set_cert_store(sc->ctx_.get(), cert_store);
755+
SSL_CTX_set_cert_store(ctx_.get(), cert_store);
741756
}
742757

743-
X509_STORE_add_crl(cert_store, crl.get());
744-
X509_STORE_set_flags(cert_store,
745-
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
758+
CHECK_EQ(1, X509_STORE_add_crl(cert_store, crl.get()));
759+
CHECK_EQ(1,
760+
X509_STORE_set_flags(
761+
cert_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL));
762+
return Just(true);
746763
}
747764

748-
void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
765+
void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
766+
Environment* env = Environment::GetCurrent(args);
767+
749768
SecureContext* sc;
750769
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
770+
771+
CHECK_GE(args.Length(), 1); // CRL argument is mandatory
772+
773+
BIOPointer bio(LoadBIO(env, args[0]));
774+
USE(sc->SetCRL(env, bio));
775+
}
776+
777+
void SecureContext::SetRootCerts() {
751778
ClearErrorOnReturn clear_error_on_return;
752-
X509_STORE* store = GetOrCreateRootCertStore();
779+
auto store = GetOrCreateRootCertStore();
780+
753781
// Increment reference count so global store is not deleted along with CTX.
754782
X509_STORE_up_ref(store);
755-
SSL_CTX_set_cert_store(sc->ctx_.get(), store);
783+
SSL_CTX_set_cert_store(ctx_.get(), store);
784+
}
785+
786+
void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
787+
SecureContext* sc;
788+
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
789+
sc->SetRootCerts();
756790
}
757791

758792
void SecureContext::SetCipherSuites(const FunctionCallbackInfo<Value>& args) {

src/crypto/crypto_context.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33

44
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
55

6-
#include "crypto/crypto_util.h"
76
#include "base_object.h"
7+
#include "crypto/crypto_keys.h"
8+
#include "crypto/crypto_util.h"
89
#include "env.h"
910
#include "memory_tracker.h"
1011
#include "v8.h"
@@ -43,13 +44,27 @@ class SecureContext final : public BaseObject {
4344

4445
const SSLCtxPointer& ctx() const { return ctx_; }
4546

47+
// Non-const ctx() that allows for non-default initialization of
48+
// the SecureContext.
49+
SSLCtxPointer& ctx() { return ctx_; }
50+
4651
SSLPointer CreateSSL();
4752

4853
void SetGetSessionCallback(GetSessionCb cb);
4954
void SetKeylogCallback(KeylogCb cb);
5055
void SetNewSessionCallback(NewSessionCb cb);
5156
void SetSelectSNIContextCallback(SelectSNIContextCb cb);
5257

58+
inline const X509Pointer& issuer() const { return issuer_; }
59+
inline const X509Pointer& cert() const { return cert_; }
60+
61+
v8::Maybe<bool> AddCert(Environment* env, BIOPointer&& bio);
62+
v8::Maybe<bool> SetCRL(Environment* env, const BIOPointer& bio);
63+
v8::Maybe<bool> UseKey(Environment* env, std::shared_ptr<KeyObjectData> key);
64+
65+
void SetCACert(const BIOPointer& bio);
66+
void SetRootCerts();
67+
5368
// TODO(joyeecheung): track the memory used by OpenSSL types
5469
SET_NO_MEMORY_INFO()
5570
SET_MEMORY_INFO_NAME(SecureContext)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy