@@ -324,6 +324,31 @@ void decaf_448_point_scalarmul ( | |||||
const decaf_448_scalar_t scalar | const decaf_448_scalar_t scalar | ||||
) API_VIS NONNULL3; | ) API_VIS NONNULL3; | ||||
/** | |||||
* @brief Multiply a base point by a scalar: scaled = scalar*base. | |||||
* This function operates directly on serialized forms. | |||||
* | |||||
* @warning This function is experimental. It may not be supported | |||||
* long-term. | |||||
* | |||||
* @param [out] scaled The scaled point base*scalar | |||||
* @param [in] base The point to be scaled. | |||||
* @param [in] scalar The scalar to multiply by. | |||||
* @param [in] allow_identity Allow the input to be the identity. | |||||
* @param [in] short_circuit Allow a fast return if the input is illegal. | |||||
* | |||||
* @retval DECAF_SUCCESS The scalarmul succeeded. | |||||
* @retval DECAF_FAILURE The scalarmul didn't succeed, because | |||||
* base does not represent a point. | |||||
*/ | |||||
decaf_bool_t decaf_448_direct_scalarmul ( | |||||
uint8_t scaled[DECAF_448_SER_BYTES], | |||||
const uint8_t base[DECAF_448_SER_BYTES], | |||||
const decaf_448_scalar_t scalar, | |||||
decaf_bool_t allow_identity, | |||||
decaf_bool_t short_circuit | |||||
) API_VIS NONNULL3 WARN_UNUSED; | |||||
/** | /** | ||||
* @brief Precompute a table for fast scalar multiplication. | * @brief Precompute a table for fast scalar multiplication. | ||||
* Some implementations do not include precomputed points; for | * Some implementations do not include precomputed points; for | ||||
@@ -367,7 +392,9 @@ void decaf_448_precomputed_scalarmul ( | |||||
* @param [in] scalar1 A first scalar to multiply by. | * @param [in] scalar1 A first scalar to multiply by. | ||||
* @param [in] base2 A second point to be scaled. | * @param [in] base2 A second point to be scaled. | ||||
* @param [in] scalar2 A second scalar to multiply by. | * @param [in] scalar2 A second scalar to multiply by. | ||||
* | |||||
* @TODO: test | * @TODO: test | ||||
* @TODO: define vartime/precomp version of this for performance?? | |||||
*/ | */ | ||||
void decaf_448_point_double_scalarmul ( | void decaf_448_point_double_scalarmul ( | ||||
decaf_448_point_t combo, | decaf_448_point_t combo, | ||||
@@ -778,6 +778,24 @@ void decaf_448_precompute ( | |||||
decaf_448_point_copy(a->p[0],b); | decaf_448_point_copy(a->p[0],b); | ||||
} | } | ||||
decaf_bool_t decaf_448_direct_scalarmul ( | |||||
uint8_t scaled[DECAF_448_SER_BYTES], | |||||
const uint8_t base[DECAF_448_SER_BYTES], | |||||
const decaf_448_scalar_t scalar, | |||||
decaf_bool_t allow_identity, | |||||
decaf_bool_t short_circuit | |||||
) { | |||||
decaf_448_point_t basep; | |||||
decaf_bool_t succ = decaf_448_point_decode(basep, base, allow_identity); | |||||
/* FIXME: compiler can probably reorder this to something non-consttime even if | |||||
* !short_circuit. | |||||
*/ | |||||
if (short_circuit && ~succ) return succ; | |||||
decaf_448_point_scalarmul(basep, basep, scalar); | |||||
decaf_448_point_encode(scaled, basep); | |||||
return succ; | |||||
} | |||||
void decaf_448_precomputed_scalarmul ( | void decaf_448_precomputed_scalarmul ( | ||||
decaf_448_point_t a, | decaf_448_point_t a, | ||||
const decaf_448_precomputed_s *b, | const decaf_448_precomputed_s *b, | ||||
@@ -809,3 +809,22 @@ void decaf_448_precomputed_scalarmul ( | |||||
) { | ) { | ||||
decaf_448_point_scalarmul(a,b->p[0],scalar); | decaf_448_point_scalarmul(a,b->p[0],scalar); | ||||
} | } | ||||
decaf_bool_t decaf_448_direct_scalarmul ( | |||||
uint8_t scaled[DECAF_448_SER_BYTES], | |||||
const uint8_t base[DECAF_448_SER_BYTES], | |||||
const decaf_448_scalar_t scalar, | |||||
decaf_bool_t allow_identity, | |||||
decaf_bool_t short_circuit | |||||
) { | |||||
decaf_448_point_t basep; | |||||
decaf_bool_t succ = decaf_448_point_decode(basep, base, allow_identity); | |||||
/* FIXME: compiler can probably reorder this to something non-consttime even if | |||||
* !short_circuit. | |||||
*/ | |||||
if (short_circuit && ~succ) return succ; | |||||
decaf_448_point_scalarmul(basep, basep, scalar); | |||||
decaf_448_point_encode(scaled, basep); | |||||
return succ; | |||||
} | |||||
@@ -116,6 +116,8 @@ single_scalarmul_compatibility_test ( | |||||
posix_memalign((void**)&dpre, alignof_decaf_448_precomputed_s, sizeof_decaf_448_precomputed_s); | posix_memalign((void**)&dpre, alignof_decaf_448_precomputed_s, sizeof_decaf_448_precomputed_s); | ||||
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); | ||||
uint8_t ser4[DECAF_448_SER_BYTES]; | |||||
decaf_448_point_encode(ser4, (struct decaf_448_point_s *)ed); | |||||
decaf_448_point_scalarmul( | decaf_448_point_scalarmul( | ||||
ed2, | ed2, | ||||
(struct decaf_448_point_s *)ed, | (struct decaf_448_point_s *)ed, | ||||
@@ -142,6 +144,7 @@ single_scalarmul_compatibility_test ( | |||||
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); | decaf_448_point_encode(ser3, ed3); | ||||
(void)decaf_448_direct_scalarmul(ser4, ser4, (struct decaf_448_scalar_s *)scalar, -1, -1); | |||||
/* check consistency mont vs window */ | /* check consistency mont vs window */ | ||||
consistent &= field_eq(mont, ct); | consistent &= field_eq(mont, ct); | ||||
@@ -150,6 +153,7 @@ single_scalarmul_compatibility_test ( | |||||
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; | consistent &= memcmp(ser1,ser3,sizeof(ser1)) ? 0 : -1; | ||||
consistent &= memcmp(ser1,ser4,sizeof(ser1)) ? 0 : -1; | |||||
} | } | ||||
/* check consistency mont vs combs */ | /* check consistency mont vs combs */ | ||||