| @@ -63,6 +63,11 @@ typedef struct decaf_448_point_s { | |||||
| decaf_word_t x[DECAF_448_LIMBS],y[DECAF_448_LIMBS],z[DECAF_448_LIMBS],t[DECAF_448_LIMBS]; | decaf_word_t x[DECAF_448_LIMBS],y[DECAF_448_LIMBS],z[DECAF_448_LIMBS],t[DECAF_448_LIMBS]; | ||||
| } decaf_448_point_t[1]; | } decaf_448_point_t[1]; | ||||
| /** Precomputed table based on a point. Can be trivial implementation. */ | |||||
| typedef struct decaf_448_precomputed_s { | |||||
| decaf_448_point_t p[1]; | |||||
| } decaf_448_precomputed_t[1]; | |||||
| /** Scalar is stored packed, because we don't need the speed. */ | /** Scalar is stored packed, because we don't need the speed. */ | ||||
| typedef struct decaf_448_scalar_s { | typedef struct decaf_448_scalar_s { | ||||
| decaf_word_t limb[DECAF_448_SCALAR_LIMBS]; | decaf_word_t limb[DECAF_448_SCALAR_LIMBS]; | ||||
| @@ -78,23 +83,26 @@ static const decaf_bool_t DECAF_SUCCESS = -(decaf_bool_t)1 /*DECAF_TRUE*/, | |||||
| /** The prime p, for debugging purposes. | /** The prime p, for debugging purposes. | ||||
| * TODO: 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_448_scalar_t decaf_448_scalar_p API_VIS; | |||||
| extern const decaf_448_scalar_t decaf_448_scalar_p API_VIS; | |||||
| /** A scalar equal to 1. */ | /** A scalar equal to 1. */ | ||||
| const decaf_448_scalar_t decaf_448_scalar_one API_VIS; | |||||
| extern const decaf_448_scalar_t decaf_448_scalar_one API_VIS; | |||||
| /** A scalar equal to 0. */ | /** A scalar equal to 0. */ | ||||
| const decaf_448_scalar_t decaf_448_scalar_zero API_VIS; | |||||
| extern const decaf_448_scalar_t decaf_448_scalar_zero API_VIS; | |||||
| /** The identity point on the curve. */ | /** The identity point on the curve. */ | ||||
| const decaf_448_point_t decaf_448_point_identity API_VIS; | |||||
| extern const decaf_448_point_t decaf_448_point_identity API_VIS; | |||||
| /** | /** | ||||
| * An arbitrarily chosen base point on the curve. | * An arbitrarily chosen base point on the curve. | ||||
| * Equal to Ed448-Goldilocks base point defined by DJB, except of course that | * 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? | * it's on the twist in this case. TODO: choose a base point with nice encoding? | ||||
| */ | */ | ||||
| const decaf_448_point_t decaf_448_point_base API_VIS; | |||||
| extern const struct decaf_448_point_s *decaf_448_point_base API_VIS; | |||||
| /** Precomputed table for the base point on the curve. */ | |||||
| extern const decaf_448_precomputed_t decaf_448_precomputed_base API_VIS; | |||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| extern "C" { | extern "C" { | ||||
| @@ -300,6 +308,37 @@ void decaf_448_point_scalarmul ( | |||||
| const decaf_448_scalar_t scalar | const decaf_448_scalar_t scalar | ||||
| ) API_VIS NONNULL3; | ) API_VIS NONNULL3; | ||||
| /** | |||||
| * @brief Precompute a table for fast scalar multiplication. | |||||
| * Some implementations do not include precomputed points; for | |||||
| * those implementations, this implementation simply copies the | |||||
| * point. | |||||
| * | |||||
| * @param [out] a A precomputed table of multiples of the point. | |||||
| * @param [in] b Any point. | |||||
| */ | |||||
| void decaf_448_precompute ( | |||||
| decaf_448_precomputed_t a, | |||||
| const decaf_448_point_t b | |||||
| ) API_VIS NONNULL2; | |||||
| /** | |||||
| * @brief Multiply a precomputed base point by a scalar: | |||||
| * scaled = scalar*base. | |||||
| * Some implementations do not include precomputed points; for | |||||
| * those implementations, this function is the same as | |||||
| * decaf_448_point_scalarmul | |||||
| * | |||||
| * @param [out] scaled The scaled point base*scalar | |||||
| * @param [in] base The point to be scaled. | |||||
| * @param [in] scalar The scalar to multiply by. | |||||
| */ | |||||
| void decaf_448_precomputed_scalarmul ( | |||||
| decaf_448_point_t scaled, | |||||
| const decaf_448_precomputed_t base, | |||||
| const decaf_448_scalar_t scalar | |||||
| ) API_VIS NONNULL3; | |||||
| /** | /** | ||||
| * @brief Multiply two base points by two scalars: | * @brief Multiply two base points by two scalars: | ||||
| * scaled = scalar1*base1 + scalar2*base2. | * scaled = scalar1*base1 + scalar2*base2. | ||||
| @@ -66,7 +66,8 @@ static const decaf_448_scalar_t decaf_448_scalar_r2 = {{{ | |||||
| static const decaf_word_t DECAF_MONTGOMERY_FACTOR = (decaf_word_t)(0x3bd440fae918bc5ull); | static const decaf_word_t DECAF_MONTGOMERY_FACTOR = (decaf_word_t)(0x3bd440fae918bc5ull); | ||||
| /** base = twist of Goldilocks base point (~,19). */ | /** base = twist of Goldilocks base point (~,19). */ | ||||
| const decaf_448_point_t decaf_448_point_base = {{ | |||||
| const decaf_448_precomputed_t decaf_448_precomputed_base = {{{{{ | |||||
| { LIMB(0xb39a2d57e08c7b),LIMB(0xb38639c75ff281), | { LIMB(0xb39a2d57e08c7b),LIMB(0xb38639c75ff281), | ||||
| LIMB(0x2ec981082b3288),LIMB(0x99fe8607e5237c), | LIMB(0x2ec981082b3288),LIMB(0x99fe8607e5237c), | ||||
| LIMB(0x0e33fbb1fadd1f),LIMB(0xe714f67055eb4a), | LIMB(0x0e33fbb1fadd1f),LIMB(0xe714f67055eb4a), | ||||
| @@ -80,7 +81,9 @@ const decaf_448_point_t decaf_448_point_base = {{ | |||||
| LIMB(0x0d79c0a7729a69),LIMB(0xc18d3f24aebc1c), | LIMB(0x0d79c0a7729a69),LIMB(0xc18d3f24aebc1c), | ||||
| LIMB(0x1fbb5389b3fda5),LIMB(0xbb24f674635948), | LIMB(0x1fbb5389b3fda5),LIMB(0xbb24f674635948), | ||||
| LIMB(0x723a55709a3983),LIMB(0xe1c0107a823dd4) } | LIMB(0x723a55709a3983),LIMB(0xe1c0107a823dd4) } | ||||
| }}; | |||||
| }}}}}; | |||||
| const struct decaf_448_point_s *decaf_448_point_base = decaf_448_precomputed_base->p[0]; | |||||
| #if (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)) || defined(DECAF_FORCE_UNROLL) | #if (defined(__OPTIMIZE__) && !defined(__OPTIMIZE_SIZE__)) || defined(DECAF_FORCE_UNROLL) | ||||
| #if DECAF_448_LIMBS==8 | #if DECAF_448_LIMBS==8 | ||||
| @@ -698,3 +701,18 @@ decaf_bool_t decaf_448_point_valid ( | |||||
| out &= ~gf_eq(p->z,ZERO); | out &= ~gf_eq(p->z,ZERO); | ||||
| return out; | return out; | ||||
| } | } | ||||
| void decaf_448_precompute ( | |||||
| decaf_448_precomputed_t a, | |||||
| const decaf_448_point_t b | |||||
| ) { | |||||
| decaf_448_point_copy(a->p[0],b); | |||||
| } | |||||
| void decaf_448_precomputed_scalarmul ( | |||||
| decaf_448_point_t a, | |||||
| const decaf_448_precomputed_t b, | |||||
| const decaf_448_scalar_t scalar | |||||
| ) { | |||||
| decaf_448_point_scalarmul(a,b->p[0],scalar); | |||||
| } | |||||
| @@ -111,10 +111,22 @@ single_scalarmul_compatibility_test ( | |||||
| scalarmul_vt(&work, scalar, nbits); | scalarmul_vt(&work, scalar, nbits); | ||||
| untwist_and_double_and_serialize(vt, &work); | untwist_and_double_and_serialize(vt, &work); | ||||
| decaf_448_point_t ed2; | |||||
| decaf_448_point_t ed2, ed3; | |||||
| decaf_448_precomputed_t dpre; | |||||
| tw_extended_a_t ed; | tw_extended_a_t ed; | ||||
| convert_tw_extensible_to_tw_extended(ed, &text); | convert_tw_extensible_to_tw_extended(ed, &text); | ||||
| decaf_448_point_scalarmul(ed2, (struct decaf_448_point_s *)ed, (struct decaf_448_scalar_s *)scalar); | |||||
| decaf_448_point_scalarmul( | |||||
| ed2, | |||||
| (struct decaf_448_point_s *)ed, | |||||
| (struct decaf_448_scalar_s *)scalar | |||||
| ); | |||||
| decaf_448_precompute(dpre, (struct decaf_448_point_s *)ed); | |||||
| decaf_448_precomputed_scalarmul( | |||||
| ed3, | |||||
| dpre, | |||||
| (struct decaf_448_scalar_s *)scalar | |||||
| ); | |||||
| scalarmul_ed(ed, scalar); | scalarmul_ed(ed, scalar); | ||||
| field_copy(work.x, ed->x); | field_copy(work.x, ed->x); | ||||
| @@ -124,9 +136,11 @@ single_scalarmul_compatibility_test ( | |||||
| field_set_ui(work.u, 1); | field_set_ui(work.u, 1); | ||||
| untwist_and_double_and_serialize(sced, &work); | untwist_and_double_and_serialize(sced, &work); | ||||
| uint8_t ser1[(FIELD_BITS+6)/8], ser2[(FIELD_BITS+6)/8]; | |||||
| uint8_t ser1[DECAF_448_SER_BYTES], ser2[DECAF_448_SER_BYTES], | |||||
| ser3[DECAF_448_SER_BYTES]; | |||||
| decaf_448_point_encode(ser1, (struct decaf_448_point_s *)ed); | decaf_448_point_encode(ser1, (struct decaf_448_point_s *)ed); | ||||
| decaf_448_point_encode(ser2, ed2); | decaf_448_point_encode(ser2, ed2); | ||||
| decaf_448_point_encode(ser3, ed3); | |||||
| /* check consistency mont vs window */ | /* check consistency mont vs window */ | ||||
| consistent &= field_eq(mont, ct); | consistent &= field_eq(mont, ct); | ||||
| @@ -134,6 +148,7 @@ single_scalarmul_compatibility_test ( | |||||
| consistent &= field_eq(mont, vt); | consistent &= field_eq(mont, vt); | ||||
| consistent &= field_eq(mont, sced); | consistent &= field_eq(mont, sced); | ||||
| consistent &= memcmp(ser1,ser2,sizeof(ser1)) ? 0 : -1; | consistent &= memcmp(ser1,ser2,sizeof(ser1)) ? 0 : -1; | ||||
| consistent &= memcmp(ser1,ser3,sizeof(ser1)) ? 0 : -1; | |||||
| } | } | ||||
| /* check consistency mont vs combs */ | /* check consistency mont vs combs */ | ||||