diff --git a/src/lib/math/pcurves/pcurves_secp521r1/pcurves_secp521r1.cpp b/src/lib/math/pcurves/pcurves_secp521r1/pcurves_secp521r1.cpp index 1dc94043df3..126cdb143f9 100644 --- a/src/lib/math/pcurves/pcurves_secp521r1/pcurves_secp521r1.cpp +++ b/src/lib/math/pcurves/pcurves_secp521r1/pcurves_secp521r1.cpp @@ -26,22 +26,34 @@ class P521Rep final { constexpr static std::array redc(const std::array& z) { constexpr W TOP_MASK = static_cast(0x1FF); - std::array hi = {}; - copy_mem(hi, std::span{z}.template subspan()); - shift_right<9>(hi); + /* + * Extract the high part of z (z >> 521) + */ + std::array t; - std::array lo = {}; - copy_mem(lo, std::span{z}.template first()); - lo[N - 1] &= TOP_MASK; + for(size_t i = 0; i != N; ++i) { + t[i] = z[(N - 1) + i] >> 9; + } - // s = hi + lo - std::array s = {}; - // Will never carry out - W carry = bigint_add(s, lo, hi); + for(size_t i = 0; i != N - 1; ++i) { + t[i] |= z[(N - 1) + i + 1] << (WordInfo::bits - 9); + } + + // Now t += z & (2**521-1) + W carry = word8_add2(t.data(), z.data(), static_cast(0)); + + if constexpr(WordInfo::bits == 32) { + constexpr size_t HN = N / 2; + carry = word8_add2(t.data() + HN, z.data() + HN, carry); + } + + // Now add the (partial) top words; this can't carry out + // since both inputs are at most 2**9-1 + t[N - 1] += (z[N - 1] & TOP_MASK) + carry; // But might be greater than modulus: - std::array r = {}; - bigint_monty_maybe_sub(r.data(), carry, s.data(), P.data()); + std::array r; + bigint_monty_maybe_sub(r.data(), static_cast(0), t.data(), P.data()); return r; }