7#ifndef BOTAN_PCURVES_IMPL_H_
8#define BOTAN_PCURVES_IMPL_H_
11#include <botan/internal/ct_utils.h>
12#include <botan/internal/loadstor.h>
13#include <botan/internal/pcurves_algos.h>
14#include <botan/internal/pcurves_mul.h>
15#include <botan/internal/pcurves_util.h>
16#include <botan/internal/stl_util.h>
58template <
typename Params>
63 static constexpr auto P = Params::P;
64 static constexpr size_t N = Params::N;
65 typedef typename Params::W
W;
67 static_assert(
N > 0 && (Params::P[0] & 1) == 1,
"Invalid Montgomery modulus");
78 constexpr static std::array<W, N>
one() {
return R1; }
83 constexpr static std::array<W, N>
redc(
const std::array<W, 2 * N>& z) {
84 if constexpr(
P_dash == 1) {
94 constexpr static std::array<W, N>
to_rep(
const std::array<W, N>& x) {
95 std::array<W, 2 * N> z;
106 constexpr static std::array<W, N>
wide_to_rep(
const std::array<W, 2 * N>& x) {
108 std::array<W, 2 * N> z;
116 constexpr static std::array<W, N>
from_rep(
const std::array<W, N>& z) {
117 std::array<W, 2 * N> ze = {};
118 copy_mem(std::span{ze}.template first<N>(), z);
141template <
typename Rep>
144 static constexpr auto P = Rep::P;
145 static constexpr size_t N = Rep::N;
146 typedef typename Rep::W W;
148 static constexpr auto P_MINUS_2 =
p_minus<2>(P);
191 if constexpr(L == N) {
192 return Self(Rep::to_rep(w));
194 static_assert(L < N);
195 std::array<W, N> ew = {};
196 copy_mem(std::span{ew}.template first<L>(), w);
197 return Self(Rep::to_rep(ew));
220 auto v = Rep::from_rep(m_val);
228 const auto flip = (even != this->
is_even());
248 for(
size_t i = 0; i != N; ++i) {
263 for(
size_t i = 0; i != N; ++i) {
281 std::array<W, N> t = value();
292 std::array<W, N> t = value();
313 std::array<W, 2 * N> z;
315 return Self(Rep::redc(z));
322 std::array<W, 2 * N> z;
324 m_val = Rep::redc(z);
336 for(
size_t i = 0; i != N; ++i) {
349 for(
size_t i = 0; i != N; ++i) {
364 for(
size_t i = 0; i != N; ++i) {
379 for(
size_t i = 0; i != N; ++i) {
393 std::array<W, 2 * N> z;
395 return Self(Rep::redc(z));
406 std::array<W, 2 * N> z;
407 for(
size_t i = 0; i != n; ++i) {
409 m_val = Rep::redc(z);
419 const W x_is_zero =
~CT::all_zeros(this->data(), N).value();
423 for(
size_t i = 0; i != N; ++i) {
444 constexpr size_t WindowBits = (
Self::BITS <= 256) ? 4 : 5;
445 constexpr size_t WindowElements = (1 << WindowBits) - 1;
447 constexpr size_t Windows = (
Self::BITS + WindowBits - 1) / WindowBits;
455 std::array<Self, WindowElements> tbl;
459 for(
size_t i = 1; i != WindowElements; ++i) {
462 tbl[i] = tbl[i / 2].square();
464 tbl[i] = tbl[i - 1] * tbl[0];
477 for(
size_t i = 1; i != Windows; ++i) {
478 r.square_n(WindowBits);
517 while((a.m_val[0] & 1) != 1) {
566 if(this->
is_zero().as_bool()) {
570 auto x =
Self(std::array<W, N>{1});
585 if(a.m_val == b.m_val) {
590 r.m_val = Rep::to_rep(r.m_val);
637 const CT::Choice correct = (z.square() == *
this);
657 const Self& x = (*this);
666 for(
size_t i = C1_C2.first; i >= 2; i--) {
669 z.conditional_assign(!e, z * c);
671 t.conditional_assign(!e, t * c);
676 const CT::Choice correct = (z.square() == *
this);
689 return CT::is_equal(this->data(), other.data(), N).as_choice();
700 constexpr std::array<W, Self::N>
to_words()
const {
return Rep::from_rep(m_val); }
705 constexpr void serialize_to(std::span<uint8_t, Self::BYTES> bytes)
const {
706 auto v = Rep::from_rep(m_val);
707 std::reverse(v.begin(), v.end());
713 const auto padded_bytes =
store_be(v);
715 copy_mem(bytes, std::span{padded_bytes}.template subspan<extra, Self::BYTES>());
726 static_assert(L >= N);
727 std::array<W, L> stash = {};
728 for(
size_t i = 0; i != N; ++i) {
741 static_assert(L >= N);
742 std::array<W, N> val = {};
743 for(
size_t i = 0; i != N; ++i) {
758 static std::optional<Self>
deserialize(std::span<const uint8_t> bytes) {
784 std::array<uint8_t, 2 * BYTES> padded_bytes = {};
785 copy_mem(std::span{padded_bytes}.template last<L>(), bytes);
801 std::array<uint8_t, 2 * Self::BYTES> padded_bytes = {};
802 copy_mem(std::span{padded_bytes}.last(bytes.size()), bytes);
818 constexpr size_t MAX_ATTEMPTS = 1000;
820 std::array<uint8_t, Self::BYTES> buf{};
822 for(
size_t i = 0; i != MAX_ATTEMPTS; ++i) {
828 constexpr uint8_t mask = 0xFF >> (8 - (
Self::BITS % 8));
834 if(s.value().is_nonzero().as_bool()) {
840 throw Internal_Error(
"Failed to generate random Scalar within bounded number of attempts");
849 std::array<W, 1> v{};
850 v[0] = (x >= 0) ? x : -x;
852 return (x >= 0) ? s : s.negate();
860 constexpr const std::array<W, N>& value()
const {
return m_val; }
862 constexpr const W* data()
const {
return m_val.data(); }
864 explicit constexpr IntMod(std::array<W, N> v) : m_val(v) {}
866 std::array<W, N> m_val;
874template <
typename FieldElement,
typename Params>
877 static constexpr size_t BYTES = 1 + 2 * FieldElement::BYTES;
887 static constexpr Self identity() {
return Self(FieldElement::zero(), FieldElement::zero()); }
891 return Self(FieldElement::zero(), FieldElement::zero());
907 constexpr void serialize_to(std::span<uint8_t, Self::BYTES> bytes)
const {
911 x().serialize_to(pack.next<FieldElement::BYTES>());
912 y().serialize_to(pack.next<FieldElement::BYTES>());
921 static constexpr auto ct_select(std::span<const Self> pts,
size_t idx) {
925 const size_t idx1 =
static_cast<size_t>(idx - 1);
926 for(
size_t i = 0; i != pts.size(); ++i) {
928 result.conditional_assign(found, pts[i]);
937 constexpr const FieldElement&
x()
const {
return m_x; }
942 constexpr const FieldElement&
y()
const {
return m_y; }
948 FieldElement::conditional_assign(m_x, m_y, cond, pt.
x(), pt.
y());
965template <
typename FieldElement,
typename Params>
971 static constexpr FieldElement
A = FieldElement::from_words(Params::AW);
974 static constexpr bool A_is_minus_3 = (
A == FieldElement::constant(-3)).as_bool();
994 auto z = FieldElement::one();
1004 static constexpr Self identity() {
return Self(FieldElement::zero(), FieldElement::one(), FieldElement::zero()); }
1010 m_x(FieldElement::zero()), m_y(FieldElement::one()), m_z(FieldElement::zero()) {}
1016 m_x(
x), m_y(
y), m_z(FieldElement::one()) {}
1022 m_x(
x), m_y(
y), m_z(
z) {}
1037 (*this) = (*this) + other;
1042 (*this) = (*this) + other;
1051 FieldElement::conditional_assign(m_x, m_y, m_z, cond, pt.
x(), pt.
y(), pt.
z());
1114 auto r = FieldElement::random(rng);
1116 auto r2 = r.square();
1128 constexpr const FieldElement&
x()
const {
return m_x; }
1133 constexpr const FieldElement&
y()
const {
return m_y; }
1138 constexpr const FieldElement&
z()
const {
return m_z; }
1156template <StringLiteral PS,
1174 static constexpr int8_t
Z = ZI;
1180template <WordType WI,
size_t NI, std::array<WI, NI> PI>
1184 static constexpr size_t N = NI;
1185 static constexpr auto P = PI;
1193template <
typename Params,
template <
typename FieldParamsT>
typename FieldRep =
MontgomeryRep>
1196 typedef typename Params::W
W;
1200 static constexpr auto PW = Params::PW;
1201 static constexpr auto NW = Params::NW;
1202 static constexpr auto AW = Params::AW;
1205 static_assert(
PW.size() ==
NW.size());
1226 static_assert(
B.is_nonzero().as_bool(),
"B must be non-zero");
1258template <
typename C,
size_t WindowBits>
1261 typedef typename C::W W;
1263 static constexpr bool BlindingEnabled =
true;
1272 static constexpr size_t blinding_bits(
size_t sb) {
1275 static_assert(wb == 32 || wb == 64,
"Unexpected W size");
1283 return blinding_bits(512);
1286 return ((sb / 4 + wb - 1) / wb) * wb;
1290 static constexpr size_t BlindingBits = blinding_bits(C::OrderBits);
1293 static_assert(BlindingBits < C::Scalar::BITS);
1296 static constexpr size_t Bits = C::Scalar::BITS + (BlindingEnabled ? BlindingBits : 0);
1302 if constexpr(BlindingEnabled) {
1306 constexpr size_t n_words = C::Words;
1308 uint8_t maskb[mask_bytes] = {0};
1319 std::array<uint8_t, C::Scalar::BYTES> sbytes = {};
1320 scalar.serialize_to(sbytes);
1321 for(
size_t i = 0; i != sbytes.size(); ++i) {
1322 maskb[i % mask_bytes] ^= sbytes[i];
1326 W mask[n_words] = {0};
1327 load_le(mask, maskb, mask_words);
1331 W mask_n[2 * n_words] = {0};
1333 const auto sw = scalar.to_words();
1337 bigint_add2(mask_n, 2 * n_words, sw.data(), sw.size());
1339 std::reverse(mask_n, mask_n + 2 * n_words);
1342 static_assert(
Bytes == C::Scalar::BYTES);
1343 m_bytes.resize(
Bytes);
1344 scalar.serialize_to(std::span{m_bytes}.template first<Bytes>());
1367 std::vector<uint8_t> m_bytes;
1370template <
typename C,
size_t WindowBits>
1373 static constexpr size_t Bits = C::Scalar::BITS;
1383 std::array<uint8_t, C::Scalar::BYTES> m_bytes;
1386template <
typename C,
size_t W>
1409 std::vector<AffinePoint> m_table;
1417template <
typename C,
size_t W>
1444 std::vector<AffinePoint> m_table;
1450template <
typename C,
size_t W>
1466 return (sb - 1) / wb;
1478 return sb - (sb / wb) * wb;
1495 auto accum = ProjectivePoint::identity();
1502 const auto [tidx, tneg] = booth_recode<WindowBits>(w_i);
1506 accum = ProjectivePoint::from_affine(m_table.ct_select(tidx));
1507 accum.conditional_assign(tneg, accum.negate());
1509 accum = ProjectivePoint::add_or_sub(accum, m_table.ct_select(tidx), tneg);
1516 accum.randomize_rep(rng);
1522 const auto [tidx, tneg] = booth_recode<WindowBits>(w_l << 1);
1523 accum = ProjectivePoint::add_or_sub(accum, m_table.ct_select(tidx), tneg);
1530 template <
size_t B, std::
unsigned_
integral T>
1531 static constexpr std::pair<size_t, CT::Choice> booth_recode(T x) {
1532 static_assert(B <
sizeof(T) * 8 - 2,
"Invalid B");
1535 const T neg_x = (1 << (B + 1)) - x - 1;
1536 T d = s_mask.select(neg_x, x);
1537 d = (d >> 1) + (d & 1);
1539 return std::make_pair(
static_cast<size_t>(d), s_mask.as_choice());
1542 AffinePointTable<C> m_table;
1545template <
typename C,
size_t W>
1549 static_assert(W >= 1 && W <= 4);
1562 BlindedScalar bits1(s1, rng);
1563 BlindedScalar bits2(s2, rng);
1572template <
typename C,
size_t W>
1576 static_assert(W >= 1 && W <= 4);
1602 bool s1_is_zero = s1.is_zero().as_bool();
1603 bool s2_is_zero = s2.is_zero().as_bool();
1606 if(s1_is_zero && s2_is_zero) {
1607 return ProjectivePoint::identity();
1610 auto [w_0, first_nonempty_window] = [&]() {
1611 for(
size_t i = 0; i != Windows; ++i) {
1614 const size_t window = w_1 + (w_2 <<
WindowBits);
1617 return std::make_pair(window, i);
1625 auto accum = ProjectivePoint::from_affine(m_table[w_0 - 1]);
1627 for(
size_t i = first_nonempty_window + 1; i < Windows; ++i) {
1633 const size_t window = w_1 + (w_2 <<
WindowBits);
1637 accum += m_table[window - 1];
1645 std::vector<AffinePoint> m_table;
1653template <
typename C>
1655 requires C::ValidForSswuHash
1667template <
typename C>
1669 requires C::ValidForSswuHash
1673 static const typename C::FieldElement C1 = (
SSWU_C2<C>() * C::SSWU_Z).negate();
1682template <
typename C>
1685 const auto z_u2 = C::SSWU_Z * u.square();
1686 const auto z2_u4 = z_u2.square();
1688 auto x1 =
SSWU_C1<C>() * (C::FieldElement::one() + tv1);
1689 x1.conditional_assign(tv1.is_zero(),
SSWU_C2<C>());
1690 const auto x2 = z_u2 * x1;
1698 auto x = C::FieldElement::choose(use_y1, x1, x2);
1699 auto y = C::FieldElement::choose(use_y1, y1.
value_or(C::FieldElement::zero()), y2.
value_or(C::FieldElement::zero()));
1701 auto pt =
typename C::AffinePoint(x, y.correct_sign(u.is_even()));
1718template <
typename C,
bool RO, std::invocable<std::span<u
int8_t>> ExpandMsg>
1719 requires C::ValidForSswuHash
1721 -> std::conditional_t<RO, typename C::ProjectivePoint, typename C::AffinePoint> {
1722 constexpr size_t SecurityLevel = (C::OrderBits + 1) / 2;
1723 constexpr size_t L = (C::PrimeFieldBits + SecurityLevel + 7) / 8;
1724 constexpr size_t Cnt = RO ? 2 : 1;
1726 std::array<uint8_t, L * Cnt> uniform_bytes = {};
1727 expand_message(uniform_bytes);
1730 const auto u0 = C::FieldElement::from_wide_bytes(std::span<const uint8_t, L>(uniform_bytes.data(), L));
1731 const auto u1 = C::FieldElement::from_wide_bytes(std::span<const uint8_t, L>(uniform_bytes.data() + L, L));
1737 const auto u = C::FieldElement::from_wide_bytes(std::span<const uint8_t, L>(uniform_bytes.data(), L));
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_DEBUG_ASSERT(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ASSERT_UNREACHABLE()
constexpr const FieldElement & y() const
static constexpr size_t BYTES
AffineCurvePoint & operator=(const Self &other)=default
static constexpr Self identity(const Self &)
static constexpr Self identity()
constexpr const FieldElement & x() const
constexpr AffineCurvePoint(const FieldElement &x, const FieldElement &y)
static constexpr auto ct_select(std::span< const Self > pts, size_t idx)
AffineCurvePoint & operator=(Self &&other)=default
~AffineCurvePoint()=default
constexpr Self negate() const
constexpr CT::Choice is_identity() const
constexpr void conditional_assign(CT::Choice cond, const Self &pt)
constexpr void _const_time_unpoison() const
AffineCurvePoint(const Self &other)=default
AffineCurvePoint(Self &&other)=default
constexpr void serialize_to(std::span< uint8_t, Self::BYTES > bytes) const
constexpr void _const_time_poison() const
AffineCurvePoint< FieldElement, Params > Self
constexpr AffineCurvePoint()
BlindedScalarBits(const BlindedScalarBits &other)=delete
BlindedScalarBits & operator=(BlindedScalarBits &&other)=delete
size_t get_window(size_t offset) const
BlindedScalarBits(BlindedScalarBits &&other)=delete
static constexpr size_t Bytes
BlindedScalarBits(const typename C::Scalar &scalar, RandomNumberGenerator &rng)
constexpr size_t bits() const
static constexpr size_t Bits
BlindedScalarBits & operator=(const BlindedScalarBits &other)=delete
Helper class to ease in-place marshalling of concatenated fixed-length values.
static constexpr Choice from_int(T v)
static constexpr Mask< T > expand(T v)
static constexpr Mask< T > from_choice(Choice c)
static constexpr Mask< T > is_equal(T x, T y)
constexpr Choice has_value() const
Return true if this Option contains a value.
constexpr T value_or(T other) const
static constexpr int8_t Z
static constexpr auto GXW
static constexpr auto GYW
static constexpr size_t PrimeFieldBits
static constexpr FieldElement SSWU_Z
IntMod< MontgomeryRep< ScalarParams > > Scalar
static constexpr bool ValidForSswuHash
static constexpr FieldElement x3_ax_b(const FieldElement &x)
static constexpr FieldElement A
static constexpr bool OrderIsLessThanField
static constexpr size_t Words
AffineCurvePoint< FieldElement, Params > AffinePoint
ProjectiveCurvePoint< FieldElement, Params > ProjectivePoint
static constexpr size_t OrderBits
static constexpr AffinePoint G
IntMod< FieldRep< FieldParams > > FieldElement
static constexpr FieldElement B
constexpr Self & operator*=(const Self &other)
static constexpr auto P_MOD_4
static constexpr void conditional_assign(Self &x, Self &y, CT::Choice cond, const Self &nx, const Self &ny)
friend constexpr Self operator*(const Self &a, const Self &b)
static constexpr std::optional< Self > from_wide_bytes_varlen(std::span< const uint8_t > bytes)
constexpr void serialize_to(std::span< uint8_t, Self::BYTES > bytes) const
static constexpr size_t BITS
constexpr CT::Choice is_zero() const
static constexpr void _invert_vartime_div2_helper(Self &a, Self &x)
std::array< W, L > stash_value() const
constexpr CT::Choice is_nonzero() const
constexpr void _const_time_unpoison() const
friend constexpr Self operator-(const Self &a, const Self &b)
IntMod(const Self &other)=default
constexpr Self correct_sign(CT::Choice even) const
constexpr void conditional_assign(CT::Choice cond, const Self &nx)
constexpr Self negate() const
constexpr Self invert_vartime() const
static consteval Self constant(int8_t x)
constexpr std::array< W, Self::N > to_words() const
static constexpr Self zero()
static Self from_stash(const std::array< W, L > &stash)
IntMod(Self &&other)=default
static std::optional< Self > deserialize(std::span< const uint8_t > bytes)
constexpr Self mul8() const
Return (*this) multiplied by 8.
constexpr Self pow_vartime(const std::array< W, N > &exp) const
constexpr void square_n(size_t n)
constexpr CT::Option< Self > sqrt() const
constexpr void _const_time_poison() const
friend constexpr Self operator+(const Self &a, const Self &b)
static constexpr size_t BYTES
static constexpr Self one()
static constexpr Self choose(CT::Choice choice, const Self &x, const Self &y)
constexpr CT::Choice operator==(const Self &other) const
constexpr Self invert() const
constexpr Self mul3() const
Return (*this) multiplied by 3.
static constexpr void conditional_assign(Self &x, Self &y, Self &z, CT::Choice cond, const Self &nx, const Self &ny, const Self &nz)
constexpr CT::Choice is_even() const
IntMod & operator=(const Self &other)=default
static constexpr Self from_words(std::array< W, L > w)
IntMod & operator=(Self &&other)=default
constexpr Self mul4() const
Return (*this) multiplied by 4.
constexpr Self mul2() const
Return (*this) multiplied by 2.
static constexpr Self from_wide_bytes(std::span< const uint8_t, L > bytes)
static Self random(RandomNumberGenerator &rng)
constexpr CT::Choice is_one() const
static constexpr void conditional_swap(CT::Choice cond, Self &x, Self &y)
constexpr Self square() const
constexpr CT::Choice operator!=(const Self &other) const
static constexpr std::array< W, N > wide_to_rep(const std::array< W, 2 *N > &x)
static constexpr auto P_dash
static constexpr std::array< W, N > from_rep(const std::array< W, N > &z)
static constexpr size_t N
MontgomeryRep< Params > Self
static constexpr std::array< W, N > one()
static constexpr std::array< W, N > to_rep(const std::array< W, N > &x)
static constexpr std::array< W, N > redc(const std::array< W, 2 *N > &z)
C::AffinePoint AffinePoint
static constexpr size_t Windows
static constexpr size_t WindowBits
PrecomputedBaseMulTable(const AffinePoint &p)
BlindedScalarBits< C, WindowBits > BlindedScalar
C::ProjectivePoint ProjectivePoint
ProjectivePoint mul(const Scalar &s, RandomNumberGenerator &rng) const
static constexpr Self add_or_sub(const Self &a, const AffinePoint &b, CT::Choice sub)
ProjectiveCurvePoint< FieldElement, Params > Self
~ProjectiveCurvePoint()=default
ProjectiveCurvePoint(const Self &other)=default
friend constexpr Self operator+(const AffinePoint &a, const Self &b)
ProjectiveCurvePoint(Self &&other)=default
static constexpr bool A_is_zero
ProjectiveCurvePoint & operator=(Self &&other)=default
constexpr const FieldElement & x() const
constexpr ProjectiveCurvePoint()
friend constexpr Self operator-(const Self &a, const Self &b)
friend constexpr Self operator+(const Self &a, const AffinePoint &b)
static constexpr bool A_is_minus_3
ProjectiveCurvePoint & operator=(const Self &other)=default
static constexpr Self from_affine(const AffinePoint &pt)
static constexpr Self add(const Self &a, const Self &b)
constexpr Self & operator+=(const AffinePoint &other)
constexpr void conditional_assign(CT::Choice cond, const Self &pt)
constexpr void _const_time_unpoison() const
constexpr const FieldElement & z() const
constexpr const FieldElement & y() const
void randomize_rep(RandomNumberGenerator &rng)
constexpr CT::Choice is_identity() const
constexpr Self negate() const
friend constexpr Self operator+(const Self &a, const Self &b)
static constexpr FieldElement A
AffineCurvePoint< FieldElement, Params > AffinePoint
constexpr ProjectiveCurvePoint(const FieldElement &x, const FieldElement &y)
static constexpr Self add_mixed(const Self &a, const AffinePoint &b)
static constexpr Self identity()
constexpr void _const_time_poison() const
constexpr Self dbl_n(size_t n) const
constexpr ProjectiveCurvePoint(const FieldElement &x, const FieldElement &y, const FieldElement &z)
constexpr Self dbl() const
constexpr Self & operator+=(const Self &other)
void randomize(std::span< uint8_t > output)
virtual bool is_seeded() const =0
static constexpr size_t Bits
UnblindedScalarBits(const typename C::Scalar &scalar)
size_t get_window(size_t offset) const
static constexpr size_t WindowBits
typename C::AffinePoint AffinePoint
VartimeMul2Table(const AffinePoint &p, const AffinePoint &q)
typename C::Scalar Scalar
typename C::ProjectivePoint ProjectivePoint
ProjectivePoint mul2_vartime(const Scalar &s1, const Scalar &s2) const
static constexpr size_t TableSize
WindowedBoothMulTable(const AffinePoint &p)
C::ProjectivePoint ProjectivePoint
static constexpr size_t WindowBits
BlindedScalarBits< C, WindowBits+1 > BlindedScalar
static constexpr size_t InitialShift
ProjectivePoint mul(const Scalar &s, RandomNumberGenerator &rng) const
static constexpr size_t FullWindows
static constexpr size_t compute_full_windows(size_t sb, size_t wb)
static constexpr size_t TableBits
static constexpr size_t compute_initial_shift(size_t sb, size_t wb)
C::AffinePoint AffinePoint
ProjectivePoint mul2(const Scalar &s1, const Scalar &s2, RandomNumberGenerator &rng) const
C::ProjectivePoint ProjectivePoint
C::AffinePoint AffinePoint
WindowedMul2Table(const AffinePoint &p, const AffinePoint &q)
C::ProjectivePoint ProjectivePoint
static constexpr size_t Windows
WindowedMulTable(const AffinePoint &p)
BlindedScalarBits< C, WindowBits > BlindedScalar
static constexpr size_t TableSize
C::AffinePoint AffinePoint
ProjectivePoint mul(const Scalar &s, RandomNumberGenerator &rng) const
static constexpr size_t WindowBits
constexpr void poison_all(const Ts &... ts)
constexpr void unpoison_all(const Ts &... ts)
constexpr CT::Mask< T > is_equal(const T x[], const T y[], size_t len)
constexpr void unpoison(const T *p, size_t n)
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
constexpr void poison(const T *p, size_t n)
C::ProjectivePoint varpoint_exec(const AffinePointTable< C > &table, const BlindedScalar &scalar, RandomNumberGenerator &rng)
constexpr auto bigint_add2(W x[], size_t x_size, const W y[], size_t y_size) -> W
auto map_to_curve_sswu(const typename C::FieldElement &u) -> typename C::AffinePoint
consteval std::array< W, N > shanks_tonelli_c3(const std::array< W, N > &c2)
auto to_affine_batch(std::span< const typename C::ProjectivePoint > projective)
consteval std::array< W, N > p_plus_1_over_4(const std::array< W, N > &p)
constexpr auto bytes_to_words(std::span< const uint8_t, L > bytes)
constexpr W shift_left(std::array< W, N > &x)
constexpr auto word_sub(W x, W y, W *carry) -> W
consteval std::array< W, N > p_minus_1_over_2(const std::array< W, N > &p)
constexpr CT::Option< typename C::FieldElement > sqrt_field_element(const typename C::FieldElement &fe)
constexpr auto word_add(W x, W y, W *carry) -> W
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr ProjectivePoint dbl_n_generic(const ProjectivePoint &pt, const FieldElement &A, size_t n)
constexpr void comba_sqr(W z[2 *N], const W x[N])
consteval auto shanks_tonelli_c4(const std::array< W, N > &p_minus_1_over_2) -> Z
constexpr size_t read_window_bits(std::span< const W, N > words, size_t offset)
constexpr ProjectivePoint dbl_a_minus_3(const ProjectivePoint &pt)
constexpr void comba_mul(W z[2 *N], const W x[N], const W y[N])
C::ProjectivePoint mul2_exec(const AffinePointTable< C > &table, const BlindedScalar &x, const BlindedScalar &y, RandomNumberGenerator &rng)
consteval std::array< W, N > p_div_2_plus_1(const std::array< W, N > &p)
constexpr auto monty_redc(const std::array< W, 2 *N > &z, const std::array< W, N > &p, W p_dash) -> std::array< W, N >
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
constexpr auto monty_inverse(W a) -> W
constexpr ProjectivePoint dbl_n_a_zero(const ProjectivePoint &pt, size_t n)
constexpr ProjectivePoint dbl_a_zero(const ProjectivePoint &pt)
C::ProjectivePoint basemul_exec(std::span< const typename C::AffinePoint > table, const BlindedScalar &scalar, RandomNumberGenerator &rng)
std::vector< typename C::ProjectivePoint > mul2_setup(const typename C::AffinePoint &p, const typename C::AffinePoint &q)
auto hash_to_curve_sswu(const ExpandMsg &expand_message) -> std::conditional_t< RO, typename C::ProjectivePoint, typename C::AffinePoint >
void secure_scrub_memory(void *ptr, size_t n)
consteval std::array< W, N > mul_mod(const std::array< W, N > &x, const std::array< W, N > &y, const std::array< W, N > &p)
constexpr int32_t bigint_cmp(const W x[], size_t x_size, const W y[], size_t y_size)
constexpr ProjectivePoint point_add_mixed(const ProjectivePoint &a, const AffinePoint &b, const FieldElement &one)
constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size)
constexpr ProjectivePoint point_add_or_sub_mixed(const ProjectivePoint &a, const AffinePoint &b, CT::Choice sub, const FieldElement &one)
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
constexpr auto invert_field_element(const typename C::FieldElement &fe)
void carry(int64_t &h0, int64_t &h1)
BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b)
constexpr ProjectivePoint dbl_n_a_minus_3(const ProjectivePoint &pt, size_t n)
AffinePointTable< C > varpoint_setup(const typename C::AffinePoint &p)
constexpr auto load_le(ParamTs &&... params)
constexpr auto bigint_ct_is_lt(const W x[], size_t x_size, const W y[], size_t y_size, bool lt_or_equal=false) -> CT::Mask< W >
constexpr auto hex_to_words(const char(&s)[N])
constexpr ProjectivePoint dbl_generic(const ProjectivePoint &pt, const FieldElement &A)
consteval std::array< W, N > p_minus(const std::array< W, N > &p)
std::vector< typename C::AffinePoint > basemul_setup(const typename C::AffinePoint &p, size_t max_scalar_bits)
constexpr ProjectivePoint point_add(const ProjectivePoint &a, const ProjectivePoint &b)
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
consteval size_t count_bits(const std::array< W, N > &p)
constexpr auto store_be(ParamTs &&... params)
constexpr auto monty_redc_pdash1(const std::array< W, 2 *N > &z, const std::array< W, N > &p) -> std::array< W, N >
consteval std::array< W, N > montygomery_r(const std::array< W, N > &p)
constexpr W shift_right(std::array< W, N > &x)
consteval std::pair< size_t, std::array< W, N > > shanks_tonelli_c1c2(const std::array< W, N > &p)
static constexpr size_t N