@@ -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;
@@ -1629,8 +1638,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16291638
16301639 EVPKeyPointer pkey (X509_get_pubkey (cert));
16311640 RSAPointer rsa;
1632- if (pkey)
1633- rsa.reset (EVP_PKEY_get1_RSA (pkey.get ()));
1641+ ECPointer ec;
1642+ if (pkey) {
1643+ switch (EVP_PKEY_id (pkey.get ())) {
1644+ case EVP_PKEY_RSA:
1645+ rsa.reset (EVP_PKEY_get1_RSA (pkey.get ()));
1646+ break ;
1647+ case EVP_PKEY_EC:
1648+ ec.reset (EVP_PKEY_get1_EC_KEY (pkey.get ()));
1649+ break ;
1650+ }
1651+ }
16341652
16351653 if (rsa) {
16361654 const BIGNUM* n;
@@ -1666,10 +1684,53 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
16661684 reinterpret_cast <unsigned char *>(Buffer::Data (pubbuff));
16671685 i2d_RSA_PUBKEY (rsa.get (), &pubserialized);
16681686 info->Set (env->context (), env->pubkey_string (), pubbuff).FromJust ();
1687+ } else if (ec) {
1688+ const EC_GROUP* group = EC_KEY_get0_group (ec.get ());
1689+ if (group != nullptr ) {
1690+ int bits = EC_GROUP_order_bits (group);
1691+ if (bits > 0 ) {
1692+ info->Set (context, env->bits_string (),
1693+ Integer::New (env->isolate (), bits)).FromJust ();
1694+ }
1695+ }
1696+
1697+ unsigned char * pub = nullptr ;
1698+ size_t publen = EC_KEY_key2buf (ec.get (), EC_KEY_get_conv_form (ec.get ()),
1699+ &pub, nullptr );
1700+ if (publen > 0 ) {
1701+ Local<Object> buf = Buffer::New (env, pub, publen).ToLocalChecked ();
1702+ // Ownership of pub pointer accepted by Buffer.
1703+ pub = nullptr ;
1704+ info->Set (context, env->pubkey_string (), buf).FromJust ();
1705+ } else {
1706+ CHECK_NULL (pub);
1707+ }
1708+
1709+ if (EC_GROUP_get_asn1_flag (group) != 0 ) {
1710+ // Curve is well-known, get its OID and NIST nick-name (if it has one).
1711+
1712+ int nid = EC_GROUP_get_curve_name (group);
1713+ if (nid != 0 ) {
1714+ if (const char * sn = OBJ_nid2sn (nid)) {
1715+ info->Set (context, env->asn1curve_string (),
1716+ OneByteString (env->isolate (), sn)).FromJust ();
1717+ }
1718+ }
1719+ if (nid != 0 ) {
1720+ if (const char * nist = EC_curve_nid2nist (nid)) {
1721+ info->Set (context, env->nistcurve_string (),
1722+ OneByteString (env->isolate (), nist)).FromJust ();
1723+ }
1724+ }
1725+ } else {
1726+ // Unnamed curves can be described by their mathematical properties,
1727+ // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1728+ }
16691729 }
16701730
16711731 pkey.reset ();
16721732 rsa.reset ();
1733+ ec.reset ();
16731734
16741735 ASN1_TIME_print (bio.get (), X509_get_notBefore (cert));
16751736 BIO_get_mem_ptr (bio.get (), &mem);
0 commit comments