Skip to content

Commit 14d7c7e

Browse files
committed
Extract EC key initialization
1 parent c90c9c7 commit 14d7c7e

File tree

1 file changed

+126
-113
lines changed

1 file changed

+126
-113
lines changed

ext/openssl/openssl.c

Lines changed: 126 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -4135,6 +4135,126 @@ static EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private)
41354135
#endif
41364136
}
41374137

4138+
#ifdef HAVE_EVP_PKEY_EC
4139+
static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_private) {
4140+
EC_GROUP *group = NULL;
4141+
EC_POINT *pnt = NULL;
4142+
BIGNUM *d = NULL;
4143+
zval *bn;
4144+
zval *x;
4145+
zval *y;
4146+
4147+
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL &&
4148+
Z_TYPE_P(bn) == IS_STRING) {
4149+
int nid = OBJ_sn2nid(Z_STRVAL_P(bn));
4150+
if (nid != NID_undef) {
4151+
group = EC_GROUP_new_by_curve_name(nid);
4152+
if (!group) {
4153+
php_openssl_store_errors();
4154+
goto clean_exit;
4155+
}
4156+
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
4157+
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
4158+
if (!EC_KEY_set_group(eckey, group)) {
4159+
php_openssl_store_errors();
4160+
goto clean_exit;
4161+
}
4162+
}
4163+
}
4164+
4165+
if (group == NULL) {
4166+
php_error_docref(NULL, E_WARNING, "Unknown curve name");
4167+
goto clean_exit;
4168+
}
4169+
4170+
// The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y'
4171+
*is_private = false;
4172+
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL &&
4173+
Z_TYPE_P(bn) == IS_STRING) {
4174+
*is_private = true;
4175+
d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL);
4176+
if (!EC_KEY_set_private_key(eckey, d)) {
4177+
php_openssl_store_errors();
4178+
goto clean_exit;
4179+
}
4180+
// Calculate the public key by multiplying the Point Q with the public key
4181+
// P = d * Q
4182+
pnt = EC_POINT_new(group);
4183+
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
4184+
php_openssl_store_errors();
4185+
goto clean_exit;
4186+
}
4187+
4188+
BN_free(d);
4189+
} else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL &&
4190+
Z_TYPE_P(x) == IS_STRING &&
4191+
(y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL &&
4192+
Z_TYPE_P(y) == IS_STRING) {
4193+
pnt = EC_POINT_new(group);
4194+
if (pnt == NULL) {
4195+
php_openssl_store_errors();
4196+
goto clean_exit;
4197+
}
4198+
if (!EC_POINT_set_affine_coordinates_GFp(
4199+
group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL),
4200+
BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) {
4201+
php_openssl_store_errors();
4202+
goto clean_exit;
4203+
}
4204+
}
4205+
4206+
if (pnt != NULL) {
4207+
if (!EC_KEY_set_public_key(eckey, pnt)) {
4208+
php_openssl_store_errors();
4209+
goto clean_exit;
4210+
}
4211+
EC_POINT_free(pnt);
4212+
pnt = NULL;
4213+
}
4214+
4215+
if (!EC_KEY_check_key(eckey)) {
4216+
PHP_OPENSSL_RAND_ADD_TIME();
4217+
EC_KEY_generate_key(eckey);
4218+
php_openssl_store_errors();
4219+
}
4220+
if (EC_KEY_check_key(eckey)) {
4221+
return true;
4222+
} else {
4223+
php_openssl_store_errors();
4224+
}
4225+
4226+
clean_exit:
4227+
BN_free(d);
4228+
EC_POINT_free(pnt);
4229+
EC_GROUP_free(group);
4230+
return false;
4231+
}
4232+
4233+
static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) {
4234+
EVP_PKEY *pkey = EVP_PKEY_new();
4235+
if (!pkey) {
4236+
php_openssl_store_errors();
4237+
return NULL;
4238+
}
4239+
4240+
EC_KEY *ec = EC_KEY_new();
4241+
if (!ec) {
4242+
EVP_PKEY_free(pkey);
4243+
return NULL;
4244+
}
4245+
4246+
if (!php_openssl_pkey_init_legacy_ec(ec, data, is_private)
4247+
|| !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
4248+
php_openssl_store_errors();
4249+
EVP_PKEY_free(pkey);
4250+
EC_KEY_free(ec);
4251+
return NULL;
4252+
}
4253+
4254+
return pkey;
4255+
}
4256+
#endif
4257+
41384258
/* {{{ Generates a new private key */
41394259
PHP_FUNCTION(openssl_pkey_new)
41404260
{
@@ -4190,120 +4310,13 @@ PHP_FUNCTION(openssl_pkey_new)
41904310
#ifdef HAVE_EVP_PKEY_EC
41914311
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ec", sizeof("ec") - 1)) != NULL &&
41924312
Z_TYPE_P(data) == IS_ARRAY) {
4193-
EC_KEY *eckey = NULL;
4194-
EC_GROUP *group = NULL;
4195-
EC_POINT *pnt = NULL;
4196-
BIGNUM *d = NULL;
4197-
pkey = EVP_PKEY_new();
4198-
if (pkey) {
4199-
eckey = EC_KEY_new();
4200-
if (eckey) {
4201-
bool is_private = false;
4202-
EC_GROUP *group = NULL;
4203-
zval *bn;
4204-
zval *x;
4205-
zval *y;
4206-
4207-
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL &&
4208-
Z_TYPE_P(bn) == IS_STRING) {
4209-
int nid = OBJ_sn2nid(Z_STRVAL_P(bn));
4210-
if (nid != NID_undef) {
4211-
group = EC_GROUP_new_by_curve_name(nid);
4212-
if (!group) {
4213-
php_openssl_store_errors();
4214-
goto clean_exit;
4215-
}
4216-
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
4217-
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
4218-
if (!EC_KEY_set_group(eckey, group)) {
4219-
php_openssl_store_errors();
4220-
goto clean_exit;
4221-
}
4222-
}
4223-
}
4224-
4225-
if (group == NULL) {
4226-
php_error_docref(NULL, E_WARNING, "Unknown curve name");
4227-
goto clean_exit;
4228-
}
4229-
4230-
// The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y'
4231-
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL &&
4232-
Z_TYPE_P(bn) == IS_STRING) {
4233-
is_private = true;
4234-
d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL);
4235-
if (!EC_KEY_set_private_key(eckey, d)) {
4236-
php_openssl_store_errors();
4237-
goto clean_exit;
4238-
}
4239-
// Calculate the public key by multiplying the Point Q with the public key
4240-
// P = d * Q
4241-
pnt = EC_POINT_new(group);
4242-
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
4243-
php_openssl_store_errors();
4244-
goto clean_exit;
4245-
}
4246-
4247-
BN_free(d);
4248-
} else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL &&
4249-
Z_TYPE_P(x) == IS_STRING &&
4250-
(y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL &&
4251-
Z_TYPE_P(y) == IS_STRING) {
4252-
pnt = EC_POINT_new(group);
4253-
if (pnt == NULL) {
4254-
php_openssl_store_errors();
4255-
goto clean_exit;
4256-
}
4257-
if (!EC_POINT_set_affine_coordinates_GFp(
4258-
group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL),
4259-
BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) {
4260-
php_openssl_store_errors();
4261-
goto clean_exit;
4262-
}
4263-
}
4264-
4265-
if (pnt != NULL) {
4266-
if (!EC_KEY_set_public_key(eckey, pnt)) {
4267-
php_openssl_store_errors();
4268-
goto clean_exit;
4269-
}
4270-
EC_POINT_free(pnt);
4271-
pnt = NULL;
4272-
}
4273-
4274-
if (!EC_KEY_check_key(eckey)) {
4275-
PHP_OPENSSL_RAND_ADD_TIME();
4276-
EC_KEY_generate_key(eckey);
4277-
php_openssl_store_errors();
4278-
}
4279-
if (EC_KEY_check_key(eckey) && EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
4280-
EC_GROUP_free(group);
4281-
php_openssl_pkey_object_init(return_value, pkey, is_private);
4282-
return;
4283-
} else {
4284-
php_openssl_store_errors();
4285-
}
4286-
} else {
4287-
php_openssl_store_errors();
4288-
}
4289-
} else {
4290-
php_openssl_store_errors();
4291-
}
4292-
clean_exit:
4293-
if (d != NULL) {
4294-
BN_free(d);
4295-
}
4296-
if (pnt != NULL) {
4297-
EC_POINT_free(pnt);
4298-
}
4299-
if (group != NULL) {
4300-
EC_GROUP_free(group);
4301-
}
4302-
if (eckey != NULL) {
4303-
EC_KEY_free(eckey);
4313+
bool is_private;
4314+
pkey = php_openssl_pkey_init_ec(data, &is_private);
4315+
if (!pkey) {
4316+
RETURN_FALSE;
43044317
}
4305-
EVP_PKEY_free(pkey);
4306-
RETURN_FALSE;
4318+
php_openssl_pkey_object_init(return_value, pkey, is_private);
4319+
return;
43074320
#endif
43084321
}
43094322
}

0 commit comments

Comments
 (0)