zedwood

openssl public key parsing in php source code (C)

Dec 30th, 2016
131
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.60 KB | None | 0 0
  1. PHP_FUNCTION(openssl_pkey_get_details)
  2. {
  3.     zval *key;
  4.     EVP_PKEY *pkey;
  5.     BIO *out;
  6.     unsigned int pbio_len;
  7.     char *pbio;
  8.     long ktype;
  9.  
  10.     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &key) == FAILURE) {
  11.         return;
  12.     }
  13.     ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key);
  14.     if (!pkey) {
  15.         RETURN_FALSE;
  16.     }
  17.     out = BIO_new(BIO_s_mem());
  18.     PEM_write_bio_PUBKEY(out, pkey);
  19.     pbio_len = BIO_get_mem_data(out, &pbio);
  20.  
  21.     array_init(return_value);
  22.     add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey));
  23.     add_assoc_stringl(return_value, "key", pbio, pbio_len, 1);
  24.     /*TODO: Use the real values once the openssl constants are used
  25.      * See the enum at the top of this file
  26.      */
  27.     switch (EVP_PKEY_type(pkey->type)) {
  28.         case EVP_PKEY_RSA:
  29.         case EVP_PKEY_RSA2:
  30.             ktype = OPENSSL_KEYTYPE_RSA;
  31.  
  32.             if (pkey->pkey.rsa != NULL) {
  33.                 zval *rsa;
  34.  
  35.                 ALLOC_INIT_ZVAL(rsa);
  36.                 array_init(rsa);
  37.                 OPENSSL_PKEY_GET_BN(rsa, n);
  38.                 OPENSSL_PKEY_GET_BN(rsa, e);
  39.                 OPENSSL_PKEY_GET_BN(rsa, d);
  40.                 OPENSSL_PKEY_GET_BN(rsa, p);
  41.                 OPENSSL_PKEY_GET_BN(rsa, q);
  42.                 OPENSSL_PKEY_GET_BN(rsa, dmp1);
  43.                 OPENSSL_PKEY_GET_BN(rsa, dmq1);
  44.                 OPENSSL_PKEY_GET_BN(rsa, iqmp);
  45.                 add_assoc_zval(return_value, "rsa", rsa);
  46.             }
  47.  
  48.             break; 
  49.         case EVP_PKEY_DSA:
  50.         case EVP_PKEY_DSA2:
  51.         case EVP_PKEY_DSA3:
  52.         case EVP_PKEY_DSA4:
  53.             ktype = OPENSSL_KEYTYPE_DSA;
  54.  
  55.             if (pkey->pkey.dsa != NULL) {
  56.                 zval *dsa;
  57.  
  58.                 ALLOC_INIT_ZVAL(dsa);
  59.                 array_init(dsa);
  60.                 OPENSSL_PKEY_GET_BN(dsa, p);
  61.                 OPENSSL_PKEY_GET_BN(dsa, q);
  62.                 OPENSSL_PKEY_GET_BN(dsa, g);
  63.                 OPENSSL_PKEY_GET_BN(dsa, priv_key);
  64.                 OPENSSL_PKEY_GET_BN(dsa, pub_key);
  65.                 add_assoc_zval(return_value, "dsa", dsa);
  66.             }
  67.             break;
  68.         case EVP_PKEY_DH:
  69.            
  70.             ktype = OPENSSL_KEYTYPE_DH;
  71.  
  72.             if (pkey->pkey.dh != NULL) {
  73.                 zval *dh;
  74.  
  75.                 ALLOC_INIT_ZVAL(dh);
  76.                 array_init(dh);
  77.                 OPENSSL_PKEY_GET_BN(dh, p);
  78.                 OPENSSL_PKEY_GET_BN(dh, g);
  79.                 OPENSSL_PKEY_GET_BN(dh, priv_key);
  80.                 OPENSSL_PKEY_GET_BN(dh, pub_key);
  81.                 add_assoc_zval(return_value, "dh", dh);
  82.             }
  83.  
  84.             break;
  85. #ifdef HAVE_EVP_PKEY_EC
  86.         case EVP_PKEY_EC:
  87.             ktype = OPENSSL_KEYTYPE_EC;
  88.             if (pkey->pkey.ec != NULL) {
  89.                 zval *ec;
  90.                 const EC_GROUP *ec_group;
  91.                 int nid;
  92.                 char *crv_sn;
  93.                 ASN1_OBJECT *obj;
  94.                 // openssl recommends a buffer length of 80
  95.                 char oir_buf[80];
  96.  
  97.                 ec_group = EC_KEY_get0_group(EVP_PKEY_get1_EC_KEY(pkey));
  98.  
  99.                 // Curve nid (numerical identifier) used for ASN1 mapping
  100.                 nid = EC_GROUP_get_curve_name(ec_group);
  101.                 if (nid == NID_undef) {
  102.                     break;
  103.                 }
  104.                 ALLOC_INIT_ZVAL(ec);
  105.                 array_init(ec);
  106.  
  107.                 // Short object name
  108.                 crv_sn = (char*) OBJ_nid2sn(nid);
  109.                 if (crv_sn != NULL) {
  110.                     add_assoc_string(ec, "curve_name", crv_sn, 1);
  111.                 }
  112.  
  113.                 obj = OBJ_nid2obj(nid);
  114.                 if (obj != NULL) {
  115.                     int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
  116.                     add_assoc_stringl(ec, "curve_oid", (char*)oir_buf, oir_len, 1);
  117.                     ASN1_OBJECT_free(obj);
  118.                 }
  119.  
  120.                 add_assoc_zval(return_value, "ec", ec);
  121.             }
  122.             break;
  123. #endif
  124.         default:
  125.             ktype = -1;
  126.             break;
  127.     }
  128.     add_assoc_long(return_value, "type", ktype);
  129.  
  130.     BIO_free(out);
  131. }
  132. /* }}} */
  133.  
  134. #define OPENSSL_PKEY_GET_BN(_type, _name) do {                          \
  135.         if (pkey->pkey._type->_name != NULL) {                          \
  136.             int len = BN_num_bytes(pkey->pkey._type->_name);            \
  137.             char *str = emalloc(len + 1);                               \
  138.             BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str);    \
  139.             str[len] = 0;                                               \
  140.             add_assoc_stringl(_type, #_name, str, len, 0);              \
  141.         }                                                               \
  142.     } while (0)
Advertisement
Add Comment
Please, Sign In to add comment