diff --git a/ed25519-donna/ed25519.c b/ed25519-donna/ed25519.c index 880b59d84..7403d3364 100644 --- a/ed25519-donna/ed25519.c +++ b/ed25519-donna/ed25519.c @@ -189,7 +189,9 @@ ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed2551 expand256_modm(hram, hash, 64); /* S */ - expand256_modm(S, RS + 32, 32); + expand_raw256_modm(S, RS + 32); + if (!is_reduced256_modm(S)) + return -1; /* SB - H(R,A,m)A */ ge25519_double_scalarmult_vartime(&R, &A, hram, S); diff --git a/ed25519-donna/modm-donna-32bit.c b/ed25519-donna/modm-donna-32bit.c index f658c4308..0086cd2cc 100644 --- a/ed25519-donna/modm-donna-32bit.c +++ b/ed25519-donna/modm-donna-32bit.c @@ -310,6 +310,18 @@ void expand_raw256_modm(bignum256modm out, const unsigned char in[32]) { out[8] = ((x[ 7] >> 16) ) & 0x0000ffff; } +int is_reduced256_modm(const bignum256modm in) +{ + int i; + uint32_t res1 = 0; + uint32_t res2 = 0; + for (i = 8; i >= 0; i--) { + res1 = (res1 << 1) | (in[i] < modm_m[i]); + res2 = (res2 << 1) | (in[i] > modm_m[i]); + } + return res1 > res2; +} + void contract256_modm(unsigned char out[32], const bignum256modm in) { U32TO8_LE(out + 0, (in[0] ) | (in[1] << 30)); U32TO8_LE(out + 4, (in[1] >> 2) | (in[2] << 28)); diff --git a/ed25519-donna/modm-donna-32bit.h b/ed25519-donna/modm-donna-32bit.h index 21306c799..f34633645 100644 --- a/ed25519-donna/modm-donna-32bit.h +++ b/ed25519-donna/modm-donna-32bit.h @@ -44,6 +44,8 @@ void expand256_modm(bignum256modm out, const unsigned char *in, size_t len); void expand_raw256_modm(bignum256modm out, const unsigned char in[32]); +int is_reduced256_modm(const bignum256modm in); + void contract256_modm(unsigned char out[32], const bignum256modm in); void contract256_window4_modm(signed char r[64], const bignum256modm in);