diff --git a/src/libsodium/crypto_core/ed25519/core_ed25519.c b/src/libsodium/crypto_core/ed25519/core_ed25519.c index 1956a4a1..0029a093 100644 --- a/src/libsodium/crypto_core/ed25519/core_ed25519.c +++ b/src/libsodium/crypto_core/ed25519/core_ed25519.c @@ -70,13 +70,21 @@ crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r) return 0; } +int +crypto_core_ed25519_from_hash(unsigned char *p, const unsigned char *h) +{ + ge25519_from_hash(p, h); + + return 0; +} + void crypto_core_ed25519_random(unsigned char *p) { - unsigned char r[crypto_core_ed25519_UNIFORMBYTES]; + unsigned char h[crypto_core_ed25519_HASHBYTES]; - randombytes_buf(r, sizeof r); - (void) crypto_core_ed25519_from_uniform(p, r); + randombytes_buf(h, sizeof h); + (void) crypto_core_ed25519_from_hash(p, h); } void @@ -204,6 +212,12 @@ crypto_core_ed25519_uniformbytes(void) return crypto_core_ed25519_UNIFORMBYTES; } +size_t +crypto_core_ed25519_hashbytes(void) +{ + return crypto_core_ed25519_HASHBYTES; +} + size_t crypto_core_ed25519_scalarbytes(void) { diff --git a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c index 7ab9bdc2..82e7e1d6 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c +++ b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c @@ -2605,6 +2605,32 @@ ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) ge25519_elligator2(s, x_sign); } +void +ge25519_from_hash(unsigned char s[32], const unsigned char h[64]) +{ + unsigned char fl[32]; + unsigned char gl[32]; + fe25519 fe_f; + fe25519 fe_g; + int i; + unsigned char x_sign; + + x_sign = h[63] & 0x80; + memcpy(fl, &h[0], 32); + memcpy(gl, &h[32], 32); + fl[31] &= 0x7f; + gl[31] &= 0x7f; + fe25519_frombytes(fe_f, fl); + fe25519_frombytes(fe_g, gl); + fe_f[0] += (h[0 + 31] >> 7) * 19; + fe_g[0] += (h[32 + 31] >> 7) * 19; + for (i = 0; i < sizeof (fe25519) / sizeof fe_f[0]; i++) { + fe_f[i] += 38 * fe_g[i]; + } + fe25519_tobytes(s, fe_f); + ge25519_elligator2(s, x_sign); +} + /* Ristretto group */ static int diff --git a/src/libsodium/include/sodium/crypto_core_ed25519.h b/src/libsodium/include/sodium/crypto_core_ed25519.h index f8d55de0..3eae00c4 100644 --- a/src/libsodium/include/sodium/crypto_core_ed25519.h +++ b/src/libsodium/include/sodium/crypto_core_ed25519.h @@ -16,6 +16,10 @@ size_t crypto_core_ed25519_bytes(void); SODIUM_EXPORT size_t crypto_core_ed25519_uniformbytes(void); +#define crypto_core_ed25519_HASHBYTES 64 +SODIUM_EXPORT +size_t crypto_core_ed25519_hashbytes(void); + #define crypto_core_ed25519_SCALARBYTES 32 SODIUM_EXPORT size_t crypto_core_ed25519_scalarbytes(void); @@ -42,6 +46,10 @@ SODIUM_EXPORT int crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r) __attribute__ ((nonnull)); +SODIUM_EXPORT +int crypto_core_ed25519_from_hash(unsigned char *p, const unsigned char *h) + __attribute__ ((nonnull)); + SODIUM_EXPORT void crypto_core_ed25519_random(unsigned char *p) __attribute__ ((nonnull)); diff --git a/src/libsodium/include/sodium/private/ed25519_ref10.h b/src/libsodium/include/sodium/private/ed25519_ref10.h index 9e18935c..3f4c45ca 100644 --- a/src/libsodium/include/sodium/private/ed25519_ref10.h +++ b/src/libsodium/include/sodium/private/ed25519_ref10.h @@ -110,6 +110,8 @@ int ge25519_has_small_order(const unsigned char s[32]); void ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]); +void ge25519_from_hash(unsigned char s[32], const unsigned char h[64]); + /* Ristretto group */ diff --git a/test/default/core_ed25519.c b/test/default/core_ed25519.c index 6d3b8ca8..e3f39c38 100644 --- a/test/default/core_ed25519.c +++ b/test/default/core_ed25519.c @@ -44,16 +44,17 @@ add_l64(unsigned char * const S) int main(void) { - unsigned char *r; + unsigned char *h, *r; unsigned char *p, *p2, *p3; unsigned char *sc, *sc2, *sc3; unsigned char *sc64; char *hex; unsigned int i, j; + h = (unsigned char *) sodium_malloc(crypto_core_ed25519_HASHBYTES); r = (unsigned char *) sodium_malloc(crypto_core_ed25519_UNIFORMBYTES); p = (unsigned char *) sodium_malloc(crypto_core_ed25519_BYTES); - for (i = 0; i < 1000; i++) { + for (i = 0; i < 500; i++) { randombytes_buf(r, crypto_core_ed25519_UNIFORMBYTES); if (crypto_core_ed25519_from_uniform(p, r) != 0) { printf("crypto_core_ed25519_from_uniform() failed\n"); @@ -62,6 +63,14 @@ main(void) printf("crypto_core_ed25519_from_uniform() returned an invalid point\n"); } + randombytes_buf(h, crypto_core_ed25519_HASHBYTES); + if (crypto_core_ed25519_from_hash(p, h) != 0) { + printf("crypto_core_ed25519_from_hash() failed\n"); + } + if (crypto_core_ed25519_is_valid_point(p) == 0) { + printf("crypto_core_ed25519_from_hash() returned an invalid point\n"); + } + crypto_core_ed25519_random(p); if (crypto_core_ed25519_is_valid_point(p) == 0) { printf("crypto_core_ed25519_random() returned an invalid point\n"); @@ -387,6 +396,7 @@ main(void) sodium_free(p2); sodium_free(p); sodium_free(r); + sodium_free(h); assert(crypto_core_ed25519_BYTES == crypto_core_ed25519_bytes()); assert(crypto_core_ed25519_SCALARBYTES == crypto_core_ed25519_scalarbytes()); @@ -394,6 +404,8 @@ main(void) assert(crypto_core_ed25519_NONREDUCEDSCALARBYTES >= crypto_core_ed25519_SCALARBYTES); assert(crypto_core_ed25519_UNIFORMBYTES == crypto_core_ed25519_uniformbytes()); assert(crypto_core_ed25519_UNIFORMBYTES >= crypto_core_ed25519_BYTES); + assert(crypto_core_ed25519_HASHBYTES == crypto_core_ed25519_hashbytes()); + assert(crypto_core_ed25519_HASHBYTES >= 2 * crypto_core_ed25519_BYTES); printf("OK\n");