diff --git a/include/decaf.h b/include/decaf.h index f9a62b2..2647aca 100644 --- a/include/decaf.h +++ b/include/decaf.h @@ -16,7 +16,8 @@ * decaf_448_decode can fail because not every sequence of bytes is a valid group * element. * - * The formulas contain no data-dependent branches, timing or memory accesses. + * The formulas contain no data-dependent branches, timing or memory accesses, + * except for decaf_448_base_double_scalarmul_non_secret. * * This library may support multiple curves eventually. The Ed448-Goldilocks * specific identifiers are prefixed with DECAF_448 or decaf_448. @@ -116,8 +117,6 @@ extern const struct decaf_448_precomputed_s *decaf_448_precomputed_base API_VIS; #ifdef __cplusplus extern "C" { #endif - -/* TODO: scalar invert? */ /** * @brief Read a scalar from wire format or from bytes. @@ -207,6 +206,17 @@ void decaf_448_scalar_mul ( const decaf_448_scalar_t b ) API_VIS NONNULL3 NOINLINE; +/** + * @brief Invert a scalar. When passed zero, return 0. The input and output may alias. + * @param [in] a A scalar. + * @param [out] out 1/a. + * @return DECAF_TRUE The input is nonzero. + */ +decaf_bool_t decaf_448_scalar_invert ( + decaf_448_scalar_t out, + const decaf_448_scalar_t a +) API_VIS NONNULL2 NOINLINE; + /** * @brief Copy a scalar. The scalars may use the same memory, in which * case this function does nothing. diff --git a/src/decaf.c b/src/decaf.c index 7de3f56..e586c48 100644 --- a/src/decaf.c +++ b/src/decaf.c @@ -11,6 +11,7 @@ #define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ #include "decaf.h" #include +#include #define WBITS DECAF_WORD_BITS @@ -363,6 +364,33 @@ void decaf_448_scalar_mul ( decaf_448_montmul(out,out,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); } +decaf_bool_t decaf_448_scalar_invert ( + decaf_448_scalar_t out, + const decaf_448_scalar_t a +) { + decaf_448_scalar_t b, ma; + int i; + decaf_448_montmul(b,decaf_448_scalar_one,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + decaf_448_montmul(ma,a,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + for (i=DECAF_448_SCALAR_BITS-1; i>=0; i--) { + decaf_448_montmul(b,b,b,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + + decaf_word_t w = decaf_448_scalar_p->limb[i/WBITS]; + if (i= 2); + w-=2; + } + if (1 & w>>(i%WBITS)) { + decaf_448_montmul(b,b,ma,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + } + } + + decaf_448_montmul(out,b,decaf_448_scalar_one,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + decaf_448_scalar_destroy(b); + decaf_448_scalar_destroy(ma); + return ~decaf_448_scalar_eq(out,decaf_448_scalar_zero); +} + void decaf_448_scalar_sub ( decaf_448_scalar_t out, const decaf_448_scalar_t a, diff --git a/src/decaf_fast.c b/src/decaf_fast.c index 00fa6de..62857b2 100644 --- a/src/decaf_fast.c +++ b/src/decaf_fast.c @@ -340,6 +340,66 @@ void decaf_448_scalar_mul ( decaf_448_montmul(out,out,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); } +/* PERF: could implement this */ +siv decaf_448_montsqr ( + decaf_448_scalar_t out, + const decaf_448_scalar_t a +) { + decaf_448_montmul(out,a,a,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); +} + +decaf_bool_t decaf_448_scalar_invert ( + decaf_448_scalar_t out, + const decaf_448_scalar_t a +) { + decaf_448_scalar_t chain[7], tmp; + decaf_448_montmul(chain[0],a,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); + + unsigned int i,j; + /* Addition chain generated by a not-too-clever SAGE script. First part: compute a^(2^222-1) */ + struct { uint8_t widx, sidx, sct, midx; } muls [] = { + {2,0,1,0}, {3,2,1,0}, {4,3,1,0}, {5,4,1,0}, /* 0x3,7,f,1f */ + {1,5,1,0}, {1,1,3,3}, {6,1,9,1}, {1,6,1,0}, {6,1,18,6}, /* a^(2^37-1) */ + {1,6,37,6}, {1,1,37,6}, {1,1,111,1} /* a^(2^222-1) */ + }; + /* Second part: sliding window */ + struct { uint8_t sct, midx; } muls1 [] = { + {6, 5}, {4, 2}, {3, 0}, {2, 0}, {4, 0}, {8, 5}, + {2, 0}, {5, 3}, {4, 0}, {4, 0}, {5, 3}, {3, 2}, + {3, 2}, {3, 2}, {2, 0}, {3, 0}, {4, 2}, {2, 0}, + {4, 3}, {3, 2}, {2, 0}, {3, 2}, {5, 2}, {3, 2}, + {2, 0}, {3, 0}, {7, 0}, {5, 0}, {3, 2}, {3, 2}, + {4, 2}, {5, 0}, {5, 3}, {3, 0}, {2, 0}, {5, 2}, + {4, 3}, {4, 0}, {3, 2}, {7, 4}, {2, 0}, {2, 0}, + {2, 0}, {2, 0}, {3, 0}, {5, 2}, {5, 4}, {5, 2}, + {5, 0}, {2, 0}, {3, 0}, {3, 0}, {2, 0}, {2, 0}, + {2, 0}, {3, 2}, {2, 0}, {3, 2}, {5, 0}, {4, 0}, + {6, 4}, {4, 0} + }; + + for (i=0; i