diff mbox series

[3/3] ecc: Add helper for creating a scalar modulo curve order

Message ID 20231109142056.12385-3-marcel@holtmann.org (mailing list archive)
State New
Headers show
Series [1/3] ecc: Make product variable of _vli_mmod_fast const | expand

Checks

Context Check Description
tedd_an/pre-ci_am success Success

Commit Message

Marcel Holtmann Nov. 9, 2023, 2:20 p.m. UTC
The SPAKE2+ key exchange protocol requires the ability have a scalar
modulo curve order. This adds a helper that allows to create a new
scalar and run modulo curver order on it. This is similar to the
helper that does the same with the curve prime value.
---
 ell/ecc.c   | 35 +++++++++++++++++++++++++++++++++++
 ell/ecc.h   |  2 ++
 ell/ell.sym |  1 +
 3 files changed, 38 insertions(+)
diff mbox series

Patch

diff --git a/ell/ecc.c b/ell/ecc.c
index ff147b84ed74..2124856dfe99 100644
--- a/ell/ecc.c
+++ b/ell/ecc.c
@@ -846,6 +846,41 @@  LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_modp(
 	return NULL;
 }
 
+LIB_EXPORT struct l_ecc_scalar *l_ecc_scalar_new_modn(
+					const struct l_ecc_curve *curve,
+					const void *bytes, size_t len)
+{
+	struct l_ecc_scalar *c;
+	uint64_t tmp[2 * L_ECC_MAX_DIGITS];
+	unsigned int ndigits = len / 8;
+
+	if (!bytes)
+		return NULL;
+
+	if (len % 8)
+		return NULL;
+
+	if (ndigits > curve->ndigits * 2)
+		return NULL;
+
+	c = _ecc_constant_new(curve, NULL, 0);
+	if (!c)
+		return NULL;
+
+	memset(tmp, 0, sizeof(tmp));
+	_ecc_be2native(tmp, bytes, ndigits);
+
+	_vli_mmod_slow(c->c, tmp, curve->n, curve->ndigits);
+
+	if (!_vli_is_zero_or_one(c->c, curve->ndigits) &&
+			secure_memcmp_64(curve->n, c->c, curve->ndigits) > 0)
+		return c;
+
+	l_ecc_scalar_free(c);
+
+	return NULL;
+}
+
 /*
  * Takes a buffer of the same size as the curve and scales it to a range
  * 1..n using value = (value mod (n - 1)) + 1.  For the curves we support
diff --git a/ell/ecc.h b/ell/ecc.h
index de116f018b44..5a8cf0341acc 100644
--- a/ell/ecc.h
+++ b/ell/ecc.h
@@ -66,6 +66,8 @@  struct l_ecc_scalar *l_ecc_scalar_new_random(
 					const struct l_ecc_curve *curve);
 struct l_ecc_scalar *l_ecc_scalar_new_modp(const struct l_ecc_curve *curve,
 						const void *buf, size_t len);
+struct l_ecc_scalar *l_ecc_scalar_new_modn(const struct l_ecc_curve *curve,
+						const void *buf, size_t len);
 struct l_ecc_scalar *l_ecc_scalar_new_reduced_1_to_n(
 					const struct l_ecc_curve *curve,
 					const void *buf, size_t len);
diff --git a/ell/ell.sym b/ell/ell.sym
index 0f593e1fc402..a887b2b09520 100644
--- a/ell/ell.sym
+++ b/ell/ell.sym
@@ -608,6 +608,7 @@  global:
 	l_ecc_scalar_new;
 	l_ecc_scalar_new_random;
 	l_ecc_scalar_new_modp;
+	l_ecc_scalar_new_modn;
 	l_ecc_scalar_new_reduced_1_to_n;
 	l_ecc_scalar_sum_x;
 	l_ecc_scalars_are_equal;