summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2014-11-30 18:18:30 -0800
committerStanislav Malyshev <stas@php.net>2014-11-30 18:24:23 -0800
commit8c08124c0ea18bc45c1b64a33953029c2c91d658 (patch)
tree645cb4f96f8f1f88e3ce87d67b9c0bf54033f5c9 /ext
parentaae5d4d9db27a11f9118546fa16c57132704b889 (diff)
parent6048ac32b4e8fc5dacb89af7e4408e3116609317 (diff)
downloadphp-git-8c08124c0ea18bc45c1b64a33953029c2c91d658.tar.gz
Merge branch 'PHP-5.5' into PHP-5.6
* PHP-5.5: Adds test cases for openssl EC improvements Adds better handling of EC keys: OPENSSL_KEYTYPE_EC
Diffstat (limited to 'ext')
-rwxr-xr-xext/openssl/openssl.c73
-rw-r--r--ext/openssl/tests/027.phpt52
-rw-r--r--ext/openssl/tests/028.phpt28
-rw-r--r--ext/openssl/tests/private_ec.key5
-rw-r--r--ext/openssl/tests/public_ec.key4
5 files changed, 157 insertions, 5 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 686fadeace..00fd444c13 100755
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -3618,9 +3618,12 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
{
struct php_x509_request req;
zval ** zpkey, * args = NULL;
- char * passphrase = NULL; int passphrase_len = 0;
- char * filename = NULL; int filename_len = 0;
+ char * passphrase = NULL;
+ int passphrase_len = 0;
+ char * filename = NULL;
+ int filename_len = 0;
long key_resource = -1;
+ int pem_write = 0;
EVP_PKEY * key;
BIO * bio_out = NULL;
const EVP_CIPHER * cipher;
@@ -3655,7 +3658,19 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
} else {
cipher = NULL;
}
- if (PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL)) {
+
+ switch (EVP_PKEY_type(key->type)) {
+#ifdef HAVE_EVP_PKEY_EC
+ case EVP_PKEY_EC:
+ pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
+ break;
+#endif
+ default:
+ pem_write = PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
+ break;
+ }
+
+ if (pem_write) {
/* Success!
* If returning the output as a string, do so now */
RETVAL_TRUE;
@@ -3678,8 +3693,10 @@ PHP_FUNCTION(openssl_pkey_export)
{
struct php_x509_request req;
zval ** zpkey, * args = NULL, *out;
- char * passphrase = NULL; int passphrase_len = 0;
+ char * passphrase = NULL;
+ int passphrase_len = 0;
long key_resource = -1;
+ int pem_write = 0;
EVP_PKEY * key;
BIO * bio_out = NULL;
const EVP_CIPHER * cipher;
@@ -3710,7 +3727,19 @@ PHP_FUNCTION(openssl_pkey_export)
} else {
cipher = NULL;
}
- if (PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL)) {
+
+ switch (EVP_PKEY_type(key->type)) {
+#ifdef HAVE_EVP_PKEY_EC
+ case EVP_PKEY_EC:
+ pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
+ break;
+#endif
+ default:
+ pem_write = PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
+ break;
+ }
+
+ if (pem_write) {
/* Success!
* If returning the output as a string, do so now */
@@ -3881,6 +3910,40 @@ PHP_FUNCTION(openssl_pkey_get_details)
#ifdef HAVE_EVP_PKEY_EC
case EVP_PKEY_EC:
ktype = OPENSSL_KEYTYPE_EC;
+ if (pkey->pkey.ec != NULL) {
+ zval *ec;
+ const EC_GROUP *ec_group;
+ int nid;
+ char *crv_sn;
+ ASN1_OBJECT *obj;
+ // openssl recommends a buffer length of 80
+ char oir_buf[80];
+
+ ec_group = EC_KEY_get0_group(EVP_PKEY_get1_EC_KEY(pkey));
+
+ // Curve nid (numerical identifier) used for ASN1 mapping
+ nid = EC_GROUP_get_curve_name(ec_group);
+ if (nid == NID_undef) {
+ break;
+ }
+ ALLOC_INIT_ZVAL(ec);
+ array_init(ec);
+
+ // Short object name
+ crv_sn = (char*) OBJ_nid2sn(nid);
+ if (crv_sn != NULL) {
+ add_assoc_string(ec, "curve_name", crv_sn, 1);
+ }
+
+ obj = OBJ_nid2obj(nid);
+ if (obj != NULL) {
+ int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
+ add_assoc_stringl(ec, "curve_oid", (char*)oir_buf, oir_len, 1);
+ ASN1_OBJECT_free(obj);
+ }
+
+ add_assoc_zval(return_value, "ec", ec);
+ }
break;
#endif
default:
diff --git a/ext/openssl/tests/027.phpt b/ext/openssl/tests/027.phpt
new file mode 100644
index 0000000000..8311ab1bd9
--- /dev/null
+++ b/ext/openssl/tests/027.phpt
@@ -0,0 +1,52 @@
+--TEST--
+openssl_pkey_export() with EC key
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!defined('OPENSSL_KEYTYPE_EC')) die("skip no EC available");
+?>
+--FILE--
+<?php
+$key = openssl_pkey_get_private('file://' . dirname(__FILE__) . '/private_ec.key');
+var_dump($key);
+
+var_dump(openssl_pkey_export($key, $output));
+echo $output;
+
+// Load the private key from the exported pem string
+$details = openssl_pkey_get_details(openssl_pkey_get_private($output));
+var_dump(OPENSSL_KEYTYPE_EC === $details['type']);
+
+// Export key with passphrase
+openssl_pkey_export($key, $output, 'passphrase');
+
+$details = openssl_pkey_get_details(openssl_pkey_get_private($output, 'passphrase'));
+var_dump(OPENSSL_KEYTYPE_EC === $details['type']);
+
+// Read public key
+$pKey = openssl_pkey_get_public('file://' . dirname(__FILE__) . '/public_ec.key');
+var_dump($pKey);
+// The details are the same for a public or private key
+var_dump($details === openssl_pkey_get_details($pKey));
+
+
+// Export to file
+$tempname = tempnam(sys_get_temp_dir(), 'openssl_ec');
+var_dump(openssl_pkey_export_to_file($key, $tempname));
+$details = openssl_pkey_get_details(openssl_pkey_get_private('file://' . $tempname));
+var_dump(OPENSSL_KEYTYPE_EC === $details['type']);
+
+// Clean the temporary file
+@unlink($tempname);
+
+?>
+--EXPECTF--
+resource(%d) of type (OpenSSL key)
+bool(true)
+-----BEGIN EC PRIVATE KEY-----%a-----END EC PRIVATE KEY-----
+bool(true)
+bool(true)
+resource(%d) of type (OpenSSL key)
+bool(true)
+bool(true)
+bool(true)
diff --git a/ext/openssl/tests/028.phpt b/ext/openssl/tests/028.phpt
new file mode 100644
index 0000000000..8e0cef46c0
--- /dev/null
+++ b/ext/openssl/tests/028.phpt
@@ -0,0 +1,28 @@
+--TEST--
+openssl_pkey_get_details() with EC key
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!defined('OPENSSL_KEYTYPE_EC')) die("skip no EC available");
+?>
+--FILE--
+<?php
+$key = openssl_pkey_get_private('file://' . dirname(__FILE__) . '/private_ec.key');
+
+print_r(openssl_pkey_get_details($key));
+?>
+--EXPECTF--
+Array
+(
+ [bits] => 256
+ [key] => -----BEGIN PUBLIC KEY-----%a
+-----END PUBLIC KEY-----
+
+ [ec] => Array
+ (
+ [curve_name] => prime256v1
+ [curve_oid] => 1.2.840.10045.3.1.7
+ )
+
+ [type] => 3
+)
diff --git a/ext/openssl/tests/private_ec.key b/ext/openssl/tests/private_ec.key
new file mode 100644
index 0000000000..51cdcb728b
--- /dev/null
+++ b/ext/openssl/tests/private_ec.key
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEILPkqoeyM7XgwYkuSj3077lrsrfWJK5LqMolv+m2oOjZoAoGCCqGSM49
+AwEHoUQDQgAEPq4hbIWHvB51rdWr8ejrjWo4qVNWVugYFtPg/xLQw0mHkIPZ4DvK
+sqOTOnMoezkbSmVVMuwz9flvnqHGmQvmug==
+-----END EC PRIVATE KEY-----
diff --git a/ext/openssl/tests/public_ec.key b/ext/openssl/tests/public_ec.key
new file mode 100644
index 0000000000..a93b2c8ab4
--- /dev/null
+++ b/ext/openssl/tests/public_ec.key
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPq4hbIWHvB51rdWr8ejrjWo4qVNW
+VugYFtPg/xLQw0mHkIPZ4DvKsqOTOnMoezkbSmVVMuwz9flvnqHGmQvmug==
+-----END PUBLIC KEY-----