From 24c54073a89169334d359478b67be13ae9c33b0a Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Thu, 2 May 2019 00:51:17 +0200 Subject: [PATCH] Add core_ed25519_from_hash() and core_{ed25519, ristretto255}_random() --- .../crypto_core/ed25519/core_ed25519.c | 25 ++++++++++- .../crypto_core/ed25519/core_ristretto255.c | 9 ++++ .../crypto_core/ed25519/ref10/ed25519_ref10.c | 41 +++++++++++++----- .../include/sodium/crypto_core_ed25519.h | 12 ++++++ .../include/sodium/crypto_core_ristretto255.h | 4 ++ .../include/sodium/private/ed25519_ref10.h | 4 +- test/default/core_ed25519.c | 43 +++++++++++++------ test/default/core_ristretto255.c | 4 ++ 8 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/libsodium/crypto_core/ed25519/core_ed25519.c b/src/libsodium/crypto_core/ed25519/core_ed25519.c index ac1eed17..0029a093 100644 --- a/src/libsodium/crypto_core/ed25519/core_ed25519.c +++ b/src/libsodium/crypto_core/ed25519/core_ed25519.c @@ -67,7 +67,24 @@ crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r) { ge25519_from_uniform(p, r); - return - ge25519_has_small_order(p); + 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 h[crypto_core_ed25519_HASHBYTES]; + + randombytes_buf(h, sizeof h); + (void) crypto_core_ed25519_from_hash(p, h); } void @@ -195,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/core_ristretto255.c b/src/libsodium/crypto_core/ed25519/core_ristretto255.c index 57305bef..cad3c802 100644 --- a/src/libsodium/crypto_core/ed25519/core_ristretto255.c +++ b/src/libsodium/crypto_core/ed25519/core_ristretto255.c @@ -67,6 +67,15 @@ crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r) return 0; } +void +crypto_core_ristretto255_random(unsigned char *p) +{ + unsigned char h[crypto_core_ristretto255_HASHBYTES]; + + randombytes_buf(h, sizeof h); + (void) crypto_core_ristretto255_from_hash(p, h); +} + void crypto_core_ristretto255_scalar_random(unsigned char *r) { diff --git a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c index cd215f2b..4b1c4194 100644 --- a/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c +++ b/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c @@ -2525,8 +2525,8 @@ chi25519(fe25519 out, const fe25519 z) fe25519_mul(out, t1, t0); } -void -ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) +static void +ge25519_elligator2(unsigned char s[32], const unsigned char x_sign) { fe25519 e; fe25519 negx; @@ -2536,15 +2536,9 @@ ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) ge25519_p1p1 p1; ge25519_p2 p2; unsigned int e_is_minus_1; - unsigned char x_sign; - - memcpy(s, r, 32); - x_sign = s[31] & 0x80; - s[31] &= 0x7f; fe25519_frombytes(rr2, s); - /* elligator */ fe25519_sq2(rr2, rr2); rr2[0]++; fe25519_invert(rr2, rr2); @@ -2600,6 +2594,31 @@ ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) ge25519_p3_tobytes(s, &p3); } +void +ge25519_from_uniform(unsigned char s[32], const unsigned char r[32]) +{ + unsigned char x_sign; + + memcpy(s, r, 32); + x_sign = s[31] & 0x80; + s[31] &= 0x7f; + ge25519_elligator2(s, x_sign); +} + +void +ge25519_from_hash(unsigned char s[32], const unsigned char h[64]) +{ + unsigned char r[64]; + unsigned char x_sign; + + memcpy(r, h, 64); + x_sign = h[63] & 0x80; + r[63] &= 0x7f; + sc25519_reduce(r); + memcpy(s, r, 32); + ge25519_elligator2(s, x_sign); +} + /* Ristretto group */ static int @@ -2815,7 +2834,7 @@ ristretto255_elligator(ge25519_p3 *p, const fe25519 t) } void -ristretto255_from_hash(unsigned char s[32], const unsigned char r[64]) +ristretto255_from_hash(unsigned char s[32], const unsigned char h[64]) { fe25519 r0, r1; ge25519_cached p1_cached; @@ -2823,8 +2842,8 @@ ristretto255_from_hash(unsigned char s[32], const unsigned char r[64]) ge25519_p3 p0, p1; ge25519_p3 p; - fe25519_frombytes(r0, r); - fe25519_frombytes(r1, r + 32); + fe25519_frombytes(r0, h); + fe25519_frombytes(r1, h + 32); ristretto255_elligator(&p0, r0); ristretto255_elligator(&p1, r1); ge25519_p3_to_cached(&p1_cached, &p1); diff --git a/src/libsodium/include/sodium/crypto_core_ed25519.h b/src/libsodium/include/sodium/crypto_core_ed25519.h index a63d8382..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,14 @@ 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)); + SODIUM_EXPORT void crypto_core_ed25519_scalar_random(unsigned char *r) __attribute__ ((nonnull)); diff --git a/src/libsodium/include/sodium/crypto_core_ristretto255.h b/src/libsodium/include/sodium/crypto_core_ristretto255.h index 9d642e33..f2820e55 100644 --- a/src/libsodium/include/sodium/crypto_core_ristretto255.h +++ b/src/libsodium/include/sodium/crypto_core_ristretto255.h @@ -43,6 +43,10 @@ int crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r) __attribute__ ((nonnull)); +SODIUM_EXPORT +void crypto_core_ristretto255_random(unsigned char *p) + __attribute__ ((nonnull)); + SODIUM_EXPORT void crypto_core_ristretto255_scalar_random(unsigned char *r) __attribute__ ((nonnull)); diff --git a/src/libsodium/include/sodium/private/ed25519_ref10.h b/src/libsodium/include/sodium/private/ed25519_ref10.h index 344905b7..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 */ @@ -118,7 +120,7 @@ int ristretto255_frombytes(ge25519_p3 *h, const unsigned char *s); void ristretto255_p3_tobytes(unsigned char *s, const ge25519_p3 *h); -void ristretto255_from_hash(unsigned char s[32], const unsigned char r[64]); +void ristretto255_from_hash(unsigned char s[32], const unsigned char h[64]); /* The set of scalars is \Z/l diff --git a/test/default/core_ed25519.c b/test/default/core_ed25519.c index cfafa83a..e3f39c38 100644 --- a/test/default/core_ed25519.c +++ b/test/default/core_ed25519.c @@ -44,29 +44,43 @@ add_l64(unsigned char * const S) int main(void) { - unsigned char *h; + 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_UNIFORMBYTES); + 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++) { - randombytes_buf(h, crypto_core_ed25519_UNIFORMBYTES); - if (crypto_core_ed25519_from_uniform(p, h) != 0) { + 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"); } if (crypto_core_ed25519_is_valid_point(p) == 0) { 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"); + } } p2 = (unsigned char *) sodium_malloc(crypto_core_ed25519_BYTES); p3 = (unsigned char *) sodium_malloc(crypto_core_ed25519_BYTES); - randombytes_buf(h, crypto_core_ed25519_UNIFORMBYTES); - crypto_core_ed25519_from_uniform(p2, h); + + crypto_core_ed25519_random(p2); j = 1 + (unsigned int) randombytes_uniform(100); memcpy(p3, p, crypto_core_ed25519_BYTES); @@ -145,8 +159,7 @@ main(void) assert(crypto_core_ed25519_sub(p3, non_canonical_invalid_p, p3) == -1); for (i = 0; i < 1000; i++) { - randombytes_buf(h, crypto_core_ed25519_UNIFORMBYTES); - crypto_core_ed25519_from_uniform(p, h); + crypto_core_ed25519_random(p); do { crypto_core_ed25519_scalar_random(sc); } while (sodium_is_zero(sc, crypto_core_ed25519_SCALARBYTES)); @@ -177,8 +190,8 @@ main(void) printf("crypto_core_ed25519_scalar_reduce() failed\n"); } - randombytes_buf(h, crypto_core_ed25519_UNIFORMBYTES); - crypto_core_ed25519_from_uniform(p, h); + randombytes_buf(r, crypto_core_ed25519_UNIFORMBYTES); + crypto_core_ed25519_from_uniform(p, r); memcpy(p2, p, crypto_core_ed25519_BYTES); crypto_core_ed25519_scalar_random(sc); if (crypto_scalarmult_ed25519_noclamp(p, sc, p) != 0) { @@ -189,15 +202,14 @@ main(void) printf("crypto_scalarmult_ed25519_noclamp() failed (2)\n"); } crypto_core_ed25519_add(p3, p, p2); - crypto_core_ed25519_from_uniform(p, h); + crypto_core_ed25519_from_uniform(p, r); crypto_core_ed25519_sub(p, p, p3); assert(p[0] == 0x01); for (i = 1; i < crypto_core_ed25519_BYTES; i++) { assert(p[i] == 0); } - randombytes_buf(h, crypto_core_ed25519_UNIFORMBYTES); - crypto_core_ed25519_from_uniform(p, h); + crypto_core_ed25519_random(p); memcpy(p2, p, crypto_core_ed25519_BYTES); crypto_core_ed25519_scalar_random(sc); if (crypto_scalarmult_ed25519_noclamp(p, sc, p) != 0) { @@ -383,6 +395,7 @@ main(void) sodium_free(p3); sodium_free(p2); sodium_free(p); + sodium_free(r); sodium_free(h); assert(crypto_core_ed25519_BYTES == crypto_core_ed25519_bytes()); @@ -391,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"); diff --git a/test/default/core_ristretto255.c b/test/default/core_ristretto255.c index a52ef8b7..10ada0a9 100644 --- a/test/default/core_ristretto255.c +++ b/test/default/core_ristretto255.c @@ -135,6 +135,10 @@ tv3(void) crypto_core_ristretto255_is_valid_point(s) != 1) { printf("crypto_scalarmult_ristretto255_base() failed\n"); } + crypto_core_ristretto255_random(s); + if (crypto_core_ristretto255_is_valid_point(s) != 1) { + printf("crypto_core_ristretto255_random() failed\n"); + } if (crypto_scalarmult_ristretto255(s, l, s) == 0) { printf("s*l != inf (1)\n"); }