@@ -51,7 +51,7 @@ void decaf_255_private_to_public ( | |||||
memcpy(pub, priv->pub, sizeof(decaf_255_public_key_t)); | memcpy(pub, priv->pub, sizeof(decaf_255_public_key_t)); | ||||
} | } | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_shared_secret ( | decaf_255_shared_secret ( | ||||
uint8_t *shared, | uint8_t *shared, | ||||
size_t shared_bytes, | size_t shared_bytes, | ||||
@@ -92,15 +92,16 @@ decaf_255_shared_secret ( | |||||
} | } | ||||
shake256_update(sponge, ss_ser, sizeof(ss_ser)); | shake256_update(sponge, ss_ser, sizeof(ss_ser)); | ||||
decaf_bool_t ret = decaf_255_direct_scalarmul(ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, DECAF_TRUE); | |||||
decaf_error_t ret = decaf_255_direct_scalarmul(ss_ser, your_pubkey, my_privkey->secret_scalar, DECAF_FALSE, DECAF_TRUE); | |||||
decaf_bool_t good = decaf_successful(ret); | |||||
/* If invalid, then replace ... */ | /* If invalid, then replace ... */ | ||||
for (i=0; i<sizeof(ss_ser); i++) { | for (i=0; i<sizeof(ss_ser); i++) { | ||||
ss_ser[i] &= ret; | |||||
ss_ser[i] &= good; | |||||
if (i < sizeof(my_privkey->sym)) { | if (i < sizeof(my_privkey->sym)) { | ||||
ss_ser[i] |= my_privkey->sym[i] & ~ret; | |||||
ss_ser[i] |= my_privkey->sym[i] & ~good; | |||||
} else if (i - sizeof(my_privkey->sym) < strlen(nope)) { | } else if (i - sizeof(my_privkey->sym) < strlen(nope)) { | ||||
ss_ser[i] |= nope[i-sizeof(my_privkey->sym)] & ~ret; | |||||
ss_ser[i] |= nope[i-sizeof(my_privkey->sym)] & ~good; | |||||
} | } | ||||
} | } | ||||
@@ -159,7 +160,7 @@ decaf_255_sign_shake ( | |||||
decaf_bzero(encoded,sizeof(encoded)); | decaf_bzero(encoded,sizeof(encoded)); | ||||
} | } | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_verify_shake ( | decaf_255_verify_shake ( | ||||
const decaf_255_signature_t sig, | const decaf_255_signature_t sig, | ||||
const decaf_255_public_key_t pub, | const decaf_255_public_key_t pub, | ||||
@@ -181,9 +182,9 @@ decaf_255_verify_shake ( | |||||
decaf_255_scalar_decode_long(challenge, overkill, sizeof(overkill)); | decaf_255_scalar_decode_long(challenge, overkill, sizeof(overkill)); | ||||
/* Decode points. */ | /* Decode points. */ | ||||
ret = decaf_255_point_decode(point, sig, DECAF_TRUE); | |||||
ret &= decaf_255_point_decode(pubpoint, pub, DECAF_FALSE); | |||||
ret &= decaf_255_scalar_decode(response, &sig[DECAF_255_SER_BYTES]); | |||||
ret = decaf_successful(decaf_255_point_decode(point, sig, DECAF_TRUE)); | |||||
ret &= decaf_successful(decaf_255_point_decode(pubpoint, pub, DECAF_FALSE)); | |||||
ret &= decaf_successful(decaf_255_scalar_decode(response, &sig[DECAF_255_SER_BYTES])); | |||||
decaf_255_base_double_scalarmul_non_secret ( | decaf_255_base_double_scalarmul_non_secret ( | ||||
pubpoint, response, pubpoint, challenge | pubpoint, response, pubpoint, challenge | ||||
@@ -191,7 +192,7 @@ decaf_255_verify_shake ( | |||||
ret &= decaf_255_point_eq(pubpoint, point); | ret &= decaf_255_point_eq(pubpoint, point); | ||||
return ret; | |||||
return decaf_succeed_if(ret); | |||||
} | } | ||||
void | void | ||||
@@ -208,7 +209,7 @@ decaf_255_sign ( | |||||
shake256_destroy(ctx); | shake256_destroy(ctx); | ||||
} | } | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_verify ( | decaf_255_verify ( | ||||
const decaf_255_signature_t sig, | const decaf_255_signature_t sig, | ||||
const decaf_255_public_key_t pub, | const decaf_255_public_key_t pub, | ||||
@@ -218,7 +219,7 @@ decaf_255_verify ( | |||||
shake256_ctx_t ctx; | shake256_ctx_t ctx; | ||||
shake256_init(ctx); | shake256_init(ctx); | ||||
shake256_update(ctx, message, message_len); | shake256_update(ctx, message, message_len); | ||||
decaf_bool_t ret = decaf_255_verify_shake(sig, pub, ctx); | |||||
decaf_error_t ret = decaf_255_verify_shake(sig, pub, ctx); | |||||
shake256_destroy(ctx); | shake256_destroy(ctx); | ||||
return ret; | return ret; | ||||
} | } |
@@ -261,7 +261,7 @@ static INLINE void sc_montsqr (scalar_t out, const scalar_t a) { | |||||
sc_montmul(out,a,a); | sc_montmul(out,a,a); | ||||
} | } | ||||
decaf_bool_t API_NS(scalar_invert) ( | |||||
decaf_error_t API_NS(scalar_invert) ( | |||||
scalar_t out, | scalar_t out, | ||||
const scalar_t a | const scalar_t a | ||||
) { | ) { | ||||
@@ -318,7 +318,7 @@ decaf_bool_t API_NS(scalar_invert) ( | |||||
/* Demontgomerize */ | /* Demontgomerize */ | ||||
sc_montmul(out,out,API_NS(scalar_one)); | sc_montmul(out,out,API_NS(scalar_one)); | ||||
decaf_bzero(precmp, sizeof(precmp)); | decaf_bzero(precmp, sizeof(precmp)); | ||||
return ~API_NS(scalar_eq)(out,API_NS(scalar_zero)); | |||||
return decaf_succeed_if(~API_NS(scalar_eq)(out,API_NS(scalar_zero))); | |||||
} | } | ||||
void API_NS(scalar_sub) ( | void API_NS(scalar_sub) ( | ||||
@@ -510,13 +510,14 @@ static decaf_bool_t gf_deser(gf s, const unsigned char ser[SER_BYTES]) { | |||||
return gf_deserialize((gf_s *)s, ser); | return gf_deserialize((gf_s *)s, ser); | ||||
} | } | ||||
decaf_bool_t API_NS(point_decode) ( | |||||
decaf_error_t API_NS(point_decode) ( | |||||
point_t p, | point_t p, | ||||
const unsigned char ser[SER_BYTES], | const unsigned char ser[SER_BYTES], | ||||
decaf_bool_t allow_identity | decaf_bool_t allow_identity | ||||
) { | ) { | ||||
gf s, a, b, c, d, e, f; | gf s, a, b, c, d, e, f; | ||||
decaf_bool_t succ = gf_deser(s, ser), zero = gf_eq(s, ZERO); | decaf_bool_t succ = gf_deser(s, ser), zero = gf_eq(s, ZERO); | ||||
allow_identity = ~word_is_zero(allow_identity); | |||||
succ &= allow_identity | ~zero; | succ &= allow_identity | ~zero; | ||||
succ &= ~hibit(s); | succ &= ~hibit(s); | ||||
gf_sqr ( a, s ); | gf_sqr ( a, s ); | ||||
@@ -566,7 +567,7 @@ decaf_bool_t API_NS(point_decode) ( | |||||
assert(API_NS(point_valid)(p) | ~succ); | assert(API_NS(point_valid)(p) | ~succ); | ||||
return succ; | |||||
return decaf_succeed_if(succ); | |||||
} | } | ||||
#if IMAGINE_TWIST | #if IMAGINE_TWIST | ||||
@@ -700,7 +701,7 @@ scalar_decode_short ( | |||||
} | } | ||||
} | } | ||||
decaf_bool_t API_NS(scalar_decode)( | |||||
decaf_error_t API_NS(scalar_decode)( | |||||
scalar_t s, | scalar_t s, | ||||
const unsigned char ser[SER_BYTES] | const unsigned char ser[SER_BYTES] | ||||
) { | ) { | ||||
@@ -710,10 +711,11 @@ decaf_bool_t API_NS(scalar_decode)( | |||||
for (i=0; i<SCALAR_LIMBS; i++) { | for (i=0; i<SCALAR_LIMBS; i++) { | ||||
accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS; | accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS; | ||||
} | } | ||||
/* Here accum == 0 or -1 */ | |||||
API_NS(scalar_mul)(s,s,API_NS(scalar_one)); /* ham-handed reduce */ | API_NS(scalar_mul)(s,s,API_NS(scalar_one)); /* ham-handed reduce */ | ||||
return accum; | |||||
return decaf_succeed_if(accum); | |||||
} | } | ||||
void API_NS(scalar_destroy) ( | void API_NS(scalar_destroy) ( | ||||
@@ -1170,7 +1172,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
assert(API_NS(point_valid)(p)); | assert(API_NS(point_valid)(p)); | ||||
} | } | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
API_NS(invert_elligator_nonuniform) ( | API_NS(invert_elligator_nonuniform) ( | ||||
unsigned char recovered_hash[SER_BYTES], | unsigned char recovered_hash[SER_BYTES], | ||||
const point_t p, | const point_t p, | ||||
@@ -1218,7 +1220,7 @@ API_NS(invert_elligator_nonuniform) ( | |||||
gf_encode(recovered_hash, b); | gf_encode(recovered_hash, b); | ||||
/* TODO: deal with overflow flag */ | /* TODO: deal with overflow flag */ | ||||
return succ; | |||||
return decaf_succeed_if(succ); | |||||
} | } | ||||
void API_NS(point_from_hash_uniform) ( | void API_NS(point_from_hash_uniform) ( | ||||
@@ -1231,7 +1233,7 @@ void API_NS(point_from_hash_uniform) ( | |||||
API_NS(point_add)(pt,pt,pt2); | API_NS(point_add)(pt,pt,pt2); | ||||
} | } | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
API_NS(invert_elligator_uniform) ( | API_NS(invert_elligator_uniform) ( | ||||
unsigned char partial_hash[2*SER_BYTES], | unsigned char partial_hash[2*SER_BYTES], | ||||
const point_t p, | const point_t p, | ||||
@@ -1481,7 +1483,7 @@ void API_NS(point_cond_sel) ( | |||||
const point_t b, | const point_t b, | ||||
decaf_bool_t pick_b | decaf_bool_t pick_b | ||||
) { | ) { | ||||
pick_b = ~(((decaf_dword_t)pick_b - 1) >> WBITS); | |||||
pick_b = ~word_is_zero(pick_b); | |||||
constant_time_select(out,b,a,sizeof(point_t),pick_b); | constant_time_select(out,b,a,sizeof(point_t),pick_b); | ||||
} | } | ||||
@@ -1491,12 +1493,12 @@ void API_NS(scalar_cond_sel) ( | |||||
const scalar_t b, | const scalar_t b, | ||||
decaf_bool_t pick_b | decaf_bool_t pick_b | ||||
) { | ) { | ||||
pick_b = ~(((decaf_dword_t)pick_b - 1) >> WBITS); | |||||
pick_b = ~word_is_zero(pick_b); | |||||
constant_time_select(out,b,a,sizeof(scalar_t),pick_b); | constant_time_select(out,b,a,sizeof(scalar_t),pick_b); | ||||
} | } | ||||
/* TODO: restore Curve25519 Montgomery ladder? */ | /* TODO: restore Curve25519 Montgomery ladder? */ | ||||
decaf_bool_t API_NS(direct_scalarmul) ( | |||||
decaf_error_t API_NS(direct_scalarmul) ( | |||||
uint8_t scaled[SER_BYTES], | uint8_t scaled[SER_BYTES], | ||||
const uint8_t base[SER_BYTES], | const uint8_t base[SER_BYTES], | ||||
const scalar_t scalar, | const scalar_t scalar, | ||||
@@ -1504,13 +1506,13 @@ decaf_bool_t API_NS(direct_scalarmul) ( | |||||
decaf_bool_t short_circuit | decaf_bool_t short_circuit | ||||
) { | ) { | ||||
point_t basep; | point_t basep; | ||||
decaf_bool_t succ = API_NS(point_decode)(basep, base, allow_identity); | |||||
if (short_circuit & ~succ) return succ; | |||||
decaf_bool_t succ = decaf_successful(API_NS(point_decode)(basep, base, allow_identity)); | |||||
if (short_circuit && ~succ) return DECAF_FAILURE; | |||||
API_NS(point_cond_sel)(basep, API_NS(point_base), basep, succ); | API_NS(point_cond_sel)(basep, API_NS(point_base), basep, succ); | ||||
API_NS(point_scalarmul)(basep, basep, scalar); | API_NS(point_scalarmul)(basep, basep, scalar); | ||||
API_NS(point_encode)(scaled, basep); | API_NS(point_encode)(scaled, basep); | ||||
API_NS(point_destroy)(basep); | API_NS(point_destroy)(basep); | ||||
return succ; | |||||
return decaf_succeed_if(succ); | |||||
} | } | ||||
/** | /** | ||||
@@ -75,7 +75,7 @@ int main(int argc, char **argv) { | |||||
API_NS(point_t) real_point_base; | API_NS(point_t) real_point_base; | ||||
int ret = API_NS(point_decode)(real_point_base,base_point_ser_for_pregen,0); | int ret = API_NS(point_decode)(real_point_base,base_point_ser_for_pregen,0); | ||||
if (!ret) return 1; | |||||
if (ret != DECAF_SUCCESS) return 1; | |||||
API_NS(precomputed_s) *pre; | API_NS(precomputed_s) *pre; | ||||
ret = posix_memalign((void**)&pre, API_NS2(alignof,precomputed_s), API_NS2(sizeof,precomputed_s)); | ret = posix_memalign((void**)&pre, API_NS2(alignof,precomputed_s), API_NS2(sizeof,precomputed_s)); | ||||
@@ -73,7 +73,6 @@ | |||||
#define UNUSED __attribute__((unused)) | #define UNUSED __attribute__((unused)) | ||||
#define INLINE __inline__ __attribute__((always_inline)) | #define INLINE __inline__ __attribute__((always_inline)) | ||||
#ifdef __ARM_NEON__ | #ifdef __ARM_NEON__ | ||||
typedef uint32x4_t vecmask_t; | typedef uint32x4_t vecmask_t; | ||||
#elif __clang__ | #elif __clang__ | ||||
@@ -51,9 +51,28 @@ extern "C" { | |||||
/** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */ | /** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */ | ||||
static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1, DECAF_FALSE = 0; | static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1, DECAF_FALSE = 0; | ||||
/** NB Success is -1, failure is 0. */ | |||||
static const decaf_bool_t DECAF_SUCCESS = -(decaf_bool_t)1 /*DECAF_TRUE*/, | |||||
DECAF_FAILURE = 0 /*DECAF_FALSE*/; | |||||
/* Success or failure */ | |||||
// FIXME: deploy project-wide | |||||
typedef enum { | |||||
DECAF_SUCCESS = -1, | |||||
DECAF_FAILURE = 0 | |||||
} decaf_error_t; | |||||
/** Return success if x is true */ | |||||
static __inline__ __attribute__((unused,always_inline)) | |||||
decaf_error_t | |||||
decaf_succeed_if(decaf_bool_t x) { | |||||
return (decaf_error_t)x; | |||||
} | |||||
/** Return DECAF_TRUE iff x == DECAF_SUCCESS */ | |||||
static __inline__ __attribute__((unused,always_inline)) | |||||
decaf_bool_t | |||||
decaf_successful(decaf_error_t e) { | |||||
decaf_dword_t w = ((decaf_word_t)e) ^ ((decaf_word_t)DECAF_SUCCESS); | |||||
return (w-1)>>DECAF_WORD_BITS; | |||||
} | |||||
/** | /** | ||||
* @brief Overwrite data with zeros. Uses memset_s if available. | * @brief Overwrite data with zeros. Uses memset_s if available. | ||||
@@ -103,7 +103,7 @@ void decaf_255_private_to_public ( | |||||
* @warning This is a pretty silly shared secret computation | * @warning This is a pretty silly shared secret computation | ||||
* and will almost definitely change in the future. | * and will almost definitely change in the future. | ||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_shared_secret ( | decaf_255_shared_secret ( | ||||
uint8_t *shared, | uint8_t *shared, | ||||
size_t shared_bytes, | size_t shared_bytes, | ||||
@@ -147,8 +147,11 @@ decaf_255_sign ( | |||||
* @param [in] sig The signature. | * @param [in] sig The signature. | ||||
* @param [in] pub The public key. | * @param [in] pub The public key. | ||||
* @param [in] shake A SHAKE256 context with the message. | * @param [in] shake A SHAKE256 context with the message. | ||||
* | |||||
* @return DECAF_SUCCESS The signature verified successfully. | |||||
* @return DECAF_FAILURE The signature did not verify successfully. | |||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_verify_shake ( | decaf_255_verify_shake ( | ||||
const decaf_255_signature_t sig, | const decaf_255_signature_t sig, | ||||
const decaf_255_public_key_t pub, | const decaf_255_public_key_t pub, | ||||
@@ -162,8 +165,11 @@ decaf_255_verify_shake ( | |||||
* @param [in] pub The public key. | * @param [in] pub The public key. | ||||
* @param [in] message The message. | * @param [in] message The message. | ||||
* @param [in] message_len The message's length. | * @param [in] message_len The message's length. | ||||
* | |||||
* @return DECAF_SUCCESS The signature verified successfully. | |||||
* @return DECAF_FAILURE The signature did not verify successfully. | |||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_verify ( | decaf_255_verify ( | ||||
const decaf_255_signature_t sig, | const decaf_255_signature_t sig, | ||||
const decaf_255_public_key_t pub, | const decaf_255_public_key_t pub, | ||||
@@ -64,14 +64,14 @@ public: | |||||
} | } | ||||
/** @brief Verify a sig. TODO: nothrow version? */ | /** @brief Verify a sig. TODO: nothrow version? */ | ||||
inline bool verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
inline void verify_shake(const SHAKE<SHAKE_BITS> &ctx_, const FixedBlock<SIG_BYTES> &sig) throw(CryptoException) { | |||||
SHAKE<SHAKE_BITS> ctx(ctx_); | SHAKE<SHAKE_BITS> ctx(ctx_); | ||||
ctx << ser << sig.slice(0,Group::Point::SER_BYTES); | ctx << ser << sig.slice(0,Group::Point::SER_BYTES); | ||||
FixedArrayBuffer<CHALLENGE_BYTES> challenge; | FixedArrayBuffer<CHALLENGE_BYTES> challenge; | ||||
ctx.output(challenge); | ctx.output(challenge); | ||||
typename Group::Scalar response; | typename Group::Scalar response; | ||||
decaf_bool_t scalar_OK = Group::Scalar::decode( | |||||
decaf_error_t scalar_OK = Group::Scalar::decode( | |||||
response, | response, | ||||
sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES) | sig.slice(Group::Point::SER_BYTES, Group::Scalar::SER_BYTES) | ||||
); | ); | ||||
@@ -79,9 +79,10 @@ public: | |||||
const typename Group::Point combo = point().non_secret_combo_with_base( | const typename Group::Point combo = point().non_secret_combo_with_base( | ||||
typename Group::Scalar(challenge), response | typename Group::Scalar(challenge), response | ||||
); | ); | ||||
//if (combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))) | |||||
// throw CryptoException(); | |||||
return scalar_OK & (combo == typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))); | |||||
if (!decaf_successful(scalar_OK) | |||||
|| combo != typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))) | |||||
throw CryptoException(); | |||||
//return scalar_OK & (combo == typename Group::Point(sig.slice(0,Group::Point::SER_BYTES))); | |||||
} | } | ||||
/** @brief Sign from a message. */ | /** @brief Sign from a message. */ | ||||
@@ -80,7 +80,7 @@ extern const struct decaf_255_precomputed_s *decaf_255_precomputed_base API_VIS; | |||||
* @retval DECAF_FAILURE The scalar was greater than the modulus, | * @retval DECAF_FAILURE The scalar was greater than the modulus, | ||||
* and has been reduced modulo that modulus. | * and has been reduced modulo that modulus. | ||||
*/ | */ | ||||
decaf_bool_t decaf_255_scalar_decode ( | |||||
decaf_error_t decaf_255_scalar_decode ( | |||||
decaf_255_scalar_t out, | decaf_255_scalar_t out, | ||||
const unsigned char ser[DECAF_255_SCALAR_BYTES] | const unsigned char ser[DECAF_255_SCALAR_BYTES] | ||||
) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ||||
@@ -164,7 +164,7 @@ void decaf_255_scalar_mul ( | |||||
* @param [out] out 1/a. | * @param [out] out 1/a. | ||||
* @return DECAF_SUCCESS The input is nonzero. | * @return DECAF_SUCCESS The input is nonzero. | ||||
*/ | */ | ||||
decaf_bool_t decaf_255_scalar_invert ( | |||||
decaf_error_t decaf_255_scalar_invert ( | |||||
decaf_255_scalar_t out, | decaf_255_scalar_t out, | ||||
const decaf_255_scalar_t a | const decaf_255_scalar_t a | ||||
) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ||||
@@ -217,7 +217,7 @@ void decaf_255_point_encode ( | |||||
* @retval DECAF_FAILURE The decoding didn't succeed, because | * @retval DECAF_FAILURE The decoding didn't succeed, because | ||||
* ser does not represent a point. | * ser does not represent a point. | ||||
*/ | */ | ||||
decaf_bool_t decaf_255_point_decode ( | |||||
decaf_error_t decaf_255_point_decode ( | |||||
decaf_255_point_t pt, | decaf_255_point_t pt, | ||||
const uint8_t ser[DECAF_255_SER_BYTES], | const uint8_t ser[DECAF_255_SER_BYTES], | ||||
decaf_bool_t allow_identity | decaf_bool_t allow_identity | ||||
@@ -335,7 +335,7 @@ void decaf_255_point_scalarmul ( | |||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because | * @retval DECAF_FAILURE The scalarmul didn't succeed, because | ||||
* base does not represent a point. | * base does not represent a point. | ||||
*/ | */ | ||||
decaf_bool_t decaf_255_direct_scalarmul ( | |||||
decaf_error_t decaf_255_direct_scalarmul ( | |||||
uint8_t scaled[DECAF_255_SER_BYTES], | uint8_t scaled[DECAF_255_SER_BYTES], | ||||
const uint8_t base[DECAF_255_SER_BYTES], | const uint8_t base[DECAF_255_SER_BYTES], | ||||
const decaf_255_scalar_t scalar, | const decaf_255_scalar_t scalar, | ||||
@@ -552,7 +552,7 @@ void decaf_255_point_from_hash_uniform ( | |||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The inverse failed. | * @retval DECAF_FAILURE The inverse failed. | ||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_invert_elligator_nonuniform ( | decaf_255_invert_elligator_nonuniform ( | ||||
unsigned char recovered_hash[DECAF_255_SER_BYTES], | unsigned char recovered_hash[DECAF_255_SER_BYTES], | ||||
const decaf_255_point_t pt, | const decaf_255_point_t pt, | ||||
@@ -577,7 +577,7 @@ decaf_255_invert_elligator_nonuniform ( | |||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The inverse failed. | * @retval DECAF_FAILURE The inverse failed. | ||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_255_invert_elligator_uniform ( | decaf_255_invert_elligator_uniform ( | ||||
unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | ||||
const decaf_255_point_t pt, | const decaf_255_point_t pt, | ||||
@@ -139,7 +139,7 @@ public: | |||||
* @brief Decode from correct-length little-endian byte sequence. | * @brief Decode from correct-length little-endian byte sequence. | ||||
* @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. | * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. | ||||
*/ | */ | ||||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | |||||
static inline decaf_error_t __attribute__((warn_unused_result)) decode ( | |||||
Scalar &sc, const FixedBlock<SER_BYTES> buffer | Scalar &sc, const FixedBlock<SER_BYTES> buffer | ||||
) NOEXCEPT { | ) NOEXCEPT { | ||||
return decaf_255_scalar_decode(sc.s,buffer.data()); | return decaf_255_scalar_decode(sc.s,buffer.data()); | ||||
@@ -268,7 +268,7 @@ public: | |||||
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, | ||||
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | ||||
*/ | */ | ||||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | |||||
static inline decaf_error_t __attribute__((warn_unused_result)) decode ( | |||||
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | ||||
) NOEXCEPT { | ) NOEXCEPT { | ||||
return decaf_255_point_decode(p.p,buffer.data(),allow_identity); | return decaf_255_point_decode(p.p,buffer.data(),allow_identity); | ||||
@@ -354,7 +354,7 @@ public: | |||||
inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } | inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } | ||||
/** @brief Validate / sanity check */ | /** @brief Validate / sanity check */ | ||||
inline bool validate() const NOEXCEPT { return DECAF_SUCCESS == decaf_255_point_valid(p); } | |||||
inline bool validate() const NOEXCEPT { return decaf_255_point_valid(p); } | |||||
/** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ | /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ | ||||
static inline Point double_scalarmul ( | static inline Point double_scalarmul ( | ||||
@@ -398,10 +398,10 @@ public: | |||||
} | } | ||||
/** | /** | ||||
* Modify buffer so that Point::from_hash(Buffer) == *this, and return true; | |||||
* or leave buf unmodified and return false. | |||||
* Modify buffer so that Point::from_hash(Buffer) == *this, and return DECAF_SUCCESS; | |||||
* or leave buf unmodified and return DECAF_FAILURE. | |||||
*/ | */ | ||||
inline bool invert_elligator ( | |||||
inline decaf_error_t invert_elligator ( | |||||
Buffer buf, uint16_t hint | Buffer buf, uint16_t hint | ||||
) const NOEXCEPT { | ) const NOEXCEPT { | ||||
unsigned char buf2[2*HASH_BYTES]; | unsigned char buf2[2*HASH_BYTES]; | ||||
@@ -409,30 +409,30 @@ public: | |||||
memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); | memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); | ||||
decaf_bool_t ret; | decaf_bool_t ret; | ||||
if (buf.size() > HASH_BYTES) { | if (buf.size() > HASH_BYTES) { | ||||
ret = decaf_255_invert_elligator_uniform(buf2, p, hint); | |||||
ret = decaf_successful(decaf_255_invert_elligator_uniform(buf2, p, hint)); | |||||
} else { | } else { | ||||
ret = decaf_255_invert_elligator_nonuniform(buf2, p, hint); | |||||
ret = decaf_successful(decaf_255_invert_elligator_nonuniform(buf2, p, hint)); | |||||
} | } | ||||
if (buf.size() < HASH_BYTES) { | if (buf.size() < HASH_BYTES) { | ||||
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ||||
} | } | ||||
if (DECAF_SUCCESS == ret) { | |||||
if (ret) { | |||||
/* TODO: make this constant time?? */ | /* TODO: make this constant time?? */ | ||||
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | ||||
} | } | ||||
decaf_bzero(buf2,sizeof(buf2)); | decaf_bzero(buf2,sizeof(buf2)); | ||||
return DECAF_SUCCESS == ret; | |||||
return decaf_succeed_if(ret); | |||||
} | } | ||||
/** @brief Steganographically encode this */ | /** @brief Steganographically encode this */ | ||||
inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const throw(std::bad_alloc, LengthException) { | inline SecureBuffer steg_encode(Rng &rng, size_t size=STEG_BYTES) const throw(std::bad_alloc, LengthException) { | ||||
if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); | if (size <= HASH_BYTES + 4 || size > 2*HASH_BYTES) throw LengthException(); | ||||
SecureBuffer out(STEG_BYTES); | SecureBuffer out(STEG_BYTES); | ||||
bool done; | |||||
decaf_error_t done; | |||||
do { | do { | ||||
rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); | rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); | ||||
done = invert_elligator(out, out[HASH_BYTES-1]); | done = invert_elligator(out, out[HASH_BYTES-1]); | ||||
} while (!done); | |||||
} while (!decaf_successful(done)); | |||||
return out; | return out; | ||||
} | } | ||||
@@ -80,7 +80,7 @@ extern const struct decaf_448_precomputed_s *decaf_448_precomputed_base API_VIS; | |||||
* @retval DECAF_FAILURE The scalar was greater than the modulus, | * @retval DECAF_FAILURE The scalar was greater than the modulus, | ||||
* and has been reduced modulo that modulus. | * and has been reduced modulo that modulus. | ||||
*/ | */ | ||||
decaf_bool_t decaf_448_scalar_decode ( | |||||
decaf_error_t decaf_448_scalar_decode ( | |||||
decaf_448_scalar_t out, | decaf_448_scalar_t out, | ||||
const unsigned char ser[DECAF_448_SCALAR_BYTES] | const unsigned char ser[DECAF_448_SCALAR_BYTES] | ||||
) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ||||
@@ -164,7 +164,7 @@ void decaf_448_scalar_mul ( | |||||
* @param [out] out 1/a. | * @param [out] out 1/a. | ||||
* @return DECAF_TRUE The input is nonzero. | * @return DECAF_TRUE The input is nonzero. | ||||
*/ | */ | ||||
decaf_bool_t decaf_448_scalar_invert ( | |||||
decaf_error_t decaf_448_scalar_invert ( | |||||
decaf_448_scalar_t out, | decaf_448_scalar_t out, | ||||
const decaf_448_scalar_t a | const decaf_448_scalar_t a | ||||
) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ) API_VIS WARN_UNUSED NONNULL2 NOINLINE; | ||||
@@ -217,7 +217,7 @@ void decaf_448_point_encode ( | |||||
* @retval DECAF_FAILURE The decoding didn't succeed, because | * @retval DECAF_FAILURE The decoding didn't succeed, because | ||||
* ser does not represent a point. | * ser does not represent a point. | ||||
*/ | */ | ||||
decaf_bool_t decaf_448_point_decode ( | |||||
decaf_error_t decaf_448_point_decode ( | |||||
decaf_448_point_t pt, | decaf_448_point_t pt, | ||||
const uint8_t ser[DECAF_448_SER_BYTES], | const uint8_t ser[DECAF_448_SER_BYTES], | ||||
decaf_bool_t allow_identity | decaf_bool_t allow_identity | ||||
@@ -335,7 +335,7 @@ void decaf_448_point_scalarmul ( | |||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because | * @retval DECAF_FAILURE The scalarmul didn't succeed, because | ||||
* base does not represent a point. | * base does not represent a point. | ||||
*/ | */ | ||||
decaf_bool_t decaf_448_direct_scalarmul ( | |||||
decaf_error_t decaf_448_direct_scalarmul ( | |||||
uint8_t scaled[DECAF_448_SER_BYTES], | uint8_t scaled[DECAF_448_SER_BYTES], | ||||
const uint8_t base[DECAF_448_SER_BYTES], | const uint8_t base[DECAF_448_SER_BYTES], | ||||
const decaf_448_scalar_t scalar, | const decaf_448_scalar_t scalar, | ||||
@@ -552,7 +552,7 @@ void decaf_448_point_from_hash_uniform ( | |||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The inverse failed. | * @retval DECAF_FAILURE The inverse failed. | ||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_448_invert_elligator_nonuniform ( | decaf_448_invert_elligator_nonuniform ( | ||||
unsigned char recovered_hash[DECAF_448_SER_BYTES], | unsigned char recovered_hash[DECAF_448_SER_BYTES], | ||||
const decaf_448_point_t pt, | const decaf_448_point_t pt, | ||||
@@ -577,7 +577,7 @@ decaf_448_invert_elligator_nonuniform ( | |||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The inverse failed. | * @retval DECAF_FAILURE The inverse failed. | ||||
*/ | */ | ||||
decaf_bool_t | |||||
decaf_error_t | |||||
decaf_448_invert_elligator_uniform ( | decaf_448_invert_elligator_uniform ( | ||||
unsigned char recovered_hash[2*DECAF_448_SER_BYTES], | unsigned char recovered_hash[2*DECAF_448_SER_BYTES], | ||||
const decaf_448_point_t pt, | const decaf_448_point_t pt, | ||||
@@ -130,7 +130,7 @@ public: | |||||
* @brief Decode from correct-length little-endian byte sequence. | * @brief Decode from correct-length little-endian byte sequence. | ||||
* @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. | * @return DECAF_FAILURE if the scalar is greater than or equal to the group order q. | ||||
*/ | */ | ||||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | |||||
static inline decaf_error_t __attribute__((warn_unused_result)) decode ( | |||||
Scalar &sc, const FixedBlock<SER_BYTES> buffer | Scalar &sc, const FixedBlock<SER_BYTES> buffer | ||||
) NOEXCEPT { | ) NOEXCEPT { | ||||
return decaf_448_scalar_decode(sc.s,buffer.data()); | return decaf_448_scalar_decode(sc.s,buffer.data()); | ||||
@@ -271,7 +271,7 @@ public: | |||||
* @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point, | ||||
* or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | * or was the identity and allow_identity was DECAF_FALSE. Contents of the buffer are undefined. | ||||
*/ | */ | ||||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | |||||
static inline decaf_error_t __attribute__((warn_unused_result)) decode ( | |||||
Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | Point &p, const FixedBlock<SER_BYTES> &buffer, decaf_bool_t allow_identity=DECAF_TRUE | ||||
) NOEXCEPT { | ) NOEXCEPT { | ||||
return decaf_448_point_decode(p.p,buffer.data(),allow_identity); | return decaf_448_point_decode(p.p,buffer.data(),allow_identity); | ||||
@@ -366,7 +366,7 @@ public: | |||||
inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } | inline Point &operator/=(const Scalar &s) throw(CryptoException) { return (*this) *= s.inverse(); } | ||||
/** @brief Validate / sanity check */ | /** @brief Validate / sanity check */ | ||||
inline bool validate() const NOEXCEPT { return DECAF_SUCCESS == decaf_448_point_valid(p); } | |||||
inline bool validate() const NOEXCEPT { return decaf_448_point_valid(p); } | |||||
/** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ | /** @brief Double-scalar multiply, equivalent to q*qs + r*rs but faster. */ | ||||
static inline Point double_scalarmul ( | static inline Point double_scalarmul ( | ||||
@@ -415,10 +415,10 @@ public: | |||||
} | } | ||||
/** | /** | ||||
* Modify buffer so that Point::from_hash(Buffer) == *this, and return true; | |||||
* or leave buf unmodified and return false. | |||||
* Modify buffer so that Point::from_hash(Buffer) == *this, and return DECAF_SUCCESS; | |||||
* or leave buf unmodified and return DECAF_FAILURE. | |||||
*/ | */ | ||||
inline bool invert_elligator ( | |||||
inline decaf_error_t invert_elligator ( | |||||
Buffer buf, uint16_t hint | Buffer buf, uint16_t hint | ||||
) const NOEXCEPT { | ) const NOEXCEPT { | ||||
unsigned char buf2[2*HASH_BYTES]; | unsigned char buf2[2*HASH_BYTES]; | ||||
@@ -426,30 +426,29 @@ public: | |||||
memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); | memcpy(buf2,buf.data(),(buf.size() > 2*HASH_BYTES) ? 2*HASH_BYTES : buf.size()); | ||||
decaf_bool_t ret; | decaf_bool_t ret; | ||||
if (buf.size() > HASH_BYTES) { | if (buf.size() > HASH_BYTES) { | ||||
ret = decaf_448_invert_elligator_uniform(buf2, p, hint); | |||||
ret = decaf_successful(decaf_448_invert_elligator_uniform(buf2, p, hint)); | |||||
} else { | } else { | ||||
ret = decaf_448_invert_elligator_nonuniform(buf2, p, hint); | |||||
ret = decaf_successful(decaf_448_invert_elligator_nonuniform(buf2, p, hint)); | |||||
} | } | ||||
if (buf.size() < HASH_BYTES) { | if (buf.size() < HASH_BYTES) { | ||||
// FIXME: this &= will fail if success becomes 0 | |||||
ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ret &= decaf_memeq(&buf2[buf.size()], &buf2[HASH_BYTES], HASH_BYTES - buf.size()); | ||||
} | } | ||||
if (DECAF_SUCCESS == ret) { | |||||
if (ret) { | |||||
/* TODO: make this constant time?? */ | /* TODO: make this constant time?? */ | ||||
memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | memcpy(buf.data(),buf2,(buf.size() < HASH_BYTES) ? buf.size() : HASH_BYTES); | ||||
} | } | ||||
decaf_bzero(buf2,sizeof(buf2)); | decaf_bzero(buf2,sizeof(buf2)); | ||||
return (ret == DECAF_SUCCESS); | |||||
return decaf_succeed_if(ret); | |||||
} | } | ||||
/** @brief Steganographically encode this */ | /** @brief Steganographically encode this */ | ||||
inline SecureBuffer steg_encode(Rng &rng) const throw(std::bad_alloc) { | inline SecureBuffer steg_encode(Rng &rng) const throw(std::bad_alloc) { | ||||
SecureBuffer out(STEG_BYTES); | SecureBuffer out(STEG_BYTES); | ||||
bool done; | |||||
decaf_error_t done; | |||||
do { | do { | ||||
rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); | rng.read(Buffer(out).slice(HASH_BYTES-1,STEG_BYTES-HASH_BYTES+1)); | ||||
done = invert_elligator(out, out[HASH_BYTES-1]); | done = invert_elligator(out, out[HASH_BYTES-1]); | ||||
} while (!done); | |||||
} while (!decaf_successful(done)); | |||||
return out; | return out; | ||||
} | } | ||||
@@ -201,8 +201,8 @@ static void test_elligator() { | |||||
if (len > Point::HASH_BYTES) | if (len > Point::HASH_BYTES) | ||||
memcpy(&(*alts2[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); | memcpy(&(*alts2[j])[Point::HASH_BYTES], &b1[Point::HASH_BYTES], len-Point::HASH_BYTES); | ||||
successes[j] = s.invert_elligator(*alts[j], j); | |||||
successes2[j] = ss.invert_elligator(*alts2[j],j); | |||||
successes[j] = decaf_successful( s.invert_elligator(*alts[j], j)); | |||||
successes2[j] = decaf_successful(ss.invert_elligator(*alts2[j],j)); | |||||
if (successes[j] != successes2[j] | if (successes[j] != successes2[j] | ||||
|| (successes[j] && successes2[j] && *alts[j] != *alts2[j]) | || (successes[j] && successes2[j] && *alts[j] != *alts2[j]) | ||||
@@ -353,17 +353,17 @@ static void test_decaf() { | |||||
decaf_255_private_to_public(p1,s1); | decaf_255_private_to_public(p1,s1); | ||||
decaf_255_derive_private_key(s2,proto2); | decaf_255_derive_private_key(s2,proto2); | ||||
decaf_255_private_to_public(p2,s2); | decaf_255_private_to_public(p2,s2); | ||||
if (!decaf_255_shared_secret (shared1,sizeof(shared1),s1,p2)) { | |||||
if (DECAF_SUCCESS != decaf_255_shared_secret (shared1,sizeof(shared1),s1,p2)) { | |||||
test.fail(); printf("Fail ss12\n"); | test.fail(); printf("Fail ss12\n"); | ||||
} | } | ||||
if (!decaf_255_shared_secret (shared2,sizeof(shared2),s2,p1)) { | |||||
if (DECAF_SUCCESS != decaf_255_shared_secret (shared2,sizeof(shared2),s2,p1)) { | |||||
test.fail(); printf("Fail ss21\n"); | test.fail(); printf("Fail ss21\n"); | ||||
} | } | ||||
if (memcmp(shared1,shared2,sizeof(shared1))) { | if (memcmp(shared1,shared2,sizeof(shared1))) { | ||||
test.fail(); printf("Fail ss21 == ss12\n"); | test.fail(); printf("Fail ss21 == ss12\n"); | ||||
} | } | ||||
decaf_255_sign (sig,s1,(const unsigned char *)message,strlen(message)); | decaf_255_sign (sig,s1,(const unsigned char *)message,strlen(message)); | ||||
if (!decaf_255_verify (sig,p1,(const unsigned char *)message,strlen(message))) { | |||||
if (DECAF_SUCCESS != decaf_255_verify (sig,p1,(const unsigned char *)message,strlen(message))) { | |||||
test.fail(); printf("Fail sig ver\n"); | test.fail(); printf("Fail sig ver\n"); | ||||
} | } | ||||
} | } | ||||