Browse Source

beginning to separate errors from bools. not there yet though

master
Michael Hamburg 9 years ago
parent
commit
a1f5348e18
12 changed files with 109 additions and 82 deletions
  1. +13
    -12
      src/decaf_crypto.c
  2. +17
    -15
      src/decaf_fast.c
  3. +1
    -1
      src/decaf_gen_tables.c
  4. +0
    -1
      src/include/word.h
  5. +22
    -3
      src/public_include/decaf/common.h
  6. +9
    -3
      src/public_include/decaf/crypto.h
  7. +6
    -5
      src/public_include/decaf/crypto.hxx
  8. +6
    -6
      src/public_include/decaf/decaf_255.h
  9. +12
    -12
      src/public_include/decaf/decaf_255.hxx
  10. +6
    -6
      src/public_include/decaf/decaf_448.h
  11. +12
    -13
      src/public_include/decaf/decaf_448.hxx
  12. +5
    -5
      test/test_decaf.cxx

+ 13
- 12
src/decaf_crypto.c View File

@@ -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;
} }

+ 17
- 15
src/decaf_fast.c View File

@@ -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);
} }


/** /**


+ 1
- 1
src/decaf_gen_tables.c View File

@@ -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));


+ 0
- 1
src/include/word.h View File

@@ -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__


+ 22
- 3
src/public_include/decaf/common.h View File

@@ -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.


+ 9
- 3
src/public_include/decaf/crypto.h View File

@@ -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,


+ 6
- 5
src/public_include/decaf/crypto.hxx View File

@@ -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. */


+ 6
- 6
src/public_include/decaf/decaf_255.h View File

@@ -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,


+ 12
- 12
src/public_include/decaf/decaf_255.hxx View File

@@ -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;
} }


+ 6
- 6
src/public_include/decaf/decaf_448.h View File

@@ -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,


+ 12
- 13
src/public_include/decaf/decaf_448.hxx View File

@@ -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;
} }


+ 5
- 5
test/test_decaf.cxx View File

@@ -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");
} }
} }


Loading…
Cancel
Save