@@ -52,6 +52,15 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
5252 | XN_FLAG_FN_SN;
5353
5454namespace node {
55+ namespace Buffer {
56+ // OpenSSL uses `unsigned char*` for raw data, make this easier for us.
57+ v8::MaybeLocal<v8::Object> New (Environment* env, unsigned char * udata,
58+ size_t length) {
59+ char * data = reinterpret_cast <char *>(udata);
60+ return Buffer::New (env, data, length);
61+ }
62+ } // namespace Buffer
63+
5564namespace crypto {
5665
5766using v8::Array;
@@ -1652,8 +1661,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16521661
16531662 EVPKeyPointer pkey (X509_get_pubkey (cert));
16541663 RSAPointer rsa;
1655- if (pkey)
1656- rsa.reset (EVP_PKEY_get1_RSA (pkey.get ()));
1664+ ECPointer ec;
1665+ if (pkey) {
1666+ switch (EVP_PKEY_id (pkey.get ())) {
1667+ case EVP_PKEY_RSA:
1668+ rsa.reset (EVP_PKEY_get1_RSA (pkey.get ()));
1669+ break ;
1670+ case EVP_PKEY_EC:
1671+ ec.reset (EVP_PKEY_get1_EC_KEY (pkey.get ()));
1672+ break ;
1673+ }
1674+ }
16571675
16581676 if (rsa) {
16591677 const BIGNUM* n;
@@ -1689,10 +1707,53 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16891707 reinterpret_cast <unsigned char *>(Buffer::Data (pubbuff));
16901708 i2d_RSA_PUBKEY (rsa.get (), &pubserialized);
16911709 info->Set (env->context (), env->pubkey_string (), pubbuff).FromJust ();
1710+ } else if (ec) {
1711+ const EC_GROUP* group = EC_KEY_get0_group (ec.get ());
1712+ if (group != nullptr ) {
1713+ int bits = EC_GROUP_order_bits (group);
1714+ if (bits > 0 ) {
1715+ info->Set (context, env->bits_string (),
1716+ Integer::New (env->isolate (), bits)).FromJust ();
1717+ }
1718+ }
1719+
1720+ unsigned char * pub = nullptr ;
1721+ size_t publen = EC_KEY_key2buf (ec.get (), EC_KEY_get_conv_form (ec.get ()),
1722+ &pub, nullptr );
1723+ if (publen > 0 ) {
1724+ Local<Object> buf = Buffer::New (env, pub, publen).ToLocalChecked ();
1725+ // Ownership of pub pointer accepted by Buffer.
1726+ pub = nullptr ;
1727+ info->Set (context, env->pubkey_string (), buf).FromJust ();
1728+ } else {
1729+ CHECK_NULL (pub);
1730+ }
1731+
1732+ if (EC_GROUP_get_asn1_flag (group) != 0 ) {
1733+ // Curve is well-known, get its OID and NIST nick-name (if it has one).
1734+
1735+ int nid = EC_GROUP_get_curve_name (group);
1736+ if (nid != 0 ) {
1737+ if (const char * sn = OBJ_nid2sn (nid)) {
1738+ info->Set (context, env->asn1curve_string (),
1739+ OneByteString (env->isolate (), sn)).FromJust ();
1740+ }
1741+ }
1742+ if (nid != 0 ) {
1743+ if (const char * nist = EC_curve_nid2nist (nid)) {
1744+ info->Set (context, env->nistcurve_string (),
1745+ OneByteString (env->isolate (), nist)).FromJust ();
1746+ }
1747+ }
1748+ } else {
1749+ // Unnamed curves can be described by their mathematical properties,
1750+ // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1751+ }
16921752 }
16931753
16941754 pkey.reset ();
16951755 rsa.reset ();
1756+ ec.reset ();
16961757
16971758 ASN1_TIME_print (bio.get (), X509_get_notBefore (cert));
16981759 BIO_get_mem_ptr (bio.get (), &mem);
0 commit comments