Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 44 additions & 51 deletions src/crypto/crypto_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ using ncrypto::X509Pointer;
using ncrypto::X509View;
using v8::ArrayBuffer;
using v8::BackingStoreInitializationMode;
using v8::Context;
using v8::DictionaryTemplate;
using v8::EscapableHandleScope;
using v8::Integer;
using v8::Local;
Expand Down Expand Up @@ -180,76 +180,69 @@ Local<Value> maybeString(Environment* env,
MaybeLocal<Object> GetCipherInfo(Environment* env, const SSLPointer& ssl) {
if (ssl.getCipher() == nullptr) return MaybeLocal<Object>();
EscapableHandleScope scope(env->isolate());
Local<Object> info = Object::New(env->isolate());

if (info->Set(env->context(),
env->name_string(),
maybeString(env, ssl.getCipherName()))
.IsNothing() ||
info->Set(env->context(),
env->standard_name_string(),
maybeString(env, ssl.getCipherStandardName()))
.IsNothing() ||
info->Set(env->context(),
env->version_string(),
maybeString(env, ssl.getCipherVersion()))
.IsNothing()) {
return MaybeLocal<Object>();

auto tmpl = env->cipherinfo_template();
if (tmpl.IsEmpty()) {
static constexpr std::string_view names[] = {
"name", "standardName", "version"};
tmpl = DictionaryTemplate::New(env->isolate(), names);
env->set_cipherinfo_template(tmpl);
}

return scope.Escape(info);
MaybeLocal<Value> values[] = {
maybeString(env, ssl.getCipherName()),
maybeString(env, ssl.getCipherStandardName()),
maybeString(env, ssl.getCipherVersion()),
};

return scope.EscapeMaybe(NewDictionaryInstance(env->context(), tmpl, values));
}

MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
CHECK(!ssl.isServer());

EscapableHandleScope scope(env->isolate());
Local<Object> info = Object::New(env->isolate());

auto tmpl = env->ephemeral_key_template();
if (tmpl.IsEmpty()) {
static constexpr std::string_view names[] = {"type", "name", "size"};
tmpl = DictionaryTemplate::New(env->isolate(), names);
env->set_ephemeral_key_template(tmpl);
}

MaybeLocal<Value> values[] = {
Undefined(env->isolate()), // type
Undefined(env->isolate()), // name
Undefined(env->isolate()), // size
};
EVPKeyPointer key = ssl.getPeerTempKey();
if (!key) return scope.Escape(info);

Local<Context> context = env->context();

int kid = key.id();
switch (kid) {
case EVP_PKEY_DH:
if (info->Set(context, env->type_string(), env->dh_string())
.IsNothing() ||
info->Set(context,
env->size_string(),
Integer::New(env->isolate(), key.bits()))
.IsNothing()) {
return MaybeLocal<Object>();
if (EVPKeyPointer key = ssl.getPeerTempKey()) {
int kid = key.id();
switch (kid) {
case EVP_PKEY_DH: {
values[0] = env->dh_string();
values[2] = Integer::New(env->isolate(), key.bits());
break;
}
break;
case EVP_PKEY_EC:
case EVP_PKEY_X25519:
case EVP_PKEY_X448:
{
case EVP_PKEY_EC:
case EVP_PKEY_X25519:
case EVP_PKEY_X448: {
const char* curve_name;
if (kid == EVP_PKEY_EC) {
int nid = ECKeyPointer::GetGroupName(key);
curve_name = OBJ_nid2sn(nid);
} else {
curve_name = OBJ_nid2sn(kid);
}
if (info->Set(context, env->type_string(), env->ecdh_string())
.IsNothing() ||
info->Set(context,
env->name_string(),
OneByteString(env->isolate(), curve_name))
.IsNothing() ||
info->Set(context,
env->size_string(),
Integer::New(env->isolate(), key.bits()))
.IsNothing()) {
return MaybeLocal<Object>();
}
values[0] = env->ecdh_string();
values[1] = OneByteString(env->isolate(), curve_name);
values[2] = Integer::New(env->isolate(), key.bits());
break;
}
break;
}
}

return scope.Escape(info);
return scope.EscapeMaybe(NewDictionaryInstance(env->context(), tmpl, values));
}

MaybeLocal<Object> ECPointToBuffer(Environment* env,
Expand Down
182 changes: 77 additions & 105 deletions src/crypto/crypto_x509.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ using v8::BackingStoreOnFailureMode;
using v8::Boolean;
using v8::Context;
using v8::Date;
using v8::DictionaryTemplate;
using v8::EscapableHandleScope;
using v8::Function;
using v8::FunctionCallbackInfo;
Expand All @@ -46,6 +47,7 @@ using v8::NewStringType;
using v8::Object;
using v8::String;
using v8::Uint32;
using v8::Undefined;
using v8::Value;

namespace crypto {
Expand Down Expand Up @@ -735,116 +737,86 @@ MaybeLocal<Value> GetCurveName(Environment* env, const int nid) {

MaybeLocal<Object> X509ToObject(Environment* env, const X509View& cert) {
EscapableHandleScope scope(env->isolate());
Local<Object> info = Object::New(env->isolate());

if (!Set<Value>(env,
info,
env->subject_string(),
GetX509NameObject(env, cert.getSubjectName())) ||
!Set<Value>(env,
info,
env->issuer_string(),
GetX509NameObject(env, cert.getIssuerName())) ||
!Set<Value>(env,
info,
env->subjectaltname_string(),
GetSubjectAltNameString(env, cert)) ||
!Set<Value>(env,
info,
env->infoaccess_string(),
GetInfoAccessString(env, cert)) ||
!Set<Boolean>(env,
info,
env->ca_string(),
Boolean::New(env->isolate(), cert.isCA()))) [[unlikely]] {
return {};
}

if (!cert.ifRsa([&](const ncrypto::Rsa& rsa) {
auto pub_key = rsa.getPublicKey();
if (!Set<Value>(env,
info,
env->modulus_string(),
GetModulusString(env, pub_key.n)) ||
!Set<Value>(env,
info,
env->bits_string(),
Integer::New(env->isolate(),
BignumPointer::GetBitCount(pub_key.n))) ||
!Set<Value>(env,
info,
env->exponent_string(),
GetExponentString(env, pub_key.e)) ||
!Set<Object>(env, info, env->pubkey_string(), GetPubKey(env, rsa)))
[[unlikely]] {
return false;
}
return true;
})) [[unlikely]] {
return {};
auto tmpl = env->x509_dictionary_template();
if (tmpl.IsEmpty()) {
static constexpr std::string_view names[] = {
"subject",
"issuer",
"subjectaltname",
"infoAccess",
"ca",
"modulus",
"exponent",
"pubkey",
"bits",
"valid_from",
"valid_to",
"fingerprint",
"fingerprint256",
"fingerprint512",
"ext_key_usage",
"serialNumber",
"raw",
"asn1Curve",
"nistCurve",
};
tmpl = DictionaryTemplate::New(env->isolate(), names);
env->set_x509_dictionary_template(tmpl);
}

if (!cert.ifEc([&](const ncrypto::Ec& ec) {
const auto group = ec.getGroup();

if (!Set<Value>(
env, info, env->bits_string(), GetECGroupBits(env, group)) ||
!Set<Value>(
env, info, env->pubkey_string(), GetECPubKey(env, group, ec)))
[[unlikely]] {
return false;
}

const int nid = ec.getCurve();
if (nid != 0) [[likely]] {
// Curve is well-known, get its OID and NIST nick-name (if it has
// one).

if (!Set<Value>(env,
info,
env->asn1curve_string(),
GetCurveName<OBJ_nid2sn>(env, nid)) ||
!Set<Value>(env,
info,
env->nistcurve_string(),
GetCurveName<EC_curve_nid2nist>(env, nid)))
[[unlikely]] {
return false;
}
}
// Unnamed curves can be described by their mathematical properties,
// but aren't used much (at all?) with X.509/TLS. Support later if
// needed.
return true;
})) [[unlikely]] {
return {};
}
MaybeLocal<Value> values[] = {
GetX509NameObject(env, cert.getSubjectName()),
GetX509NameObject(env, cert.getIssuerName()),
GetSubjectAltNameString(env, cert),
GetInfoAccessString(env, cert),
Boolean::New(env->isolate(), cert.isCA()),
Undefined(env->isolate()), // modulus
Undefined(env->isolate()), // exponent
Undefined(env->isolate()), // pubkey
Undefined(env->isolate()), // bits
GetValidFrom(env, cert),
GetValidTo(env, cert),
GetFingerprintDigest(env, Digest::SHA1, cert),
GetFingerprintDigest(env, Digest::SHA256, cert),
GetFingerprintDigest(env, Digest::SHA512, cert),
GetKeyUsage(env, cert),
GetSerialNumber(env, cert),
GetDer(env, cert),
Undefined(env->isolate()), // asn1curve
Undefined(env->isolate()), // nistcurve
};

cert.ifRsa([&](const ncrypto::Rsa& rsa) {
auto pub_key = rsa.getPublicKey();
values[5] = GetModulusString(env, pub_key.n); // modulus
values[6] = GetExponentString(env, pub_key.e); // exponent
values[7] = GetPubKey(env, rsa); // pubkey
values[8] = Integer::New(env->isolate(),
BignumPointer::GetBitCount(pub_key.n)); // bits
// TODO(@jasnell): The true response is a left-over from the original
// non DictionaryTemplate-based implementation. It can be removed later.
return true;
});

if (!Set<Value>(
env, info, env->valid_from_string(), GetValidFrom(env, cert)) ||
!Set<Value>(env, info, env->valid_to_string(), GetValidTo(env, cert)) ||
!Set<Value>(env,
info,
env->fingerprint_string(),
GetFingerprintDigest(env, Digest::SHA1, cert)) ||
!Set<Value>(env,
info,
env->fingerprint256_string(),
GetFingerprintDigest(env, Digest::SHA256, cert)) ||
!Set<Value>(env,
info,
env->fingerprint512_string(),
GetFingerprintDigest(env, Digest::SHA512, cert)) ||
!Set<Value>(
env, info, env->ext_key_usage_string(), GetKeyUsage(env, cert)) ||
!Set<Value>(
env, info, env->serial_number_string(), GetSerialNumber(env, cert)) ||
!Set<Value>(env, info, env->raw_string(), GetDer(env, cert)))
[[unlikely]] {
return {};
}
cert.ifEc([&](const ncrypto::Ec& ec) {
const auto group = ec.getGroup();
values[7] = GetECPubKey(env, group, ec); // pubkey
values[8] = GetECGroupBits(env, group); // bits
const int nid = ec.getCurve();
if (nid != 0) {
// Curve is well-known, get its OID and NIST nick-name (if it has
// one).
values[17] = GetCurveName<OBJ_nid2sn>(env, nid); // asn1curve
values[18] = GetCurveName<EC_curve_nid2nist>(env, nid); // nistcurve
}
// Unnamed curves can be described by their mathematical properties,
// but aren't used much (at all?) with X.509/TLS. Support later if
// needed.
return true;
});

return scope.Escape(info);
return scope.EscapeMaybe(NewDictionaryInstance(env->context(), tmpl, values));
}
} // namespace

Expand Down
Loading
Loading