Skip to content

Commit e795675

Browse files
committed
Adds better handling of EC keys: OPENSSL_KEYTYPE_EC
When working with elliptic curve and openssl some functions are not aware of the different handling. Improvements: - Fixes export of EC private keys - Adds curve information to openssl_pkey_get_details
1 parent 01893e3 commit e795675

1 file changed

Lines changed: 64 additions & 2 deletions

File tree

ext/openssl/openssl.c

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,6 +3595,7 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
35953595
char * filename = NULL;
35963596
size_t filename_len = 0;
35973597
zend_resource *key_resource = NULL;
3598+
int pem_write = 0;
35983599
EVP_PKEY * key;
35993600
BIO * bio_out = NULL;
36003601
const EVP_CIPHER * cipher;
@@ -3629,7 +3630,19 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
36293630
} else {
36303631
cipher = NULL;
36313632
}
3632-
if (PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL)) {
3633+
3634+
switch (EVP_PKEY_type(key->type)) {
3635+
#ifdef HAVE_EVP_PKEY_EC
3636+
case EVP_PKEY_EC:
3637+
pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
3638+
break;
3639+
#endif
3640+
default:
3641+
pem_write = PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
3642+
break;
3643+
}
3644+
3645+
if (pem_write) {
36333646
/* Success!
36343647
* If returning the output as a string, do so now */
36353648
RETVAL_TRUE;
@@ -3653,6 +3666,7 @@ PHP_FUNCTION(openssl_pkey_export)
36533666
struct php_x509_request req;
36543667
zval * zpkey, * args = NULL, *out;
36553668
char * passphrase = NULL; size_t passphrase_len = 0;
3669+
int pem_write = 0;
36563670
zend_resource *key_resource = NULL;
36573671
EVP_PKEY * key;
36583672
BIO * bio_out = NULL;
@@ -3684,7 +3698,19 @@ PHP_FUNCTION(openssl_pkey_export)
36843698
} else {
36853699
cipher = NULL;
36863700
}
3687-
if (PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL)) {
3701+
3702+
switch (EVP_PKEY_type(key->type)) {
3703+
#ifdef HAVE_EVP_PKEY_EC
3704+
case EVP_PKEY_EC:
3705+
pem_write = PEM_write_bio_ECPrivateKey(bio_out, EVP_PKEY_get1_EC_KEY(key), cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
3706+
break;
3707+
#endif
3708+
default:
3709+
pem_write = PEM_write_bio_PrivateKey(bio_out, key, cipher, (unsigned char *)passphrase, passphrase_len, NULL, NULL);
3710+
break;
3711+
}
3712+
3713+
if (pem_write) {
36883714
/* Success!
36893715
* If returning the output as a string, do so now */
36903716

@@ -3853,6 +3879,42 @@ PHP_FUNCTION(openssl_pkey_get_details)
38533879
#ifdef HAVE_EVP_PKEY_EC
38543880
case EVP_PKEY_EC:
38553881
ktype = OPENSSL_KEYTYPE_EC;
3882+
if (pkey->pkey.ec == NULL) {
3883+
break;
3884+
}
3885+
3886+
zval ec;
3887+
const EC_GROUP *ec_group;
3888+
int nid;
3889+
char *crv_sn;
3890+
ASN1_OBJECT *obj;
3891+
// openssl recommends a buffer length of 80
3892+
char oir_buf[80];
3893+
3894+
ec_group = EC_KEY_get0_group(EVP_PKEY_get1_EC_KEY(pkey));
3895+
3896+
// Curve nid (numerical identifier) used for ASN1 mapping
3897+
nid = EC_GROUP_get_curve_name(ec_group);
3898+
if (nid == NID_undef) {
3899+
break;
3900+
}
3901+
3902+
array_init(&ec);
3903+
3904+
// Short object name
3905+
crv_sn = (char*) OBJ_nid2sn(nid);
3906+
if (crv_sn != NULL) {
3907+
add_assoc_string(&ec, "curve_name", crv_sn);
3908+
}
3909+
3910+
obj = OBJ_nid2obj(nid);
3911+
if (obj != NULL) {
3912+
int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
3913+
add_assoc_stringl(&ec, "curve_oid", (char*)oir_buf, oir_len);
3914+
ASN1_OBJECT_free(obj);
3915+
}
3916+
3917+
add_assoc_zval(return_value, "ec", &ec);
38563918
break;
38573919
#endif
38583920
default:

0 commit comments

Comments
 (0)