Download | Plain Text | No Line Numbers


  1. Index: ext/openssl/tests/026.phpt
  2. ===================================================================
  3. --- ext/openssl/tests/026.phpt (revision 0)
  4. +++ ext/openssl/tests/026.phpt (revision 0)
  5. @@ -0,0 +1,84 @@
  6. +--TEST--
  7. +openssl_*() with OPENSSL_KEYTYPE_EC
  8. +--SKIPIF--
  9. +<?php if (!extension_loaded("openssl") && !defined("OPENSSL_KEYTYPE_EC")) print "skip"; ?>
  10. +--FILE--
  11. +<?php
  12. +
  13. +$args = array(
  14. + "ec_group_name" => "secp384r1",
  15. + "private_key_type" => OPENSSL_KEYTYPE_EC,
  16. +);
  17. +
  18. +$key1 = openssl_pkey_new($args);
  19. +var_dump($key1);
  20. +
  21. +$d1 = openssl_pkey_get_details($key1);
  22. +var_dump($d1["bits"]);
  23. +var_dump(strlen($d1["key"]));
  24. +var_dump($d1["ec"]["group_name"]);
  25. +var_dump(strlen($d1["ec"]["priv_key"]));
  26. +var_dump(strlen($d1["ec"]["pub_key"]));
  27. +var_dump($d1["type"] == OPENSSL_KEYTYPE_EC);
  28. +
  29. +$key2 = openssl_pkey_new($d1);
  30. +var_dump($key2);
  31. +
  32. +$d2 = openssl_pkey_get_details($key2);
  33. +var_dump(array_diff_assoc($d2, $d1));
  34. +var_dump(array_diff_assoc($d2["ec"], $d1["ec"]));
  35. +
  36. +
  37. +$dn = array(
  38. + "countryName" => "BR",
  39. + "stateOrProvinceName" => "Rio Grande do Sul",
  40. + "localityName" => "Porto Alegre",
  41. + "commonName" => "Henrique do N. Angelo",
  42. + "emailAddress" => "hnangelo@php.net"
  43. +);
  44. +$csr = openssl_csr_new($dn, $key1, $args);
  45. +
  46. +$args["digest_alg"] = "sha1";
  47. +$csr = openssl_csr_new($dn, $key1, $args);
  48. +var_dump($csr);
  49. +
  50. +$pubkey1 = openssl_pkey_get_details(openssl_csr_get_public_key($csr));
  51. +var_dump(array_diff_assoc($d1, $pubkey1));
  52. +var_dump(isset($pubkey1["ec"]["priv_key"]));
  53. +unset($d1["ec"]["priv_key"]);
  54. +var_dump(array_diff($d1["ec"], $pubkey1["ec"]));
  55. +
  56. +$x509 = openssl_csr_sign($csr, null, $key1, 365, $args);
  57. +var_dump($x509);
  58. +
  59. +
  60. +var_dump(openssl_x509_check_private_key($x509, $key1));
  61. +
  62. +$key3 = openssl_pkey_new($args);
  63. +var_dump(openssl_x509_check_private_key($x509, $key3));
  64. +
  65. +?>
  66. +--EXPECTF--
  67. +resource(%d) of type (OpenSSL key)
  68. +int(384)
  69. +int(215)
  70. +string(9) "secp384r1"
  71. +int(48)
  72. +int(97)
  73. +bool(true)
  74. +resource(%d) of type (OpenSSL key)
  75. +array(0) {
  76. +}
  77. +array(0) {
  78. +}
  79. +
  80. +Warning: openssl_csr_new(): Error signing request in %s on line %d
  81. +resource(%d) of type (OpenSSL X.509 CSR)
  82. +array(0) {
  83. +}
  84. +bool(false)
  85. +array(0) {
  86. +}
  87. +resource(%d) of type (OpenSSL X.509)
  88. +bool(true)
  89. +bool(false)
  90. Index: ext/openssl/openssl.c
  91. ===================================================================
  92. --- ext/openssl/openssl.c (revision 323630)
  93. +++ ext/openssl/openssl.c (working copy)
  94. @@ -98,6 +98,9 @@
  95.  
  96. PHP_FUNCTION(openssl_get_md_methods);
  97. PHP_FUNCTION(openssl_get_cipher_methods);
  98. +#ifdef EVP_PKEY_EC
  99. +PHP_FUNCTION(openssl_get_curve_names);
  100. +#endif
  101.  
  102. PHP_FUNCTION(openssl_digest);
  103. PHP_FUNCTION(openssl_encrypt);
  104. @@ -340,6 +343,11 @@
  105. ZEND_ARG_INFO(0, aliases)
  106. ZEND_END_ARG_INFO()
  107.  
  108. +#ifdef EVP_PKEY_EC
  109. +ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_get_curve_names, 0, 0, 0)
  110. +ZEND_END_ARG_INFO()
  111. +#endif
  112. +
  113. ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_digest, 0, 0, 2)
  114. ZEND_ARG_INFO(0, data)
  115. ZEND_ARG_INFO(0, method)
  116. @@ -437,6 +445,9 @@
  117.  
  118. PHP_FE(openssl_get_md_methods, arginfo_openssl_get_md_methods)
  119. PHP_FE(openssl_get_cipher_methods, arginfo_openssl_get_cipher_methods)
  120. +#ifdef EVP_PKEY_EC
  121. + PHP_FE(openssl_get_curve_names, arginfo_openssl_get_curve_names)
  122. +#endif
  123.  
  124. PHP_FE(openssl_dh_compute_key, arginfo_openssl_dh_compute_key)
  125.  
  126. @@ -535,6 +546,10 @@
  127.  
  128. int priv_key_encrypt;
  129.  
  130. +#ifdef EVP_PKEY_EC
  131. + int ec_group_name;
  132. +#endif
  133. +
  134. EVP_PKEY * priv_key;
  135.  
  136. const EVP_CIPHER * priv_key_encrypt_cipher;
  137. @@ -858,6 +873,18 @@
  138. }
  139.  
  140. PHP_SSL_CONFIG_SYNTAX_CHECK(request_extensions_section);
  141. +
  142. +#ifdef EVP_PKEY_EC
  143. + /* set the ec group curve name */
  144. + req->ec_group_name = 0;
  145. + if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), "ec_group_name", sizeof("ec_group_name"), (void**)&item) == SUCCESS) {
  146. + req->ec_group_name = OBJ_sn2nid(Z_STRVAL_PP(item));
  147. + if (req->ec_group_name == NID_undef) {
  148. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown elliptic curve group (short) name %s", Z_STRVAL_PP(item));
  149. + return FAILURE;
  150. + }
  151. + }
  152. +#endif
  153.  
  154. return SUCCESS;
  155. }
  156. @@ -2843,6 +2870,26 @@
  157. }
  158. break;
  159. #endif
  160. +#ifdef EVP_PKEY_EC
  161. + case OPENSSL_KEYTYPE_EC:
  162. + {
  163. + if (req->ec_group_name == NID_undef) {
  164. + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing configuration value: 'ec_group_name' not set");
  165. + return NULL;
  166. + }
  167. + EC_KEY *eckey = EC_KEY_new_by_curve_name(req->ec_group_name);
  168. + if (eckey) {
  169. + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
  170. + if (EC_KEY_generate_key(eckey) &&
  171. + EVP_PKEY_assign_EC_KEY(req->priv_key, eckey)) {
  172. + return_val = req->priv_key;
  173. + } else {
  174. + EC_KEY_free(eckey);
  175. + }
  176. + }
  177. + }
  178. + break;
  179. +#endif
  180. default:
  181. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unsupported private key type");
  182. }
  183. @@ -2898,6 +2945,14 @@
  184. }
  185. break;
  186. #endif
  187. +#ifdef EVP_PKEY_EC
  188. + case EVP_PKEY_EC:
  189. + assert(pkey->pkey.ec != NULL);
  190. + if (EC_KEY_get0_private_key(pkey->pkey.ec) == NULL) {
  191. + return 0;
  192. + }
  193. + break;
  194. +#endif
  195. default:
  196. php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!");
  197. break;
  198. @@ -3015,6 +3070,56 @@
  199. }
  200. RETURN_FALSE;
  201. }
  202. +#ifdef EVP_PKEY_EC
  203. + else if (zend_hash_find(Z_ARRVAL_P(args), "ec", sizeof("ec"), (void**)&data) == SUCCESS &&
  204. + Z_TYPE_PP(data) == IS_ARRAY) {
  205. + pkey = EVP_PKEY_new();
  206. + if (pkey) {
  207. + EC_KEY *eckey = EC_KEY_new();
  208. + if (eckey) {
  209. + EC_GROUP *group = NULL;
  210. + zval **bn;
  211. +
  212. + if (zend_hash_find(Z_ARRVAL_PP(data), "group_name", sizeof("group_name"), (void**)&bn) == SUCCESS &&
  213. + Z_TYPE_PP(bn) == IS_STRING) {
  214. + int name = OBJ_sn2nid(Z_STRVAL_PP(bn));
  215. + if (name != NID_undef) {
  216. + group = EC_GROUP_new_by_curve_name(name);
  217. + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
  218. + EC_KEY_set_group(eckey, group);
  219. + }
  220. + }
  221. +
  222. + if (zend_hash_find(Z_ARRVAL_PP(data), "priv_key", sizeof("priv_key"), (void**)&bn) == SUCCESS &&
  223. + Z_TYPE_PP(bn) == IS_STRING) {
  224. + EC_KEY_set_private_key(eckey, BN_bin2bn((unsigned char*)Z_STRVAL_PP(bn), Z_STRLEN_PP(bn), NULL));
  225. + }
  226. +
  227. + if (zend_hash_find(Z_ARRVAL_PP(data), "pub_key", sizeof("pub_key"), (void**)&bn) == SUCCESS &&
  228. + Z_TYPE_PP(bn) == IS_STRING && group != NULL) {
  229. + EC_POINT *pub_key = EC_POINT_new(group);
  230. + EC_POINT_oct2point(group, pub_key, (unsigned char*)Z_STRVAL_PP(bn), Z_STRLEN_PP(bn), NULL);
  231. + EC_KEY_set_public_key(eckey, pub_key);
  232. + }
  233. +
  234. + /* we don't need that any longer. key holds it's own copy */
  235. + if (group != NULL) {
  236. + EC_GROUP_free(group);
  237. + }
  238. +
  239. + if (!EC_KEY_check_key(eckey)) {
  240. + EC_KEY_generate_key(eckey);
  241. + }
  242. + if (EC_KEY_check_key(eckey) && EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
  243. + RETURN_RESOURCE(zend_list_insert(pkey, le_key));
  244. + }
  245. + EC_KEY_free(eckey);
  246. + }
  247. + EVP_PKEY_free(pkey);
  248. + }
  249. + RETURN_FALSE;
  250. + }
  251. +#endif
  252. }
  253.  
  254. PHP_SSL_REQ_INIT(&req);
  255. @@ -3299,6 +3404,38 @@
  256. #ifdef EVP_PKEY_EC
  257. case EVP_PKEY_EC:
  258. ktype = OPENSSL_KEYTYPE_EC;
  259. + if (pkey->pkey.ec != NULL) {
  260. + zval *ec;
  261. +
  262. + ALLOC_INIT_ZVAL(ec);
  263. + array_init(ec);
  264. +
  265. + const EC_GROUP *group = EC_KEY_get0_group(pkey->pkey.ec);
  266. + int name = (group != NULL) ? EC_GROUP_get_curve_name(group) : 0;
  267. + if (name) {
  268. + add_assoc_string(ec, "group_name", estrdup(OBJ_nid2sn(name)), 0);
  269. + }
  270. +
  271. + const BIGNUM *key = EC_KEY_get0_private_key(pkey->pkey.ec);
  272. + if (key != NULL) {
  273. + int len = BN_num_bytes(key);
  274. + char *str = emalloc(len + 1);
  275. + BN_bn2bin(key, (unsigned char*)str);
  276. + str[len] = 0;
  277. + add_assoc_stringl(ec, "priv_key", str, len, 0);
  278. + }
  279. +
  280. + const EC_POINT *pub_key = EC_KEY_get0_public_key(pkey->pkey.ec);
  281. + if (group != NULL && pub_key != NULL) {
  282. + int len = EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
  283. + char *str = emalloc(len + 1);
  284. + EC_POINT_point2oct(group, pub_key, POINT_CONVERSION_UNCOMPRESSED, str, len, NULL);
  285. + str[len] = 0;
  286. + add_assoc_stringl(ec, "pub_key", str, len, 0);
  287. + }
  288. +
  289. + add_assoc_zval(return_value, "ec", ec);
  290. + }
  291. break;
  292. #endif
  293. default:
  294. @@ -4609,6 +4746,34 @@
  295. }
  296. /* }}} */
  297.  
  298. +/* {{{ proto array openssl_get_curve_names([bool aliases = false])
  299. + Return array of available elliptic curves */
  300. +#ifdef EVP_PKEY_EC
  301. +PHP_FUNCTION(openssl_get_curve_names)
  302. +{
  303. + EC_builtin_curve *curves = NULL;
  304. + const char *sname;
  305. + int i;
  306. +
  307. + array_init(return_value);
  308. + size_t len = EC_get_builtin_curves(NULL, 0);
  309. + curves = emalloc((int)(sizeof(EC_builtin_curve) * len));
  310. + if (!EC_get_builtin_curves(curves, len)) {
  311. + return;
  312. + }
  313. +
  314. + for(i = 0; i < len; i++)
  315. + {
  316. + sname = OBJ_nid2sn(curves[i].nid);
  317. + if (sname == NULL)
  318. + continue;
  319. + add_next_index_string(return_value, sname, 1);
  320. + }
  321. + efree(curves);
  322. +}
  323. +#endif
  324. +/* }}} */
  325. +
  326. /* {{{ proto string openssl_digest(string data, string method [, bool raw_output=false])
  327. Computes digest hash value for given data using given method, returns raw or binhex encoded string */
  328. PHP_FUNCTION(openssl_digest)
  329.