From 1174633d9f834c4de440758a10bd96921d22ba79 Mon Sep 17 00:00:00 2001 From: Eno <895183594@qq.com> Date: Sat, 13 May 2023 01:15:24 +0800 Subject: [PATCH] Improve ext-openssl to generate EC keys with custom EC parameters Generate EC keys using the macro OPENSSL_EC_EXPLICIT_CURVE compatible with OpenSSL versions below 1.1.0 Fix SM2 compatibility bugs Separate EC tests Add SM2 compatibility test --- 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, 492 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 4009a5b84df1f..33f51bfa4de9b 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 a881d59c9a2be..c5a6f2899898c 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 0000000000000..0c63af1450ba6 --- /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 0000000000000..11d4c22ae5b26 --- /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)