summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Mihatsch <oliver.mihatsch@virtual-solution.com>2023-02-02 12:15:14 +0100
committerTodd Short <todd.short@me.com>2023-02-08 10:27:07 -0500
commita8aad913ecc632405096b2b61942b2c782cc74f4 (patch)
tree50d837c6a5166070c7012e619c0eece502f92231
parentee17148792943f7f6455213a3b9a86a4cc082c9a (diff)
New function EC_GROUP_to_params to convert an EC_GROUP to an array of OSSL_PARAM.
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Todd Short <todd.short@me.com> (Merged from https://github.com/openssl/openssl/pull/20205)
-rw-r--r--CHANGES.md5
-rw-r--r--crypto/ec/ec_lib.c36
-rw-r--r--doc/man3/EC_GROUP_new.pod13
-rw-r--r--include/openssl/ec.h16
-rw-r--r--test/ectest.c113
-rw-r--r--util/libcrypto.num1
6 files changed, 184 insertions, 0 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 1f76a23d2f..77a053a425 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -25,6 +25,11 @@ OpenSSL 3.2
### Changes between 3.1 and 3.2 [xx XXX xxxx]
+ * Added EC_GROUP_to_params which creates an OSSL_PARAM array
+ from a given EC_GROUP.
+
+ *Oliver Mihatsch*
+
* Added support for Hybrid Public Key Encryption (HPKE) as defined
in RFC9180. HPKE is required for TLS Encrypted ClientHello (ECH),
Message Layer Security (MLS) and other IETF specifications.
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index 2e7139cbdd..9e262b427d 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -19,6 +19,7 @@
#include <openssl/core_names.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
+#include <openssl/param_build.h>
#include "crypto/ec.h"
#include "internal/nelem.h"
#include "ec_local.h"
@@ -1748,3 +1749,38 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
return group;
#endif /* FIPS_MODULE */
}
+
+OSSL_PARAM *EC_GROUP_to_params(const EC_GROUP *group, OSSL_LIB_CTX *libctx,
+ const char *propq, BN_CTX *bnctx)
+{
+ OSSL_PARAM_BLD *tmpl = NULL;
+ BN_CTX *new_bnctx = NULL;
+ unsigned char *gen_buf = NULL;
+ OSSL_PARAM *params = NULL;
+
+ if (group == NULL)
+ goto err;
+
+ tmpl = OSSL_PARAM_BLD_new();
+ if (tmpl == NULL)
+ goto err;
+
+ if (bnctx == NULL)
+ bnctx = new_bnctx = BN_CTX_new_ex(libctx);
+ if (bnctx == NULL)
+ goto err;
+ BN_CTX_start(bnctx);
+
+ if (!ossl_ec_group_todata(
+ group, tmpl, NULL, libctx, propq, bnctx, &gen_buf))
+ goto err;
+
+ params = OSSL_PARAM_BLD_to_param(tmpl);
+
+ err:
+ OSSL_PARAM_BLD_free(tmpl);
+ OPENSSL_free(gen_buf);
+ BN_CTX_end(bnctx);
+ BN_CTX_free(new_bnctx);
+ return params;
+}
diff --git a/doc/man3/EC_GROUP_new.pod b/doc/man3/EC_GROUP_new.pod
index b6d67b6176..d7f8d001c2 100644
--- a/doc/man3/EC_GROUP_new.pod
+++ b/doc/man3/EC_GROUP_new.pod
@@ -5,6 +5,7 @@
EC_GROUP_get_ecparameters,
EC_GROUP_get_ecpkparameters,
EC_GROUP_new_from_params,
+EC_GROUP_to_params,
EC_GROUP_new_from_ecparameters,
EC_GROUP_new_from_ecpkparameters,
EC_GROUP_new,
@@ -30,6 +31,8 @@ Functions for creating and destroying EC_GROUP objects
EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx, const char *propq);
+ OSSL_PARAM *EC_GROUP_to_params(const EC_GROUP *group, OSSL_LIB_CTX *libctx,
+ const char *propq, BN_CTX *bnctx);
EC_GROUP *EC_GROUP_new_from_ecparameters(const ECPARAMETERS *params);
EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params);
void EC_GROUP_free(EC_GROUP *group);
@@ -107,6 +110,16 @@ The values for I<ctx> and I<propq> may be NULL.
The I<params> that can be used are described in
L<B<EVP_PKEY-EC>(7)|EVP_PKEY-EC(7)/Common EC parameters>.
+EC_GROUP_to_params creates an OSSL_PARAM array with the corresponding parameters
+describing the given EC_GROUP. The resulting parameters may contain parameters
+describing a named or explicit curve depending on the EC_GROUP.
+The library context I<libctx> (see L<OSSL_LIB_CTX(3)>) and property query string
+I<propq> are used to fetch algorithms from providers.
+I<bnctx> is an optional preallocated BN_CTX (to save the overhead of allocating
+and freeing the structure in a loop).
+The values for I<libctx>, I<propq> and I<bnctx> may be NULL.
+The caller is responsible for freeing the OSSL_PARAM pointer returned.
+
EC_GROUP_new_from_ecparameters() will create a group from the
specified I<params> and
EC_GROUP_new_from_ecpkparameters() will create a group from the specific PK
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index be9fb2f089..3089dfccd4 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -461,6 +461,22 @@ EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
OSSL_LIB_CTX *libctx, const char *propq);
/**
+ * Creates an OSSL_PARAM array with the parameters describing the given
+ * EC_GROUP.
+ * The resulting parameters may contain an explicit or a named curve depending
+ * on the EC_GROUP.
+ * \param group pointer to the EC_GROUP object
+ * \param libctx The associated library context or NULL for the default
+ * context
+ * \param propq A property query string
+ * \param bnctx BN_CTX object (optional)
+ * \return newly created OSSL_PARAM array with the parameters
+ * describing the given EC_GROUP or NULL if an error occurred
+ */
+OSSL_PARAM *EC_GROUP_to_params(const EC_GROUP *group, OSSL_LIB_CTX *libctx,
+ const char *propq, BN_CTX *bnctx);
+
+/**
* Creates a EC_GROUP object with a curve specified by a NID
* \param libctx The associated library context or NULL for the default
* context
diff --git a/test/ectest.c b/test/ectest.c
index c0337e1c95..f93fd76811 100644
--- a/test/ectest.c
+++ b/test/ectest.c
@@ -2054,6 +2054,118 @@ err:
return r;
}
+/*
+ * 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)
@@ -3015,6 +3127,7 @@ int setup_tests(void)
return 0;
ADD_TEST(parameter_test);
+ ADD_TEST(ossl_parameter_test);
ADD_TEST(cofactor_range_test);
ADD_ALL_TESTS(cardinality_test, crv_len);
ADD_TEST(prime_field_tests);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 2487861a18..78fd4813ee 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -5512,3 +5512,4 @@ BIO_get_wpoll_descriptor ? 3_2_0 EXIST::FUNCTION:
ASN1_item_unpack_ex ? 3_2_0 EXIST::FUNCTION:
PKCS12_SAFEBAG_get1_cert_ex ? 3_2_0 EXIST::FUNCTION:
PKCS12_SAFEBAG_get1_crl_ex ? 3_2_0 EXIST::FUNCTION:
+EC_GROUP_to_params ? 3_2_0 EXIST::FUNCTION:EC