[PATCH 6/8] mpi:ec: Use affine coordinate for mpi_ec_mul_point_lli.
NIIBE Yutaka via Gcrypt-devel <[email protected]> Thu, 27 Mar 2025 14:19:09 +0900
| Newsgroups | gmane.comp.encryption.gpg.libgcrypt.devel |
|---|---|
| Message-ID | <de69a27fa12b0e4d7820ed5b2ec197ff37e074ca.1743052412.git.gniibe@fsij.org> |
* mpi/ec.c (add_points_weierstrass_a, add_points_edwards_a): New. (mpi_ec_mul_point_lli): Use those routines directly. -- GnuPG-bug-id: 7519 Signed-off-by: NIIBE Yutaka <[email protected]> --- mpi/ec.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 237 insertions(+), 10 deletions(-) _______________________________________________ Gcrypt-devel mailing list [email protected] https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
0006-mpi-ec-Use-affine-coordinate-for-mpi_ec_mul_point_ll.patch
(text/x-patch, 8.1 KB)
diff --git a/mpi/ec.c b/mpi/ec.c
index d13c0fd8..7ee616bb 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1396,6 +1396,81 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
}
+/* RESULT = P1 + P2 (Weierstrass version).
+ * P2 is represented by affine coordinate (X2,Y2).
+ * P1 is never same to P1. */
+static void
+add_points_weierstrass_a (mpi_point_t result,
+ mpi_point_t p1,
+ gcry_mpi_t x2, gcry_mpi_t y2,
+ mpi_ec_t ctx)
+{
+#define x1 (p1->x )
+#define y1 (p1->y )
+#define z1 (p1->z )
+#define x3 (result->x)
+#define y3 (result->y)
+#define z3 (result->z)
+#define l1 (ctx->t.scratch[0])
+#define l2 (ctx->t.scratch[1])
+#define l3 (ctx->t.scratch[2])
+#define l4 (ctx->t.scratch[3])
+#define l5 (ctx->t.scratch[4])
+#define l6 (ctx->t.scratch[5])
+#define l7 (ctx->t.scratch[6])
+#define l8 (ctx->t.scratch[7])
+#define l9 (ctx->t.scratch[8])
+
+ /* l2 = x2 z1^2 */
+ ec_pow2 (l5, z1, ctx);
+ ec_mulm (l2, l5, x2, ctx);
+ /* l3 = x1 - l2 */
+ ec_subm (l3, x1, l2, ctx);
+ /* l5 = y2 z1^3 */
+ ec_mulm (l5, z1, l5, ctx);
+ ec_mulm (l5, l5, y2, ctx);
+ /* l6 = y1 - l5 */
+ ec_subm (l6, y1, l5, ctx);
+
+ /* l7 = x1 + l2 */
+ ec_addm (l7, x1, l2, ctx);
+ /* l8 = y1 + l5 */
+ ec_addm (l8, y1, l5, ctx);
+ /* z3 = z1 l3 */
+ ec_mulm (z3, z1, l3, ctx);
+ /* x3 = l6^2 - l7 l3^2 */
+ ec_pow2 (l1, l6, ctx);
+ ec_pow2 (l2, l3, ctx);
+ ec_mulm (l4, l2, l7, ctx);
+ ec_subm (x3, l1, l4, ctx);
+ /* l9 = l7 l3^2 - 2 x3 */
+ ec_mul2 (l1, x3, ctx);
+ ec_subm (l9, l4, l1, ctx);
+ /* y3 = (l9 l6 - l8 l3^3)/2 */
+ ec_mulm (l9, l9, l6, ctx);
+ ec_mulm (l1, l3, l2, ctx);
+ ec_mulm (l1, l1, l8, ctx);
+ ec_subm (y3, l9, l1, ctx);
+ ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
+
+#undef x1
+#undef y1
+#undef z1
+#undef x3
+#undef y3
+#undef z3
+#undef l1
+#undef l2
+#undef l3
+#undef l4
+#undef l5
+#undef l6
+#undef l7
+#undef l8
+#undef l9
+}
+
+
/* RESULT = P1 + P2 (Weierstrass version).*/
static void
add_points_weierstrass (mpi_point_t result,
@@ -1562,7 +1637,7 @@ add_points_edwards (mpi_point_t result,
mpi_point_resize (result, ctx);
- /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3) */
+ /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_2) */
/* A = Z1 · Z2 */
ctx->mulm (A, Z1, Z2, ctx);
@@ -1632,6 +1707,99 @@ add_points_edwards (mpi_point_t result,
}
+/* RESULT = P1 + P2 (Twisted Edwards version).
+ * P2 is represented by affine coordinate (X2,Y2).
+ * P1 is never same to P1. */
+static void
+add_points_edwards_a (mpi_point_t result,
+ mpi_point_t p1,
+ gcry_mpi_t x2, gcry_mpi_t y2,
+ mpi_ec_t ctx)
+{
+#define X1 (p1->x)
+#define Y1 (p1->y)
+#define Z1 (p1->z)
+#define X2 x2
+#define Y2 y2
+#define X3 (result->x)
+#define Y3 (result->y)
+#define Z3 (result->z)
+#define B (ctx->t.scratch[1])
+#define C (ctx->t.scratch[2])
+#define D (ctx->t.scratch[3])
+#define E (ctx->t.scratch[4])
+#define F (ctx->t.scratch[5])
+#define G (ctx->t.scratch[6])
+#define tmp (ctx->t.scratch[7])
+
+ mpi_point_resize (result, ctx);
+
+ /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : 1) */
+
+ /* B = Z1^2 */
+ ctx->pow2 (B, Z1, ctx);
+
+ /* C = X1 · X2 */
+ ctx->mulm (C, X1, X2, ctx);
+
+ /* D = Y1 · Y2 */
+ ctx->mulm (D, Y1, Y2, ctx);
+
+ /* E = d · C · D */
+ ctx->mulm (E, ctx->b, C, ctx);
+ ctx->mulm (E, E, D, ctx);
+
+ /* F = B - E */
+ ctx->subm (F, B, E, ctx);
+
+ /* G = B + E */
+ ctx->addm (G, B, E, ctx);
+
+ /* X_3 = Z1 · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
+ ctx->addm (tmp, X1, Y1, ctx);
+ ctx->addm (X3, X2, Y2, ctx);
+ ctx->mulm (X3, X3, tmp, ctx);
+ ctx->subm (X3, X3, C, ctx);
+ ctx->subm (X3, X3, D, ctx);
+ ctx->mulm (X3, X3, F, ctx);
+ ctx->mulm (X3, X3, Z1, ctx);
+
+ /* Y_3 = Z1 · G · (D - aC) */
+ if (ctx->dialect == ECC_DIALECT_ED25519)
+ {
+ ctx->addm (Y3, D, C, ctx);
+ }
+ else
+ {
+ ctx->mulm (Y3, ctx->a, C, ctx);
+ ctx->subm (Y3, D, Y3, ctx);
+ }
+ ctx->mulm (Y3, Y3, G, ctx);
+ ctx->mulm (Y3, Y3, Z1, ctx);
+
+ /* Z_3 = F · G */
+ ctx->mulm (Z3, F, G, ctx);
+
+
+#undef X1
+#undef Y1
+#undef Z1
+#undef X2
+#undef Y2
+#undef X3
+#undef Y3
+#undef Z3
+#undef A
+#undef B
+#undef C
+#undef D
+#undef E
+#undef F
+#undef G
+#undef tmp
+}
+
+
/* Compute a step of Montgomery Ladder (only use X and Z in the point).
Inputs: P1, P2, and x-coordinate of DIF = P1 - P1.
Outputs: PRD = 2 * P1 and SUM = P1 + P2. */
@@ -1858,17 +2026,50 @@ montgomery_mul_point (mpi_point_t result,
/* Compute scalar point multiplication, Least Leak Intended. */
static void
mpi_ec_mul_point_lli (mpi_point_t result,
- gcry_mpi_t scalar, mpi_point_t point,
+ gcry_mpi_t scalar, mpi_point_t point1,
mpi_ec_t ctx)
{
unsigned int nbits;
int j;
mpi_point_struct tmppnt;
+ mpi_point_struct point_;
+ mpi_point_t point = &point_;
+
+ mpi_point_resize (point1, ctx);
+
+ /* Convert POINT1 into affine coordinate, so that we can use
+ add_points_*_a routine with affine coordinate. */
+ point_init (point);
+ if (_gcry_mpih_cmp_ui (point1->z->d, ctx->p->nlimbs, 1))
+ {
+ gcry_mpi_t x, y;
- if (mpi_cmp (scalar, ctx->p) >= 0)
- nbits = mpi_get_nbits (scalar);
+ x = mpi_new (0);
+ y = mpi_new (0);
+
+ if (_gcry_mpi_ec_get_affine (x, y, point1, ctx))
+ {
+ mpi_free (x);
+ mpi_free (y);
+ point_free (point);
+ point_set (result, point1);
+ return;
+ }
+
+ mpi_set (point->x, x);
+ mpi_set (point->y, y);
+ mpi_set_ui (point->z, 1);
+ mpi_free (x);
+ mpi_free (y);
+ }
else
- nbits = mpi_get_nbits (ctx->p);
+ point_set (point, point1);
+
+ mpi_point_resize (point, ctx);
+
+ nbits = mpi_get_nbits (scalar);
+ if (nbits < ctx->nbits)
+ nbits = ctx->nbits;
if (ctx->model == MPI_EC_WEIERSTRASS)
{
@@ -1881,19 +2082,40 @@ mpi_ec_mul_point_lli (mpi_point_t result,
mpi_set_ui (result->x, 0);
mpi_set_ui (result->y, 1);
mpi_set_ui (result->z, 1);
- mpi_point_resize (point, ctx);
}
point_init (&tmppnt);
mpi_point_resize (result, ctx);
mpi_point_resize (&tmppnt, ctx);
- for (j=nbits-1; j >= 0; j--)
+ if (ctx->model == MPI_EC_WEIERSTRASS)
{
- _gcry_mpi_ec_dup_point (result, result, ctx);
- _gcry_mpi_ec_add_points (&tmppnt, result, point, ctx);
- point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+ for (j=nbits-1; j >= 0; j--)
+ {
+ unsigned long is_z_zero;
+
+ dup_point_weierstrass (result, result, ctx);
+ is_z_zero = _gcry_mpih_cmp_ui (result->z->d, ctx->p->nlimbs, 0) == 0;
+ add_points_weierstrass_a (&tmppnt, result, point->x, point->y, ctx);
+ mpi_point_resize (&tmppnt, ctx);
+ /* When P1 is O (at infinity), computation of
+ add_points_weierstrass_a is invalid, and RESULT is P2. */
+ mpih_set_cond (tmppnt.x->d, point->x->d, ctx->p->nlimbs, is_z_zero);
+ mpih_set_cond (tmppnt.y->d, point->y->d, ctx->p->nlimbs, is_z_zero);
+ mpih_set_cond (tmppnt.z->d, point->z->d, ctx->p->nlimbs, is_z_zero);
+ point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+ }
+ }
+ else /* MPI_EC_EDWARDS */
+ {
+ for (j=nbits-1; j >= 0; j--)
+ {
+ dup_point_edwards (result, result, ctx);
+ add_points_edwards_a (&tmppnt, result, point->x, point->y, ctx);
+ point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+ }
}
point_free (&tmppnt);
+ point_free (point);
}
@@ -1922,6 +2144,11 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
montgomery_mul_point (result, scalar, point, ctx);
return;
}
+ else if ((ctx->flags & GCRYECC_FLAG_LEAST_LEAK))
+ {
+ mpi_ec_mul_point_lli (result, scalar, point, ctx);
+ return;
+ }
else if (mpi_is_secure (scalar))
{
mpi_ec_mul_point_lli (result, scalar, point, ctx);