From 1cedeee7fecf2f8d52a79dd2a8fe9050555e9864 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 30 Mar 2020 14:15:16 +0200 Subject: [PATCH] Code cleanup --- .../crypto_core/ed25519/ref10/ed25519_ref10.c | 195 +++++++++++++----- .../ed25519/ref10/fe_25_5/constants.h | 5 + .../ed25519/ref10/fe_51/constants.h | 5 + 3 files changed, 149 insertions(+), 56 deletions(-) diff --git a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c index dda67360..43933c03 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c +++ b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c @@ -53,10 +53,7 @@ load_4(const unsigned char *in) void fe25519_invert(fe25519 out, const fe25519 z) { - fe25519 t0; - fe25519 t1; - fe25519 t2; - fe25519 t3; + fe25519 t0, t1, t2, t3; int i; fe25519_sq(t0, z); @@ -111,9 +108,7 @@ fe25519_invert(fe25519 out, const fe25519 z) static void fe25519_pow22523(fe25519 out, const fe25519 z) { - fe25519 t0; - fe25519 t1; - fe25519 t2; + fe25519 t0, t1, t2; int i; fe25519_sq(t0, z); @@ -179,6 +174,37 @@ fe25519_abs(fe25519 h, const fe25519 f) fe25519_cneg(h, f, fe25519_isnegative(f)); } +static void +fe25519_unchecked_sqrt(fe25519 x, const fe25519 x2) +{ + fe25519 p_root; + fe25519 m_root; + fe25519 m_root2; + fe25519 e; + + fe25519_pow22523(e, x); + fe25519_mul(p_root, e, x); + fe25519_mul(m_root, p_root, sqrtm1); + fe25519_sq(m_root2, m_root); + fe25519_sub(e, x2, m_root2); + fe25519_copy(x, p_root); + fe25519_cmov(x, m_root, fe25519_iszero(e)); +} + +static int +fe25519_sqrt(fe25519 x, const fe25519 x2) +{ + fe25519 check; + fe25519 x2_copy; + + fe25519_copy(x2_copy, x2); + fe25519_unchecked_sqrt(x, x2); + fe25519_sq(check, x); + fe25519_sub(check, check, x2_copy); + + return fe25519_iszero(check) - 1; +} + /* r = p + q */ @@ -2483,7 +2509,6 @@ chi25519(fe25519 out, const fe25519 z) fe25519_mul(t2, t2, t0); fe25519_mul(t1, t2, z); fe25519_sq(t2, t1); - for (i = 1; i < 5; i++) { fe25519_sq(t2, t2); } @@ -2525,84 +2550,128 @@ chi25519(fe25519 out, const fe25519 z) fe25519_mul(out, t1, t0); } +/* montgomery to edwards - xed = sqrt(-A)*x/y */ static void -ge25519_elligator2(unsigned char s[32], const fe25519 r, const unsigned char x_sign) +ge25519_xymont_to_xed(fe25519 xed, const fe25519 x, const fe25519 y) +{ + fe25519 yinv; + + fe25519_invert(yinv, y); + fe25519_mul(xed, x, yinv); + fe25519_mul(xed, xed, sqrtam2); +} + +/* montgomery to edwards -- yed = (x-1)/(x+1) */ +static void +ge25519_xmont_to_yed(fe25519 yed, const fe25519 x) +{ + fe25519 one; + fe25519 x_plus_one; + fe25519 x_plus_one_inv; + fe25519 x_minus_one; + + fe25519_1(one); + fe25519_add(x_plus_one, x, one); + fe25519_sub(x_minus_one, x, one); + fe25519_invert(x_plus_one_inv, x_plus_one); + fe25519_mul(yed, x_minus_one, x_plus_one_inv); +} + +/* montgomery -- recover y = sqrt(x^3 + A*x^2 + x) */ +static int +ge25519_xmont_to_ymont(fe25519 y, const fe25519 x) +{ + fe25519 x2; + fe25519 x3; + + fe25519_sq(x2, x); + fe25519_mul(x3, x, x2); + fe25519_mul(x2, x2, curve25519_A); + fe25519_add(y, x3, x); + fe25519_add(y, y, x2); + + return fe25519_sqrt(y, y); +} + +/* multiply by the cofactor */ +static void +ge25519_clear_cofactor(ge25519_p3 *p3) { - fe25519 e; - fe25519 negx; - fe25519 rr2; - fe25519 x, x2, x3; - ge25519_p3 p3; ge25519_p1p1 p1; ge25519_p2 p2; - unsigned int e_is_minus_1; + + ge25519_p3_dbl(&p1, p3); + ge25519_p1p1_to_p2(&p2, &p1); + ge25519_p2_dbl(&p1, &p2); + ge25519_p1p1_to_p2(&p2, &p1); + ge25519_p2_dbl(&p1, &p2); + ge25519_p1p1_to_p3(p3, &p1); +} + +static void +ge25519_elligator2(fe25519 x, fe25519 y, const fe25519 r) +{ + fe25519 e; + fe25519 gx1; + fe25519 rr2; + fe25519 x2, x3, negx; + unsigned char s[32]; + unsigned int e_is_minus_1; fe25519_sq2(rr2, r); rr2[0]++; fe25519_invert(rr2, rr2); fe25519_mul(x, curve25519_A, rr2); - fe25519_neg(x, x); + fe25519_neg(x, x); /* x=x1 */ fe25519_sq(x2, x); fe25519_mul(x3, x, x2); - fe25519_add(e, x3, x); - fe25519_mul(x2, x2, curve25519_A); - fe25519_add(e, x2, e); - - chi25519(e, e); + fe25519_mul(x2, x2, curve25519_A); /* x2 = A*x1^2 */ + fe25519_add(gx1, x3, x); + fe25519_add(gx1, gx1, x2); /* gx1 = x1^3 + A*x1^2 + x1 */ + chi25519(e, gx1); fe25519_tobytes(s, e); e_is_minus_1 = s[1] & 1; + + /* e=-1 => x = -x1-A */ fe25519_neg(negx, x); fe25519_cmov(x, negx, e_is_minus_1); fe25519_0(x2); fe25519_cmov(x2, curve25519_A, e_is_minus_1); fe25519_sub(x, x, x2); - /* yed = (x-1)/(x+1) */ - { - fe25519 one; - fe25519 x_plus_one; - fe25519 x_plus_one_inv; - fe25519 x_minus_one; - fe25519 yed; - - fe25519_1(one); - fe25519_add(x_plus_one, x, one); - fe25519_sub(x_minus_one, x, one); - fe25519_invert(x_plus_one_inv, x_plus_one); - fe25519_mul(yed, x_minus_one, x_plus_one_inv); - fe25519_tobytes(s, yed); + /* y = sqrt(gx1) or sqrt(gx2) with gx2 = gx1 * (A+x1) / -x1 */ + /* but it is about as fast to just recompute from the curve equation. */ + if (ge25519_xmont_to_ymont(y, x) != 0) { + abort(); } - - /* recover x */ - s[31] |= x_sign; - if (ge25519_frombytes(&p3, s) != 0) { - abort(); /* LCOV_EXCL_LINE */ - } - - /* multiply by the cofactor */ - ge25519_p3_dbl(&p1, &p3); - ge25519_p1p1_to_p2(&p2, &p1); - ge25519_p2_dbl(&p1, &p2); - ge25519_p1p1_to_p2(&p2, &p1); - ge25519_p2_dbl(&p1, &p2); - ge25519_p1p1_to_p3(&p3, &p1); - - ge25519_p3_tobytes(s, &p3); } void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) { + ge25519_p3 p3; + fe25519 x, y, negxed; fe25519 r_fe; unsigned char x_sign; memcpy(s, r, 32); - x_sign = s[31] & 0x80; + x_sign = s[31] >> 7; s[31] &= 0x7f; fe25519_frombytes(r_fe, s); - ge25519_elligator2(s, r_fe, x_sign); + + ge25519_elligator2(x, y, r_fe); + + ge25519_xymont_to_xed(p3.X, x, y); + ge25519_xmont_to_yed(p3.Y, x); + fe25519_neg(negxed, p3.X); + fe25519_cmov(p3.X, negxed, fe25519_isnegative(p3.X) ^ x_sign); + + fe25519_1(p3.Z); + fe25519_mul(p3.T, p3.X, p3.Y); + ge25519_clear_cofactor(&p3); + ge25519_p3_tobytes(s, &p3); } void @@ -2610,12 +2679,13 @@ ge25519_from_hash(unsigned char s[32], const unsigned char h[64]) { unsigned char fl[32]; unsigned char gl[32]; + ge25519_p3 p3; + fe25519 x, y, negy; fe25519 fe_f; fe25519 fe_g; size_t i; - unsigned char x_sign; + unsigned char y_sign; - x_sign = h[0] & 0x80; for (i = 0; i < 32; i++) { fl[i] = h[63 - i]; gl[i] = h[31 - i]; @@ -2629,7 +2699,20 @@ ge25519_from_hash(unsigned char s[32], const unsigned char h[64]) fe_f[i] += 38 * fe_g[i]; } fe25519_reduce(fe_f, fe_f); - ge25519_elligator2(s, fe_f, x_sign); + + ge25519_elligator2(x, y, fe_f); + + y_sign = fe_f[0] & 1; + fe25519_neg(negy, y); + fe25519_cmov(y, negy, fe25519_isnegative(y) ^ y_sign); + + ge25519_xymont_to_xed(p3.X, x, y); + ge25519_xmont_to_yed(p3.Y, x); + + fe25519_1(p3.Z); + fe25519_mul(p3.T, p3.X, p3.Y); + ge25519_clear_cofactor(&p3); + ge25519_p3_tobytes(s, &p3); } /* Ristretto group */ diff --git a/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h b/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h index dd6da1b8..1ac3587c 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h +++ b/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h @@ -38,3 +38,8 @@ static const fe25519 onemsqd = { static const fe25519 sqdmone = { 15551795, -11097455, -13425098, -10125071, -11896535, 10178284, -26634327, 4729244, -5282110, -10116402 }; + +/* sqrt(-486664) */ +static const fe25519 sqrtam2 = { + -12222970, -8312128, -11511410, 9067497, -15300785, -241793, 25456130, 14121551, -12187136, 3972024 +}; diff --git a/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h b/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h index 24e5cb5e..76b2714b 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h +++ b/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h @@ -39,3 +39,8 @@ static const fe25519 onemsqd = { static const fe25519 sqdmone = { 1507062230895904, 1572317787530805, 683053064812840, 317374165784489, 1572899562415810 }; + +/* sqrt(-486664) */ +static const fe25519 sqrtam2 = { + 1693982333959686, 608509411481997, 2235573344831311, 947681270984193, 266558006233600 +};