summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSam Roberts <vieuxtech@gmail.com>2018-11-09 15:05:34 -0800
committerSam Roberts <vieuxtech@gmail.com>2018-11-20 13:21:08 -0800
commitfe303b9b2dd8224e368ed69d6b797bc34dd94d07 (patch)
tree2591608d18e88eb9c21a099c0ef02eff0f8291d3 /src
parenta856406c2dc0f6edf9b33067cd91fa1a71eab041 (diff)
downloadandroid-node-v8-fe303b9b2dd8224e368ed69d6b797bc34dd94d07.tar.gz
android-node-v8-fe303b9b2dd8224e368ed69d6b797bc34dd94d07.tar.bz2
android-node-v8-fe303b9b2dd8224e368ed69d6b797bc34dd94d07.zip
tls: include elliptic curve X.509 public key info
X.509 certs are provided to the user in a parsed object form by a number of TLS APIs. Include public key info for elliptic curves as well, not just RSA. - pubkey: the public key - bits: the strength of the curve - asn1Curve: the ASN.1 OID for the curve - nistCurve: the NIST nickname for the curve, if it has one PR-URL: https://github.com/nodejs/node/pull/24358 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Diffstat (limited to 'src')
-rw-r--r--src/env.h3
-rw-r--r--src/node_crypto.cc65
-rw-r--r--src/node_crypto.h1
3 files changed, 67 insertions, 2 deletions
diff --git a/src/env.h b/src/env.h
index 6bed104dbb..c99f1d6830 100644
--- a/src/env.h
+++ b/src/env.h
@@ -124,7 +124,9 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
V(address_string, "address") \
V(aliases_string, "aliases") \
V(args_string, "args") \
+ V(asn1curve_string, "asn1Curve") \
V(async_ids_stack_string, "async_ids_stack") \
+ V(bits_string, "bits") \
V(buffer_string, "buffer") \
V(bytes_parsed_string, "bytesParsed") \
V(bytes_read_string, "bytesRead") \
@@ -207,6 +209,7 @@ constexpr size_t kFsStatsBufferLength = kFsStatsFieldsNumber * 2;
V(modulus_string, "modulus") \
V(name_string, "name") \
V(netmask_string, "netmask") \
+ V(nistcurve_string, "nistCurve") \
V(nsname_string, "nsname") \
V(ocsp_request_string, "OCSPRequest") \
V(onaltsvc_string, "onaltsvc") \
diff --git a/src/node_crypto.cc b/src/node_crypto.cc
index cf50821314..91583c18d9 100644
--- a/src/node_crypto.cc
+++ b/src/node_crypto.cc
@@ -52,6 +52,15 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
| XN_FLAG_FN_SN;
namespace node {
+namespace Buffer {
+// OpenSSL uses `unsigned char*` for raw data, make this easier for us.
+v8::MaybeLocal<v8::Object> New(Environment* env, unsigned char* udata,
+ size_t length) {
+ char* data = reinterpret_cast<char*>(udata);
+ return Buffer::New(env, data, length);
+}
+} // namespace Buffer
+
namespace crypto {
using v8::Array;
@@ -1652,8 +1661,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
EVPKeyPointer pkey(X509_get_pubkey(cert));
RSAPointer rsa;
- if (pkey)
- rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
+ ECPointer ec;
+ if (pkey) {
+ switch (EVP_PKEY_id(pkey.get())) {
+ case EVP_PKEY_RSA:
+ rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
+ break;
+ case EVP_PKEY_EC:
+ ec.reset(EVP_PKEY_get1_EC_KEY(pkey.get()));
+ break;
+ }
+ }
if (rsa) {
const BIGNUM* n;
@@ -1689,10 +1707,53 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
reinterpret_cast<unsigned char*>(Buffer::Data(pubbuff));
i2d_RSA_PUBKEY(rsa.get(), &pubserialized);
info->Set(env->context(), env->pubkey_string(), pubbuff).FromJust();
+ } else if (ec) {
+ const EC_GROUP* group = EC_KEY_get0_group(ec.get());
+ if (group != nullptr) {
+ int bits = EC_GROUP_order_bits(group);
+ if (bits > 0) {
+ info->Set(context, env->bits_string(),
+ Integer::New(env->isolate(), bits)).FromJust();
+ }
+ }
+
+ unsigned char* pub = nullptr;
+ size_t publen = EC_KEY_key2buf(ec.get(), EC_KEY_get_conv_form(ec.get()),
+ &pub, nullptr);
+ if (publen > 0) {
+ Local<Object> buf = Buffer::New(env, pub, publen).ToLocalChecked();
+ // Ownership of pub pointer accepted by Buffer.
+ pub = nullptr;
+ info->Set(context, env->pubkey_string(), buf).FromJust();
+ } else {
+ CHECK_NULL(pub);
+ }
+
+ if (EC_GROUP_get_asn1_flag(group) != 0) {
+ // Curve is well-known, get its OID and NIST nick-name (if it has one).
+
+ int nid = EC_GROUP_get_curve_name(group);
+ if (nid != 0) {
+ if (const char* sn = OBJ_nid2sn(nid)) {
+ info->Set(context, env->asn1curve_string(),
+ OneByteString(env->isolate(), sn)).FromJust();
+ }
+ }
+ if (nid != 0) {
+ if (const char* nist = EC_curve_nid2nist(nid)) {
+ info->Set(context, env->nistcurve_string(),
+ OneByteString(env->isolate(), nist)).FromJust();
+ }
+ }
+ } else {
+ // Unnamed curves can be described by their mathematical properties,
+ // but aren't used much (at all?) with X.509/TLS. Support later if needed.
+ }
}
pkey.reset();
rsa.reset();
+ ec.reset();
ASN1_TIME_print(bio.get(), X509_get_notBefore(cert));
BIO_get_mem_ptr(bio.get(), &mem);
diff --git a/src/node_crypto.h b/src/node_crypto.h
index f85cdd3208..5f98af754e 100644
--- a/src/node_crypto.h
+++ b/src/node_crypto.h
@@ -81,6 +81,7 @@ using EVPKeyPointer = DeleteFnPtr<EVP_PKEY, EVP_PKEY_free>;
using EVPKeyCtxPointer = DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
using EVPMDPointer = DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free>;
using RSAPointer = DeleteFnPtr<RSA, RSA_free>;
+using ECPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
using BignumPointer = DeleteFnPtr<BIGNUM, BN_free>;
using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
using ECGroupPointer = DeleteFnPtr<EC_GROUP, EC_GROUP_free>;