diff --git a/src/decaf_fast.c b/src/decaf_fast.c index f0d4e22..1254752 100644 --- a/src/decaf_fast.c +++ b/src/decaf_fast.c @@ -64,10 +64,10 @@ const precomputed_s *API_NS(precomputed_base) = const size_t API_NS2(sizeof,precomputed_s) = sizeof(precomputed_s); const size_t API_NS2(alignof,precomputed_s) = 32; -/* FIXME PERF: Vectorize vs unroll */ +/* TODO PERF: Vectorize vs unroll */ #ifdef __clang__ #if 100*__clang_major__ + __clang_minor__ > 305 -#define UNROLL _Pragma("clang loop unroll(full)") // PERF FIXME: vectorize? +#define UNROLL _Pragma("clang loop unroll(full)") // PERF TODO: vectorize? #endif #endif @@ -1464,6 +1464,26 @@ void API_NS(precomputed_scalarmul) ( decaf_bzero(scalar1x,sizeof(scalar1x)); } +void API_NS(point_cond_sel) ( + point_t out, + const point_t a, + const point_t b, + decaf_bool_t pick_b +) { + pick_b = ~(((decaf_dword_t)pick_b - 1) >> WBITS); + constant_time_select(out,b,a,sizeof(point_t),pick_b); +} + +void API_NS(scalar_cond_sel) ( + scalar_t out, + const scalar_t a, + const scalar_t b, + decaf_bool_t pick_b +) { + pick_b = ~(((decaf_dword_t)pick_b - 1) >> WBITS); + constant_time_select(out,b,a,sizeof(scalar_t),pick_b); +} + /* TODO: restore Curve25519 Montgomery ladder? */ decaf_bool_t API_NS(direct_scalarmul) ( uint8_t scaled[SER_BYTES], @@ -1472,10 +1492,10 @@ decaf_bool_t API_NS(direct_scalarmul) ( decaf_bool_t allow_identity, decaf_bool_t short_circuit ) { - /* FIXME: this can cause assertions if !short_circuit and the input is garbage.*/ point_t basep; decaf_bool_t succ = API_NS(point_decode)(basep, base, allow_identity); if (short_circuit & ~succ) return succ; + API_NS(point_cond_sel)(basep, API_NS(point_base), basep, succ); API_NS(point_scalarmul)(basep, basep, scalar); API_NS(point_encode)(scaled, basep); API_NS(point_destroy)(basep); diff --git a/src/public_include/decaf/decaf_255.h b/src/public_include/decaf/decaf_255.h index 1054b09..1bbddb6 100644 --- a/src/public_include/decaf/decaf_255.h +++ b/src/public_include/decaf/decaf_255.h @@ -416,6 +416,38 @@ void decaf_255_base_double_scalarmul_non_secret ( const decaf_255_scalar_t scalar2 ) API_VIS NONNULL4 NOINLINE; +/** + * @brief Constant-time decision between two points. If pick_b + * is zero, out = a; else out = b. + * + * @param [out] q The output. It may be the same as either input. + * @param [in] a Any point. + * @param [in] b Any point. + * @param [in] pick_b If nonzero, choose point b. + */ +void decaf_255_point_cond_sel ( + decaf_255_point_t out, + const decaf_255_point_t a, + const decaf_255_point_t b, + decaf_word_t pick_b +) API_VIS NONNULL3 NOINLINE; + +/** + * @brief Constant-time decision between two scalars. If pick_b + * is zero, out = a; else out = b. + * + * @param [out] q The output. It may be the same as either input. + * @param [in] a Any scalar. + * @param [in] b Any scalar. + * @param [in] pick_b If nonzero, choose scalar b. + */ +void decaf_255_scalar_cond_sel ( + decaf_255_scalar_t out, + const decaf_255_scalar_t a, + const decaf_255_scalar_t b, + decaf_word_t pick_b +) API_VIS NONNULL3 NOINLINE; + /** * @brief Test that a point is valid, for debugging purposes. * diff --git a/src/public_include/decaf/decaf_448.h b/src/public_include/decaf/decaf_448.h index 001aaed..83d173a 100644 --- a/src/public_include/decaf/decaf_448.h +++ b/src/public_include/decaf/decaf_448.h @@ -413,6 +413,39 @@ void decaf_448_base_double_scalarmul_non_secret ( const decaf_448_point_t base2, const decaf_448_scalar_t scalar2 ) API_VIS NONNULL4 NOINLINE; + + +/** +* @brief Constant-time decision between two points. If pick_b +* is zero, out = a; else out = b. +* +* @param [out] q The output. It may be the same as either input. +* @param [in] a Any point. +* @param [in] b Any point. +* @param [in] pick_b If nonzero, choose point b. +*/ +void decaf_448_point_cond_sel ( + decaf_448_point_t out, + const decaf_448_point_t a, + const decaf_448_point_t b, + decaf_word_t pick_b +) API_VIS NONNULL3 NOINLINE; + +/** +* @brief Constant-time decision between two scalars. If pick_b +* is zero, out = a; else out = b. +* +* @param [out] q The output. It may be the same as either input. +* @param [in] a Any scalar. +* @param [in] b Any scalar. +* @param [in] pick_b If nonzero, choose scalar b. +*/ +void decaf_448_scalar_cond_sel ( + decaf_448_scalar_t out, + const decaf_448_scalar_t a, + const decaf_448_scalar_t b, + decaf_word_t pick_b +) API_VIS NONNULL3 NOINLINE; /** * @brief Test that a point is valid, for debugging purposes.