#else
#define WNAF_BITS 256
#endif
-#define WNAF_SIZE(w) ((WNAF_BITS + (w) - 1) / (w))
+#define WNAF_SIZE_BITS(bits, w) (((bits) + (w) - 1) / (w))
+#define WNAF_SIZE(w) WNAF_SIZE_BITS(WNAF_BITS, w)
/** The number of entries a table with precomputed multiples needs to have. */
#define ECMULT_TABLE_SIZE(w) (1 << ((w)-2))
* It has the following guarantees:
* - each wnaf[i] is either 0 or an odd integer between -(1 << w) and (1 << w)
* - the number of words set is always WNAF_SIZE(w)
- * - the returned skew is 0 without endomorphism, or 0 or 1 with endomorphism
+ * - the returned skew is 0 or 1
*/
static int secp256k1_wnaf_fixed(int *wnaf, const secp256k1_scalar *s, int w) {
- int sign = 0;
int skew = 0;
- int pos = 1;
-#ifndef USE_ENDOMORPHISM
- secp256k1_scalar neg_s;
-#endif
+ int pos;
+ int max_pos;
+ int last_w;
const secp256k1_scalar *work = s;
if (secp256k1_scalar_is_zero(s)) {
- while (pos * w < WNAF_BITS) {
+ for (pos = 0; pos < WNAF_SIZE(w); pos++) {
wnaf[pos] = 0;
- ++pos;
}
return 0;
}
if (secp256k1_scalar_is_even(s)) {
-#ifdef USE_ENDOMORPHISM
skew = 1;
-#else
- secp256k1_scalar_negate(&neg_s, s);
- work = &neg_s;
- sign = -1;
-#endif
}
- wnaf[0] = (secp256k1_scalar_get_bits_var(work, 0, w) + skew + sign) ^ sign;
+ wnaf[0] = secp256k1_scalar_get_bits_var(work, 0, w) + skew;
+ /* Compute last window size. Relevant when window size doesn't divide the
+ * number of bits in the scalar */
+ last_w = WNAF_BITS - (WNAF_SIZE(w) - 1) * w;
- while (pos * w < WNAF_BITS) {
- int now = w;
- int val;
- if (now + pos * w > WNAF_BITS) {
- now = WNAF_BITS - pos * w;
+ /* Store the position of the first nonzero word in max_pos to allow
+ * skipping leading zeros when calculating the wnaf. */
+ for (pos = WNAF_SIZE(w) - 1; pos > 0; pos--) {
+ int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w);
+ if(val != 0) {
+ break;
}
- val = secp256k1_scalar_get_bits_var(work, pos * w, now);
+ wnaf[pos] = 0;
+ }
+ max_pos = pos;
+ pos = 1;
+
+ while (pos <= max_pos) {
+ int val = secp256k1_scalar_get_bits_var(work, pos * w, pos == WNAF_SIZE(w)-1 ? last_w : w);
if ((val & 1) == 0) {
- wnaf[pos - 1] -= ((1 << w) + sign) ^ sign;
- wnaf[pos] = (val + 1 + sign) ^ sign;
+ wnaf[pos - 1] -= (1 << w);
+ wnaf[pos] = (val + 1);
} else {
- wnaf[pos] = (val + sign) ^ sign;
+ wnaf[pos] = val;
+ }
+ /* Set a coefficient to zero if it is 1 or -1 and the proceeding digit
+ * is strictly negative or strictly positive respectively. Only change
+ * coefficients at previous positions because above code assumes that
+ * wnaf[pos - 1] is odd.
+ */
+ if (pos >= 2 && ((wnaf[pos - 1] == 1 && wnaf[pos - 2] < 0) || (wnaf[pos - 1] == -1 && wnaf[pos - 2] > 0))) {
+ if (wnaf[pos - 1] == 1) {
+ wnaf[pos - 2] += 1 << w;
+ } else {
+ wnaf[pos - 2] -= 1 << w;
+ }
+ wnaf[pos - 1] = 0;
}
++pos;
}
- VERIFY_CHECK(pos == WNAF_SIZE(w));
return skew;
}
* to the point's wnaf[i]. Second, the buckets are added together such that
* r += 1*bucket[0] + 3*bucket[1] + 5*bucket[2] + ...
*/
-static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, secp256k1_scalar *sc, secp256k1_ge *pt, size_t num) {
+static int secp256k1_ecmult_pippenger_wnaf(secp256k1_gej *buckets, int bucket_window, struct secp256k1_pippenger_state *state, secp256k1_gej *r, const secp256k1_scalar *sc, const secp256k1_ge *pt, size_t num) {
size_t n_wnaf = WNAF_SIZE(bucket_window+1);
size_t np;
size_t no = 0;
secp256k1_ge tmp;
int idx;
-#ifdef USE_ENDOMORPHISM
if (i == 0) {
/* correct for wnaf skew */
int skew = point_state.skew_na;
secp256k1_gej_add_ge_var(&buckets[0], &buckets[0], &tmp, NULL);
}
}
-#endif
if (n > 0) {
idx = (n - 1)/2;
secp256k1_gej_add_ge_var(&buckets[idx], &buckets[idx], &pt[point_state.input_pos], NULL);