diff --git a/0dadd6616a491418871fb0b41590a73b128aa212.patch b/0dadd6616a491418871fb0b41590a73b128aa212.patch deleted file mode 100644 index eac321cd8b28422439d25caa2ca5f283d5cb837f..0000000000000000000000000000000000000000 --- a/0dadd6616a491418871fb0b41590a73b128aa212.patch +++ /dev/null @@ -1,798 +0,0 @@ -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/10-opcache.ini b/10-opcache.ini index b6e6b0b6f1cb3bf859c497634b9b7d0591287c6f..b3d4e6e6ee5cf9c6e96cbf8bb499636a7122d72a 100644 --- a/10-opcache.ini +++ b/10-opcache.ini @@ -67,10 +67,6 @@ opcache.blacklist_filename=/etc/php.d/opcache*.blacklist ; are cached. ;opcache.max_file_size=0 -; Check the cache checksum each N requests. -; The default value of "0" means that the checks are disabled. -;opcache.consistency_checks=0 - ; How long to wait (in seconds) for a scheduled restart to begin if the cache ; is not being accessed. ;opcache.force_restart_timeout=180 diff --git a/macros.php b/macros.php index 4a039aac1ada864a27d81607a825e7100d4247e1..13a84f12118e97bdb3b7e7504d299b337dd6fe5a 100644 --- a/macros.php +++ b/macros.php @@ -18,4 +18,10 @@ %__php %{_bindir}/php %__ztsphp %{_bindir}/zts-php +%__phpize %{_bindir}/phpize +%__ztsphpize %{_bindir}/zts-phpize + +%__phpconfig %{_bindir}/php-config +%__ztsphpconfig %{_bindir}/zts-php-config + %pecl_xmldir %{_sharedstatedir}/php/peclxml diff --git a/php-7.4.0-phpize.patch b/php-7.4.0-phpize.patch index fb99f3e619ac6053bb58922f1d786dc756658aeb..46aff56782a2457b404946d6185a0c2e64485d78 100644 --- a/php-7.4.0-phpize.patch +++ b/php-7.4.0-phpize.patch @@ -1,7 +1,7 @@ diff -up ./scripts/phpize.in.headers ./scripts/phpize.in --- ./scripts/phpize.in.headers 2019-07-23 10:05:11.000000000 +0200 +++ ./scripts/phpize.in 2019-07-23 10:18:13.648098089 +0200 -@@ -165,6 +165,15 @@ phpize_autotools() +@@ -166,6 +166,15 @@ phpize_autotools() $PHP_AUTOHEADER || exit 1 } @@ -17,7 +17,7 @@ diff -up ./scripts/phpize.in.headers ./scripts/phpize.in # Main script case "$1" in -@@ -183,12 +192,15 @@ case "$1" in +@@ -184,12 +193,15 @@ case "$1" in # Version --version|-v) @@ -33,3 +33,33 @@ diff -up ./scripts/phpize.in.headers ./scripts/phpize.in phpize_check_configm4 0 phpize_check_build_files +From c454f120857df6f771c5475bf1fcc99e683b87dc Mon Sep 17 00:00:00 2001 +From: Remi Collet +Date: Thu, 7 Sep 2023 09:56:51 +0200 +Subject: [PATCH] also display PHP version in phpize + +--- + scripts/phpize.in | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/scripts/phpize.in b/scripts/phpize.in +index 7d9c1df14c8e..81605e06a590 100644 +--- a/scripts/phpize.in ++++ b/scripts/phpize.in +@@ -59,6 +59,8 @@ phpize_check_configm4() + phpize_get_api_numbers() + { + # extracting API NOs: ++ PHP_MINOR_VERSION=`grep '#define PHP_MINOR_VERSION' $includedir/main/php_version.h|$SED 's/#define PHP_MINOR_VERSION //'` ++ PHP_MAJOR_VERSION=`grep '#define PHP_MAJOR_VERSION' $includedir/main/php_version.h|$SED 's/#define PHP_MAJOR_VERSION//'` + PHP_API_VERSION=`grep '#define PHP_API_VERSION' $includedir/main/php.h|$SED 's/#define PHP_API_VERSION//'` + ZEND_MODULE_API_NO=`grep '#define ZEND_MODULE_API_NO' $includedir/Zend/zend_modules.h|$SED 's/#define ZEND_MODULE_API_NO//'` + ZEND_EXTENSION_API_NO=`grep '#define ZEND_EXTENSION_API_NO' $includedir/Zend/zend_extensions.h|$SED 's/#define ZEND_EXTENSION_API_NO//'` +@@ -68,6 +70,7 @@ phpize_print_api_numbers() + { + phpize_get_api_numbers + echo "Configuring for:" ++ echo "PHP Version: ${PHP_MAJOR_VERSION}.${PHP_MINOR_VERSION}" + echo "PHP Api Version: "$PHP_API_VERSION + echo "Zend Module Api No: "$ZEND_MODULE_API_NO + echo "Zend Extension Api No: "$ZEND_EXTENSION_API_NO diff --git a/php-8.1.14.tar.xz.asc b/php-8.1.14.tar.xz.asc deleted file mode 100644 index fe9adc436e461c9f67ebb0b8c9e7a34e5d91edcc..0000000000000000000000000000000000000000 --- a/php-8.1.14.tar.xz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEEObZBND2MEEsrFG3D+cOdwLlphUQFAmO1tsIACgkQ+cOdwLlp -hUQV2xAAm9uAMVqbFlD0ZRMSb3+FAiRXTNB8DKEWcolMpxVTRs50lBp8MlKfpg/X -1QtW9KUSQFce6I6lakkbhj3mYJqXPQjkTUHSZhG52gSh8GOPWwEjudjSMyUYmalK -wj2kV1dMsmkNgWxjOv30qmZQq4fgjGl1zTKX1Z8wTK4MOakdZwlAy4+vI+y/kfuh -oGlLqNthc6m8UUH9lasuZleWyX9CZE+S/6PfgUlAhi6Vov7F6gdh9JawqmOAqIve -+TKZ7vGZ/7JV2RYJwUrevgIe+HHaBkOpGmGyI94RULzhQ7q53TP3ihISA77/qwfM -YRGJTXSttADndlVql95FjxM44cT9CBlnqFzRGs95hiR3YUlsooD4mTlJXLxzjhZQ -QoHFCCXRbeMPl77/qWUNU+xw1qNCcZh2sDyBz+2YOSgFZvWUVJPDmouVNDvIEpC1 -r+A5aoEVQUG6yw7cv8JjtJ9x+YJRenDa26PjuwJwU5pIFb/slbQi0tYdEvze0Z7A -DmwWTkFA9eLVSprQ5xH1wphYtytb7yKhFHs311f+3fgYLqDhbq6fBBnx9dZKfwH4 -qlS894zKdFRyb2fcH4uocJUXs9AlLuGwfyoyeQcavI2tTDvGsM1WLTTzKEkEuo+Y -GzXAqAjyb0l1lFrS5x0cZrYLgvmjd7SoPIonn+Uo1HlWiHOwYbU= -=9naU ------END PGP SIGNATURE----- diff --git a/php-8.3.0-openssl-ec-param.patch b/php-8.3.0-openssl-ec-param.patch new file mode 100644 index 0000000000000000000000000000000000000000..94e4037fcec5e9cf821c0ca50ab2d8b82606b4b6 --- /dev/null +++ b/php-8.3.0-openssl-ec-param.patch @@ -0,0 +1,47 @@ +From 21f9d16e130b412b6839494dcf30a2f1d7dcee0f Mon Sep 17 00:00:00 2001 +From: Remi Collet +Date: Mon, 24 Jul 2023 10:54:49 +0200 +Subject: [PATCH] Always warn about missing curve_name + +Both Fedora and RHEL do not support arbitrary EC parameters +See https://bugzilla.redhat.com/2223953 +--- + ext/openssl/openssl.c | 13 ++----------- + 1 file changed, 2 insertions(+), 11 deletions(-) + +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 33f51bfa4d..340b0467d3 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -4299,13 +4299,8 @@ static bool php_openssl_pkey_init_legacy_ec(EC_KEY *eckey, zval *data, bool *is_ + OPENSSL_PKEY_SET_BN(data, b); + OPENSSL_PKEY_SET_BN(data, order); + ++ php_error_docref(NULL, E_WARNING, "Missing params: curve_name (params only is not supported by OpenSSL)"); + 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; + } + +@@ -4455,12 +4450,8 @@ static EVP_PKEY *php_openssl_pkey_init_ec(zval *data, bool *is_private) { + OPENSSL_PKEY_SET_BN(data, b); + OPENSSL_PKEY_SET_BN(data, order); + ++ php_error_docref(NULL, E_WARNING, "Missing params: curve_name"); + 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; + } + +-- +2.41.0 + diff --git a/php-8.1.0-systzdata-v22.patch b/php-8.3.11-systzdata-v24.patch similarity index 90% rename from php-8.1.0-systzdata-v22.patch rename to php-8.3.11-systzdata-v24.patch index b0e07d15cc55089ab29867fe9f4c6ee890f4ba82..90bdc78b0b6f009171dfe6a0c7376ff209dba039 100644 --- a/php-8.1.0-systzdata-v22.patch +++ b/php-8.3.11-systzdata-v24.patch @@ -5,6 +5,8 @@ Add support for use of the system timezone database, rather than embedding a copy. Discussed upstream but was not desired. History: +f24: add internal UTC if tzdata is missing +r23: fix possible buffer overflow r22: retrieve tzdata version from /usr/share/zoneinfo/tzdata.zi r21: adapt for timelib 2021.03 (in 8.1.0) r20: adapt for timelib 2020.03 (in 8.0.10RC1) @@ -33,11 +35,12 @@ r3: fix a crash if /usr/share/zoneinfo doesn't exist (Raphael Geissert) r2: add filesystem trawl to set up name alias index r1: initial revision + diff --git a/ext/date/config0.m4 b/ext/date/config0.m4 -index 18b8106bd2..3d1f63c758 100644 +index 6b803bf33e..53c3cdb3f4 100644 --- a/ext/date/config0.m4 +++ b/ext/date/config0.m4 -@@ -4,6 +4,19 @@ AC_CHECK_HEADERS([io.h]) +@@ -4,6 +4,19 @@ dnl Check for strtoll, atoll AC_CHECK_FUNCS(strtoll atoll) @@ -58,10 +61,10 @@ index 18b8106bd2..3d1f63c758 100644 [PHP_DATE_CFLAGS="$PHP_DATE_CFLAGS -Wno-implicit-fallthrough"],, [-Werror]) diff --git a/ext/date/lib/parse_tz.c b/ext/date/lib/parse_tz.c -index e41315efdb..4b6547c0a3 100644 +index c7f93580d7..ec196a98b6 100644 --- a/ext/date/lib/parse_tz.c +++ b/ext/date/lib/parse_tz.c -@@ -26,9 +26,22 @@ +@@ -26,9 +26,33 @@ #include "timelib.h" #include "timelib_private.h" @@ -74,6 +77,17 @@ index e41315efdb..4b6547c0a3 100644 + +#include "php_scandir.h" + ++static const unsigned char internal_utc[] = { ++ 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x55, 0x54, 0x43, 0x00, 0x54, 0x5a, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, ++ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x54, 0x43, 0x00, 0x0a, 0x55, 0x54, 0x43, ++ 0x30, 0x0a ++}; ++ +#else #define TIMELIB_SUPPORTS_V2DATA #define TIMELIB_SUPPORT_SLIM_FILE @@ -84,7 +98,7 @@ index e41315efdb..4b6547c0a3 100644 #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)) # if defined(__LITTLE_ENDIAN__) -@@ -95,6 +108,11 @@ static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz) +@@ -95,6 +119,11 @@ static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz) { uint32_t version; @@ -96,7 +110,7 @@ index e41315efdb..4b6547c0a3 100644 /* read ID */ version = (*tzf)[3] - '0'; *tzf += 4; -@@ -577,7 +595,467 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz) +@@ -577,7 +606,475 @@ void timelib_dump_tzinfo(timelib_tzinfo *tz) } } @@ -440,6 +454,9 @@ index e41315efdb..4b6547c0a3 100644 + + qsort(db_index, index_next, sizeof *db_index, sysdbcmp); + ++ if (!index_next) { ++ db_index[index_next++].id = strdup("UTC"); ++ } + db->index = db_index; + db->index_size = index_next; + @@ -456,7 +473,7 @@ index e41315efdb..4b6547c0a3 100644 + size_t n; + char *data, *p; + -+ data = malloc(3 * sysdb->index_size + 7); ++ data = malloc(3 * sysdb->index_size + sizeof(FAKE_HEADER) - 1); + + p = mempcpy(data, FAKE_HEADER, sizeof(FAKE_HEADER) - 1); + @@ -546,7 +563,12 @@ index e41315efdb..4b6547c0a3 100644 + + fd = open(fname, O_RDONLY); + if (fd == -1) { -+ return NULL; ++ if (strcmp(timezone, "UTC")) { ++ return NULL; ++ } else { ++ *length = sizeof(internal_utc); ++ return internal_utc; ++ } + } else if (fstat(fd, &st) != 0 || !is_valid_tzfile(&st, fd)) { + close(fd); + return NULL; @@ -565,7 +587,7 @@ index e41315efdb..4b6547c0a3 100644 { int left = 0, right = tzdb->index_size - 1; -@@ -603,9 +1081,49 @@ static int seek_to_tz_position(const unsigned char **tzf, const char *timezone, +@@ -603,9 +1100,49 @@ static int seek_to_tz_position(const unsigned char **tzf, const char *timezone, return 0; } @@ -599,7 +621,7 @@ index e41315efdb..4b6547c0a3 100644 + if (timezonedb_system == NULL) { + timelib_tzdb *tmp = malloc(sizeof *tmp); + -+ tmp->version = "0.system"; ++ tmp->version = "0"; + tmp->data = NULL; + create_zone_index(tmp); + retrieve_zone_version(tmp); @@ -615,7 +637,7 @@ index e41315efdb..4b6547c0a3 100644 } const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count) -@@ -617,7 +1135,30 @@ const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_ +@@ -617,7 +1154,32 @@ const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_ int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb) { const unsigned char *tzf; @@ -629,7 +651,9 @@ index e41315efdb..4b6547c0a3 100644 + if (timezone[0] == '\0' || strstr(timezone, "..") != NULL) { + return 0; + } -+ ++ if (!strcmp(timezone, "UTC")) { ++ return 1; ++ } + if (system_location_table) { + if (find_zone_info(system_location_table, timezone) != NULL) { + /* found in cache */ @@ -647,7 +671,7 @@ index e41315efdb..4b6547c0a3 100644 } static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz) -@@ -662,6 +1203,8 @@ static timelib_tzinfo* timelib_tzinfo_ctor(const char *name) +@@ -662,6 +1224,8 @@ static timelib_tzinfo* timelib_tzinfo_ctor(const char *name) timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code) { const unsigned char *tzf; @@ -656,7 +680,7 @@ index e41315efdb..4b6547c0a3 100644 timelib_tzinfo *tmp; int version; int transitions_result, types_result; -@@ -669,7 +1212,7 @@ timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *t +@@ -669,7 +1233,7 @@ timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *t *error_code = TIMELIB_ERROR_NO_ERROR; @@ -665,7 +689,7 @@ index e41315efdb..4b6547c0a3 100644 tmp = timelib_tzinfo_ctor(timezone); version = read_preamble(&tzf, tmp, &type); -@@ -712,11 +1255,36 @@ timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *t +@@ -712,11 +1276,38 @@ timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *t return NULL; } @@ -688,7 +712,9 @@ index e41315efdb..4b6547c0a3 100644 + } + + /* Now done with the mmap segment - discard it. */ -+ munmap(memmap, maplen); ++ if (memmap != internal_utc) { ++ munmap(memmap, maplen); ++ } + } else { +#endif if (type == TIMELIB_TZINFO_PHP) { @@ -703,10 +729,10 @@ index e41315efdb..4b6547c0a3 100644 *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE; tmp = NULL; diff --git a/ext/date/php_date.c b/ext/date/php_date.c -index cf4a11b8a2..cd49abc78d 100644 +index 48c82bf7ec..443299c089 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c -@@ -457,7 +457,11 @@ PHP_MINFO_FUNCTION(date) +@@ -490,7 +490,11 @@ PHP_MINFO_FUNCTION(date) php_info_print_table_row(2, "date/time support", "enabled"); php_info_print_table_row(2, "timelib version", TIMELIB_ASCII_VERSION); php_info_print_table_row(2, "\"Olson\" Timezone Database Version", tzdb->version); diff --git a/php-8.1.0-phpinfo.patch b/php-8.3.13-phpinfo.patch similarity index 100% rename from php-8.1.0-phpinfo.patch rename to php-8.3.13-phpinfo.patch diff --git a/php-8.2.27.tar.xz b/php-8.3.15.tar.xz similarity index 58% rename from php-8.2.27.tar.xz rename to php-8.3.15.tar.xz index b8635b6958d35cef88129f4ad470bfced23bbf55..bd47ff506be7ba0aa56a7d4b2812736907738088 100644 Binary files a/php-8.2.27.tar.xz and b/php-8.3.15.tar.xz differ diff --git a/php-8.2.0-parser.patch b/php-8.3.3-parser.patch similarity index 71% rename from php-8.2.0-parser.patch rename to php-8.3.3-parser.patch index dcfe617d4e80e35424a6746d1ba9759de207aded..49f7d5e4c50b3461180f71f5a92873c0f91a1f6e 100644 --- a/php-8.2.0-parser.patch +++ b/php-8.3.3-parser.patch @@ -6,11 +6,11 @@ diff -up ./build/gen_stub.php.syslib ./build/gen_stub.php $isInitialized = true; + -+ if (file_exists('/usr/share/php/PhpParser4/autoload.php')) { -+ require_once '/usr/share/php/PhpParser4/autoload.php'; ++ if (file_exists('/usr/share/php/PhpParser5/autoload.php')) { ++ require_once '/usr/share/php/PhpParser5/autoload.php'; + return; + } + - $version = "4.15.1"; + $version = "5.0.0"; $phpParserDir = __DIR__ . "/PHP-Parser-$version"; if (!is_dir($phpParserDir)) { diff --git a/php-8.3.7-argon2.patch b/php-8.3.7-argon2.patch new file mode 100644 index 0000000000000000000000000000000000000000..d6d2766ef2bd90938200122ee1ce90738a51a7f9 --- /dev/null +++ b/php-8.3.7-argon2.patch @@ -0,0 +1,842 @@ +From c6c39b2b1cb1ff9916a8db606b19fc4282feacd2 Mon Sep 17 00:00:00 2001 +From: Remi Collet +Date: Wed, 17 Apr 2024 15:58:49 +0200 +Subject: [PATCH] Implement PASSWORD_ARGON2 from OpenSSL 3.2 Backported from + 8.4 to 8.3 + +--- + ext/openssl/config0.m4 | 2 +- + ext/openssl/openssl.c | 24 + + ext/openssl/openssl_pwhash.c | 412 ++++++++++++++++++ + ext/openssl/openssl_pwhash.stub.php | 38 ++ + ext/openssl/openssl_pwhash_arginfo.h | Bin 0 -> 2571 bytes + ext/openssl/php_openssl.h | 31 +- + ext/openssl/tests/openssl_password.phpt | 42 ++ + .../tests/openssl_password_compat.phpt | 52 +++ + .../tests/openssl_password_compat2.phpt | 52 +++ + 9 files changed, 651 insertions(+), 2 deletions(-) + create mode 100644 ext/openssl/openssl_pwhash.c + create mode 100644 ext/openssl/openssl_pwhash.stub.php + create mode 100644 ext/openssl/openssl_pwhash_arginfo.h + create mode 100644 ext/openssl/tests/openssl_password.phpt + create mode 100644 ext/openssl/tests/openssl_password_compat.phpt + create mode 100644 ext/openssl/tests/openssl_password_compat2.phpt + +diff --git a/ext/openssl/config0.m4 b/ext/openssl/config0.m4 +index ffd4e0751c..aae3812752 100644 +--- a/ext/openssl/config0.m4 ++++ b/ext/openssl/config0.m4 +@@ -18,7 +18,7 @@ PHP_ARG_WITH([system-ciphers], + [no]) + + if test "$PHP_OPENSSL" != "no"; then +- PHP_NEW_EXTENSION(openssl, openssl.c xp_ssl.c, $ext_shared) ++ PHP_NEW_EXTENSION(openssl, openssl.c openssl_pwhash.c xp_ssl.c, $ext_shared) + PHP_SUBST(OPENSSL_SHARED_LIBADD) + + if test "$PHP_KERBEROS" != "no"; then +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index 6f85e9852f..1f164a60b6 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -263,9 +263,21 @@ static void php_openssl_pkey_free_obj(zend_object *object) + zend_object_std_dtor(&key_object->std); + } + ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++static const zend_module_dep openssl_deps[] = { ++ ZEND_MOD_REQUIRED("standard") ++ ZEND_MOD_END ++}; ++#endif ++ + /* {{{ openssl_module_entry */ + zend_module_entry openssl_module_entry = { ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ STANDARD_MODULE_HEADER_EX, NULL, ++ openssl_deps, ++#else + STANDARD_MODULE_HEADER, ++#endif + "openssl", + ext_functions, + PHP_MINIT(openssl), +@@ -1321,6 +1333,12 @@ PHP_MINIT_FUNCTION(openssl) + + REGISTER_INI_ENTRIES(); + ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ if (FAILURE == PHP_MINIT(openssl_pwhash)(INIT_FUNC_ARGS_PASSTHRU)) { ++ return FAILURE; ++ } ++#endif ++ + return SUCCESS; + } + /* }}} */ +@@ -1395,6 +1413,12 @@ PHP_MSHUTDOWN_FUNCTION(openssl) + php_stream_xport_unregister("tlsv1.3"); + #endif + ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ if (FAILURE == PHP_MSHUTDOWN(openssl_pwhash)(SHUTDOWN_FUNC_ARGS_PASSTHRU)) { ++ return FAILURE; ++ } ++#endif ++ + /* reinstate the default tcp handler */ + php_stream_xport_register("tcp", php_stream_generic_socket_factory); + +diff --git a/ext/openssl/openssl_pwhash.c b/ext/openssl/openssl_pwhash.c +new file mode 100644 +index 0000000000..56ab62ff83 +--- /dev/null ++++ b/ext/openssl/openssl_pwhash.c +@@ -0,0 +1,412 @@ ++/* ++ +----------------------------------------------------------------------+ ++ | Copyright (c) The PHP Group | ++ +----------------------------------------------------------------------+ ++ | This source file is subject to version 3.01 of the PHP license, | ++ | that is bundled with this package in the file LICENSE, and is | ++ | available through the world-wide-web at the following url: | ++ | https://www.php.net/license/3_01.txt | ++ | If you did not receive a copy of the PHP license and are unable to | ++ | obtain it through the world-wide-web, please send a note to | ++ | license@php.net so we can mail you a copy immediately. | ++ +----------------------------------------------------------------------+ ++ | Authors: Remi Collet | ++ +----------------------------------------------------------------------+ ++*/ ++ ++#ifdef HAVE_CONFIG_H ++# include "config.h" ++#endif ++ ++#include "php.h" ++#include "ext/standard/php_password.h" ++#include "php_openssl.h" ++ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++#include "Zend/zend_attributes.h" ++#include "openssl_pwhash_arginfo.h" ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PHP_OPENSSL_MEMLIMIT_MIN 8u ++#define PHP_OPENSSL_MEMLIMIT_MAX UINT32_MAX ++#define PHP_OPENSSL_ITERLIMIT_MIN 1u ++#define PHP_OPENSSL_ITERLIMIT_MAX UINT32_MAX ++#define PHP_OPENSSL_THREADS_MIN 1u ++#define PHP_OPENSSL_THREADS_MAX UINT32_MAX ++ ++#define PHP_OPENSSL_ARGON_VERSION 0x13 ++ ++#define PHP_OPENSSL_SALT_SIZE 16 ++#define PHP_OPENSSL_HASH_SIZE 32 ++#define PHP_OPENSSL_DIGEST_SIZE 128 ++ ++static inline zend_result get_options(zend_array *options, uint32_t *memlimit, uint32_t *iterlimit, uint32_t *threads) ++{ ++ zval *opt; ++ ++ *iterlimit = PHP_OPENSSL_PWHASH_ITERLIMIT; ++ *memlimit = PHP_OPENSSL_PWHASH_MEMLIMIT; ++ *threads = PHP_OPENSSL_PWHASH_THREADS; ++ ++ if (!options) { ++ return SUCCESS; ++ } ++ if ((opt = zend_hash_str_find(options, "memory_cost", strlen("memory_cost")))) { ++ zend_long smemlimit = zval_get_long(opt); ++ ++ if ((smemlimit < 0) || (smemlimit < PHP_OPENSSL_MEMLIMIT_MIN) || (smemlimit > (PHP_OPENSSL_MEMLIMIT_MAX))) { ++ zend_value_error("Memory cost is outside of allowed memory range"); ++ return FAILURE; ++ } ++ *memlimit = smemlimit; ++ } ++ if ((opt = zend_hash_str_find(options, "time_cost", strlen("time_cost")))) { ++ zend_long siterlimit = zval_get_long(opt); ++ if ((siterlimit < PHP_OPENSSL_ITERLIMIT_MIN) || (siterlimit > PHP_OPENSSL_ITERLIMIT_MAX)) { ++ zend_value_error("Time cost is outside of allowed time range"); ++ return FAILURE; ++ } ++ *iterlimit = siterlimit; ++ } ++ if ((opt = zend_hash_str_find(options, "threads", strlen("threads"))) && (zval_get_long(opt) != 1)) { ++ zend_long sthreads = zval_get_long(opt); ++ if ((sthreads < PHP_OPENSSL_THREADS_MIN) || (sthreads > PHP_OPENSSL_THREADS_MAX)) { ++ zend_value_error("Invalid number of threads"); ++ return FAILURE; ++ } ++ *threads = sthreads; ++ } ++ return SUCCESS; ++} ++ ++static bool php_openssl_argon2_compute_hash( ++ const char *algo, ++ uint32_t version, uint32_t memlimit, uint32_t iterlimit, uint32_t threads, ++ const char *pass, size_t pass_len, ++ const unsigned char *salt, size_t salt_len, ++ unsigned char *hash, size_t hash_len) ++{ ++ OSSL_PARAM params[7], *p = params; ++ EVP_KDF *kdf = NULL; ++ EVP_KDF_CTX *kctx = NULL; ++ bool ret = false; ++ ++ if (threads > 1) { ++ if (OSSL_set_max_threads(NULL, threads) != 1) { ++ goto fail; ++ } ++ } ++ p = params; ++ *p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_THREADS, ++ &threads); ++ *p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_LANES, ++ &threads); ++ *p++= OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ITER, ++ &iterlimit); ++ *p++ = OSSL_PARAM_construct_uint32(OSSL_KDF_PARAM_ARGON2_MEMCOST, ++ &memlimit); ++ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, ++ (void *)salt, salt_len); ++ *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, ++ (void *)pass, pass_len); ++ *p++ = OSSL_PARAM_construct_end(); ++ ++ if ((kdf = EVP_KDF_fetch(NULL, algo, NULL)) == NULL) { ++ goto fail; ++ } ++ if ((kctx = EVP_KDF_CTX_new(kdf)) == NULL) { ++ goto fail; ++ } ++ if (EVP_KDF_derive(kctx, hash, hash_len, params) != 1) { ++ zend_value_error("Unexpected failure hashing password"); ++ goto fail; ++ } ++ ++ ret = true; ++ ++fail: ++ EVP_KDF_free(kdf); ++ EVP_KDF_CTX_free(kctx); ++ ++ if (threads > 1) { ++ OSSL_set_max_threads(NULL, 0); ++ } ++ return ret; ++} ++ ++static zend_string *php_openssl_argon2_hash(const zend_string *password, zend_array *options, const char *algo) ++{ ++ uint32_t iterlimit, memlimit, threads, version = PHP_OPENSSL_ARGON_VERSION; ++ zend_string *digest = NULL, *salt64 = NULL, *hash64 = NULL; ++ unsigned char hash[PHP_OPENSSL_HASH_SIZE+1], salt[PHP_OPENSSL_SALT_SIZE+1]; ++ ++ if ((ZSTR_LEN(password) >= UINT32_MAX)) { ++ zend_value_error("Password is too long"); ++ return NULL; ++ } ++ if (get_options(options, &memlimit, &iterlimit, &threads) == FAILURE) { ++ return NULL; ++ } ++ if (RAND_bytes(salt, PHP_OPENSSL_SALT_SIZE) <= 0) { ++ return NULL; ++ } ++ ++ if (!php_openssl_argon2_compute_hash(algo, version, memlimit, iterlimit, threads, ++ ZSTR_VAL(password), ZSTR_LEN(password), salt, PHP_OPENSSL_SALT_SIZE, hash, PHP_OPENSSL_HASH_SIZE)) { ++ return NULL; ++ } ++ ++ hash64 = php_base64_encode(hash, PHP_OPENSSL_HASH_SIZE); ++ /* No padding utsing 32 *4 / 3 = 42.6 (43 + 1 padding char) */ ++ ZEND_ASSERT(ZSTR_LEN(hash64)==44 && ZSTR_VAL(hash64)[43]=='='); ++ ZSTR_VAL(hash64)[43] = 0; ++ ZSTR_LEN(hash64) = 43; ++ ++ salt64 = php_base64_encode(salt, PHP_OPENSSL_SALT_SIZE); ++ /* No padding using 16 *4 / 3 = 21.3 (22 + 2 padding char) */ ++ ZEND_ASSERT(ZSTR_LEN(salt64)==24 && ZSTR_VAL(salt64)[22]=='=' && ZSTR_VAL(salt64)[23]=='='); ++ ZSTR_VAL(salt64)[22] = 0; ++ ZSTR_LEN(salt64) = 22; ++ ++ digest = zend_string_alloc(PHP_OPENSSL_DIGEST_SIZE, 0); ++ ZSTR_LEN(digest) = snprintf(ZSTR_VAL(digest), ZSTR_LEN(digest), "$%s$v=%d$m=%u,t=%u,p=%u$%s$%s", ++ algo, version, memlimit, iterlimit, threads, ZSTR_VAL(salt64), ZSTR_VAL(hash64)); ++ ++ zend_string_release(salt64); ++ zend_string_release(hash64); ++ ++ return digest; ++} ++ ++static int php_openssl_argon2_extract( ++ const zend_string *digest, uint32_t *version, uint32_t *memlimit, uint32_t *iterlimit, ++ uint32_t *threads, zend_string **salt, zend_string **hash) ++{ ++ const char *p; ++ char *hash64, *salt64; ++ ++ if (!digest || (ZSTR_LEN(digest) < sizeof("$argon2id$"))) { ++ return FAILURE; ++ } ++ p = ZSTR_VAL(digest); ++ if (!memcmp(p, "$argon2i$", strlen("$argon2i$"))) { ++ p += strlen("$argon2i$"); ++ } else if (!memcmp(p, "$argon2id$", strlen("$argon2id$"))) { ++ p += strlen("$argon2id$"); ++ } else { ++ return FAILURE; ++ } ++ if (sscanf(p, "v=%" PRIu32 "$m=%" PRIu32 ",t=%" PRIu32 ",p=%" PRIu32, ++ version, memlimit, iterlimit, threads) != 4) { ++ return FAILURE; ++ } ++ if (salt && hash) { ++ /* start of param */ ++ p = strchr(p, '$'); ++ if (!p) { ++ return FAILURE; ++ } ++ /* start of salt */ ++ p = strchr(p+1, '$'); ++ if (!p) { ++ return FAILURE; ++ } ++ salt64 = estrdup(p+1); ++ /* start of hash */ ++ hash64 = strchr(salt64, '$'); ++ if (!hash64) { ++ efree(salt64); ++ return FAILURE; ++ } ++ *hash64++ = 0; ++ *salt = php_base64_decode((unsigned char *)salt64, strlen(salt64)); ++ *hash = php_base64_decode((unsigned char *)hash64, strlen(hash64)); ++ efree(salt64); ++ } ++ return SUCCESS; ++} ++ ++static bool php_openssl_argon2_verify(const zend_string *password, const zend_string *digest, const char *algo) ++{ ++ uint32_t version, iterlimit, memlimit, threads; ++ zend_string *salt, *hash, *new; ++ bool ret = false; ++ ++ if ((ZSTR_LEN(password) >= UINT32_MAX) || (ZSTR_LEN(digest) >= UINT32_MAX)) { ++ return false; ++ } ++ if (FAILURE == php_openssl_argon2_extract(digest, &version, &memlimit, &iterlimit, &threads, &salt, &hash)) { ++ return false; ++ } ++ ++ new = zend_string_alloc(ZSTR_LEN(hash), 0); ++ if (php_openssl_argon2_compute_hash(algo, version, memlimit, iterlimit, threads, ++ ZSTR_VAL(password), ZSTR_LEN(password), (unsigned char *)ZSTR_VAL(salt), ++ ZSTR_LEN(salt), (unsigned char *)ZSTR_VAL(new), ZSTR_LEN(new))) { ++ ret = (php_safe_bcmp(hash, new) == 0); ++ } ++ ++ zend_string_release(new); ++ zend_string_release(salt); ++ zend_string_release(hash); ++ ++ return ret; ++} ++ ++static bool php_openssl_argon2i_verify(const zend_string *password, const zend_string *digest) ++{ ++ return php_openssl_argon2_verify(password, digest, "argon2i"); ++} ++ ++static bool php_openssl_argon2id_verify(const zend_string *password, const zend_string *digest) ++{ ++ return php_openssl_argon2_verify(password, digest, "argon2id"); ++} ++ ++static bool php_openssl_argon2_needs_rehash(const zend_string *hash, zend_array *options) ++{ ++ uint32_t version, iterlimit, memlimit, threads; ++ uint32_t new_version = PHP_OPENSSL_ARGON_VERSION, new_iterlimit, new_memlimit, new_threads; ++ ++ if (FAILURE == get_options(options, &new_memlimit, &new_iterlimit, &new_threads)) { ++ return true; ++ } ++ if (FAILURE == php_openssl_argon2_extract(hash, &version, &memlimit, &iterlimit, &threads, NULL, NULL)) { ++ return true; ++ } ++ ++ // Algo already checked in pasword_needs_rehash implementation ++ return (version != new_version) || ++ (iterlimit != new_iterlimit) || ++ (memlimit != new_memlimit) || ++ (threads != new_threads); ++} ++ ++static int php_openssl_argon2_get_info(zval *return_value, const zend_string *hash) ++{ ++ uint32_t v, threads; ++ uint32_t memory_cost; ++ uint32_t time_cost; ++ ++ if (FAILURE == php_openssl_argon2_extract(hash, &v, &memory_cost, &time_cost, &threads, NULL, NULL)) { ++ return FAILURE; ++ } ++ add_assoc_long(return_value, "memory_cost", memory_cost); ++ add_assoc_long(return_value, "time_cost", time_cost); ++ add_assoc_long(return_value, "threads", threads); ++ ++ return SUCCESS; ++} ++ ++ ++static zend_string *php_openssl_argon2i_hash(const zend_string *password, zend_array *options) ++{ ++ return php_openssl_argon2_hash(password, options, "argon2i"); ++} ++ ++static const php_password_algo openssl_algo_argon2i = { ++ "argon2i", ++ php_openssl_argon2i_hash, ++ php_openssl_argon2i_verify, ++ php_openssl_argon2_needs_rehash, ++ php_openssl_argon2_get_info, ++ NULL, ++}; ++ ++static zend_string *php_openssl_argon2id_hash(const zend_string *password, zend_array *options) ++{ ++ return php_openssl_argon2_hash(password, options, "argon2id"); ++} ++ ++static const php_password_algo openssl_algo_argon2id = { ++ "argon2id", ++ php_openssl_argon2id_hash, ++ php_openssl_argon2id_verify, ++ php_openssl_argon2_needs_rehash, ++ php_openssl_argon2_get_info, ++ NULL, ++}; ++ ++PHP_FUNCTION(openssl_password_hash) ++{ ++ zend_string *password, *algo, *digest; ++ zend_array *options = NULL; ++ ++ ZEND_PARSE_PARAMETERS_START(2, 3) ++ Z_PARAM_STR(algo) ++ Z_PARAM_STR(password) ++ Z_PARAM_OPTIONAL ++ Z_PARAM_ARRAY_HT(options) ++ ZEND_PARSE_PARAMETERS_END(); ++ ++ if (strcmp(ZSTR_VAL(algo), "argon2i") && strcmp(ZSTR_VAL(algo), "argon2id")) { ++ zend_argument_value_error(1, "must be a valid password openssl hashing algorithm"); ++ RETURN_THROWS(); ++ } ++ ++ digest = php_openssl_argon2_hash(password, options, ZSTR_VAL(algo)); ++ if (!digest) { ++ if (!EG(exception)) { ++ zend_throw_error(NULL, "Password hashing failed for unknown reason"); ++ } ++ RETURN_THROWS(); ++ } ++ ++ RETURN_NEW_STR(digest); ++} ++ ++PHP_FUNCTION(openssl_password_verify) ++{ ++ zend_string *password, *algo, *digest; ++ ++ ZEND_PARSE_PARAMETERS_START(3, 3) ++ Z_PARAM_STR(algo) ++ Z_PARAM_STR(password) ++ Z_PARAM_STR(digest) ++ ZEND_PARSE_PARAMETERS_END(); ++ ++ if (strcmp(ZSTR_VAL(algo), "argon2i") && strcmp(ZSTR_VAL(algo), "argon2id")) { ++ zend_argument_value_error(1, "must be a valid password openssl hashing algorithm"); ++ RETURN_THROWS(); ++ } ++ ++ RETURN_BOOL(php_openssl_argon2_verify(password, digest, ZSTR_VAL(algo))); ++} ++ ++PHP_MINIT_FUNCTION(openssl_pwhash) ++{ ++ zend_string *argon2i = ZSTR_INIT_LITERAL("argon2i", 1); ++ ++ zend_register_functions(NULL, ext_functions, NULL, type); ++ ++ if (php_password_algo_find(argon2i)) { ++ /* Nothing to do. Core or sodium has registered these algorithms for us. */ ++ zend_string_release(argon2i); ++ return SUCCESS; ++ } ++ zend_string_release(argon2i); ++ ++ register_openssl_pwhash_symbols(module_number); ++ ++ if (FAILURE == php_password_algo_register("argon2i", &openssl_algo_argon2i)) { ++ return FAILURE; ++ } ++ if (FAILURE == php_password_algo_register("argon2id", &openssl_algo_argon2id)) { ++ return FAILURE; ++ } ++ ++ return SUCCESS; ++} ++ ++PHP_MSHUTDOWN_FUNCTION(openssl_pwhash) ++{ ++ zend_unregister_functions(ext_functions, -1, NULL); ++ ++ return SUCCESS; ++} ++#endif /* PHP_OPENSSL_API_VERSION >= 0x30200 */ +diff --git a/ext/openssl/openssl_pwhash.stub.php b/ext/openssl/openssl_pwhash.stub.php +new file mode 100644 +index 0000000000..85c2f04d55 +--- /dev/null ++++ b/ext/openssl/openssl_pwhash.stub.php +@@ -0,0 +1,38 @@ ++= 0x30200 ++/** ++ * @var string ++ */ ++const PASSWORD_ARGON2I = "argon2i"; ++/** ++ * @var string ++ */ ++const PASSWORD_ARGON2ID = "argon2id"; ++/** ++ * @var int ++ * @cvalue PHP_OPENSSL_PWHASH_MEMLIMIT ++ */ ++const PASSWORD_ARGON2_DEFAULT_MEMORY_COST = UNKNOWN; ++/** ++ * @var int ++ * @cvalue PHP_OPENSSL_PWHASH_ITERLIMIT ++ */ ++const PASSWORD_ARGON2_DEFAULT_TIME_COST = UNKNOWN; ++/** ++ * @var int ++ * @cvalue PHP_OPENSSL_PWHASH_THREADS ++ */ ++const PASSWORD_ARGON2_DEFAULT_THREADS = UNKNOWN; ++/** ++ * @var string ++ */ ++const PASSWORD_ARGON2_PROVIDER = "openssl"; ++ ++function openssl_password_hash(string $algo, #[\SensitiveParameter] string $password, array $options = []): string {} ++function openssl_password_verify(string $algo, #[\SensitiveParameter] string $password, string $hash): bool {} ++ ++#endif ++ +diff --git a/ext/openssl/openssl_pwhash_arginfo.h b/ext/openssl/openssl_pwhash_arginfo.h +new file mode 100644 +index 0000000000..f60a1f5b08 +--- /dev/null ++++ b/ext/openssl/openssl_pwhash_arginfo.h +@@ -0,0 +1,68 @@ ++/* This is a generated file, edit the .stub.php file instead. ++ * Stub hash: a01216f790c4c42499bd85448aacb3a6d58acc94 */ ++ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_password_hash, 0, 2, IS_STRING, 0) ++ ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) ++ ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0) ++ ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]") ++ZEND_END_ARG_INFO() ++#endif ++ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_password_verify, 0, 3, _IS_BOOL, 0) ++ ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0) ++ ZEND_ARG_TYPE_INFO(0, password, IS_STRING, 0) ++ ZEND_ARG_TYPE_INFO(0, hash, IS_STRING, 0) ++ZEND_END_ARG_INFO() ++#endif ++ ++ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ZEND_FUNCTION(openssl_password_hash); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ZEND_FUNCTION(openssl_password_verify); ++#endif ++ ++ ++static const zend_function_entry ext_functions[] = { ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ ZEND_FE(openssl_password_hash, arginfo_openssl_password_hash) ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ ZEND_FE(openssl_password_verify, arginfo_openssl_password_verify) ++#endif ++ ZEND_FE_END ++}; ++ ++static void register_openssl_pwhash_symbols(int module_number) ++{ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_STRING_CONSTANT("PASSWORD_ARGON2I", "argon2i", CONST_PERSISTENT); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_STRING_CONSTANT("PASSWORD_ARGON2ID", "argon2id", CONST_PERSISTENT); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_MEMORY_COST", PHP_OPENSSL_PWHASH_MEMLIMIT, CONST_PERSISTENT); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_TIME_COST", PHP_OPENSSL_PWHASH_ITERLIMIT, CONST_PERSISTENT); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_LONG_CONSTANT("PASSWORD_ARGON2_DEFAULT_THREADS", PHP_OPENSSL_PWHASH_THREADS, CONST_PERSISTENT); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ REGISTER_STRING_CONSTANT("PASSWORD_ARGON2_PROVIDER", "openssl", CONST_PERSISTENT); ++#endif ++ ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ ++ zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_password_hash", sizeof("openssl_password_hash") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); ++#endif ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++ ++ zend_add_parameter_attribute(zend_hash_str_find_ptr(CG(function_table), "openssl_password_verify", sizeof("openssl_password_verify") - 1), 1, ZSTR_KNOWN(ZEND_STR_SENSITIVEPARAMETER), 0); ++#endif ++} +diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h +index 304854b4bf..9532cfe6f9 100644 +--- a/ext/openssl/php_openssl.h ++++ b/ext/openssl/php_openssl.h +@@ -39,8 +39,10 @@ extern zend_module_entry openssl_module_entry; + #define PHP_OPENSSL_API_VERSION 0x10002 + #elif OPENSSL_VERSION_NUMBER < 0x30000000L + #define PHP_OPENSSL_API_VERSION 0x10100 +-#else ++#elif OPENSSL_VERSION_NUMBER < 0x30200000L + #define PHP_OPENSSL_API_VERSION 0x30000 ++#else ++#define PHP_OPENSSL_API_VERSION 0x30200 + #endif + #endif + +@@ -158,6 +160,33 @@ static inline php_openssl_certificate_object *php_openssl_certificate_from_obj(z + + #define Z_OPENSSL_CERTIFICATE_P(zv) php_openssl_certificate_from_obj(Z_OBJ_P(zv)) + ++#if PHP_OPENSSL_API_VERSION >= 0x30200 ++/** ++ * MEMLIMIT is normalized to KB even though sodium uses Bytes in order to ++ * present a consistent user-facing API. ++ * ++ * When updating these values, synchronize ext/standard/php_password.h values. ++ */ ++#if defined(PHP_PASSWORD_ARGON2_MEMORY_COST) ++#define PHP_OPENSSL_PWHASH_MEMLIMIT PHP_PASSWORD_ARGON2_MEMORY_COST ++#else ++#define PHP_OPENSSL_PWHASH_MEMLIMIT (64 << 10) ++#endif ++#if defined(PHP_PASSWORD_ARGON2_TIME_COST) ++#define PHP_OPENSSL_PWHASH_ITERLIMIT PHP_PASSWORD_ARGON2_TIME_COST ++#else ++#define PHP_OPENSSL_PWHASH_ITERLIMIT 4 ++#endif ++#if defined(PHP_PASSWORD_ARGON2_THREADS) ++#define PHP_OPENSSL_PWHASH_THREADS PHP_PASSWORD_ARGON2_THREADS ++#else ++#define PHP_OPENSSL_PWHASH_THREADS 1 ++#endif ++ ++PHP_MINIT_FUNCTION(openssl_pwhash); ++PHP_MSHUTDOWN_FUNCTION(openssl_pwhash); ++#endif ++ + PHP_MINIT_FUNCTION(openssl); + PHP_MSHUTDOWN_FUNCTION(openssl); + PHP_MINFO_FUNCTION(openssl); +diff --git a/ext/openssl/tests/openssl_password.phpt b/ext/openssl/tests/openssl_password.phpt +new file mode 100644 +index 0000000000..7881803038 +--- /dev/null ++++ b/ext/openssl/tests/openssl_password.phpt +@@ -0,0 +1,42 @@ ++--TEST-- ++Basic features of password_hash ++--EXTENSIONS-- ++openssl ++--SKIPIF-- ++ ++--FILE-- ++ PASSWORD_ARGON2_DEFAULT_MEMORY_COST / $mem, ++ 'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST / $time, ++ 'threads' => PASSWORD_ARGON2_DEFAULT_THREADS, ++ ]; ++ foreach(['argon2i', 'argon2id'] as $algo) { ++ $pass = "secret$mem$time$algo"; ++ $hash = openssl_password_hash($algo, $pass, $opts); ++ var_dump(openssl_password_verify($algo, $pass, $hash)); ++ } ++ } ++} ++?> ++--EXPECTF-- ++Argon2 provider: string(%d) "%s" ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++ +diff --git a/ext/openssl/tests/openssl_password_compat.phpt b/ext/openssl/tests/openssl_password_compat.phpt +new file mode 100644 +index 0000000000..0de683616a +--- /dev/null ++++ b/ext/openssl/tests/openssl_password_compat.phpt +@@ -0,0 +1,52 @@ ++--TEST-- ++Compatibility of password_hash (libsodium / openssl) ++--EXTENSIONS-- ++openssl ++sodium ++--SKIPIF-- ++ ++--FILE-- ++ PASSWORD_ARGON2_DEFAULT_MEMORY_COST / $mem, ++ 'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST / $time, ++ 'threads' => PASSWORD_ARGON2_DEFAULT_THREADS, ++ ]; ++ $algo = 'argon2id'; ++ $pass = "secret$mem$time$algo"; ++ ++ /* hash with libsodium / verify with openssl */ ++ $hash = sodium_crypto_pwhash_str($pass, PASSWORD_ARGON2_DEFAULT_TIME_COST / $time, PASSWORD_ARGON2_DEFAULT_MEMORY_COST / $mem); ++ var_dump(openssl_password_verify($algo, $pass, $hash)); ++ ++ /* hash with openssl / verify with libsodium */ ++ $hash = openssl_password_hash($algo, $pass, $opts); ++ var_dump(sodium_crypto_pwhash_str_verify($hash, $pass)); ++ } ++} ++?> ++--EXPECTF-- ++Argon2 provider: string(%d) "%s" ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++ +diff --git a/ext/openssl/tests/openssl_password_compat2.phpt b/ext/openssl/tests/openssl_password_compat2.phpt +new file mode 100644 +index 0000000000..42cf8682fd +--- /dev/null ++++ b/ext/openssl/tests/openssl_password_compat2.phpt +@@ -0,0 +1,52 @@ ++--TEST-- ++Compatibility of password_hash (libargon2 / openssl) ++--EXTENSIONS-- ++openssl ++sodium ++--SKIPIF-- ++ ++--FILE-- ++ PASSWORD_ARGON2_DEFAULT_MEMORY_COST / $mem, ++ 'time_cost' => PASSWORD_ARGON2_DEFAULT_TIME_COST / $time, ++ 'threads' => PASSWORD_ARGON2_DEFAULT_THREADS, ++ ]; ++ $algo = 'argon2id'; ++ $pass = "secret$mem$time$algo"; ++ ++ /* hash with libargon2 / verify with openssl */ ++ $hash = password_hash($pass, PASSWORD_ARGON2ID, $opts); ++ var_dump(openssl_password_verify($algo, $pass, $hash)); ++ ++ /* hash with openssl / verify with libargon2 */ ++ $hash = openssl_password_hash($algo, $pass, $opts); ++ var_dump(password_verify($pass, $hash)); ++ } ++} ++?> ++--EXPECT-- ++Argon2 provider: string(8) "standard" ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++bool(true) ++ +-- +2.45.0 + diff --git a/php-keyring.gpg b/php-keyring.gpg index 870d81693e5df48c5519c37b22c196029745dae4..0774fa8fe0634989891fac9fc1a43ac78946d9d2 100644 --- a/php-keyring.gpg +++ b/php-keyring.gpg @@ -1,415 +1,780 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -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 -bh57GXdFtudEaKvQbGW9yalYwuj7Yip5XJGttg== -=XZOV +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 +5zO4pPQ1rIGTN4CBa7QcJH3fc3i9rYMYAtuVlpCUmDMEYHHgIBYJKwYBBAHaRw8B +AQdAOm0RDYTmM6omlqoTx6Wy65agVJ4q8EPGczNnYOrHyo20HUpha3ViIFplbGVu +a2EgPGJ1a2thQHBocC5uZXQ+iJMEExYIADsCGwMFCwkIBwIGFQoJCAsCBBYCAwEC +HgECF4AWIQTCjZN1dWA+tKu3JYYcB3ncXAqd5AUCYHHi+QIZAQAKCRAcB3ncXAqd +5MZdAP0eAbdHgjHqKYol3QaXRhErAvvLHPSEXN5cAImF3zIICgD+NJZZMQDXd1OO +KDt+YLiIqIq2ibRhOP5mZryPCGkq9QG0J0pha3ViIFplbGVua2EgPGpha3ViLm9w +ZW5zc2xAZ21haWwuY29tPoiQBBMWCAA4FiEEwo2TdXVgPrSrtyWGHAd53FwKneQF +AmBx4owCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQHAd53FwKneS0NwEA +t0IRpoCN/JNwg1TIseybpmC65nSzYVyX10xe4Ji50dcBAI6TYA+47z6F4IVRg2c8 +Vtg1xktot7b/tKn6hgdv59sLtCdKYWt1YiBaZWxlbmthIDxqYWt1Yi56ZWxlbmth +QGdtYWlsLmNvbT6IkAQTFggAOBYhBMKNk3V1YD60q7clhhwHedxcCp3kBQJgceAg +AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEBwHedxcCp3k+3MBAKuK15Xy +Hw+sdFATFuW9vN+lXqHnYid2jRzQUoh5wG/FAQDcBXQgXRfe72XRoxY4AE3E4onG +MfzW3kbDKDVF7o4zDrg4BGBx4CASCisGAQQBl1UBBQEBB0Bm2FjWsSDUwL5nbAht +l+rwnGLKbWiVYrwHQocgKFj6GwMBCAeIeAQYFggAIBYhBMKNk3V1YD60q7clhhwH +edxcCp3kBQJgceAgAhsMAAoJEBwHedxcCp3k8ZwA/jLRHUBKIeRAxeGJhoqJRr2o +TxrP887FuX9/ikSX21bcAQD90AB2fu6dpAkOFyZzX9UdE7QxtBhHVWRx3DRr4P/c +DpgzBGYgDVwWCSsGAQQB2kcPAQEHQET/J56AhF3VoW7XvfydS3kGVTEN7zzOwA06 +KmRjb1w3tCZDYWx2aW4gQnVja2xleSAoUEhQKSA8Y2FsdmluYkBwaHAubmV0PoiT +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 +=ilrq -----END PGP PUBLIC KEY BLOCK----- diff --git a/php.ini b/php.ini index adb94c7ac18c22870e0dc536b6d58469b9a91ee5..d0ae9d12009bb1c0dc77ea237b1c55242ce8535d 100644 --- a/php.ini +++ b/php.ini @@ -75,7 +75,7 @@ ; php.ini-production contains settings which hold security, performance and ; best practices at its core. But please be aware, these settings may break -; compatibility with older or less security conscience applications. We +; compatibility with older or less security-conscious applications. We ; recommending using the production ini in production and testing environments. ; php.ini-development is very similar to its production variant, except it is @@ -144,6 +144,11 @@ ; Development Value: 5 ; Production Value: 5 +; session.sid_length +; Default Value: 32 +; Development Value: 26 +; Production Value: 26 + ; short_open_tag ; Default Value: On ; Development Value: Off @@ -154,6 +159,11 @@ ; Development Value: "GPCS" ; Production Value: "GPCS" +; zend.assertions +; Default Value: 1 +; Development Value: 1 +; Production Value: -1 + ; zend.exception_ignore_args ; Default Value: Off ; Development Value: Off @@ -1045,6 +1055,10 @@ sendmail_path = /usr/sbin/sendmail -t -i ; Add X-PHP-Originating-Script: that will include uid of the script followed by the filename mail.add_x_header = Off +; Use mixed LF and CRLF line separators to keep compatibility with some +; RFC 2822 non conformant MTA. +mail.mixed_lf_and_crlf = Off + ; The path to a log file that will log all mail() calls. Log entries include ; the full path of the script, line number, To address and headers. ;mail.log = @@ -1142,9 +1156,6 @@ mysqli.default_user = ; https://php.net/mysqli.default-pw mysqli.default_pw = -; Allow or prevent reconnect -mysqli.reconnect = Off - ; If this option is enabled, closing a persistent connection will rollback ; any pending transactions of this connection, before it is put back ; into the persistent connection pool. @@ -1476,33 +1487,14 @@ session.sid_bits_per_character = 5 ; -1: Do not compile at all ; 0: Jump over assertion at run-time ; 1: Execute assertions -; Changing from or to a negative value is only possible in php.ini! (For turning assertions on and off at run-time, see assert.active, when zend.assertions = 1) +; Changing from or to a negative value is only possible in php.ini! +; (For turning assertions on and off at run-time, toggle zend.assertions between the values 1 and 0) ; Default Value: 1 ; Development Value: 1 ; Production Value: -1 ; https://php.net/zend.assertions zend.assertions = -1 -; Assert(expr); active by default. -; https://php.net/assert.active -;assert.active = On - -; Throw an AssertionError on failed assertions -; https://php.net/assert.exception -;assert.exception = On - -; Issue a PHP warning for each failed assertion. (Overridden by assert.exception if active) -; https://php.net/assert.warning -;assert.warning = On - -; Don't bail out by default. -; https://php.net/assert.bail -;assert.bail = Off - -; User-function to be called if an assertion fails. -; https://php.net/assert.callback -;assert.callback = 0 - [mbstring] ; language for internal character representation. ; This affects mb_send_mail() and mbstring.detect_order. diff --git a/php.spec b/php.spec index 270f487d83e055d7e9548cb60d60005884dcdc18..2e9a1a985eae16022cc9f362ebf863a476fb37a9 100644 --- a/php.spec +++ b/php.spec @@ -1,8 +1,8 @@ %define anolis_release 1 # API/ABI check -%global apiver 20220829 -%global zendver 20220829 +%global apiver 20230831 +%global zendver 20230831 %global pdover 20170320 %global zipver 1.21.1 %bcond_with zts @@ -16,7 +16,6 @@ %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 @@ -25,7 +24,7 @@ %global _hardened_build 1 # version used for php embedded library soname -%global embed_version 8.2 +%global embed_version 8.3 %global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock) @@ -42,7 +41,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: php -Version: 8.2.27 +Version: 8.3.15 Release: %{anolis_release}%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend @@ -51,7 +50,7 @@ Release: %{anolis_release}%{?dist} # ext/date/lib is MIT # Zend/zend_sort is NCSA # Zend/asm is Boost -License: PHP and Zend and BSD and MIT and ASL 1.0 and NCSA and Boost +License: PHP-3.01 AND Zend-2.0 AND BSD-2-Clause AND MIT AND Apache-1.0 AND NCSA AND BSL-1.0 URL: http://www.php.net/ Source0: https://www.php.net/distributions/php-%{version}.tar.xz @@ -79,23 +78,19 @@ Patch5: php-7.2.0-includedir.patch Patch6: php-8.0.0-embed.patch Patch8: php-8.1.0-libdb.patch -# Functional changes -# Use system nikic/php-parser -Patch41: php-8.2.0-parser.patch -# use system tzdata -Patch42: php-8.1.0-systzdata-v22.patch -# Add check for php headers in phpize +Patch41: php-8.3.3-parser.patch +Patch42: php-8.3.11-systzdata-v24.patch Patch43: php-7.4.0-phpize.patch -# Use -lldap_r for OpenLDAP Patch45: php-7.4.0-ldap_r.patch -# drop "Configure command" from phpinfo output -# and only use gcc (instead of full version) -Patch47: php-8.1.0-phpinfo.patch +Patch47: php-8.3.13-phpinfo.patch +Patch48: php-8.3.0-openssl-ec-param.patch +Patch49: php-8.3.7-argon2.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 +# Security fixes (200+) + +# Fixes for tests (300+) # Factory is droped from system tzdata Patch300: php-7.4.0-datetests.patch @@ -103,7 +98,7 @@ Patch300: php-7.4.0-datetests.patch BuildRequires: gnupg2 BuildRequires: bzip2-devel BuildRequires: pkgconfig(libcurl) >= 7.29.0 -BuildRequires: httpd-devel >= 2.0.46 +BuildRequires: httpd-devel >= 2.0.46-1 BuildRequires: pam-devel # to ensure we are using httpd with filesystem feature BuildRequires: httpd-filesystem @@ -111,6 +106,7 @@ BuildRequires: httpd-filesystem BuildRequires: nginx-filesystem BuildRequires: libstdc++-devel # no pkgconfig to avoid compat-openssl10 +BuildRequires: systemtap-sdt-dtrace BuildRequires: systemtap-sdt-devel BuildRequires: libtool-ltdl-devel BuildRequires: libtool @@ -183,7 +179,7 @@ running in prefork mode. This module is deprecated. %package cli Summary: Command-line interface for PHP # sapi/cli/ps_title.c is PostgreSQL -License: PHP and Zend and BSD and MIT and ASL 1.0 and NCSA and PostgreSQL +License: PHP-3.01 AND Zend-2.0 AND BSD-2-Clause AND MIT AND Apache-1.0 AND NCSA AND PostgreSQL Requires: php-common = %{version}-%{release} Provides: php-cgi = %{version}-%{release} Provides: php-pcntl @@ -206,8 +202,8 @@ The php-dbg package contains the interactive PHP debugger. Summary: PHP FastCGI Process Manager BuildRequires: libacl-devel BuildRequires: pkgconfig(libsystemd) >= 209 +BuildRequires: pkgconfig(libselinux) Requires: php-common = %{version}-%{release} -Requires(pre): /usr/sbin/useradd %{?systemd_requires} # To ensure correct /var/lib/php/session ownership: Requires(pre): httpd-filesystem @@ -229,7 +225,8 @@ Summary: Common files for PHP # All files licensed under PHP version 3.01, except # fileinfo is licensed under PHP version 3.0 # regex, libmagic are licensed under BSD -License: PHP and BSD +License: PHP-3.01 AND BSD-2-Clause +Requires: tzdata # ABI/API check - Arch specific Provides: php(api) = %{apiver} Provides: php(zend-abi) = %{zendver} @@ -248,6 +245,7 @@ Provides: php-openssl Provides: php-libxml Provides: php-json = %{version} Obsoletes: php-json < 8 +Obsoletes: php-pecl-zip < %{version} Provides: php-iconv Provides: php-mhash = %{version} Provides: php-hash @@ -288,7 +286,7 @@ Requires: zlib-devel %if %{with zts} Provides: php-zts-devel = %{version}-%{release} %endif -Recommends: php-nikic-php-parser4 >= 4.13.0 +Recommends: php-nikic-php-parser5 >= 5.0.0 %description devel @@ -329,20 +327,6 @@ The php-sodium package provides a simple, low-level PHP extension for the libsodium cryptographic library. %endif -%package zip -Summary: ZIP archive management extension for PHP -# All files licensed under PHP version 3.0.1 -License: PHP -Requires: php-common = %{version}-%{release} -Obsoletes: php-pecl-zip < %{zipver} -Provides: php-pecl(zip) = %{zipver} -Provides: php-pecl-zip = %{zipver} -BuildRequires: pkgconfig(libzip) >= 0.11 - -%description zip -The php-zip package provides an extension that will add -support for ZIP archive management to PHP. - %package enchant Summary: Enchant spelling extension for PHP applications # All files licensed under PHP version 3.0 @@ -409,7 +393,7 @@ PHP to Microsoft SQL Server and Sybase databases through the FreeTDS library. %package tidy Summary: Standard PHP module provides tidy library support # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} BuildRequires: libtidy-devel @@ -463,7 +447,7 @@ support for using the bcmath library to PHP. %package gd Summary: A module for PHP applications for using the gd graphics library # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} BuildRequires: pkgconfig(gdlib) >= 2.1.1 @@ -476,7 +460,7 @@ Summary: A module for PHP applications which need multi-byte string handling # All files licensed under PHP version 3.01, except # libmbfl is licensed under LGPLv2 # ucgendat is licensed under OpenLDAP -License: PHP and LGPLv2 and OpenLDAP +License: PHP-3.01 AND LGPL-2.1-only AND OLDAP-2.8 BuildRequires: pkgconfig(oniguruma) >= 6.8 Provides: bundled(libmbfl) = 1.3.2 Requires: php-common = %{version}-%{release} @@ -488,7 +472,7 @@ support for multi-byte string handling to PHP. %package xml Summary: A module for PHP applications which use XML # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} Provides: php-dom Provides: php-domxml @@ -508,7 +492,7 @@ and performing XSL transformations on XML documents. %package snmp Summary: A module for PHP applications that query SNMP-managed devices # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release}, net-snmp BuildRequires: net-snmp-devel @@ -522,7 +506,7 @@ will need to install this package and the php package. %package pdo-firebird Summary: PDO driver for Interbase/Firebird databases # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 # for fb_config command BuildRequires: firebird-devel Requires: php-pdo = %{version}-%{release} @@ -537,7 +521,7 @@ Interbase/Firebird databases. %package soap Summary: A module for PHP applications that use the SOAP protocol # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} BuildRequires: pkgconfig(libxml-2.0) @@ -549,7 +533,7 @@ support to PHP for using the SOAP web services protocol. Summary: A module for PHP applications that use ODBC databases # All files licensed under PHP version 3.01, except # pdo_odbc is licensed under PHP version 3.0 -License: PHP +License: PHP-3.01 Requires: php-pdo = %{version}-%{release} Provides: php_database Provides: php-pdo_odbc @@ -567,7 +551,7 @@ package. %package process Summary: Modules for PHP script using system process interfaces # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} Provides: php-posix Provides: php-shmop @@ -583,7 +567,7 @@ communication. %package pgsql Summary: A PostgreSQL database module for PHP # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-pdo = %{version}-%{release} Provides: php_database Provides: php-pdo_pgsql @@ -602,7 +586,7 @@ php package. %package mysqlnd Summary: A module for PHP applications that use MySQL databases # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-pdo = %{version}-%{release} Provides: php_database Provides: php-mysqli = %{version}-%{release} @@ -620,7 +604,7 @@ This package use the MySQL Native Driver %package pdo Summary: A database access abstraction module for PHP applications # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} # ABI/API check - Arch specific Provides: php-pdo-abi = %{pdover} @@ -637,7 +621,7 @@ databases. %package ldap Summary: A module for PHP applications that use LDAP # All files licensed under PHP version 3.01 -License: PHP +License: PHP-3.01 Requires: php-common = %{version}-%{release} BuildRequires: pkgconfig(libsasl2) BuildRequires: openldap-devel @@ -652,8 +636,8 @@ language. %if %{with imap} %package imap Summary: A module for PHP applications that use IMAP -# All files licensed under PHP version 3.01 -License: PHP +# All files licensed under PHP version 3.0 +License: PHP-3.01 Requires: php-common = %{version}-%{release} BuildRequires: pkgconfig(krb5) BuildRequires: pkgconfig(krb5-gssapi) @@ -669,7 +653,8 @@ messages on mail servers. PHP is an HTML-embedded scripting language. %package opcache Summary: The Zend OPcache -License: PHP +License: PHP-3.01 +BuildRequires: pkgconfig(capstone) >= 3.0 Requires: php-common = %{version}-%{release} Provides: php-pecl-zendopcache = %{version} Provides: php-pecl(opcache) = %{version} @@ -694,9 +679,12 @@ bytecode optimization patterns that make code execution faster. %patch -P 43 -p1 -b .headers %patch -P 45 -p1 -b .ldap_r %patch -P 47 -p1 -b .phpinfo +%patch -P 48 -p1 -b .ec-param +%patch -P 49 -p1 -b .argon2 # upstream patches -%patch -P 100 -p1 -b .ec_keys + +# security patches # Fixes for tests %patch -P 300 -p1 -b .datetests @@ -734,6 +722,7 @@ rm Zend/tests/bug54268.phpt rm Zend/tests/bug68412.phpt # tar issue rm ext/zlib/tests/004-mb.phpt +rm ext/openssl/tests/ecc_custom_params.phpt # Safety check for API version change. pver=$(sed -n '/#define PHP_VERSION /{s/.* "//;s/".*$//;p}' main/php_version.h) @@ -765,7 +754,7 @@ if test "x${vpdo}" != "x%{pdover}"; then exit 1 fi -# Not needed but installed headers. +# https://bugs.php.net/63362 - Not needed but installed headers. # Drop some Windows specific headers to avoid installation, # before build to ensure they are really not needed. rm -f TSRM/tsrm_win32.h \ @@ -829,6 +818,7 @@ mkdir Zend && cp ../Zend/zend_{language,ini}_{parser,scanner}.[ch] Zend # date, ereg, filter, libxml, reflection, spl: not supported # hash: for PHAR_SIG_SHA256 and PHAR_SIG_SHA512 # session: dep on hash, used by soap +# sockets: heavily used by FPM test suite # pcre: used by filter, zip # pcntl, readline: only used by CLI sapi # openssl: for PHAR_SIG_OPENSSL @@ -858,6 +848,8 @@ ln -sf ../configure --with-libdir=%{_lib} \ --cache-file=../config.cache \ --enable-rtld-now \ + --with-exec-dir=%{_bindir} \ + --enable-sockets \ $* if test $? != 0; then tail -500 config.log @@ -874,7 +866,8 @@ pushd build-cgi build --libdir=%{_libdir}/php \ --enable-pcntl \ --enable-opcache \ - --enable-phpdbg \ + --with-capstone \ + --enable-phpdbg --enable-phpdbg-readline \ %if %{with imap} --with-imap=shared --with-imap-ssl \ %endif @@ -919,7 +912,6 @@ build --libdir=%{_libdir}/php \ --enable-ftp=shared \ --with-gettext=shared \ --with-iconv=shared \ - --enable-sockets=shared \ --enable-tokenizer=shared \ --with-ldap=shared --with-ldap-sasl \ --enable-mysqlnd=shared \ @@ -929,7 +921,6 @@ build --libdir=%{_libdir}/php \ --with-pdo-dblib=shared,%{_prefix} \ %endif --with-sqlite3=shared \ - --with-zip=shared \ --without-readline \ --with-libedit \ %if %{with pspell} @@ -954,8 +945,8 @@ build --libdir=%{_libdir}/php \ --with-enchant=shared popd -without_shared="--disable-gd \ - --disable-shmop --disable-sockets --disable-tokenizer \ +without_shared="--without-gd \ + --disable-shmop -disable-tokenizer \ --without-iconv --disable-ftp --without-bz2 --disable-ctype \ --disable-simplexml --disable-exif --without-gettext \ --without-curl --disable-posix --disable-xml \ @@ -985,6 +976,7 @@ pushd build-fpm build --enable-fpm \ --with-fpm-acl \ --with-fpm-systemd \ + --with-fpm-selinux \ --libdir=%{_libdir}/php \ --without-mysqli \ --disable-pdo \ @@ -992,7 +984,7 @@ build --enable-fpm \ popd # Build for inclusion as embedded script language into applications, -# /usr/lib[64]/libphp7.so +# /usr/lib[64]/libphp.so pushd build-embedded build --enable-embed \ --without-mysqli --disable-pdo \ @@ -1012,6 +1004,7 @@ build --includedir=%{_includedir}/php-zts \ --with-config-file-scan-dir=%{_sysconfdir}/php-zts.d \ --enable-pcntl \ --enable-opcache \ + --with-capstone \ %if %{with imap} --with-imap=shared --with-imap-ssl \ %endif @@ -1037,7 +1030,6 @@ build --includedir=%{_includedir}/php-zts \ %endif --with-gettext=shared \ --with-iconv=shared \ - --enable-sockets=shared \ --enable-tokenizer=shared \ --enable-exif=shared \ --enable-ftp=shared \ @@ -1111,7 +1103,7 @@ export NO_INTERACTION=1 REPORT_EXIT_STATUS=1 MALLOC_CHECK_=2 export SKIP_ONLINE_TESTS=1 export SKIP_IO_CAPTURE_TESTS=1 unset TZ LANG LC_ALL -if ! make test TESTS=-j4; then +if ! make test TESTS=%{?_smp_mflags}; then set +x for f in $(find .. -name \*.diff -type f -print); do if ! grep -q XFAIL "${f/.diff/.phpt}" @@ -1162,8 +1154,6 @@ install -m 755 -d $RPM_BUILD_ROOT%{_httpd_moddir} install -m 755 build-apache/libs/libphp.so $RPM_BUILD_ROOT%{_httpd_moddir} %endif -# Apache config fragment -# Dual config file with httpd >= 2.4 %if %{with modphp} install -D -m 644 %{SOURCE9} $RPM_BUILD_ROOT%{_httpd_modconfdir}/20-php.conf %endif @@ -1221,8 +1211,7 @@ for mod in pgsql odbc ldap snmp \ mysqlnd mysqli \ mbstring gd dom xsl soap bcmath dba \ simplexml bz2 calendar ctype exif ftp gettext gmp iconv \ - sockets tokenizer opcache \ - zip \ + tokenizer opcache \ sqlite3 \ enchant phar fileinfo intl \ ffi \ @@ -1315,7 +1304,7 @@ cat files.sqlite3 >> files.pdo # Package curl, phar and fileinfo in -common. cat files.curl files.phar files.fileinfo \ files.exif files.gettext files.iconv files.calendar \ - files.ftp files.bz2 files.ctype files.sockets \ + files.ftp files.bz2 files.ctype \ files.tokenizer > files.common # The default Zend OPcache blacklist file @@ -1345,7 +1334,8 @@ rm -rf $RPM_BUILD_ROOT%{_libdir}/php/modules/*.a \ $RPM_BUILD_ROOT%{_datadir}/pear \ $RPM_BUILD_ROOT%{_bindir}/zts-phar* \ $RPM_BUILD_ROOT%{_mandir}/man1/zts-phar* \ - $RPM_BUILD_ROOT%{_libdir}/libphp.a + $RPM_BUILD_ROOT%{_libdir}/libphp.a \ + $RPM_BUILD_ROOT%{_libdir}/libphp.la # Remove irrelevant docs rm -f README.{Zeus,QNX,CVS-RULES} @@ -1502,7 +1492,6 @@ systemctl try-restart php-fpm.service >/dev/null 2>&1 || : %if %{with zts} %config(noreplace) %{_sysconfdir}/php-zts.d/opcache-default.blacklist %endif -%files zip -f files.zip %if %{with sodium} %files sodium -f files.sodium %endif @@ -1511,6 +1500,23 @@ systemctl try-restart php-fpm.service >/dev/null 2>&1 || : %changelog +* Fri Mar 21 2025 Zhao Hang - 8.3.15-1 +- Update to 8.3.15-1 from 8.2.27-1 +- Migrated to SPDX license +- Remove patches which already exist in code +- enable command history in phpdbg, add internal UTC if tzdata is missing and backport Argon2 password hashing in OpenSSL ext + [Patches cherry-pick from c10s. Original changelog: + - rebase to 8.3.7 + backport Argon2 password hashing in OpenSSL ext + - update to 8.3.0RC3 https://fedoraproject.org/wiki/Changes/php83 + add internal UTC if tzdata is missing + bump to final API/ABI + switch to nikic/php-parser version 5 + openssl: always warn about missing curve_name + - rebase to 8.3.12 + enable command history in phpdbg +] + * Tue Jan 14 2025 yangxinyu - 8.2.27-1 - Update to version 8.2.27 - fix cve-2024-8929 cve-2024-11233 cve-2024-11234