From 488e2548bd1fc7599d1c277d1300f6f0eb3fa30d Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Tue, 23 May 2017 15:57:00 -0700 Subject: [PATCH] fix(?! needs testing) a critical bug in SHAKE XOF: the state would never transition to SQUEEZING, resulting in incorrect outputs --- aux/decaffeinate_ed25519_too.sage | 28 ++++++++++++++++++---------- src/GENERATED/include/decaf/shake.h | 12 +++++++----- src/public_include/decaf/shake.h | 12 +++++++----- src/shake.c | 8 +++++--- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/aux/decaffeinate_ed25519_too.sage b/aux/decaffeinate_ed25519_too.sage index 456a840..d18d0c6 100644 --- a/aux/decaffeinate_ed25519_too.sage +++ b/aux/decaffeinate_ed25519_too.sage @@ -5,12 +5,15 @@ ii = sqrt(F(-1)) def lobit(x): return int(x) & 1 def hibit(x): return lobit(2*x) -magic = sqrt(F(-121666)) +magic = sqrt(dM-1) if lobit(magic): magic = -magic -def eddsa_decode(y): - hi = int(y) & 2^255 - y = F(y-hi) +def eddsa_decode(y_ser): + """ + Recover x,y corresponding to the eddsa standard representation. + """ + hi = int(y_ser) & 2^255 + y = F(y_ser-hi) x = sqrt((y^2-1)/(d*y^2+1)) if int(x) & 1: x = -x @@ -37,6 +40,11 @@ def eddsa_to_decaf(x,y): return s def isqrt_trick(to_isr,to_inv): + """ + The "inverse square root" trick: + Return 1/sqrt(to_isr), 1/to_inv. + Also return their product because that turns out to be useful. + """ to_sqrt = to_isr*to_inv^2 if to_sqrt == 0: return 0,0,0 # This happens automatically in C; just to avoid problems in SAGE @@ -58,7 +66,7 @@ def eddsa_to_decaf_opt(x,y,z=None): but whatever. """ if z is None: - # Pretend that we're in projective + # Pretend that we're in projective coordinates z = F.random_element() x *= z y *= z @@ -105,9 +113,9 @@ def decaf_to_eddsa(s): def decaf_to_eddsa_opt(s): """ Convert a Decaf representation to an EdDSA point, in a manner compatible - with libdecaf. + with libdecaf. Optimized to use only one invsqrt. - This function is slightly less horrible if we don't want to decode to affine. + This function would be slightly simpler if we didn't want to decode to affine. """ if s < 0 or s >= F.modulus(): raise Exception("out of field!") s = F(s) @@ -118,13 +126,13 @@ def decaf_to_eddsa_opt(s): isr,inv,isr_times_inv = isqrt_trick(curve_eqn,s*(1-s^2)*(1+s^2)) if isr == 0: raise Exception("Invalid: nonstandard encoding of zero") - t = isr_times_inv * curve_eqn * (1-s^2) * (1+s^2) x = 2 * magic * s * isr y = (1-s^2)^2 * s * inv - hibit_t = hibit(t) + tmp = isr_times_inv * curve_eqn * (1+s^2) # = sqrt(curve_eqn) / s / (1-s^2) + hibit_t = hibit(tmp * (1-s^2)) if hibit_t: x = -x - if lobit(t * (1+s^2)^2 * s * inv) != hibit_t: raise Exception("invalid: t/y has high bit") + if lobit(tmp * (1+s^2)) != hibit_t: raise Exception("invalid: bits don't match") assert y^2 - x^2 == 1+d*x^2*y^2 return (x,y) diff --git a/src/GENERATED/include/decaf/shake.h b/src/GENERATED/include/decaf/shake.h index 881889d..3fb13c7 100644 --- a/src/GENERATED/include/decaf/shake.h +++ b/src/GENERATED/include/decaf/shake.h @@ -53,8 +53,10 @@ void decaf_sponge_init ( * @param [inout] sponge The context. * @param [in] in The input data. * @param [in] len The input data's length in bytes. + * @return DECAF_FAILURE if the sponge has already been used for output. + * @return DECAF_SUCCESS otherwise. */ -void decaf_sha3_update ( +decaf_error_t decaf_sha3_update ( struct decaf_keccak_sponge_s * __restrict__ sponge, const uint8_t *in, size_t len @@ -156,8 +158,8 @@ decaf_error_t decaf_sponge_hash ( static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ } \ - static inline void DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ - decaf_sha3_update(sponge->s, in, inlen); \ + static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ } \ static inline void DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ decaf_sha3_output(sponge->s, out, outlen); \ @@ -182,8 +184,8 @@ decaf_error_t decaf_sponge_hash ( static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ } \ - static inline void DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ - decaf_sha3_update(sponge->s, in, inlen); \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ } \ static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ diff --git a/src/public_include/decaf/shake.h b/src/public_include/decaf/shake.h index 881889d..3fb13c7 100644 --- a/src/public_include/decaf/shake.h +++ b/src/public_include/decaf/shake.h @@ -53,8 +53,10 @@ void decaf_sponge_init ( * @param [inout] sponge The context. * @param [in] in The input data. * @param [in] len The input data's length in bytes. + * @return DECAF_FAILURE if the sponge has already been used for output. + * @return DECAF_SUCCESS otherwise. */ -void decaf_sha3_update ( +decaf_error_t decaf_sha3_update ( struct decaf_keccak_sponge_s * __restrict__ sponge, const uint8_t *in, size_t len @@ -156,8 +158,8 @@ decaf_error_t decaf_sponge_hash ( static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ } \ - static inline void DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ - decaf_sha3_update(sponge->s, in, inlen); \ + static inline decaf_error_t DECAF_NONNULL decaf_shake##n##_update(decaf_shake##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ } \ static inline void DECAF_NONNULL decaf_shake##n##_final(decaf_shake##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ decaf_sha3_output(sponge->s, out, outlen); \ @@ -182,8 +184,8 @@ decaf_error_t decaf_sponge_hash ( static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ } \ - static inline void DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ - decaf_sha3_update(sponge->s, in, inlen); \ + static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_update(decaf_sha3_##n##_ctx_t sponge, const uint8_t *in, size_t inlen ) { \ + return decaf_sha3_update(sponge->s, in, inlen); \ } \ static inline decaf_error_t DECAF_NONNULL decaf_sha3_##n##_final(decaf_sha3_##n##_ctx_t sponge, uint8_t *out, size_t outlen ) { \ decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ diff --git a/src/shake.c b/src/shake.c index 75ecf0b..b74b88e 100644 --- a/src/shake.c +++ b/src/shake.c @@ -85,12 +85,11 @@ void keccakf(kdomain_t state, uint8_t start_round) { for (i=0; i<25; i++) a[i] = htole64(a[i]); } -void decaf_sha3_update ( +decaf_error_t decaf_sha3_update ( struct decaf_keccak_sponge_s * __restrict__ decaf_sponge, const uint8_t *in, size_t len ) { - if (!len) return; assert(decaf_sponge->params->position < decaf_sponge->params->rate); assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); assert(decaf_sponge->params->flags == FLAG_ABSORBING); @@ -100,7 +99,7 @@ void decaf_sha3_update ( if (cando > len) { for (i = 0; i < len; i += 1) state[i] ^= in[i]; decaf_sponge->params->position += len; - return; + break; } else { for (i = 0; i < cando; i += 1) state[i] ^= in[i]; dokeccak(decaf_sponge); @@ -108,6 +107,7 @@ void decaf_sha3_update ( in += cando; } } + return (decaf_sponge->params->flags == FLAG_ABSORBING) ? DECAF_SUCCESS : DECAF_FAILURE; } decaf_error_t decaf_sha3_output ( @@ -136,6 +136,7 @@ decaf_error_t decaf_sha3_output ( state[decaf_sponge->params->position] ^= decaf_sponge->params->pad; state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad; dokeccak(decaf_sponge); + decaf_sponge->params->flags = FLAG_SQUEEZING; break; } default: @@ -173,6 +174,7 @@ void decaf_sha3_reset ( decaf_keccak_sponge_t decaf_sponge ) { decaf_sponge_init(decaf_sponge, decaf_sponge->params); + decaf_sponge->params->flags = FLAG_ABSORBING; decaf_sponge->params->remaining = decaf_sponge->params->max_out; }