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 <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Minwoo Jung <[email protected]> Reviewed-By: Robert Nagy <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
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

+82-48
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

+16-1
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)