diff --git a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c index 3552b63f..43c34969 100644 --- a/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c +++ b/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c @@ -3,7 +3,9 @@ #include #include "crypto_verify_32.h" +#include "private/common.h" #include "private/curve25519_ref10.h" +#include "utils.h" static inline uint64_t load_3(const unsigned char *in) @@ -441,21 +443,19 @@ fe_isnegative(const fe f) /* return 1 if f == 0 return 0 if f != 0 - * + Preconditions: |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. */ -static unsigned char zero[32]; - int -fe_isnonzero(const fe f) +fe_iszero(const fe f) { unsigned char s[32]; fe_tobytes(s, f); - return crypto_verify_32(s, zero); + return sodium_is_zero(s, 32); } /* @@ -1433,9 +1433,9 @@ 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_isnonzero(check)) { + if (fe_iszero(check) == 0) { fe_add(check, vxx, u); /* vx^2+u */ - if (fe_isnonzero(check)) { + if (fe_iszero(check) == 0) { return -1; } fe_mul(h->X, h->X, sqrtm1); @@ -2037,7 +2037,7 @@ ge_scalarmult_base(ge_p3 *h, const unsigned char *a) } /* multiply by the order of the main subgroup l = 2^252+27742317777372353535851937790883648493 */ -void +static void ge_mul_l(ge_p3 *r, const ge_p3 *A) { static const signed char aslide[253] = { @@ -2091,6 +2091,91 @@ ge_mul_l(ge_p3 *r, const ge_p3 *A) } } +int +ge_is_on_main_subgroup(const ge_p3 *p) +{ + ge_p3 pl; + + ge_mul_l(&pl, p); + + return fe_iszero(pl.X); +} + +int +ge_has_small_order(const unsigned char s[32], unsigned char neg) +{ + CRYPTO_ALIGN(16) + static const unsigned char blacklist[][32] = { + /* 0 (order 4) */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* 1 (order 1) */ + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 + (order 8) */ + { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, + 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, + 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 }, + /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 + (order 8) */ + { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, + 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, + 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a }, + /* p-1 (order 2) */ + { 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, + 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, + 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 }, + /* p (order 4) */ + { 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, + 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, + 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa }, + /* p+1 (order 1) */ + { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 + (order 8) */ + { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 + (order 8) */ + { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + /* 2p-1 (order 2) */ + { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + /* 2p (order 4) */ + { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + /* 2p+1 (order 1) */ + { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } + }; + size_t i, j; + unsigned char c; + + neg <<= 7; + for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) { + c = 0; + for (j = 0; j < 31; j++) { + c |= s[j] ^ blacklist[i][j]; + } + c |= s[j] ^ blacklist[i][j] ^ neg; + if (c == 0) { + return 1; + } + } + return 0; +} + /* Input: a[0]+256*a[1]+...+256^31*a[31] = a @@ -2912,3 +2997,25 @@ sc_reduce(unsigned char *s) s[30] = s11 >> 9; s[31] = s11 >> 17; } + +int +sc_is_less_than_L(const unsigned char *s) +{ + /* 2^252+27742317777372353535851937790883648493 */ + static const unsigned char L[32] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, + 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 + }; + unsigned char c = 0; + unsigned char n = 1; + unsigned int i = 32; + + do { + i--; + c |= ((s[i] - L[i]) >> 8) & n; + n &= ((s[i] ^ L[i]) - 1) >> 8; + } while (i != 0); + + return (c != 0); +} diff --git a/src/libsodium/crypto_sign/ed25519/ref10/ed25519_ref10.h b/src/libsodium/crypto_sign/ed25519/ref10/ed25519_ref10.h index d8a4d70e..8d93892b 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/ed25519_ref10.h +++ b/src/libsodium/crypto_sign/ed25519/ref10/ed25519_ref10.h @@ -15,7 +15,4 @@ int _crypto_sign_ed25519_verify_detached(const unsigned char *sig, unsigned long long mlen, const unsigned char *pk, int prehashed); - -int _crypto_sign_ed25519_small_order(const unsigned char p[32], unsigned char neg); - #endif diff --git a/src/libsodium/crypto_sign/ed25519/ref10/keypair.c b/src/libsodium/crypto_sign/ed25519/ref10/keypair.c index 271ffd7c..0e8aa885 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/keypair.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/keypair.c @@ -16,14 +16,10 @@ crypto_sign_ed25519_scalarmult(unsigned char *q, const unsigned char *n, unsigned char *t = q; ge_p3 Q; ge_p3 P; - ge_p3 pl; - if (_crypto_sign_ed25519_small_order(p, 1) || - ge_frombytes_negate_vartime(&P, p) != 0) { - return -1; - } - ge_mul_l(&pl, &P); - if (fe_isnonzero(pl.X)) { + if (ge_has_small_order(p, 1) != 0 || + ge_frombytes_negate_vartime(&P, p) != 0 || + ge_is_on_main_subgroup(&P) == 0) { return -1; } memmove(t, n, 32); @@ -79,16 +75,12 @@ crypto_sign_ed25519_pk_to_curve25519(unsigned char *curve25519_pk, const unsigned char *ed25519_pk) { ge_p3 A; - ge_p3 pl; fe x; fe one_minus_y; - if (_crypto_sign_ed25519_small_order(ed25519_pk, 1) || - ge_frombytes_negate_vartime(&A, ed25519_pk) != 0) { - return -1; - } - ge_mul_l(&pl, &A); - if (fe_isnonzero(pl.X)) { + if (ge_has_small_order(ed25519_pk, 1) != 0 || + ge_frombytes_negate_vartime(&A, ed25519_pk) != 0 || + ge_is_on_main_subgroup(&A) == 0) { return -1; } fe_1(one_minus_y); diff --git a/src/libsodium/crypto_sign/ed25519/ref10/open.c b/src/libsodium/crypto_sign/ed25519/ref10/open.c index 94c55e83..4a237dbf 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/open.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/open.c @@ -10,105 +10,6 @@ #include "private/curve25519_ref10.h" #include "utils.h" -#ifndef ED25519_COMPAT -static int -crypto_sign_check_S_lt_L(const unsigned char *S) -{ - /* 2^252+27742317777372353535851937790883648493 */ - static const unsigned char L[32] = { - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, - 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 - }; - unsigned char c = 0; - unsigned char n = 1; - unsigned int i = 32; - - do { - i--; - c |= ((S[i] - L[i]) >> 8) & n; - n &= ((S[i] ^ L[i]) - 1) >> 8; - } while (i != 0); - - return -(c == 0); -} - -int -_crypto_sign_ed25519_small_order(const unsigned char p[32], unsigned char neg) -{ - CRYPTO_ALIGN(16) - static const unsigned char blacklist[][32] = { - /* 0 (order 4) */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* 1 (order 1) */ - { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, - /* 2707385501144840649318225287225658788936804267575313519463743609750303402022 - (order 8) */ - { 0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, - 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, - 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05 }, - /* 55188659117513257062467267217118295137698188065244968500265048394206261417927 - (order 8) */ - { 0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, - 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, - 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a }, - /* p-1 (order 2) */ - { 0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, - 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, - 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85 }, - /* p (order 4) */ - { 0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, - 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, - 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa }, - /* p+1 (order 1) */ - { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, - /* p+2707385501144840649318225287225658788936804267575313519463743609750303402022 - (order 8) */ - { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, - /* p+55188659117513257062467267217118295137698188065244968500265048394206261417927 - (order 8) */ - { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, - /* 2p-1 (order 2) */ - { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - /* 2p (order 4) */ - { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, - /* 2p+1 (order 1) */ - { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } - }; - size_t i, j; - unsigned char c; - - neg <<= 7; - for (i = 0; i < sizeof blacklist / sizeof blacklist[0]; i++) { - c = 0; - for (j = 0; j < 31; j++) { - c |= p[j] ^ blacklist[i][j]; - } - c |= p[j] ^ blacklist[i][j] ^ neg; - if (c == 0) { - return 1; - } - } - return 0; -} -#endif - int _crypto_sign_ed25519_verify_detached(const unsigned char *sig, const unsigned char *m, @@ -125,8 +26,8 @@ _crypto_sign_ed25519_verify_detached(const unsigned char *sig, ge_p2 R; #ifndef ED25519_COMPAT - if (crypto_sign_check_S_lt_L(sig + 32) != 0 || - _crypto_sign_ed25519_small_order(sig, 0) != 0) { + if (sc_is_less_than_L(sig + 32) == 0 || + ge_has_small_order(sig, 0) != 0) { return -1; } #else diff --git a/src/libsodium/include/sodium/private/curve25519_ref10.h b/src/libsodium/include/sodium/private/curve25519_ref10.h index 0494c379..5728c5e7 100644 --- a/src/libsodium/include/sodium/private/curve25519_ref10.h +++ b/src/libsodium/include/sodium/private/curve25519_ref10.h @@ -104,7 +104,8 @@ typedef struct { #define ge_scalarmult_base crypto_core_curve25519_ref10_ge_scalarmult_base #define ge_double_scalarmult_vartime crypto_core_curve25519_ref10_ge_double_scalarmult_vartime #define ge_scalarmult_vartime crypto_core_curve25519_ref10_ge_scalarmult_vartime -#define ge_mul_l crypto_core_curve25519_ref10_ge_mul_l +#define ge_is_on_main_subgroup crypto_core_curve25519_ref10_ge_is_on_main_subgroup +#define ge_has_small_order crypto_core_curve25519_ref10_ge_has_small_order extern void ge_tobytes(unsigned char *,const ge_p2 *); extern void ge_p3_tobytes(unsigned char *,const ge_p3 *); @@ -118,7 +119,8 @@ extern void ge_scalarmult_base(ge_p3 *,const unsigned char *); extern void ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *,const ge_p3 *,const unsigned char *); extern void ge_scalarmult(ge_p3 *,const unsigned char *,const ge_p3 *); extern void ge_scalarmult_vartime(ge_p3 *,const unsigned char *,const ge_p3 *); -extern void ge_mul_l(ge_p3 *r, const ge_p3 *A); +extern int ge_is_on_main_subgroup(const ge_p3 *p); +extern int ge_has_small_order(const unsigned char s[32], unsigned char neg); /* The set of scalars is \Z/l @@ -127,8 +129,10 @@ extern void ge_mul_l(ge_p3 *r, const ge_p3 *A); #define sc_reduce crypto_core_curve25519_ref10_sc_reduce #define sc_muladd crypto_core_curve25519_ref10_sc_muladd +#define sc_is_less_than_L crypto_core_curve25519_ref10_sc_is_less_than_L extern void sc_reduce(unsigned char *); extern void sc_muladd(unsigned char *,const unsigned char *,const unsigned char *,const unsigned char *); +extern int sc_is_less_than_L(const unsigned char *s); #endif