diff --git a/0dadd6616a491418871fb0b41590a73b128aa212.patch b/0dadd6616a491418871fb0b41590a73b128aa212.patch new file mode 100644 index 0000000000000000000000000000000000000000..eac321cd8b28422439d25caa2ca5f283d5cb837f --- /dev/null +++ b/0dadd6616a491418871fb0b41590a73b128aa212.patch @@ -0,0 +1,798 @@ +From 0dadd6616a491418871fb0b41590a73b128aa212 Mon Sep 17 00:00:00 2001 +From: Eno <895183594@qq.com> +Date: Sat, 13 May 2023 01:15:24 +0800 +Subject: [PATCH] Improve openssl ext to generate EC keys with custom EC + parameters + +This change extends supported parameter when generating EC keys. + +Specifically following parameters are now supported: p, a, b, order, +generator, seed, cofactory, g_x, g_y, x, y and d. + +Those parameters can be passed to ec field in openssl_pkey_new options. + +It also fixes some issues openssl_pkey_get_details related to SM2 +support. + +Closes GH-9991 +--- + ext/openssl/openssl.c | 400 ++++++++++++++++------- + ext/openssl/tests/ecc.phpt | 8 +- + ext/openssl/tests/ecc_custom_params.phpt | 113 +++++++ + ext/openssl/tests/ecc_sm2.phpt | 92 ++++++ + 4 files changed, 495 insertions(+), 121 deletions(-) + create mode 100644 ext/openssl/tests/ecc_custom_params.phpt + create mode 100644 ext/openssl/tests/ecc_sm2.phpt + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 4009a5b84df1..33f51bfa4de9 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -97,6 +97,14 @@ + + #if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC) + #define HAVE_EVP_PKEY_EC 1 ++ ++/* the OPENSSL_EC_EXPLICIT_CURVE value was added ++ * in OpenSSL 1.1.0; previous versions should ++ * use 0 instead. ++ */ ++#ifndef OPENSSL_EC_EXPLICIT_CURVE ++#define OPENSSL_EC_EXPLICIT_CURVE 0x000 ++#endif + #endif + + ZEND_DECLARE_MODULE_GLOBALS(openssl) +@@ -4264,158 +4272,290 @@ static EVP_PKEY *php_openssl_pkey_init_dh(zval *data, bool *is_private) + #ifdef HAVE_EVP_PKEY_EC + #if PHP_OPENSSL_API_VERSION < 0x30000 + static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_private) { ++ BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *g_x = NULL, *g_y = NULL , *cofactor = NULL; ++ BIGNUM *x = NULL, *y = NULL, *d = NULL; ++ EC_POINT *point_g = NULL; ++ EC_POINT *point_q = NULL; + EC_GROUP *group = NULL; +- EC_POINT *pnt = NULL; +- BIGNUM *d = NULL; +- zval *bn; +- zval *x; +- zval *y; ++ BN_CTX *bctx = BN_CTX_new(); + + *is_private = false; + +- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL && +- Z_TYPE_P(bn) == IS_STRING) { +- int nid = OBJ_sn2nid(Z_STRVAL_P(bn)); +- if (nid != NID_undef) { +- group = EC_GROUP_new_by_curve_name(nid); +- if (!group) { +- php_openssl_store_errors(); ++ zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1); ++ if (curve_name_zv && Z_TYPE_P(curve_name_zv) == IS_STRING && Z_STRLEN_P(curve_name_zv) > 0) { ++ int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv)); ++ if (nid == NID_undef) { ++ php_error_docref(NULL, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(curve_name_zv)); ++ goto clean_exit; ++ } ++ ++ if (!(group = EC_GROUP_new_by_curve_name(nid))) { ++ goto clean_exit; ++ } ++ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); ++ } else { ++ OPENSSL_PKEY_SET_BN(data, p); ++ OPENSSL_PKEY_SET_BN(data, a); ++ OPENSSL_PKEY_SET_BN(data, b); ++ OPENSSL_PKEY_SET_BN(data, order); ++ ++ if (!(p && a && b && order)) { ++ if (!p && !a && !b && !order) { ++ php_error_docref(NULL, E_WARNING, "Missing params: curve_name"); ++ } else { ++ php_error_docref( ++ NULL, E_WARNING, "Missing params: curve_name or p, a, b, order"); ++ } ++ goto clean_exit; ++ } ++ ++ if (!(group = EC_GROUP_new_curve_GFp(p, a, b, bctx))) { ++ goto clean_exit; ++ } ++ ++ if (!(point_g = EC_POINT_new(group))) { ++ goto clean_exit; ++ } ++ ++ zval *generator_zv = zend_hash_str_find(Z_ARRVAL_P(data), "generator", sizeof("generator") - 1); ++ if (generator_zv && Z_TYPE_P(generator_zv) == IS_STRING && Z_STRLEN_P(generator_zv) > 0) { ++ if (!(EC_POINT_oct2point(group, point_g, (unsigned char *)Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv), bctx))) { + goto clean_exit; + } +- EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); +- EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); +- if (!EC_KEY_set_group(eckey, group)) { +- php_openssl_store_errors(); ++ } else { ++ OPENSSL_PKEY_SET_BN(data, g_x); ++ OPENSSL_PKEY_SET_BN(data, g_y); ++ ++ if (!g_x || !g_y) { ++ php_error_docref( ++ NULL, E_WARNING, "Missing params: generator or g_x and g_y"); ++ goto clean_exit; ++ } ++ ++ if (!EC_POINT_set_affine_coordinates_GFp(group, point_g, g_x, g_y, bctx)) { + goto clean_exit; + } + } ++ ++ zval *seed_zv = zend_hash_str_find(Z_ARRVAL_P(data), "seed", sizeof("seed") - 1); ++ if (seed_zv && Z_TYPE_P(seed_zv) == IS_STRING && Z_STRLEN_P(seed_zv) > 0) { ++ if (!EC_GROUP_set_seed(group, (unsigned char *)Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv))) { ++ goto clean_exit; ++ } ++ } ++ ++ /* ++ * OpenSSL uses 0 cofactor as a marker for "unknown cofactor". ++ * So accept cofactor == NULL or cofactor >= 0. ++ * Internally, the lib will check the cofactor value. ++ */ ++ OPENSSL_PKEY_SET_BN(data, cofactor); ++ if (!EC_GROUP_set_generator(group, point_g, order, cofactor)) { ++ goto clean_exit; ++ } ++ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE); + } + +- if (group == NULL) { +- php_error_docref(NULL, E_WARNING, "Unknown curve name"); ++ EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); ++ ++ if (!EC_KEY_set_group(eckey, group)) { + goto clean_exit; + } + +- // The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y' +- if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL && +- Z_TYPE_P(bn) == IS_STRING) { ++ OPENSSL_PKEY_SET_BN(data, d); ++ OPENSSL_PKEY_SET_BN(data, x); ++ OPENSSL_PKEY_SET_BN(data, y); ++ ++ if (d) { + *is_private = true; +- d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL); + if (!EC_KEY_set_private_key(eckey, d)) { +- php_openssl_store_errors(); +- goto clean_exit; +- } +- // Calculate the public key by multiplying the Point Q with the public key +- // P = d * Q +- pnt = EC_POINT_new(group); +- if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) { +- php_openssl_store_errors(); + goto clean_exit; + } + +- BN_free(d); +- } else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL && +- Z_TYPE_P(x) == IS_STRING && +- (y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL && +- Z_TYPE_P(y) == IS_STRING) { +- pnt = EC_POINT_new(group); +- if (pnt == NULL) { +- php_openssl_store_errors(); ++ point_q = EC_POINT_new(group); ++ if (!point_q || !EC_POINT_mul(group, point_q, d, NULL, NULL, bctx)) { + goto clean_exit; + } +- if (!EC_POINT_set_affine_coordinates_GFp( +- group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL), +- BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) { +- php_openssl_store_errors(); ++ } else if (x && y) { ++ /* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */ ++ point_q = EC_POINT_new(group); ++ if (!point_q || !EC_POINT_set_affine_coordinates_GFp(group, point_q, x, y, bctx)) { + goto clean_exit; + } + } + +- if (pnt != NULL) { +- if (!EC_KEY_set_public_key(eckey, pnt)) { +- php_openssl_store_errors(); ++ if (point_q != NULL) { ++ if (!EC_KEY_set_public_key(eckey, point_q)) { + goto clean_exit; + } +- EC_POINT_free(pnt); +- pnt = NULL; + } + + if (!EC_KEY_check_key(eckey)) { + *is_private = true; + PHP_OPENSSL_RAND_ADD_TIME(); + EC_KEY_generate_key(eckey); +- php_openssl_store_errors(); +- } +- if (EC_KEY_check_key(eckey)) { +- EC_GROUP_free(group); +- return true; +- } else { +- php_openssl_store_errors(); + } + + clean_exit: +- BN_free(d); +- EC_POINT_free(pnt); ++ php_openssl_store_errors(); ++ BN_CTX_free(bctx); + EC_GROUP_free(group); +- return false; ++ EC_POINT_free(point_g); ++ EC_POINT_free(point_q); ++ BN_free(p); ++ BN_free(a); ++ BN_free(b); ++ BN_free(order); ++ BN_free(g_x); ++ BN_free(g_y); ++ BN_free(cofactor); ++ BN_free(d); ++ BN_free(x); ++ BN_free(y); ++ return EC_KEY_check_key(eckey); + } + #endif + + static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { + #if PHP_OPENSSL_API_VERSION >= 0x30000 +- BIGNUM *d = NULL, *x = NULL, *y = NULL; ++ int nid = NID_undef; ++ BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *g_x = NULL, *g_y = NULL, *cofactor = NULL; ++ BIGNUM *x = NULL, *y = NULL, *d = NULL; ++ EC_POINT *point_g = NULL; ++ EC_POINT *point_q = NULL; ++ unsigned char *point_g_buf = NULL; ++ unsigned char *point_q_buf = NULL; + EC_GROUP *group = NULL; +- EC_POINT *pnt = NULL; +- unsigned char *pnt_oct = NULL; + EVP_PKEY *param_key = NULL, *pkey = NULL; + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); ++ BN_CTX *bctx = BN_CTX_new(); + OSSL_PARAM *params = NULL; + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); +- zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1); +- +- OPENSSL_PKEY_SET_BN(data, d); +- OPENSSL_PKEY_SET_BN(data, x); +- OPENSSL_PKEY_SET_BN(data, y); + + *is_private = false; + +- if (!ctx || !bld || !curve_name_zv || Z_TYPE_P(curve_name_zv) != IS_STRING) { +- goto cleanup; +- } ++ zval *curve_name_zv = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1); ++ if (curve_name_zv && Z_TYPE_P(curve_name_zv) == IS_STRING && Z_STRLEN_P(curve_name_zv) > 0) { ++ nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv)); ++ if (nid == NID_undef) { ++ php_error_docref(NULL, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(curve_name_zv)); ++ goto cleanup; ++ } + +- int nid = OBJ_sn2nid(Z_STRVAL_P(curve_name_zv)); +- group = EC_GROUP_new_by_curve_name(nid); +- if (!group) { +- php_error_docref(NULL, E_WARNING, "Unknown curve name"); +- goto cleanup; +- } ++ if (!(group = EC_GROUP_new_by_curve_name(nid))) { ++ goto cleanup; ++ } + +- OSSL_PARAM_BLD_push_utf8_string( +- bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv)); ++ if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME, Z_STRVAL_P(curve_name_zv), Z_STRLEN_P(curve_name_zv))) { ++ goto cleanup; ++ } ++ } else { ++ OPENSSL_PKEY_SET_BN(data, p); ++ OPENSSL_PKEY_SET_BN(data, a); ++ OPENSSL_PKEY_SET_BN(data, b); ++ OPENSSL_PKEY_SET_BN(data, order); ++ ++ if (!(p && a && b && order)) { ++ if (!p && !a && !b && !order) { ++ php_error_docref(NULL, E_WARNING, "Missing params: curve_name"); ++ } else { ++ php_error_docref(NULL, E_WARNING, "Missing params: curve_name or p, a, b, order"); ++ } ++ goto cleanup; ++ } + +- if (d) { +- OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d); ++ if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, p) || ++ !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, a) || ++ !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, b) || ++ !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_ORDER, order) || ++ !OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE, SN_X9_62_prime_field, 0)) { ++ goto cleanup; ++ } + +- pnt = EC_POINT_new(group); +- if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) { ++ if (!(group = EC_GROUP_new_curve_GFp(p, a, b, bctx))) { + goto cleanup; + } +- } else if (x && y) { +- /* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */ +- pnt = EC_POINT_new(group); +- if (!pnt || !EC_POINT_set_affine_coordinates(group, pnt, x, y, NULL)) { ++ ++ if (!(point_g = EC_POINT_new(group))) { + goto cleanup; + } +- } + +- if (pnt) { +- size_t pnt_oct_len = +- EC_POINT_point2buf(group, pnt, POINT_CONVERSION_COMPRESSED, &pnt_oct, NULL); +- if (!pnt_oct_len) { ++ zval *generator_zv = zend_hash_str_find(Z_ARRVAL_P(data), "generator", sizeof("generator") - 1); ++ if (generator_zv && Z_TYPE_P(generator_zv) == IS_STRING && Z_STRLEN_P(generator_zv) > 0) { ++ if (!EC_POINT_oct2point(group, point_g, (unsigned char *)Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv), bctx) || ++ !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR, Z_STRVAL_P(generator_zv), Z_STRLEN_P(generator_zv))) { ++ goto cleanup; ++ } ++ } else { ++ OPENSSL_PKEY_SET_BN(data, g_x); ++ OPENSSL_PKEY_SET_BN(data, g_y); ++ ++ if (!g_x || !g_y) { ++ php_error_docref( ++ NULL, E_WARNING, "Missing params: generator or g_x and g_y"); ++ goto cleanup; ++ } ++ ++ if (!EC_POINT_set_affine_coordinates(group, point_g, g_x, g_y, bctx)) { ++ goto cleanup; ++ } ++ ++ size_t point_g_buf_len = ++ EC_POINT_point2buf(group, point_g, POINT_CONVERSION_COMPRESSED, &point_g_buf, bctx); ++ if (!point_g_buf_len) { ++ goto cleanup; ++ } ++ ++ if (!OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_GENERATOR, point_g_buf, point_g_buf_len)) { ++ goto cleanup; ++ } ++ } ++ ++ zval *seed_zv = zend_hash_str_find(Z_ARRVAL_P(data), "seed", sizeof("seed") - 1); ++ if (seed_zv && Z_TYPE_P(seed_zv) == IS_STRING && Z_STRLEN_P(seed_zv) > 0) { ++ if (!EC_GROUP_set_seed(group, (unsigned char *)Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv)) || ++ !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_EC_SEED, Z_STRVAL_P(seed_zv), Z_STRLEN_P(seed_zv))) { ++ goto cleanup; ++ } ++ } ++ ++ OPENSSL_PKEY_SET_BN(data, cofactor); ++ if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_COFACTOR, cofactor) || ++ !EC_GROUP_set_generator(group, point_g, order, cofactor)) { + goto cleanup; + } + +- OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, pnt_oct, pnt_oct_len); ++ nid = EC_GROUP_check_named_curve(group, 0, bctx); ++ } ++ ++ /* custom params not supported with SM2, SKIP */ ++ if (nid != NID_sm2) { ++ OPENSSL_PKEY_SET_BN(data, d); ++ OPENSSL_PKEY_SET_BN(data, x); ++ OPENSSL_PKEY_SET_BN(data, y); ++ ++ if (d) { ++ point_q = EC_POINT_new(group); ++ if (!point_q || !EC_POINT_mul(group, point_q, d, NULL, NULL, bctx) || ++ !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, d)) { ++ goto cleanup; ++ } ++ } else if (x && y) { ++ /* OpenSSL does not allow setting EC_PUB_X/EC_PUB_Y, so convert to encoded format. */ ++ point_q = EC_POINT_new(group); ++ if (!point_q || !EC_POINT_set_affine_coordinates(group, point_q, x, y, bctx)) { ++ goto cleanup; ++ } ++ } ++ ++ if (point_q) { ++ size_t point_q_buf_len = ++ EC_POINT_point2buf(group, point_q, POINT_CONVERSION_COMPRESSED, &point_q_buf, bctx); ++ if (!point_q_buf_len || ++ !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY, point_q_buf, point_q_buf_len)) { ++ goto cleanup; ++ } ++ } + } + + params = OSSL_PARAM_BLD_to_param(bld); +@@ -4423,21 +4563,25 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { + goto cleanup; + } + +- if (EVP_PKEY_fromdata_init(ctx) <= 0 || ++ if (d || (x && y)) { ++ if (EVP_PKEY_fromdata_init(ctx) <= 0 || + EVP_PKEY_fromdata(ctx, ¶m_key, EVP_PKEY_KEYPAIR, params) <= 0) { +- goto cleanup; ++ goto cleanup; ++ } ++ EVP_PKEY_CTX_free(ctx); ++ ctx = EVP_PKEY_CTX_new(param_key, NULL); + } +- +- EVP_PKEY_CTX_free(ctx); +- ctx = EVP_PKEY_CTX_new(param_key, NULL); +- if (EVP_PKEY_check(ctx)) { ++ ++ if (EVP_PKEY_check(ctx) || EVP_PKEY_public_check_quick(ctx)) { + *is_private = d != NULL; + EVP_PKEY_up_ref(param_key); + pkey = param_key; + } else { + *is_private = true; + PHP_OPENSSL_RAND_ADD_TIME(); +- if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &pkey) <= 0) { ++ if (EVP_PKEY_keygen_init(ctx) != 1 || ++ EVP_PKEY_CTX_set_params(ctx, params) != 1 || ++ EVP_PKEY_generate(ctx, &pkey) != 1) { + goto cleanup; + } + } +@@ -4446,11 +4590,21 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { + php_openssl_store_errors(); + EVP_PKEY_free(param_key); + EVP_PKEY_CTX_free(ctx); ++ BN_CTX_free(bctx); + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); +- EC_POINT_free(pnt); + EC_GROUP_free(group); +- OPENSSL_free(pnt_oct); ++ EC_POINT_free(point_g); ++ EC_POINT_free(point_q); ++ OPENSSL_free(point_g_buf); ++ OPENSSL_free(point_q_buf); ++ BN_free(p); ++ BN_free(a); ++ BN_free(b); ++ BN_free(order); ++ BN_free(g_x); ++ BN_free(g_y); ++ BN_free(cofactor); + BN_free(d); + BN_free(x); + BN_free(y); +@@ -4796,7 +4950,21 @@ PHP_FUNCTION(openssl_pkey_get_details) + */ + #if PHP_OPENSSL_API_VERSION >= 0x30000 + zval ary; +- switch (EVP_PKEY_base_id(pkey)) { ++ int base_id = 0; ++ ++ if (EVP_PKEY_id(pkey) != EVP_PKEY_KEYMGMT) { ++ base_id = EVP_PKEY_base_id(pkey); ++ } else { ++ const char *type_name = EVP_PKEY_get0_type_name(pkey); ++ if (type_name) { ++ int nid = OBJ_txt2nid(type_name); ++ if (nid != NID_undef) { ++ base_id = EVP_PKEY_type(nid); ++ } ++ } ++ } ++ ++ switch (base_id) { + case EVP_PKEY_RSA: + ktype = OPENSSL_KEYTYPE_RSA; + array_init(&ary); +@@ -4859,7 +5027,9 @@ PHP_FUNCTION(openssl_pkey_get_details) + break; + } + #endif +- EMPTY_SWITCH_DEFAULT_CASE(); ++ default: ++ ktype = -1; ++ break; + } + #else + switch (EVP_PKEY_base_id(pkey)) { +@@ -4955,24 +5125,22 @@ PHP_FUNCTION(openssl_pkey_get_details) + + ec_group = EC_KEY_get0_group(ec_key); + +- // Curve nid (numerical identifier) used for ASN1 mapping +- nid = EC_GROUP_get_curve_name(ec_group); +- if (nid == NID_undef) { +- break; +- } + array_init(&ec); + +- // Short object name +- crv_sn = (char*) OBJ_nid2sn(nid); +- if (crv_sn != NULL) { +- add_assoc_string(&ec, "curve_name", crv_sn); +- } ++ /** Curve nid (numerical identifier) used for ASN1 mapping */ ++ nid = EC_GROUP_get_curve_name(ec_group); ++ if (nid != NID_undef) { ++ crv_sn = (char*) OBJ_nid2sn(nid); ++ if (crv_sn != NULL) { ++ add_assoc_string(&ec, "curve_name", crv_sn); ++ } + +- 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); +- ASN1_OBJECT_free(obj); ++ 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); ++ ASN1_OBJECT_free(obj); ++ } + } + + pub = EC_KEY_get0_public_key(ec_key); +diff --git a/ext/openssl/tests/ecc.phpt b/ext/openssl/tests/ecc.phpt +index a881d59c9a2b..c5a6f2899898 100644 +--- a/ext/openssl/tests/ecc.phpt ++++ b/ext/openssl/tests/ecc.phpt +@@ -74,7 +74,8 @@ var_dump($csr); + $pubkey1 = openssl_pkey_get_details(openssl_csr_get_public_key($csr)); + var_dump(isset($pubkey1["ec"]["priv_key"])); + unset($d1["ec"]["priv_key"]); +-var_dump(array_diff($d1["ec"], $pubkey1["ec"])); ++$diff = array_diff($d1["ec"], $pubkey1["ec"]); ++var_dump(isset($diff["d"]) && is_string($diff["d"]) && strlen($diff["d"]) > 0); + + $x509 = openssl_csr_sign($csr, null, $key1, 365, $args); + var_dump($x509); +@@ -121,10 +122,7 @@ Testing openssl_csr_new with existing ecc key + object(OpenSSLCertificateSigningRequest)#%d (0) { + } + bool(false) +-array(1) { +- ["d"]=> +- string(%d) "%a" +-} ++bool(true) + object(OpenSSLCertificate)#%d (0) { + } + Testing openssl_x509_check_private_key +diff --git a/ext/openssl/tests/ecc_custom_params.phpt b/ext/openssl/tests/ecc_custom_params.phpt +new file mode 100644 +index 000000000000..0c63af1450ba +--- /dev/null ++++ b/ext/openssl/tests/ecc_custom_params.phpt +@@ -0,0 +1,113 @@ ++--TEST-- ++openssl_*() with OPENSSL_KEYTYPE_EC for ec custom params ++--EXTENSIONS-- ++openssl ++--SKIPIF-- ++ ++--FILE-- ++ array( ++ 'curve_name' => $curve_name, ++ ) ++)); ++ ++var_dump($ec); ++$details = openssl_pkey_get_details($ec); ++$ec_details = $details['ec']; ++var_dump($ec_details['curve_name'] === $curve_name); ++ ++// EC - generate keypair from priv_key "d" with explicit parameters (OSCCA WAPIP192v1 Elliptic curve) ++echo "Testing openssl_pkey_new with ec explicit parameters\n"; ++$d = hex2bin('8D0AC65AAEA0D6B96254C65817D4A143A9E7A03876F1A37D'); ++$x = hex2bin('98E07AAD50C31F9189EBE6B8B5C70E5DEE59D7A8BC344CC6'); ++$y = hex2bin('6109D3D96E52D0867B9D05D72D07BE5876A3D973E0E96792'); ++$p = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D46F4C318CEFE4AFE3B6B8551F'); ++$a = hex2bin('BB8E5E8FBC115E139FE6A814FE48AAA6F0ADA1AA5DF91985'); ++$b = hex2bin('1854BEBDC31B21B7AEFC80AB0ECD10D5B1B3308E6DBF11C1'); ++$g_x = hex2bin('4AD5F7048DE709AD51236DE65E4D4B482C836DC6E4106640'); ++$g_y = hex2bin('02BB3A02D4AAADACAE24817A4CA3A1B014B5270432DB27D2'); ++$order = hex2bin('BDB6F4FE3E8B1D9E0DA8C0D40FC962195DFAE76F56564677'); ++ ++$ec = openssl_pkey_new(array( ++ 'ec'=> array( ++ 'p' => $p, ++ 'a' => $a, ++ 'b' => $b, ++ 'order' => $order, ++ 'g_x' => $g_x, ++ 'g_y' => $g_y, ++ 'd' => $d, ++ ) ++)); ++ ++$details = openssl_pkey_get_details($ec); ++$ec_details = $details['ec']; ++var_dump($ec_details['x'] === $x); ++var_dump($ec_details['y'] === $y); ++var_dump($ec_details['d'] === $d); ++ ++echo "Testing openssl_pkey_new with ec missing params \n"; ++// EC - invalid curve_name ++$ec = openssl_pkey_new(array( ++ 'ec'=> array( ++ 'curve_name' => 'invalid_curve_name', ++ ) ++)); ++var_dump($ec); ++ ++// EC - missing all params ++$ec = openssl_pkey_new(array( ++ 'ec'=> array() ++)); ++var_dump($ec); ++ ++// EC - missing "p" param ++$ec = openssl_pkey_new(array( ++ 'ec'=> array( ++ 'a' => $a, ++ 'b' => $b, ++ 'order' => $order ++ ) ++)); ++var_dump($ec); ++ ++// EC - missing "generator" or "g_x" and "g_y" param ++$ec = openssl_pkey_new(array( ++ 'ec'=> array( ++ 'p' => $p, ++ 'a' => $a, ++ 'b' => $b, ++ 'order' => $order ++ ) ++)); ++var_dump($ec); ++?> ++--EXPECTF-- ++Testing openssl_pkey_new with ec curve_name ++object(OpenSSLAsymmetricKey)#%d (0) { ++} ++bool(true) ++Testing openssl_pkey_new with ec explicit parameters ++bool(true) ++bool(true) ++bool(true) ++Testing openssl_pkey_new with ec missing params ++ ++Warning: openssl_pkey_new(): Unknown elliptic curve (short) name invalid_curve_name in %s on line %d ++bool(false) ++ ++Warning: openssl_pkey_new(): Missing params: curve_name in %s on line %d ++bool(false) ++ ++Warning: openssl_pkey_new(): Missing params: curve_name or p, a, b, order in %s on line %d ++bool(false) ++ ++Warning: openssl_pkey_new(): Missing params: generator or g_x and g_y in %s on line %d ++bool(false) +diff --git a/ext/openssl/tests/ecc_sm2.phpt b/ext/openssl/tests/ecc_sm2.phpt +new file mode 100644 +index 000000000000..11d4c22ae5b2 +--- /dev/null ++++ b/ext/openssl/tests/ecc_sm2.phpt +@@ -0,0 +1,92 @@ ++--TEST-- ++openssl_*() with OPENSSL_KEYTYPE_EC for SM2 ++--EXTENSIONS-- ++openssl ++--SKIPIF-- ++ ++--FILE-- ++ array( ++ 'curve_name' => 'SM2', ++ ) ++)); ++ ++var_dump($ec); ++$details = openssl_pkey_get_details($ec); ++var_dump($details["bits"]); ++var_dump(strlen($details["key"])); ++var_dump($details["ec"]["curve_name"]); ++var_dump($details["type"] == OPENSSL_KEYTYPE_EC); ++ ++// EC - generate SM2 keypair with curve_name ++echo "Testing openssl_pkey_get_public from SM2 pem pubkey\n"; ++$public_key = openssl_pkey_get_public($details["key"]); ++var_dump($public_key); ++$details_public_key = openssl_pkey_get_details($public_key); ++var_dump(strlen($details["key"])); ++var_dump($details_public_key["ec"]["curve_name"]); ++var_dump($details["type"] == OPENSSL_KEYTYPE_EC); ++var_dump($details_public_key["ec"]["x"] === $details["ec"]["x"]); ++var_dump($details_public_key["ec"]["y"] === $details["ec"]["y"]); ++ ++// EC - generate keypair with explicit parameters (SM2 curve) ++echo "Testing openssl_pkey_new with ec explicit parameters (SM2 curve)\n"; ++$p = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF'); ++$a = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC'); ++$b = hex2bin('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93'); ++$g_x = hex2bin('32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'); ++$g_y = hex2bin('BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'); ++$order = hex2bin('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123'); ++ ++$ec = openssl_pkey_new(array( ++ 'ec'=> array( ++ 'p' => $p, ++ 'a' => $a, ++ 'b' => $b, ++ 'order' => $order, ++ 'g_x' => $g_x, ++ 'g_y' => $g_y ++ ) ++)); ++ ++$details = openssl_pkey_get_details($ec); ++var_dump($details['bits']); ++var_dump(strlen($details['key'])); ++var_dump($details['type'] == OPENSSL_KEYTYPE_EC); ++$public_key = openssl_pkey_get_public($details["key"]); ++$details_public_key = openssl_pkey_get_details($public_key); ++var_dump(strlen($details["key"])); ++var_dump($details["type"] == OPENSSL_KEYTYPE_EC); ++var_dump($details_public_key["ec"]["x"] === $details["ec"]["x"]); ++var_dump($details_public_key["ec"]["y"] === $details["ec"]["y"]); ++?> ++--EXPECTF-- ++Testing openssl_pkey_new with ec curve_name SM2 ++object(OpenSSLAsymmetricKey)#%d (0) { ++} ++int(256) ++int(178) ++string(3) "SM2" ++bool(true) ++Testing openssl_pkey_get_public from SM2 pem pubkey ++object(OpenSSLAsymmetricKey)#%d (0) { ++} ++int(178) ++string(3) "SM2" ++bool(true) ++bool(true) ++bool(true) ++Testing openssl_pkey_new with ec explicit parameters (SM2 curve) ++int(256) ++int(475) ++bool(true) ++int(475) ++bool(true) ++bool(true) ++bool(true) diff --git a/php-8.2.8.tar.xz b/php-8.2.10.tar.xz similarity index 59% rename from php-8.2.8.tar.xz rename to php-8.2.10.tar.xz index b1fe53de507e07e487c435fe4b813421d36dc14b..4eb262109e8d92c6797b2e3c3363be7fb391de0d 100644 Binary files a/php-8.2.8.tar.xz and b/php-8.2.10.tar.xz differ diff --git a/php.spec b/php.spec index 87f5b957c1aed08292364f9aebc7e348ec53b17c..568013f75460bbd870b015ea01e0906b59836b1f 100644 --- a/php.spec +++ b/php.spec @@ -1,4 +1,4 @@ -%define anolis_release 2 +%define anolis_release 1 # API/ABI check %global apiver 20220829 @@ -16,6 +16,7 @@ %bcond_with modphp %bcond_with imap %bcond_without lmdb +%bcond_without sodium # we don't want -z defs linker flag %undefine _strict_symbol_defs_build @@ -41,7 +42,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: php -Version: 8.2.8 +Version: 8.2.10 Release: %{anolis_release}%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend @@ -92,6 +93,8 @@ Patch45: php-7.4.0-ldap_r.patch Patch47: php-8.1.0-phpinfo.patch # Upstream fixes (100+) +# openssl enhancements for ec keys (mainly sm2 related), php-8.3 branch +Patch100: https://github.com/php/php-src/commit/0dadd6616a491418871fb0b41590a73b128aa212.patch # Factory is droped from system tzdata Patch300: php-7.4.0-datetests.patch @@ -681,21 +684,22 @@ bytecode optimization patterns that make code execution faster. %prep %setup -q -n php-%{version} -%patch1 -p1 -b .mpmcheck -%patch5 -p1 -b .includedir -%patch6 -p1 -b .embed -%patch8 -p1 -b .libdb +%patch -P 1 -p1 -b .mpmcheck +%patch -P 5 -p1 -b .includedir +%patch -P 6 -p1 -b .embed +%patch -P 8 -p1 -b .libdb -%patch41 -p1 -b .syslib -%patch42 -p1 -b .systzdata -%patch43 -p1 -b .headers -%patch45 -p1 -b .ldap_r -%patch47 -p1 -b .phpinfo +%patch -P 41 -p1 -b .syslib +%patch -P 42 -p1 -b .systzdata +%patch -P 43 -p1 -b .headers +%patch -P 45 -p1 -b .ldap_r +%patch -P 47 -p1 -b .phpinfo # upstream patches +%patch -P 100 -p1 -b .ec_keys # Fixes for tests -%patch300 -p1 -b .datetests +%patch -P 300 -p1 -b .datetests # Prevent %%doc confusion over LICENSE files @@ -1191,8 +1195,8 @@ mv $RPM_BUILD_ROOT%{_sysconfdir}/php-fpm.d/www.conf.default . # install systemd unit files and scripts for handling server startup install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/php-fpm.service.d install -Dm 644 %{SOURCE6} $RPM_BUILD_ROOT%{_unitdir}/php-fpm.service -install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/httpd.service.d/php-fpm.conf -install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_unitdir}/nginx.service.d/php-fpm.conf +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/httpd.service.d/php-fpm.conf +install -Dm 644 %{SOURCE12} $RPM_BUILD_ROOT%{_sysconfdir}/systemd/system/nginx.service.d/php-fpm.conf # LogRotate install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/php-fpm @@ -1429,8 +1433,8 @@ systemctl try-restart php-fpm.service >/dev/null 2>&1 || : %config(noreplace) %{_sysconfdir}/nginx/conf.d/php-fpm.conf %config(noreplace) %{_sysconfdir}/nginx/default.d/php.conf %{_unitdir}/php-fpm.service -%{_unitdir}/httpd.service.d/php-fpm.conf -%{_unitdir}/nginx.service.d/php-fpm.conf +%config(noreplace) %{_sysconfdir}/systemd/system/httpd.service.d/php-fpm.conf +%config(noreplace) %{_sysconfdir}/systemd/system/nginx.service.d/php-fpm.conf %{_sbindir}/php-fpm %dir %{_sysconfdir}/systemd/system/php-fpm.service.d %dir %{_sysconfdir}/php-fpm.d @@ -1507,6 +1511,10 @@ systemctl try-restart php-fpm.service >/dev/null 2>&1 || : %changelog +* Wed Aug 30 2023 Funda Wang - 8.2.10-1 +- New version 8.2.10 +- Backport openssl ext enhancements from 8.3 branch for sm2 + * Mon Aug 28 2023 mgb01105731 - 8.2.8-2 - Rebuild for sodium