diff --git a/include/decaf.h b/include/decaf.h index 7ebc2f1..4349819 100644 --- a/include/decaf.h +++ b/include/decaf.h @@ -29,6 +29,7 @@ #define NONNULL2 __attribute__((nonnull(1,2))) #define NONNULL3 __attribute__((nonnull(1,2,3))) +/** Types of internal words. TODO: ARCH: make 32-bit clean */ typedef uint64_t decaf_word_t, decaf_bool_t; /* TODO: prefix all these operations and factor to support multiple curves. */ @@ -49,21 +50,20 @@ typedef struct decaf_point_s { decaf_word_t x[DECAF_LIMBS],y[DECAF_LIMBS],z[DECAF_LIMBS],t[DECAF_LIMBS]; } decaf_point_t[1]; +/** Scalar is stored packed, because we don't need the speed. */ typedef struct decaf_scalar_s { decaf_word_t limb[DECAF_SCALAR_LIMBS]; } decaf_scalar_t[1]; +/** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */ static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1, DECAF_FALSE = 0; /** NB Success is -1, failure is 0. TODO: see if people would rather the reverse. */ static const decaf_bool_t DECAF_SUCCESS = -(decaf_bool_t)1 /*DECAF_TRUE*/, DECAF_FAILURE = 0 /*DECAF_FALSE*/; -/** The identity point on the curve. */ -const decaf_point_t decaf_identity API_VIS; - /** The prime p, for debugging purposes. - * FIXME: prevent this scalar from actually being used for non-debugging purposes? + * TODO: prevent this scalar from actually being used for non-debugging purposes? */ const decaf_scalar_t decaf_scalar_p API_VIS; @@ -73,17 +73,22 @@ const decaf_scalar_t decaf_scalar_one API_VIS; /** A scalar equal to 0. */ const decaf_scalar_t decaf_scalar_zero API_VIS; -/** An arbitrarily chosen base point on the curve. TODO: define */ -const decaf_point_t decaf_basepoint API_VIS; +/** The identity point on the curve. */ +const decaf_point_t decaf_point_identity API_VIS; + +/** + * An arbitrarily chosen base point on the curve. + * Equal to Ed448-Goldilocks base point defined by DJB, except of course that + * it's on the twist in this case. TODO: choose a base point with nice encoding? + */ +const decaf_point_t decaf_point_base API_VIS; #ifdef __cplusplus extern "C" { #endif + +/* TODO: scalar invert? */ - // TODO: ser, deser, inv?. - // FIXME: scalar math is untested, and therefore probably wrong. - - /** * @brief Read a scalar from wire format or from bytes. * @@ -96,7 +101,7 @@ extern "C" { * @param [in] ser Serialized form of a scalar. * @param [out] out Deserialized form. */ -decaf_bool_t decaf_decode_scalar( +decaf_bool_t decaf_scalar_decode ( decaf_scalar_t s, const unsigned char ser[DECAF_SER_BYTES] ) API_VIS NONNULL2; @@ -107,7 +112,7 @@ decaf_bool_t decaf_decode_scalar( * @param [out] ser Serialized form of a scalar. * @param [in] s Deserialized scalar. */ -void decaf_encode_scalar( +void decaf_scalar_encode ( unsigned char ser[DECAF_SER_BYTES], const decaf_scalar_t s ) API_VIS NONNULL2; @@ -118,7 +123,7 @@ void decaf_encode_scalar( * @param [in] b Another scalar. * @param [out] out a+b. */ -void decaf_add_scalars ( +void decaf_scalar_add ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -131,7 +136,7 @@ void decaf_add_scalars ( * @retval DECAF_TRUE The scalars are equal. * @retval DECAF_FALSE The scalars are not equal. */ -decaf_bool_t decaf_eq_scalars ( +decaf_bool_t decaf_scalar_eq ( const decaf_scalar_t a, const decaf_scalar_t b ) API_VIS WARN_UNUSED NONNULL2; @@ -142,7 +147,7 @@ decaf_bool_t decaf_eq_scalars ( * @param [in] b Another scalar. * @param [out] out a-b. */ -void decaf_sub_scalars ( +void decaf_scalar_sub ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -154,7 +159,7 @@ void decaf_sub_scalars ( * @param [in] b Another scalar. * @param [out] out a*b. */ -void decaf_mul_scalars ( +void decaf_scalar_mul ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -166,7 +171,7 @@ void decaf_mul_scalars ( * @param [out] ser The byte representation of the point. * @param [in] pt The point to encode. */ -void decaf_encode ( +void decaf_point_encode ( uint8_t ser[DECAF_SER_BYTES], const decaf_point_t pt ) API_VIS NONNULL2; @@ -184,7 +189,7 @@ void decaf_encode ( * @retval DECAF_FAILURE The decoding didn't succeed, because * ser does not represent a point. */ -decaf_bool_t decaf_decode ( +decaf_bool_t decaf_point_decode ( decaf_point_t pt, const uint8_t ser[DECAF_SER_BYTES], decaf_bool_t allow_identity @@ -197,7 +202,7 @@ decaf_bool_t decaf_decode ( * @param [out] a A copy of the point. * @param [in] b Any point. */ -void decaf_copy ( +void decaf_point_copy ( decaf_point_t a, const decaf_point_t b ) API_VIS NONNULL2; @@ -211,7 +216,7 @@ void decaf_copy ( * @retval DECAF_TRUE The points are equal. * @retval DECAF_FALSE The points are not equal. */ -decaf_bool_t decaf_eq ( +decaf_bool_t decaf_point_eq ( const decaf_point_t a, const decaf_point_t b ) API_VIS WARN_UNUSED NONNULL2; @@ -225,7 +230,7 @@ decaf_bool_t decaf_eq ( * @param [in] a An addend. * @param [in] b An addend. */ -void decaf_add ( +void decaf_point_add ( decaf_point_t sum, const decaf_point_t a, const decaf_point_t b @@ -240,7 +245,7 @@ void decaf_add ( * @param [in] a The minuend. * @param [in] b The subtrahend. */ -void decaf_sub ( +void decaf_point_sub ( decaf_point_t diff, const decaf_point_t a, const decaf_point_t b @@ -252,13 +257,11 @@ void decaf_sub ( * @param [out] scaled The scaled point base*scalar * @param [in] base The point to be scaled. * @param [in] scalar The scalar to multilpy by. - * @param [in] scalar_words The number of words in the scalar [TODO] */ -void decaf_scalarmul ( +void decaf_point_scalarmul ( decaf_point_t scaled, const decaf_point_t base, - const decaf_word_t *scalar, - unsigned int scalar_words + const decaf_scalar_t scalar ) API_VIS NONNULL3; /** @@ -268,7 +271,7 @@ void decaf_scalarmul ( * @retval DECAF_TRUE The point is valid. * @retval DECAF_FALSE The point is invalid. */ -decaf_bool_t decaf_valid ( +decaf_bool_t decaf_point_valid ( const decaf_point_t toTest ) API_VIS WARN_UNUSED NONNULL1; @@ -299,7 +302,7 @@ decaf_bool_t decaf_valid ( * @param [in] hashed_data Output of some hash function. * @param [out] pt The data hashed to the curve. */ -void decaf_nonuniform_map_to_curve ( +void decaf_point_from_hash_nonuniform ( decaf_point_t pt, const unsigned char hashed_data[DECAF_SER_BYTES] ) API_VIS NONNULL2; @@ -307,18 +310,21 @@ void decaf_nonuniform_map_to_curve ( /** * @brief Indifferentiable hash function encoding to curve. * - * Equivalent to calling decaf_nonuniform_map_to_curve twice and adding. + * Equivalent to calling decaf_point_from_hash_nonuniform twice and adding. * * @param [in] hashed_data Output of some hash function. * @param [out] pt The data hashed to the curve. */ -void decaf_uniform_map_to_curve ( +void decaf_point_from_hash_uniform ( decaf_point_t pt, const unsigned char hashed_data[2*DECAF_SER_BYTES] ) API_VIS NONNULL2; +/* TODO: functions to invert point_from_hash?? */ + #undef API_VIS #undef WARN_UNUSED +#undef NONNULL1 #undef NONNULL2 #undef NONNULL3 diff --git a/src/decaf.c b/src/decaf.c index e52d065..ed2e847 100644 --- a/src/decaf.c +++ b/src/decaf.c @@ -279,7 +279,7 @@ sv decaf_montmul ( decaf_subx(out, accum, p, p, hi_carry); } -void decaf_mul_scalars ( +void decaf_scalar_mul ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -288,7 +288,7 @@ void decaf_mul_scalars ( decaf_montmul(out,out,decaf_scalar_r2,decaf_scalar_p,DECAF_MONTGOMERY_FACTOR); } -void decaf_sub_scalars ( +void decaf_scalar_sub ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -296,7 +296,7 @@ void decaf_sub_scalars ( decaf_subx(out, a->limb, b, decaf_scalar_p, 0); } -void decaf_add_scalars ( +void decaf_scalar_add ( decaf_scalar_t out, const decaf_scalar_t a, const decaf_scalar_t b @@ -311,7 +311,7 @@ void decaf_add_scalars ( decaf_subx(out, out->limb, decaf_scalar_p, decaf_scalar_p, chain); } -decaf_bool_t decaf_eq_scalars ( +decaf_bool_t decaf_scalar_eq ( const decaf_scalar_t a, const decaf_scalar_t b ) { @@ -326,9 +326,20 @@ decaf_bool_t decaf_eq_scalars ( /* *** API begins here *** */ /** identity = (0,1) */ -const decaf_point_t decaf_identity = {{{0},{1},{1},{0}}}; - -void decaf_encode( unsigned char ser[DECAF_SER_BYTES], const decaf_point_t p ) { +const decaf_point_t decaf_point_identity = {{{0},{1},{1},{0}}}; + +/** base = twist of Goldilocks base point (~,19). FIXME: ARCH */ +const decaf_point_t decaf_point_base = {{ + { 0xb39a2d57e08c7bull,0xb38639c75ff281ull,0x2ec981082b3288ull,0x99fe8607e5237cull, + 0x0e33fbb1fadd1full,0xe714f67055eb4aull,0xc9ae06d64067ddull,0xf7be45054760faull }, + { 0xbd8715f551617full,0x8c17fbeca8f5fcull,0xaae0eec209c06full,0xce41ad80cbe6b8ull, + 0xdf360b5c828c00ull,0xaf25b6bbb40e3bull,0x8ed37f0ce4ed31ull,0x72a1c3214557b9ull }, + { 1 }, + { 0x97ca9c8ed8bde9ull,0xf0b780da83304cull,0x0d79c0a7729a69ull,0xc18d3f24aebc1cull, + 0x1fbb5389b3fda5ull,0xbb24f674635948ull,0x723a55709a3983ull,0xe1c0107a823dd4ull } +}}; + +void decaf_point_encode( unsigned char ser[DECAF_SER_BYTES], const decaf_point_t p ) { gf a, b, c, d; gf_mlw ( a, p->y, 1-EDWARDS_D ); gf_mul ( c, a, p->t ); @@ -380,7 +391,7 @@ static decaf_bool_t gf_deser(gf s, const unsigned char ser[DECAF_SER_BYTES]) { } /* Constant-time add or subtract */ -sv decaf_add_sub ( +sv decaf_point_add_sub ( decaf_point_t p, const decaf_point_t q, const decaf_point_t r, @@ -410,7 +421,7 @@ sv decaf_add_sub ( gf_mul ( p->t, b, c ); } -decaf_bool_t decaf_decode ( +decaf_bool_t decaf_point_decode ( decaf_point_t p, const unsigned char ser[DECAF_SER_BYTES], decaf_bool_t allow_identity @@ -444,16 +455,16 @@ decaf_bool_t decaf_decode ( return succ; } -void decaf_sub(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) { - decaf_add_sub(a,b,c,-1); +void decaf_point_sub(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) { + decaf_point_add_sub(a,b,c,-1); } -void decaf_add(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) { - decaf_add_sub(a,b,c,0); +void decaf_point_add(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) { + decaf_point_add_sub(a,b,c,0); } /* No dedicated point double (PERF) */ -#define decaf_dbl(a,b) decaf_add(a,b,b) +#define decaf_dbl(a,b) decaf_point_add(a,b,b) void decaf_copy ( decaf_point_t a, @@ -465,7 +476,7 @@ void decaf_copy ( gf_cpy(a->t, b->t); } -decaf_bool_t decaf_decode_scalar( +decaf_bool_t decaf_scalar_decode( decaf_scalar_t s, const unsigned char ser[DECAF_SER_BYTES] ) { @@ -483,12 +494,12 @@ decaf_bool_t decaf_decode_scalar( accum = (accum + s->limb[i] - decaf_scalar_p->limb[i]) >> WBITS; } - //decaf_mul_scalars(s,s,decaf_scalar_one); /* ham-handed reduce */ + decaf_scalar_mul(s,s,decaf_scalar_one); /* ham-handed reduce */ return accum; } -void decaf_encode_scalar( +void decaf_scalar_encode( unsigned char ser[DECAF_SER_BYTES], const decaf_scalar_t s ) { @@ -500,16 +511,11 @@ void decaf_encode_scalar( } } -void decaf_scalarmul ( +void decaf_point_scalarmul ( decaf_point_t a, const decaf_point_t b, - const decaf_word_t *scalar, - unsigned int scalar_words + const decaf_scalar_t scalar ) { - if (scalar_words == 0) { - decaf_copy(a,decaf_identity); - return; - } /* w=2 signed window uses about 1.5 adds per bit. * I figured a few extra lines was worth the 25% speedup. * NB: if adapting this function to scalarmul by a @@ -518,22 +524,22 @@ void decaf_scalarmul ( decaf_point_t w,b3,tmp; decaf_dbl(w,b); /* b3 = b*3 */ - decaf_add(b3,w,b); + decaf_point_add(b3,w,b); int i; - for (i=scalar_words*WBITS-2; i>0; i-=2) { - decaf_word_t bits = scalar[i/WBITS]>>(i%WBITS); + for (i=DECAF_SCALAR_LIMBS*WBITS-2; i>0; i-=2) { + decaf_word_t bits = scalar->limb[i/WBITS]>>(i%WBITS); decaf_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1); decaf_dbl(w,w); - decaf_add_sub(w,w,tmp,((bits>>1)&1)-1); + decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1); decaf_dbl(w,w); } - decaf_add_sub(w,w,b,((scalar[0]>>1)&1)-1); + decaf_point_add_sub(w,w,b,((scalar->limb[0]>>1)&1)-1); /* low bit is special because fo signed window */ - decaf_cond_sel(tmp,b,decaf_identity,-(scalar[0]&1)); - decaf_sub(a,w,tmp); + decaf_cond_sel(tmp,b,decaf_point_identity,-(scalar->limb[0]&1)); + decaf_point_sub(a,w,tmp); } -decaf_bool_t decaf_eq ( const decaf_point_t p, const decaf_point_t q ) { +decaf_bool_t decaf_point_eq ( const decaf_point_t p, const decaf_point_t q ) { /* equality mod 2-torsion compares x/y */ gf a, b; gf_mul ( a, p->y, q->x ); @@ -543,7 +549,7 @@ decaf_bool_t decaf_eq ( const decaf_point_t p, const decaf_point_t q ) { static const int QUADRATIC_NONRESIDUE = -1; -void decaf_nonuniform_map_to_curve ( +void decaf_point_from_hash_nonuniform ( decaf_point_t p, const unsigned char ser[DECAF_SER_BYTES] ) { @@ -583,17 +589,17 @@ void decaf_nonuniform_map_to_curve ( gf_mul(p->t,b,e); } -void decaf_uniform_map_to_curve ( +void decaf_point_from_hash_uniform ( decaf_point_t pt, const unsigned char hashed_data[2*DECAF_SER_BYTES] ) { decaf_point_t pt2; - decaf_nonuniform_map_to_curve(pt,hashed_data); - decaf_nonuniform_map_to_curve(pt2,&hashed_data[DECAF_SER_BYTES]); - decaf_add(pt,pt,pt2); + decaf_point_from_hash_nonuniform(pt,hashed_data); + decaf_point_from_hash_nonuniform(pt2,&hashed_data[DECAF_SER_BYTES]); + decaf_point_add(pt,pt,pt2); } -decaf_bool_t decaf_valid ( +decaf_bool_t decaf_point_valid ( const decaf_point_t p ) { gf a,b,c; diff --git a/test/bench.c b/test/bench.c index c60569e..6152e68 100644 --- a/test/bench.c +++ b/test/bench.c @@ -271,7 +271,7 @@ int main(int argc, char **argv) { memset(bsc,0,sizeof(bsc)); when = now(); for (i=0; ix); @@ -125,8 +125,8 @@ single_scalarmul_compatibility_test ( untwist_and_double_and_serialize(sced, &work); uint8_t ser1[(FIELD_BITS+6)/8], ser2[(FIELD_BITS+6)/8]; - decaf_encode(ser1, (struct decaf_point_s *)ed); - decaf_encode(ser2, ed2); + decaf_point_encode(ser1, (struct decaf_point_s *)ed); + decaf_point_encode(ser2, ed2); /* check consistency mont vs window */ consistent &= field_eq(mont, ct);