@@ -52,6 +52,15 @@ static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
52
52
| XN_FLAG_FN_SN;
53
53
54
54
namespace 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
+
55
64
namespace crypto {
56
65
57
66
using v8::Array;
@@ -1629,8 +1638,17 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
1629
1638
1630
1639
EVPKeyPointer pkey (X509_get_pubkey (cert));
1631
1640
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
+ }
1634
1652
1635
1653
if (rsa) {
1636
1654
const BIGNUM* n;
@@ -1666,10 +1684,53 @@ static Local<Object> X509ToObject(Environment* env, X509* cert) {
1666
1684
reinterpret_cast <unsigned char *>(Buffer::Data (pubbuff));
1667
1685
i2d_RSA_PUBKEY (rsa.get (), &pubserialized);
1668
1686
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
+ }
1669
1729
}
1670
1730
1671
1731
pkey.reset ();
1672
1732
rsa.reset ();
1733
+ ec.reset ();
1673
1734
1674
1735
ASN1_TIME_print (bio.get (), X509_get_notBefore (cert));
1675
1736
BIO_get_mem_ptr (bio.get (), &mem);
0 commit comments