From 52fce922f4fdb0d96d8065f3b132df47393e7ba1 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Tue, 31 Oct 2017 15:27:48 +0100 Subject: [PATCH] Add constant-time edx recovery; use it in ed25519_scalarmult() --- .../curve25519/ref10/curve25519_ref10.c | 65 ++++++++++++++++--- .../ed25519/ref10/scalarmult_ed25519_ref10.c | 5 +- .../include/sodium/private/curve25519_ref10.h | 2 + 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c index cb793e14..9af8a72e 100644 --- a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c +++ b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c @@ -1405,13 +1405,16 @@ static const fe sqrtm1 = { -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 }; int -ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) +ge_frombytes(ge_p3 *h, const unsigned char *s) { - fe u; - fe v; - fe v3; - fe vxx; - fe check; + fe u; + fe v; + fe v3; + fe vxx; + fe m_root_check, p_root_check; + fe negx; + fe x_sqrtm1; + int has_m_root, has_p_root; fe_frombytes(h->Y, s); fe_1(h->Z); @@ -1432,10 +1435,52 @@ ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) fe_sq(vxx, h->X); fe_mul(vxx, vxx, v); - fe_sub(check, vxx, u); /* vx^2-u */ - if (fe_iszero(check) == 0) { - fe_add(check, vxx, u); /* vx^2+u */ - if (fe_iszero(check) == 0) { + fe_sub(m_root_check, vxx, u); /* vx^2-u */ + fe_add(p_root_check, vxx, u); /* vx^2+u */ + has_m_root = fe_iszero(m_root_check); + has_p_root = fe_iszero(p_root_check); + fe_mul(x_sqrtm1, h->X, sqrtm1); /* x*sqrt(-1) */ + fe_cmov(h->X, x_sqrtm1, 1 - has_m_root); + + fe_neg(negx, h->X); + fe_cmov(h->X, negx, fe_isnegative(h->X) ^ (s[31] >> 7)); + fe_mul(h->T, h->X, h->Y); + + return (has_m_root | has_p_root) - 1; +} + +int +ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) +{ + fe u; + fe v; + fe v3; + fe vxx; + fe m_root_check, p_root_check; + + fe_frombytes(h->Y, s); + fe_1(h->Z); + fe_sq(u, h->Y); + fe_mul(v, u, d); + fe_sub(u, u, h->Z); /* u = y^2-1 */ + fe_add(v, v, h->Z); /* v = dy^2+1 */ + + fe_sq(v3, v); + fe_mul(v3, v3, v); /* v3 = v^3 */ + fe_sq(h->X, v3); + fe_mul(h->X, h->X, v); + fe_mul(h->X, h->X, u); /* x = uv^7 */ + + fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */ + fe_mul(h->X, h->X, v3); + fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */ + + fe_sq(vxx, h->X); + fe_mul(vxx, vxx, v); + fe_sub(m_root_check, vxx, u); /* vx^2-u */ + if (fe_iszero(m_root_check) == 0) { + fe_add(p_root_check, vxx, u); /* vx^2+u */ + if (fe_iszero(p_root_check) == 0) { return -1; } fe_mul(h->X, h->X, sqrtm1); diff --git a/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c b/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c index 7d7e9dc0..8b511f66 100644 --- a/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c +++ b/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c @@ -38,8 +38,7 @@ crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n, unsigned int i; if (ge_is_canonical(p) == 0 || ge_has_small_order(p) != 0 || - ge_frombytes_negate_vartime(&P, p) != 0 || - ge_is_on_main_subgroup(&P) == 0) { + ge_frombytes(&P, p) != 0 || ge_is_on_main_subgroup(&P) == 0) { return -1; } for (i = 0; i < 32; ++i) { @@ -51,8 +50,6 @@ crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n, if (_crypto_scalarmult_ed25519_is_inf(q) != 0) { return -1; } - q[31] ^= 0x80; - return 0; } diff --git a/src/libsodium/include/sodium/private/curve25519_ref10.h b/src/libsodium/include/sodium/private/curve25519_ref10.h index c4a019e0..aaf43af5 100644 --- a/src/libsodium/include/sodium/private/curve25519_ref10.h +++ b/src/libsodium/include/sodium/private/curve25519_ref10.h @@ -93,6 +93,7 @@ typedef struct { } ge_cached; #define ge_frombytes_negate_vartime crypto_core_curve25519_ref10_ge_frombytes_negate_vartime +#define ge_frombytes crypto_core_curve25519_ref10_ge_frombytes #define ge_tobytes crypto_core_curve25519_ref10_ge_tobytes #define ge_p3_tobytes crypto_core_curve25519_ref10_ge_p3_tobytes @@ -111,6 +112,7 @@ typedef struct { extern void ge_tobytes(unsigned char *,const ge_p2 *); extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); +extern int ge_frombytes(ge_p3 *,const unsigned char *); extern int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); extern void ge_p3_to_cached(ge_cached *,const ge_p3 *);