diff --git a/src/libsodium/crypto_core/ed25519/core_ed25519.c b/src/libsodium/crypto_core/ed25519/core_ed25519.c index 70e81c7e..0a7a8959 100644 --- a/src/libsodium/crypto_core/ed25519/core_ed25519.c +++ b/src/libsodium/crypto_core/ed25519/core_ed25519.c @@ -16,9 +16,9 @@ crypto_core_ed25519_is_valid_point(const unsigned char *p) ge25519_p3 p_p3; if (ge25519_is_canonical(p) == 0 || - ge25519_has_small_order(p) != 0 || ge25519_frombytes(&p_p3, p) != 0 || ge25519_is_on_curve(&p_p3) == 0 || + ge25519_has_small_order(&p_p3) != 0 || ge25519_is_on_main_subgroup(&p_p3) == 0) { return 0; } diff --git a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c index 43c26100..6acb4b00 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c +++ b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c @@ -1151,59 +1151,29 @@ ge25519_is_canonical(const unsigned char *s) } int -ge25519_has_small_order(const unsigned char s[32]) +ge25519_has_small_order(const ge25519_p3 *p) { - CRYPTO_ALIGN(16) - static const unsigned char blocklist[][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) */ - { 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 (=0, order 4) */ - { 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+1 (=1, order 1) */ - { 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 } - }; - unsigned char c[7] = { 0 }; - unsigned int k; - size_t i, j; + fe25519 recip; + fe25519 x; + fe25519 x_neg; + fe25519 y; + fe25519 y_sqrtm1; + fe25519 c; + int ret = 0; - COMPILER_ASSERT(7 == sizeof blocklist / sizeof blocklist[0]); - for (j = 0; j < 31; j++) { - for (i = 0; i < sizeof blocklist / sizeof blocklist[0]; i++) { - c[i] |= s[j] ^ blocklist[i][j]; - } - } - for (i = 0; i < sizeof blocklist / sizeof blocklist[0]; i++) { - c[i] |= (s[j] & 0x7f) ^ blocklist[i][j]; - } - k = 0; - for (i = 0; i < sizeof blocklist / sizeof blocklist[0]; i++) { - k |= (c[i] - 1); - } - return (int) ((k >> 8) & 1); + fe25519_invert(recip, p->Z); + fe25519_mul(x, p->X, recip); + ret |= fe25519_iszero(x); + fe25519_mul(y, p->Y, recip); + ret |= fe25519_iszero(y); + fe25519_neg(x_neg, p->X); + fe25519_mul(y_sqrtm1, y, fe25519_sqrtm1); + fe25519_sub(c, y_sqrtm1, x); + ret |= fe25519_iszero(c); + fe25519_sub(c, y_sqrtm1, x_neg); + ret |= fe25519_iszero(c); + + return ret; } /* 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 7c980893..c7d87a3c 100644 --- a/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c +++ b/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c @@ -36,8 +36,8 @@ _crypto_scalarmult_ed25519(unsigned char *q, const unsigned char *n, ge25519_p3 P; unsigned int i; - if (ge25519_is_canonical(p) == 0 || ge25519_has_small_order(p) != 0 || - ge25519_frombytes(&P, p) != 0 || ge25519_is_on_main_subgroup(&P) == 0) { + if (ge25519_is_canonical(p) == 0 || ge25519_frombytes(&P, p) != 0 || + ge25519_has_small_order(&P) != 0 || ge25519_is_on_main_subgroup(&P) == 0) { return -1; } for (i = 0; i < 32; ++i) { diff --git a/src/libsodium/crypto_sign/ed25519/ref10/keypair.c b/src/libsodium/crypto_sign/ed25519/ref10/keypair.c index e8e40150..c8273a03 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/keypair.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/keypair.c @@ -50,8 +50,8 @@ crypto_sign_ed25519_pk_to_curve25519(unsigned char *curve25519_pk, fe25519 x; fe25519 one_minus_y; - if (ge25519_has_small_order(ed25519_pk) != 0 || - ge25519_frombytes_negate_vartime(&A, ed25519_pk) != 0 || + if (ge25519_frombytes_negate_vartime(&A, ed25519_pk) != 0 || + ge25519_has_small_order(&A) != 0 || ge25519_is_on_main_subgroup(&A) == 0) { return -1; } diff --git a/src/libsodium/crypto_sign/ed25519/ref10/open.c b/src/libsodium/crypto_sign/ed25519/ref10/open.c index 70ac8d07..fb999c29 100644 --- a/src/libsodium/crypto_sign/ed25519/ref10/open.c +++ b/src/libsodium/crypto_sign/ed25519/ref10/open.c @@ -20,7 +20,6 @@ _crypto_sign_ed25519_verify_detached(const unsigned char *sig, { crypto_hash_sha512_state hs; unsigned char h[64]; - unsigned char rcheck[32]; ge25519_p3 check; ge25519_p3 expected_r; ge25519_p3 A; @@ -37,18 +36,16 @@ _crypto_sign_ed25519_verify_detached(const unsigned char *sig, sc25519_is_canonical(sig + 32) == 0) { return -1; } - if (ge25519_has_small_order(sig) != 0) { - return -1; - } - if (ge25519_is_canonical(pk) == 0 || - ge25519_has_small_order(pk) != 0) { + if (ge25519_is_canonical(pk) == 0) { return -1; } #endif - if (ge25519_frombytes_negate_vartime(&A, pk) != 0) { + if (ge25519_frombytes_negate_vartime(&A, pk) != 0 || + ge25519_has_small_order(&A) != 0) { return -1; } - if (ge25519_frombytes(&expected_r, sig) != 0) { + if (ge25519_frombytes(&expected_r, sig) != 0 || + ge25519_has_small_order(&expected_r) != 0) { return -1; } _crypto_sign_ed25519_ref10_hinit(&hs, prehashed); @@ -61,9 +58,8 @@ _crypto_sign_ed25519_verify_detached(const unsigned char *sig, ge25519_double_scalarmult_vartime(&sb_ah_p2, h, &A, sig + 32); ge25519_p2_to_p3(&sb_ah, &sb_ah_p2); ge25519_p3_sub(&check, &expected_r, &sb_ah); - ge25519_clear_cofactor(&check); - return fe25519_iszero(check.X) - 1; + return ge25519_has_small_order(&check) - 1; } int diff --git a/src/libsodium/include/sodium/private/ed25519_ref10.h b/src/libsodium/include/sodium/private/ed25519_ref10.h index 1d5476c1..9c66cd9d 100644 --- a/src/libsodium/include/sodium/private/ed25519_ref10.h +++ b/src/libsodium/include/sodium/private/ed25519_ref10.h @@ -109,7 +109,7 @@ int ge25519_is_on_curve(const ge25519_p3 *p); int ge25519_is_on_main_subgroup(const ge25519_p3 *p); -int ge25519_has_small_order(const unsigned char s[32]); +int ge25519_has_small_order(const ge25519_p3 *p); void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]);