+
+/*
+ * This test validates converting an EC_GROUP to an OSSL_PARAM array
+ * using EC_GROUP_to_params(). A named and an explicit curve are tested.
+ */
+static int ossl_parameter_test(void)
+{
+ EC_GROUP *group_nmd = NULL, *group_nmd2 = NULL, *group_nmd3 = NULL;
+ EC_GROUP *group_exp = NULL, *group_exp2 = NULL;
+ OSSL_PARAM *params_nmd = NULL, *params_nmd2 = NULL;
+ OSSL_PARAM *params_exp = NULL, *params_exp2 = NULL;
+ unsigned char *buf = NULL, *buf2 = NULL;
+ BN_CTX *bn_ctx = NULL;
+ OSSL_PARAM_BLD *bld = NULL;
+ BIGNUM *p, *a, *b;
+ const EC_POINT *group_gen = NULL;
+ size_t bsize;
+ int r = 0;
+
+ if (!TEST_ptr(bn_ctx = BN_CTX_new()))
+ goto err;
+
+ /* test named curve */
+ if (!TEST_ptr(group_nmd = EC_GROUP_new_by_curve_name(NID_secp384r1))
+ /* test with null BN_CTX */
+ || !TEST_ptr(params_nmd = EC_GROUP_to_params(
+ group_nmd, NULL, NULL, NULL))
+ || !TEST_ptr(group_nmd2 = EC_GROUP_new_from_params(
+ params_nmd, NULL, NULL))
+ || !TEST_int_eq(EC_GROUP_cmp(group_nmd, group_nmd2, NULL), 0)
+ /* test with BN_CTX set */
+ || !TEST_ptr(params_nmd2 = EC_GROUP_to_params(
+ group_nmd, NULL, NULL, bn_ctx))
+ || !TEST_ptr(group_nmd3 = EC_GROUP_new_from_params(
+ params_nmd2, NULL, NULL))
+ || !TEST_int_eq(EC_GROUP_cmp(group_nmd, group_nmd3, NULL), 0))
+ goto err;
+
+ /* test explicit curve */
+ if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()))
+ goto err;
+
+ BN_CTX_start(bn_ctx);
+ p = BN_CTX_get(bn_ctx);
+ a = BN_CTX_get(bn_ctx);
+ b = BN_CTX_get(bn_ctx);
+
+ if (!TEST_true(EC_GROUP_get_curve(group_nmd, p, a, b, bn_ctx))
+ || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(
+ bld, OSSL_PKEY_PARAM_EC_FIELD_TYPE, SN_X9_62_prime_field, 0))
+ || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_P, p))
+ || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_A, a))
+ || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_B, b)))
+ goto err;
+
+ if (EC_GROUP_get0_seed(group_nmd) != NULL) {
+ if (!TEST_true(OSSL_PARAM_BLD_push_octet_string(
+ bld, OSSL_PKEY_PARAM_EC_SEED, EC_GROUP_get0_seed(group_nmd),
+ EC_GROUP_get_seed_len(group_nmd))))
+ goto err;
+ }
+ if (EC_GROUP_get0_cofactor(group_nmd) != NULL) {
+ if (!TEST_true(OSSL_PARAM_BLD_push_BN(
+ bld, OSSL_PKEY_PARAM_EC_COFACTOR,
+ EC_GROUP_get0_cofactor(group_nmd))))
+ goto err;
+ }
+
+ if (!TEST_ptr(group_gen = EC_GROUP_get0_generator(group_nmd))
+ || !TEST_size_t_gt(bsize = EC_POINT_point2oct(
+ group_nmd, EC_GROUP_get0_generator(group_nmd),
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx), 0)
+ || !TEST_ptr(buf2 = OPENSSL_malloc(bsize))
+ || !TEST_size_t_eq(EC_POINT_point2oct(
+ group_nmd, EC_GROUP_get0_generator(group_nmd),
+ POINT_CONVERSION_UNCOMPRESSED, buf2, bsize, bn_ctx), bsize)
+ || !TEST_true(OSSL_PARAM_BLD_push_octet_string(
+ bld, OSSL_PKEY_PARAM_EC_GENERATOR, buf2, bsize))
+ || !TEST_true(OSSL_PARAM_BLD_push_BN(
+ bld, OSSL_PKEY_PARAM_EC_ORDER, EC_GROUP_get0_order(group_nmd))))
+ goto err;
+
+ if (!TEST_ptr(params_exp = OSSL_PARAM_BLD_to_param(bld))
+ || !TEST_ptr(group_exp =
+ EC_GROUP_new_from_params(params_exp, NULL, NULL))
+ || !TEST_ptr(params_exp2 =
+ EC_GROUP_to_params(group_exp, NULL, NULL, NULL))
+ || !TEST_ptr(group_exp2 =
+ EC_GROUP_new_from_params(params_exp2, NULL, NULL))
+ || !TEST_int_eq(EC_GROUP_cmp(group_exp, group_exp2, NULL), 0))
+ goto err;
+
+ r = 1;
+
+err:
+ EC_GROUP_free(group_nmd);
+ EC_GROUP_free(group_nmd2);
+ EC_GROUP_free(group_nmd3);
+ OSSL_PARAM_free(params_nmd);
+ OSSL_PARAM_free(params_nmd2);
+ OPENSSL_free(buf);
+
+ EC_GROUP_free(group_exp);
+ EC_GROUP_free(group_exp2);
+ BN_CTX_end(bn_ctx);
+ BN_CTX_free(bn_ctx);
+ OPENSSL_free(buf2);
+ OSSL_PARAM_BLD_free(bld);
+ OSSL_PARAM_free(params_exp);
+ OSSL_PARAM_free(params_exp2);
+ return r;
+}
+
+/*-
+ * random 256-bit explicit parameters curve, cofactor absent
+ * order: 0x0c38d96a9f892b88772ec2e39614a82f4f (132 bit)
+ * cofactor: 0x12bc94785251297abfafddf1565100da (125 bit)
+ */
+static const unsigned char params_cf_pass[] = {
+ 0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xe5, 0x00, 0x1f, 0xc5,
+ 0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
+ 0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
+ 0x44, 0x88, 0xe6, 0x91, 0x30, 0x44, 0x04, 0x20, 0xe5, 0x00, 0x1f, 0xc5,
+ 0xca, 0x71, 0x9d, 0x8e, 0xf7, 0x07, 0x4b, 0x48, 0x37, 0xf9, 0x33, 0x2d,
+ 0x71, 0xbf, 0x79, 0xe7, 0xdc, 0x91, 0xc2, 0xff, 0xb6, 0x7b, 0xc3, 0x93,
+ 0x44, 0x88, 0xe6, 0x8e, 0x04, 0x20, 0x18, 0x8c, 0x59, 0x57, 0xc4, 0xbc,
+ 0x85, 0x57, 0xc3, 0x66, 0x9f, 0x89, 0xd5, 0x92, 0x0d, 0x7e, 0x42, 0x27,
+ 0x07, 0x64, 0xaa, 0x26, 0xed, 0x89, 0xc4, 0x09, 0x05, 0x4d, 0xc7, 0x23,
+ 0x47, 0xda, 0x04, 0x41, 0x04, 0x1b, 0x6b, 0x41, 0x0b, 0xf9, 0xfb, 0x77,
+ 0xfd, 0x50, 0xb7, 0x3e, 0x23, 0xa3, 0xec, 0x9a, 0x3b, 0x09, 0x31, 0x6b,
+ 0xfa, 0xf6, 0xce, 0x1f, 0xff, 0xeb, 0x57, 0x93, 0x24, 0x70, 0xf3, 0xf4,
+ 0xba, 0x7e, 0xfa, 0x86, 0x6e, 0x19, 0x89, 0xe3, 0x55, 0x6d, 0x5a, 0xe9,
+ 0xc0, 0x3d, 0xbc, 0xfb, 0xaf, 0xad, 0xd4, 0x7e, 0xa6, 0xe5, 0xfa, 0x1a,
+ 0x58, 0x07, 0x9e, 0x8f, 0x0d, 0x3b, 0xf7, 0x38, 0xca, 0x02, 0x11, 0x0c,
+ 0x38, 0xd9, 0x6a, 0x9f, 0x89, 0x2b, 0x88, 0x77, 0x2e, 0xc2, 0xe3, 0x96,
+ 0x14, 0xa8, 0x2f, 0x4f
+};
+
+/*-
+ * random 256-bit explicit parameters curve, cofactor absent
+ * order: 0x045a75c0c17228ebd9b169a10e34a22101 (131 bit)
+ * cofactor: 0x2e134b4ede82649f67a2e559d361e5fe (126 bit)
+ */
+static const unsigned char params_cf_fail[] = {
+ 0x30, 0x81, 0xcd, 0x02, 0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86,
+ 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21, 0x00, 0xc8, 0x95, 0x27, 0x37,
+ 0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
+ 0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
+ 0x33, 0xc2, 0xea, 0x13, 0x30, 0x44, 0x04, 0x20, 0xc8, 0x95, 0x27, 0x37,
+ 0xe8, 0xe1, 0xfd, 0xcc, 0xf9, 0x6e, 0x0c, 0xa6, 0x21, 0xc1, 0x7d, 0x6b,
+ 0x9d, 0x44, 0x42, 0xea, 0x73, 0x4e, 0x04, 0xb6, 0xac, 0x62, 0x50, 0xd0,
+ 0x33, 0xc2, 0xea, 0x10, 0x04, 0x20, 0xbf, 0xa6, 0xa8, 0x05, 0x1d, 0x09,
+ 0xac, 0x70, 0x39, 0xbb, 0x4d, 0xb2, 0x90, 0x8a, 0x15, 0x41, 0x14, 0x1d,
+ 0x11, 0x86, 0x9f, 0x13, 0xa2, 0x63, 0x1a, 0xda, 0x95, 0x22, 0x4d, 0x02,
+ 0x15, 0x0a, 0x04, 0x41, 0x04, 0xaf, 0x16, 0x71, 0xf9, 0xc4, 0xc8, 0x59,
+ 0x1d, 0xa3, 0x6f, 0xe7, 0xc3, 0x57, 0xa1, 0xfa, 0x9f, 0x49, 0x7c, 0x11,
+ 0x27, 0x05, 0xa0, 0x7f, 0xff, 0xf9, 0xe0, 0xe7, 0x92, 0xdd, 0x9c, 0x24,
+ 0x8e, 0xc7, 0xb9, 0x52, 0x71, 0x3f, 0xbc, 0x7f, 0x6a, 0x9f, 0x35, 0x70,
+ 0xe1, 0x27, 0xd5, 0x35, 0x8a, 0x13, 0xfa, 0xa8, 0x33, 0x3e, 0xd4, 0x73,
+ 0x1c, 0x14, 0x58, 0x9e, 0xc7, 0x0a, 0x87, 0x65, 0x8d, 0x02, 0x11, 0x04,
+ 0x5a, 0x75, 0xc0, 0xc1, 0x72, 0x28, 0xeb, 0xd9, 0xb1, 0x69, 0xa1, 0x0e,
+ 0x34, 0xa2, 0x21, 0x01
+};
+
+/*-
+ * Test two random 256-bit explicit parameters curves with absent cofactor.
+ * The two curves are chosen to roughly straddle the bounds at which the lib
+ * can compute the cofactor automatically, roughly 4*sqrt(p). So test that:
+ *
+ * - params_cf_pass: order is sufficiently close to p to compute cofactor
+ * - params_cf_fail: order is too far away from p to compute cofactor
+ *
+ * For standards-compliant curves, cofactor is chosen as small as possible.
+ * So you can see neither of these curves are fit for cryptographic use.
+ *
+ * Some standards even mandate an upper bound on the cofactor, e.g. SECG1 v2:
+ * h <= 2**(t/8) where t is the security level of the curve, for which the lib
+ * will always succeed in computing the cofactor. Neither of these curves
+ * conform to that -- this is just robustness testing.
+ */
+static int cofactor_range_test(void)
+{
+ EC_GROUP *group = NULL;
+ BIGNUM *cf = NULL;
+ int ret = 0;
+ const unsigned char *b1 = (const unsigned char *)params_cf_fail;
+ const unsigned char *b2 = (const unsigned char *)params_cf_pass;
+
+ if (!TEST_ptr(group = d2i_ECPKParameters(NULL, &b1, sizeof(params_cf_fail)))
+ || !TEST_BN_eq_zero(EC_GROUP_get0_cofactor(group))
+ || !TEST_ptr(group = d2i_ECPKParameters(&group, &b2,
+ sizeof(params_cf_pass)))
+ || !TEST_int_gt(BN_hex2bn(&cf, "12bc94785251297abfafddf1565100da"), 0)
+ || !TEST_BN_eq(cf, EC_GROUP_get0_cofactor(group)))
+ goto err;
+ ret = 1;
+ err:
+ BN_free(cf);
+ EC_GROUP_free(group);
+ return ret;
+}
+
+/*-
+ * For named curves, test that:
+ * - the lib correctly computes the cofactor if passed a NULL or zero cofactor
+ * - a nonsensical cofactor throws an error (negative test)
+ * - nonsensical orders throw errors (negative tests)
+ */
+static int cardinality_test(int n)
+{
+ int ret = 0, is_binary = 0;
+ int nid = curves[n].nid;
+ BN_CTX *ctx = NULL;
+ EC_GROUP *g1 = NULL, *g2 = NULL;
+ EC_POINT *g2_gen = NULL;
+ BIGNUM *g1_p = NULL, *g1_a = NULL, *g1_b = NULL, *g1_x = NULL, *g1_y = NULL,
+ *g1_order = NULL, *g1_cf = NULL, *g2_cf = NULL;
+
+ TEST_info("Curve %s cardinality test", OBJ_nid2sn(nid));
+
+ if (!TEST_ptr(ctx = BN_CTX_new())
+ || !TEST_ptr(g1 = EC_GROUP_new_by_curve_name(nid))) {
+ BN_CTX_free(ctx);
+ return 0;
+ }
+
+ is_binary = (EC_GROUP_get_field_type(g1) == NID_X9_62_characteristic_two_field);
+
+ BN_CTX_start(ctx);
+ g1_p = BN_CTX_get(ctx);
+ g1_a = BN_CTX_get(ctx);
+ g1_b = BN_CTX_get(ctx);
+ g1_x = BN_CTX_get(ctx);
+ g1_y = BN_CTX_get(ctx);
+ g1_order = BN_CTX_get(ctx);
+ g1_cf = BN_CTX_get(ctx);
+
+ if (!TEST_ptr(g2_cf = BN_CTX_get(ctx))
+ /* pull out the explicit curve parameters */
+ || !TEST_true(EC_GROUP_get_curve(g1, g1_p, g1_a, g1_b, ctx))
+ || !TEST_true(EC_POINT_get_affine_coordinates(g1,
+ EC_GROUP_get0_generator(g1), g1_x, g1_y, ctx))
+ || !TEST_true(BN_copy(g1_order, EC_GROUP_get0_order(g1)))
+ || !TEST_true(EC_GROUP_get_cofactor(g1, g1_cf, ctx))
+ /* construct g2 manually with g1 parameters */
+#ifndef OPENSSL_NO_EC2M
+ || !TEST_ptr(g2 = (is_binary) ?
+ EC_GROUP_new_curve_GF2m(g1_p, g1_a, g1_b, ctx) :
+ EC_GROUP_new_curve_GFp(g1_p, g1_a, g1_b, ctx))
+#else
+ || !TEST_int_eq(0, is_binary)
+ || !TEST_ptr(g2 = EC_GROUP_new_curve_GFp(g1_p, g1_a, g1_b, ctx))
+#endif
+ || !TEST_ptr(g2_gen = EC_POINT_new(g2))
+ || !TEST_true(EC_POINT_set_affine_coordinates(g2, g2_gen, g1_x, g1_y, ctx))
+ /* pass NULL cofactor: lib should compute it */
+ || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+ || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
+ || !TEST_BN_eq(g1_cf, g2_cf)
+ /* pass zero cofactor: lib should compute it */
+ || !TEST_true(BN_set_word(g2_cf, 0))
+ || !TEST_true(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
+ || !TEST_true(EC_GROUP_get_cofactor(g2, g2_cf, ctx))
+ || !TEST_BN_eq(g1_cf, g2_cf)
+ /* negative test for invalid cofactor */
+ || !TEST_true(BN_set_word(g2_cf, 0))
+ || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
+ || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, g2_cf))
+ /* negative test for NULL order */
+ || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, NULL, NULL))
+ /* negative test for zero order */
+ || !TEST_true(BN_set_word(g1_order, 0))
+ || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+ /* negative test for negative order */
+ || !TEST_true(BN_set_word(g2_cf, 0))
+ || !TEST_true(BN_sub(g2_cf, g2_cf, BN_value_one()))
+ || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL))
+ /* negative test for too large order */
+ || !TEST_true(BN_lshift(g1_order, g1_p, 2))
+ || !TEST_false(EC_GROUP_set_generator(g2, g2_gen, g1_order, NULL)))
+ goto err;
+ ret = 1;
+ err:
+ EC_POINT_free(g2_gen);
+ EC_GROUP_free(g1);
+ EC_GROUP_free(g2);
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+ return ret;
+}
+
+static int check_ec_key_field_public_range_test(int id)
+{
+ int ret = 0, type = 0;
+ const EC_POINT *pub = NULL;
+ const EC_GROUP *group = NULL;
+ const BIGNUM *field = NULL;
+ BIGNUM *x = NULL, *y = NULL;
+ EC_KEY *key = NULL;
+
+ if (!TEST_ptr(x = BN_new())
+ || !TEST_ptr(y = BN_new())
+ || !TEST_ptr(key = EC_KEY_new_by_curve_name(curves[id].nid))
+ || !TEST_ptr(group = EC_KEY_get0_group(key))
+ || !TEST_ptr(field = EC_GROUP_get0_field(group))
+ || !TEST_int_gt(EC_KEY_generate_key(key), 0)
+ || !TEST_int_gt(EC_KEY_check_key(key), 0)
+ || !TEST_ptr(pub = EC_KEY_get0_public_key(key))
+ || !TEST_int_gt(EC_POINT_get_affine_coordinates(group, pub, x, y,
+ NULL), 0))
+ goto err;
+
+ /*
+ * Make the public point out of range by adding the field (which will still
+ * be the same point on the curve). The add is different for char2 fields.
+ */
+ type = EC_GROUP_get_field_type(group);
+#ifndef OPENSSL_NO_EC2M
+ if (type == NID_X9_62_characteristic_two_field) {
+ /* test for binary curves */
+ if (!TEST_true(BN_GF2m_add(x, x, field)))
+ goto err;
+ } else
+#endif
+ if (type == NID_X9_62_prime_field) {
+ /* test for prime curves */
+ if (!TEST_true(BN_add(x, x, field)))
+ goto err;
+ } else {
+ /* this should never happen */
+ TEST_error("Unsupported EC_METHOD field_type");
+ goto err;
+ }
+ if (!TEST_int_le(EC_KEY_set_public_key_affine_coordinates(key, x, y), 0))
+ goto err;
+
+ ret = 1;
+err:
+ BN_free(x);
+ BN_free(y);
+ EC_KEY_free(key);
+ return ret;
+}
+
+/*
+ * Helper for ec_point_hex2point_test
+ *
+ * Self-tests EC_POINT_point2hex() against EC_POINT_hex2point() for the given
+ * (group,P) pair.
+ *
+ * If P is NULL use point at infinity.
+ */
+static ossl_inline
+int ec_point_hex2point_test_helper(const EC_GROUP *group, const EC_POINT *P,
+ point_conversion_form_t form,
+ BN_CTX *bnctx)
+{
+ int ret = 0;
+ EC_POINT *Q = NULL, *Pinf = NULL;
+ char *hex = NULL;
+
+ if (P == NULL) {
+ /* If P is NULL use point at infinity. */
+ if (!TEST_ptr(Pinf = EC_POINT_new(group))
+ || !TEST_true(EC_POINT_set_to_infinity(group, Pinf)))
+ goto err;
+ P = Pinf;
+ }
+
+ if (!TEST_ptr(hex = EC_POINT_point2hex(group, P, form, bnctx))
+ || !TEST_ptr(Q = EC_POINT_hex2point(group, hex, NULL, bnctx))
+ || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, bnctx)))
+ goto err;
+
+ /*
+ * The next check is most likely superfluous, as EC_POINT_cmp should already
+ * cover this.
+ * Nonetheless it increases the test coverage for EC_POINT_is_at_infinity,
+ * so we include it anyway!
+ */
+ if (Pinf != NULL
+ && !TEST_true(EC_POINT_is_at_infinity(group, Q)))
+ goto err;
+
+ ret = 1;
+
+ err:
+ EC_POINT_free(Pinf);
+ OPENSSL_free(hex);
+ EC_POINT_free(Q);
+
+ return ret;
+}
+
+/*
+ * This test self-validates EC_POINT_hex2point() and EC_POINT_point2hex()
+ */
+static int ec_point_hex2point_test(int id)
+{
+ int ret = 0, nid;
+ EC_GROUP *group = NULL;
+ const EC_POINT *G = NULL;
+ EC_POINT *P = NULL;
+ BN_CTX *bnctx = NULL;
+
+ /* Do some setup */
+ nid = curves[id].nid;
+ if (!TEST_ptr(bnctx = BN_CTX_new())
+ || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid))
+ || !TEST_ptr(G = EC_GROUP_get0_generator(group))
+ || !TEST_ptr(P = EC_POINT_dup(G, group)))
+ goto err;
+
+ if (!TEST_true(ec_point_hex2point_test_helper(group, P,
+ POINT_CONVERSION_COMPRESSED,
+ bnctx))
+ || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+ POINT_CONVERSION_COMPRESSED,
+ bnctx))
+ || !TEST_true(ec_point_hex2point_test_helper(group, P,
+ POINT_CONVERSION_UNCOMPRESSED,
+ bnctx))
+ || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+ POINT_CONVERSION_UNCOMPRESSED,
+ bnctx))
+ || !TEST_true(ec_point_hex2point_test_helper(group, P,
+ POINT_CONVERSION_HYBRID,
+ bnctx))
+ || !TEST_true(ec_point_hex2point_test_helper(group, NULL,
+ POINT_CONVERSION_HYBRID,
+ bnctx)))
+ goto err;
+
+ ret = 1;
+
+ err:
+ EC_POINT_free(P);
+ EC_GROUP_free(group);
+ BN_CTX_free(bnctx);
+
+ return ret;
+}
+
+static int do_test_custom_explicit_fromdata(EC_GROUP *group, BN_CTX *ctx,
+ unsigned char *gen, int gen_size)
+{
+ int ret = 0, i_out;
+ EVP_PKEY_CTX *pctx = NULL;
+ EVP_PKEY *pkeyparam = NULL;
+ OSSL_PARAM_BLD *bld = NULL;
+ const char *field_name;
+ OSSL_PARAM *params = NULL;
+ const OSSL_PARAM *gettable;
+ BIGNUM *p, *a, *b;
+ BIGNUM *p_out = NULL, *a_out = NULL, *b_out = NULL;
+ BIGNUM *order_out = NULL, *cofactor_out = NULL;
+ char name[80];
+ unsigned char buf[1024];
+ size_t buf_len, name_len;
+#ifndef OPENSSL_NO_EC2M
+ unsigned int k1 = 0, k2 = 0, k3 = 0;
+ const char *basis_name = NULL;