Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: update src/crypto/* in preparation for quic #45912

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/crypto/crypto_common.cc
Expand Up @@ -545,6 +545,16 @@ MaybeLocal<Value> GetKeyUsage(Environment* env, X509* cert) {
return Undefined(env->isolate());
}

MaybeLocal<Value> GetCurrentCipherName(Environment* env,
const SSLPointer& ssl) {
return GetCipherName(env, SSL_get_current_cipher(ssl.get()));
}

MaybeLocal<Value> GetCurrentCipherVersion(Environment* env,
const SSLPointer& ssl) {
return GetCipherVersion(env, SSL_get_current_cipher(ssl.get()));
}

MaybeLocal<Value> GetFingerprintDigest(
Environment* env,
const EVP_MD* method,
Expand Down
4 changes: 4 additions & 0 deletions src/crypto/crypto_common.h
Expand Up @@ -111,6 +111,10 @@ v8::MaybeLocal<v8::Value> GetFingerprintDigest(
X509* cert);

v8::MaybeLocal<v8::Value> GetKeyUsage(Environment* env, X509* cert);
v8::MaybeLocal<v8::Value> GetCurrentCipherName(Environment* env,
const SSLPointer& ssl);
v8::MaybeLocal<v8::Value> GetCurrentCipherVersion(Environment* env,
const SSLPointer& ssl);

v8::MaybeLocal<v8::Value> GetSerialNumber(Environment* env, X509* cert);

Expand Down
130 changes: 82 additions & 48 deletions src/crypto/crypto_context.cc
Expand Up @@ -32,7 +32,10 @@ using v8::HandleScope;
using v8::Int32;
using v8::Integer;
using v8::Isolate;
using v8::Just;
using v8::Local;
using v8::Maybe;
using v8::Nothing;
using v8::Object;
using v8::PropertyAttribute;
using v8::ReadOnly;
Expand Down Expand Up @@ -574,6 +577,22 @@ void SecureContext::SetKeylogCallback(KeylogCb cb) {
SSL_CTX_set_keylog_callback(ctx_.get(), cb);
}

Maybe<bool> SecureContext::UseKey(Environment* env,
std::shared_ptr<KeyObjectData> key) {
if (key->GetKeyType() != KeyType::kKeyTypePrivate) {
THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
return Nothing<bool>();
}

ClearErrorOnReturn clear_error_on_return;
if (!SSL_CTX_use_PrivateKey(ctx_.get(), key->GetAsymmetricKey().get())) {
ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_PrivateKey");
return Nothing<bool>();
}

return Just(true);
}

void SecureContext::SetKey(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

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

void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

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

CHECK_GE(args.Length(), 1); // Certificate argument is mandator

BIOPointer bio(LoadBIO(env, args[0]));
if (!bio)
return;

sc->cert_.reset();
sc->issuer_.reset();
Maybe<bool> SecureContext::AddCert(Environment* env, BIOPointer&& bio) {
ClearErrorOnReturn clear_error_on_return;
if (!bio) return Just(false);
cert_.reset();
issuer_.reset();

if (!SSL_CTX_use_certificate_chain(
sc->ctx_.get(),
std::move(bio),
&sc->cert_,
&sc->issuer_)) {
return ThrowCryptoError(
env,
ERR_get_error(),
"SSL_CTX_use_certificate_chain");
// The SSL_CTX_use_certificate_chain call here is not from openssl, this is
// the method implemented elsewhere in this file. The naming is a bit
// confusing, unfortunately.
if (SSL_CTX_use_certificate_chain(
ctx_.get(), std::move(bio), &cert_, &issuer_) == 0) {
ThrowCryptoError(env, ERR_get_error(), "SSL_CTX_use_certificate_chain");
return Nothing<bool>();
}
return Just(true);
}

void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
void SecureContext::SetCert(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
ClearErrorOnReturn clear_error_on_return;

CHECK_GE(args.Length(), 1); // CA certificate argument is mandatory
CHECK_GE(args.Length(), 1); // Certificate argument is mandatory

BIOPointer bio(LoadBIO(env, args[0]));
if (!bio)
return;
USE(sc->AddCert(env, std::move(bio)));
}

X509_STORE* cert_store = SSL_CTX_get_cert_store(sc->ctx_.get());
void SecureContext::SetCACert(const BIOPointer& bio) {
ClearErrorOnReturn clear_error_on_return;
if (!bio) return;
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
while (X509Pointer x509 = X509Pointer(PEM_read_bio_X509_AUX(
bio.get(), nullptr, NoPasswordCallback, nullptr))) {
if (cert_store == GetOrCreateRootCertStore()) {
cert_store = NewRootCertStore();
SSL_CTX_set_cert_store(sc->ctx_.get(), cert_store);
SSL_CTX_set_cert_store(ctx_.get(), cert_store);
}
X509_STORE_add_cert(cert_store, x509.get());
SSL_CTX_add_client_CA(sc->ctx_.get(), x509.get());
CHECK_EQ(1, X509_STORE_add_cert(cert_store, x509.get()));
CHECK_EQ(1, SSL_CTX_add_client_CA(ctx_.get(), x509.get()));
}
}

void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
void SecureContext::AddCACert(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

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

CHECK_GE(args.Length(), 1); // CRL argument is mandatory

ClearErrorOnReturn clear_error_on_return;
CHECK_GE(args.Length(), 1); // CA certificate argument is mandatory

BIOPointer bio(LoadBIO(env, args[0]));
if (!bio)
return;
sc->SetCACert(bio);
}

Maybe<bool> SecureContext::SetCRL(Environment* env, const BIOPointer& bio) {
ClearErrorOnReturn clear_error_on_return;
if (!bio) return Just(false);

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

if (!crl)
return THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to parse CRL");
if (!crl) {
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "Failed to parse CRL");
return Nothing<bool>();
}

X509_STORE* cert_store = SSL_CTX_get_cert_store(sc->ctx_.get());
X509_STORE* cert_store = SSL_CTX_get_cert_store(ctx_.get());
if (cert_store == GetOrCreateRootCertStore()) {
cert_store = NewRootCertStore();
SSL_CTX_set_cert_store(sc->ctx_.get(), cert_store);
SSL_CTX_set_cert_store(ctx_.get(), cert_store);
}

X509_STORE_add_crl(cert_store, crl.get());
X509_STORE_set_flags(cert_store,
X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
CHECK_EQ(1, X509_STORE_add_crl(cert_store, crl.get()));
CHECK_EQ(1,
X509_STORE_set_flags(
cert_store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL));
return Just(true);
}

void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
void SecureContext::AddCRL(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);

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

CHECK_GE(args.Length(), 1); // CRL argument is mandatory

BIOPointer bio(LoadBIO(env, args[0]));
USE(sc->SetCRL(env, bio));
}

void SecureContext::SetRootCerts() {
ClearErrorOnReturn clear_error_on_return;
X509_STORE* store = GetOrCreateRootCertStore();
auto store = GetOrCreateRootCertStore();

// Increment reference count so global store is not deleted along with CTX.
X509_STORE_up_ref(store);
SSL_CTX_set_cert_store(sc->ctx_.get(), store);
SSL_CTX_set_cert_store(ctx_.get(), store);
}

void SecureContext::AddRootCerts(const FunctionCallbackInfo<Value>& args) {
SecureContext* sc;
ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder());
sc->SetRootCerts();
}

void SecureContext::SetCipherSuites(const FunctionCallbackInfo<Value>& args) {
Expand Down
17 changes: 16 additions & 1 deletion src/crypto/crypto_context.h
Expand Up @@ -3,8 +3,9 @@

#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS

#include "crypto/crypto_util.h"
#include "base_object.h"
#include "crypto/crypto_keys.h"
#include "crypto/crypto_util.h"
#include "env.h"
#include "memory_tracker.h"
#include "v8.h"
Expand Down Expand Up @@ -43,13 +44,27 @@ class SecureContext final : public BaseObject {

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

// Non-const ctx() that allows for non-default initialization of
// the SecureContext.
SSLCtxPointer& ctx() { return ctx_; }

SSLPointer CreateSSL();

void SetGetSessionCallback(GetSessionCb cb);
void SetKeylogCallback(KeylogCb cb);
void SetNewSessionCallback(NewSessionCb cb);
void SetSelectSNIContextCallback(SelectSNIContextCb cb);

inline const X509Pointer& issuer() const { return issuer_; }
inline const X509Pointer& cert() const { return cert_; }

v8::Maybe<bool> AddCert(Environment* env, BIOPointer&& bio);
v8::Maybe<bool> SetCRL(Environment* env, const BIOPointer& bio);
v8::Maybe<bool> UseKey(Environment* env, std::shared_ptr<KeyObjectData> key);

void SetCACert(const BIOPointer& bio);
void SetRootCerts();

// TODO(joyeecheung): track the memory used by OpenSSL types
SET_NO_MEMORY_INFO()
SET_MEMORY_INFO_NAME(SecureContext)
Expand Down
53 changes: 28 additions & 25 deletions src/crypto/crypto_keys.cc
Expand Up @@ -889,33 +889,36 @@ size_t KeyObjectData::GetSymmetricKeySize() const {
return symmetric_key_.size();
}

bool KeyObjectHandle::HasInstance(Environment* env, Local<Value> value) {
Local<FunctionTemplate> t = env->crypto_key_object_handle_constructor();
return !t.IsEmpty() && t->HasInstance(value);
}

v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
Local<Function> templ = env->crypto_key_object_handle_constructor();
if (!templ.IsEmpty()) {
return templ;
Local<FunctionTemplate> templ = env->crypto_key_object_handle_constructor();
if (templ.IsEmpty()) {
Isolate* isolate = env->isolate();
templ = NewFunctionTemplate(isolate, New);
templ->InstanceTemplate()->SetInternalFieldCount(
KeyObjectHandle::kInternalFieldCount);
templ->Inherit(BaseObject::GetConstructorTemplate(env));

SetProtoMethod(isolate, templ, "init", Init);
SetProtoMethodNoSideEffect(
isolate, templ, "getSymmetricKeySize", GetSymmetricKeySize);
SetProtoMethodNoSideEffect(
isolate, templ, "getAsymmetricKeyType", GetAsymmetricKeyType);
SetProtoMethod(isolate, templ, "export", Export);
SetProtoMethod(isolate, templ, "exportJwk", ExportJWK);
SetProtoMethod(isolate, templ, "initECRaw", InitECRaw);
SetProtoMethod(isolate, templ, "initEDRaw", InitEDRaw);
SetProtoMethod(isolate, templ, "initJwk", InitJWK);
SetProtoMethod(isolate, templ, "keyDetail", GetKeyDetail);
SetProtoMethod(isolate, templ, "equals", Equals);

env->set_crypto_key_object_handle_constructor(templ);
}
Isolate* isolate = env->isolate();
Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
t->InstanceTemplate()->SetInternalFieldCount(
KeyObjectHandle::kInternalFieldCount);
t->Inherit(BaseObject::GetConstructorTemplate(env));

SetProtoMethod(isolate, t, "init", Init);
SetProtoMethodNoSideEffect(
isolate, t, "getSymmetricKeySize", GetSymmetricKeySize);
SetProtoMethodNoSideEffect(
isolate, t, "getAsymmetricKeyType", GetAsymmetricKeyType);
SetProtoMethod(isolate, t, "export", Export);
SetProtoMethod(isolate, t, "exportJwk", ExportJWK);
SetProtoMethod(isolate, t, "initECRaw", InitECRaw);
SetProtoMethod(isolate, t, "initEDRaw", InitEDRaw);
SetProtoMethod(isolate, t, "initJwk", InitJWK);
SetProtoMethod(isolate, t, "keyDetail", GetKeyDetail);
SetProtoMethod(isolate, t, "equals", Equals);

auto function = t->GetFunction(env->context()).ToLocalChecked();
env->set_crypto_key_object_handle_constructor(function);
return function;
return templ->GetFunction(env->context()).ToLocalChecked();
}

void KeyObjectHandle::RegisterExternalReferences(
Expand Down
1 change: 1 addition & 0 deletions src/crypto/crypto_keys.h
Expand Up @@ -163,6 +163,7 @@ class KeyObjectData : public MemoryRetainer {

class KeyObjectHandle : public BaseObject {
public:
static bool HasInstance(Environment* env, v8::Local<v8::Value> value);
static v8::Local<v8::Function> Initialize(Environment* env);
static void RegisterExternalReferences(ExternalReferenceRegistry* registry);

Expand Down
2 changes: 1 addition & 1 deletion src/env_properties.h
Expand Up @@ -332,6 +332,7 @@
V(contextify_global_template, v8::ObjectTemplate) \
V(contextify_wrapper_template, v8::ObjectTemplate) \
V(compiled_fn_entry_template, v8::ObjectTemplate) \
V(crypto_key_object_handle_constructor, v8::FunctionTemplate) \
V(env_proxy_template, v8::ObjectTemplate) \
V(env_proxy_ctor_template, v8::FunctionTemplate) \
V(dir_instance_template, v8::ObjectTemplate) \
Expand Down Expand Up @@ -374,7 +375,6 @@
V(async_hooks_promise_resolve_function, v8::Function) \
V(buffer_prototype_object, v8::Object) \
V(crypto_key_object_constructor, v8::Function) \
V(crypto_key_object_handle_constructor, v8::Function) \
V(crypto_key_object_private_constructor, v8::Function) \
V(crypto_key_object_public_constructor, v8::Function) \
V(crypto_key_object_secret_constructor, v8::Function) \
Expand Down