@@ -5,12 +5,15 @@ ii = sqrt(F(-1)) | |||||
def lobit(x): return int(x) & 1 | def lobit(x): return int(x) & 1 | ||||
def hibit(x): return lobit(2*x) | def hibit(x): return lobit(2*x) | ||||
magic = sqrt(F(-121666)) | |||||
magic = sqrt(dM-1) | |||||
if lobit(magic): magic = -magic | 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)) | x = sqrt((y^2-1)/(d*y^2+1)) | ||||
if int(x) & 1: x = -x | if int(x) & 1: x = -x | ||||
@@ -37,6 +40,11 @@ def eddsa_to_decaf(x,y): | |||||
return s | return s | ||||
def isqrt_trick(to_isr,to_inv): | 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 | 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 | 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. | but whatever. | ||||
""" | """ | ||||
if z is None: | if z is None: | ||||
# Pretend that we're in projective | |||||
# Pretend that we're in projective coordinates | |||||
z = F.random_element() | z = F.random_element() | ||||
x *= z | x *= z | ||||
y *= z | y *= z | ||||
@@ -105,9 +113,9 @@ def decaf_to_eddsa(s): | |||||
def decaf_to_eddsa_opt(s): | def decaf_to_eddsa_opt(s): | ||||
""" | """ | ||||
Convert a Decaf representation to an EdDSA point, in a manner compatible | 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!") | if s < 0 or s >= F.modulus(): raise Exception("out of field!") | ||||
s = F(s) | 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)) | 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") | 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 | x = 2 * magic * s * isr | ||||
y = (1-s^2)^2 * s * inv | 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 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 | assert y^2 - x^2 == 1+d*x^2*y^2 | ||||
return (x,y) | return (x,y) | ||||
@@ -53,8 +53,10 @@ void decaf_sponge_init ( | |||||
* @param [inout] sponge The context. | * @param [inout] sponge The context. | ||||
* @param [in] in The input data. | * @param [in] in The input data. | ||||
* @param [in] len The input data's length in bytes. | * @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, | struct decaf_keccak_sponge_s * __restrict__ sponge, | ||||
const uint8_t *in, | const uint8_t *in, | ||||
size_t len | 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) { \ | static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | ||||
decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ | 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 ) { \ | 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); \ | 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) { \ | static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | ||||
decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ | 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 ) { \ | 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); \ | decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ | ||||
@@ -53,8 +53,10 @@ void decaf_sponge_init ( | |||||
* @param [inout] sponge The context. | * @param [inout] sponge The context. | ||||
* @param [in] in The input data. | * @param [in] in The input data. | ||||
* @param [in] len The input data's length in bytes. | * @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, | struct decaf_keccak_sponge_s * __restrict__ sponge, | ||||
const uint8_t *in, | const uint8_t *in, | ||||
size_t len | 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) { \ | static inline void DECAF_NONNULL decaf_shake##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | ||||
decaf_sponge_init(sponge, &DECAF_SHAKE##n##_params_s); \ | 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 ) { \ | 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); \ | 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) { \ | static inline void DECAF_NONNULL decaf_sha3_##n##_gen_init(decaf_keccak_sponge_t sponge) { \ | ||||
decaf_sponge_init(sponge, &DECAF_SHA3_##n##_params_s); \ | 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 ) { \ | 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); \ | decaf_error_t ret = decaf_sha3_output(sponge->s, out, outlen); \ | ||||
@@ -85,12 +85,11 @@ void keccakf(kdomain_t state, uint8_t start_round) { | |||||
for (i=0; i<25; i++) a[i] = htole64(a[i]); | 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, | struct decaf_keccak_sponge_s * __restrict__ decaf_sponge, | ||||
const uint8_t *in, | const uint8_t *in, | ||||
size_t len | size_t len | ||||
) { | ) { | ||||
if (!len) return; | |||||
assert(decaf_sponge->params->position < decaf_sponge->params->rate); | assert(decaf_sponge->params->position < decaf_sponge->params->rate); | ||||
assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | assert(decaf_sponge->params->rate < sizeof(decaf_sponge->state)); | ||||
assert(decaf_sponge->params->flags == FLAG_ABSORBING); | assert(decaf_sponge->params->flags == FLAG_ABSORBING); | ||||
@@ -100,7 +99,7 @@ void decaf_sha3_update ( | |||||
if (cando > len) { | if (cando > len) { | ||||
for (i = 0; i < len; i += 1) state[i] ^= in[i]; | for (i = 0; i < len; i += 1) state[i] ^= in[i]; | ||||
decaf_sponge->params->position += len; | decaf_sponge->params->position += len; | ||||
return; | |||||
break; | |||||
} else { | } else { | ||||
for (i = 0; i < cando; i += 1) state[i] ^= in[i]; | for (i = 0; i < cando; i += 1) state[i] ^= in[i]; | ||||
dokeccak(decaf_sponge); | dokeccak(decaf_sponge); | ||||
@@ -108,6 +107,7 @@ void decaf_sha3_update ( | |||||
in += cando; | in += cando; | ||||
} | } | ||||
} | } | ||||
return (decaf_sponge->params->flags == FLAG_ABSORBING) ? DECAF_SUCCESS : DECAF_FAILURE; | |||||
} | } | ||||
decaf_error_t decaf_sha3_output ( | 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->position] ^= decaf_sponge->params->pad; | ||||
state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad; | state[decaf_sponge->params->rate - 1] ^= decaf_sponge->params->rate_pad; | ||||
dokeccak(decaf_sponge); | dokeccak(decaf_sponge); | ||||
decaf_sponge->params->flags = FLAG_SQUEEZING; | |||||
break; | break; | ||||
} | } | ||||
default: | default: | ||||
@@ -173,6 +174,7 @@ void decaf_sha3_reset ( | |||||
decaf_keccak_sponge_t decaf_sponge | decaf_keccak_sponge_t decaf_sponge | ||||
) { | ) { | ||||
decaf_sponge_init(decaf_sponge, decaf_sponge->params); | decaf_sponge_init(decaf_sponge, decaf_sponge->params); | ||||
decaf_sponge->params->flags = FLAG_ABSORBING; | |||||
decaf_sponge->params->remaining = decaf_sponge->params->max_out; | decaf_sponge->params->remaining = decaf_sponge->params->max_out; | ||||
} | } | ||||