Allow arbitrary long string-to-H2C-hash operations

Make the ristretto and edwards25519 string to hash code lookalike.
This commit is contained in:
Frank Denis
2021-01-23 21:41:20 +01:00
parent 41e6cb3368
commit 5ff2b1a0e7
3 changed files with 93 additions and 52 deletions
@@ -1,4 +1,5 @@
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -75,24 +76,21 @@ crypto_core_ed25519_from_uniform(unsigned char *p, const unsigned char *r)
#define HASH_BYTES crypto_hash_sha512_BYTES
#define HASH_BLOCKBYTES 128U
#define HASH_L 48U
static int
_string_to_points(unsigned char * const px, size_t n,
const char *ctx, const unsigned char *msg, size_t msg_len)
static void
_string_to_h2c_hash(unsigned char *h, const size_t h_len,
const char *ctx, const unsigned char *msg, size_t msg_len)
{
crypto_hash_sha512_state st;
const unsigned char empty_block[HASH_BLOCKBYTES] = { 0 };
unsigned char u0[HASH_BYTES], u[2 * HASH_BYTES];
unsigned char t[3] = { 0U, n * HASH_L, 0U};
unsigned char u0[HASH_BYTES];
unsigned char ux[HASH_BYTES] = { 0 };
unsigned char t[3] = { 0U, (unsigned char) h_len, 0U};
unsigned char ctx_len_u8;
size_t ctx_len = ctx != NULL ? strlen(ctx) : 0U;
size_t i, j;
if (n > 2U) {
abort(); /* LCOV_EXCL_LINE */
}
COMPILER_ASSERT(2U * HASH_L <= 0xff);
assert(h_len <= 0xff);
if (ctx_len > (size_t) 0xff) {
crypto_hash_sha512_init(&st);
crypto_hash_sha512_update(&st,
@@ -113,23 +111,43 @@ _string_to_points(unsigned char * const px, size_t n,
crypto_hash_sha512_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha512_final(&st, u0);
for (i = 0U; i < n * HASH_BYTES; i += HASH_BYTES) {
memcpy(&u[i], u0, HASH_BYTES);
for (j = 0U; i > 0U && j < HASH_BYTES; j++) {
u[i + j] ^= u[i + j - HASH_BYTES];
for (i = 0U; i < h_len; i += HASH_BYTES) {
for (j = 0U; j < HASH_BYTES; j++) {
ux[j] ^= u0[j];
}
t[2]++;
crypto_hash_sha512_init(&st);
crypto_hash_sha512_update(&st, &u[i], HASH_BYTES);
crypto_hash_sha512_update(&st, ux, HASH_BYTES);
crypto_hash_sha512_update(&st, &t[2], 1U);
crypto_hash_sha512_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha512_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha512_final(&st, &u[i]);
crypto_hash_sha512_final(&st, ux);
memcpy(&h[i], ux, h_len - i >= (sizeof ux) ? (sizeof ux) : h_len - i);
}
}
#define HASH_GE_L 48U
static int
_string_to_points(unsigned char * const px, const size_t n,
const char *ctx, const unsigned char *msg, size_t msg_len)
{
unsigned char h[crypto_core_ed25519_HASHBYTES];
unsigned char h_be[2U * HASH_GE_L];
size_t i, j;
if (n > 2U) {
abort(); /* LCOV_EXCL_LINE */
}
_string_to_h2c_hash(h_be, n * HASH_GE_L, ctx, msg, msg_len);
COMPILER_ASSERT(sizeof h >= HASH_GE_L);
for (i = 0U; i < n; i++) {
memset(u0, 0U, HASH_BYTES - HASH_L);
memcpy(u0 + HASH_BYTES - HASH_L, &u[i * HASH_L], HASH_L);
ge25519_from_hash(&px[i * crypto_core_ed25519_BYTES], u0);
for (j = 0U; j < HASH_GE_L; j++) {
h[j] = h_be[i * HASH_GE_L + HASH_GE_L - 1U - j];
}
memset(&h[j], 0, (sizeof h) - j);
ge25519_from_hash(&px[i * crypto_core_ed25519_BYTES], h);
}
return 0;
}
@@ -1,5 +1,7 @@
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "crypto_core_ed25519.h"
#include "crypto_core_ristretto255.h"
@@ -70,23 +72,21 @@ crypto_core_ristretto255_from_hash(unsigned char *p, const unsigned char *r)
#define HASH_BYTES crypto_hash_sha256_BYTES
#define HASH_BLOCKBYTES 64U
#define HASH_L crypto_core_ristretto255_HASHBYTES
static int
_string_to_element(unsigned char *p,
const char *ctx, const unsigned char *msg, size_t msg_len)
static void
_string_to_h2c_hash(unsigned char *h, const size_t h_len,
const char *ctx, const unsigned char *msg, size_t msg_len)
{
crypto_hash_sha256_state st;
const unsigned char empty_block[HASH_BLOCKBYTES] = { 0 };
unsigned char u0[HASH_BYTES];
unsigned char u[2 * HASH_BYTES];
unsigned char t[3] = { 0U, HASH_L, 0U};
unsigned char ux[HASH_BYTES] = { 0 };
unsigned char t[3] = { 0U, (unsigned char) h_len, 0U};
unsigned char ctx_len_u8;
size_t ctx_len = ctx != NULL ? strlen(ctx) : 0U;
size_t i;
size_t i, j;
COMPILER_ASSERT(HASH_L == sizeof u);
COMPILER_ASSERT(HASH_L <= 0xff);
assert(h_len <= 0xff);
if (ctx_len > (size_t) 0xff) {
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st,
@@ -107,27 +107,29 @@ _string_to_element(unsigned char *p,
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, u0);
t[2]++;
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st, u0, HASH_BYTES);
crypto_hash_sha256_update(&st, &t[2], 1U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, u);
t[2]++;
crypto_hash_sha256_init(&st);
for (i = 0; i < HASH_BYTES; i++) {
u[32 + i] = u[i] ^ u0[i];
for (i = 0U; i < h_len; i += HASH_BYTES) {
for (j = 0U; j < HASH_BYTES; j++) {
ux[j] ^= u0[j];
}
t[2]++;
crypto_hash_sha256_init(&st);
crypto_hash_sha256_update(&st, ux, HASH_BYTES);
crypto_hash_sha256_update(&st, &t[2], 1U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, ux);
memcpy(&h[i], ux, h_len - i >= (sizeof ux) ? (sizeof ux) : h_len - i);
}
crypto_hash_sha256_update(&st, &u[32], HASH_BYTES);
crypto_hash_sha256_update(&st, &t[2], 1U);
crypto_hash_sha256_update(&st, (const unsigned char *) ctx, ctx_len);
crypto_hash_sha256_update(&st, &ctx_len_u8, 1U);
crypto_hash_sha256_final(&st, &u[32]);
}
COMPILER_ASSERT(crypto_core_ristretto255_HASHBYTES == HASH_L);
ristretto255_from_hash(p, u);
static int
_string_to_element(unsigned char *p,
const char *ctx, const unsigned char *msg, size_t msg_len)
{
unsigned char h[crypto_core_ristretto255_HASHBYTES];
_string_to_h2c_hash(h, sizeof h, ctx, msg, msg_len);
ristretto255_from_hash(p, h);
return 0;
}
@@ -218,6 +220,29 @@ crypto_core_ristretto255_scalar_is_canonical(const unsigned char *s)
return sc25519_is_canonical(s);
}
#define HASH_SC_L 48U
int
crypto_core_ristretto255_scalar_from_string(unsigned char *s,
const char *ctx, const unsigned char *msg,
size_t msg_len)
{
unsigned char h[crypto_core_ristretto255_NONREDUCEDSCALARBYTES];
unsigned char h_be[HASH_SC_L];
size_t i;
_string_to_h2c_hash(h_be, sizeof h_be, ctx, msg, msg_len);
COMPILER_ASSERT(sizeof h >= sizeof h_be);
for (i = 0U; i < HASH_SC_L; i++) {
h[i] = h_be[HASH_SC_L - 1U - i];
}
memset(&h[i], 0, (sizeof h) - i);
crypto_core_ristretto255_scalar_reduce(s, h);
return 0;
}
size_t
crypto_core_ristretto255_bytes(void)
{
@@ -2714,15 +2714,13 @@ fe25519_reduce64(fe25519 fe_f, const unsigned char h[64])
fe25519 fe_g;
size_t i;
for (i = 0; i < 32; i++) {
fl[i] = h[63 - i];
gl[i] = h[31 - i];
}
memcpy(fl, h, 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[32] >> 7) * 19;
fe_f[0] += (h[31] >> 7) * 19;
for (i = 0; i < sizeof (fe25519) / sizeof fe_f[0]; i++) {
fe_f[i] += 38 * fe_g[i];
}