diff options
Diffstat (limited to 'ext')
-rwxr-xr-x | ext/openssl/openssl.c | 73 | ||||
-rw-r--r-- | ext/openssl/tests/027.phpt | 52 | ||||
-rw-r--r-- | ext/openssl/tests/028.phpt | 28 | ||||
-rw-r--r-- | ext/openssl/tests/private_ec.key | 5 | ||||
-rw-r--r-- | ext/openssl/tests/public_ec.key | 4 |
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----- |