7#ifndef BOTAN_PCURVES_IMPL_H_
8#define BOTAN_PCURVES_IMPL_H_
11#include <botan/internal/buffer_stuffer.h>
12#include <botan/internal/ct_utils.h>
13#include <botan/internal/loadstor.h>
14#include <botan/internal/mem_utils.h>
15#include <botan/internal/pcurves_algos.h>
16#include <botan/internal/pcurves_mul.h>
17#include <botan/internal/pcurves_util.h>
34 for(
size_t i = 0; i != N; ++i) {
79template <
typename Params>
84 static constexpr auto P = Params::P;
85 static constexpr size_t N = Params::N;
86 typedef typename Params::W
W;
88 static_assert(
N > 0 && (Params::P[0] & 1) == 1,
"Invalid Montgomery modulus");
99 constexpr static std::array<W, N>
one() {
return R1; }
104 constexpr static std::array<W, N>
redc(
const std::array<W, 2 * N>& z) {
105 if constexpr(
P_dash == 1) {
115 constexpr static std::array<W, N>
to_rep(
const std::array<W, N>& x) {
116 std::array<W, 2 * N> z;
127 constexpr static std::array<W, N>
wide_to_rep(
const std::array<W, 2 * N>& x) {
129 std::array<W, 2 * N> z;
137 constexpr static std::array<W, N>
from_rep(
const std::array<W, N>& z) {
138 std::array<W, 2 * N> ze = {};
139 copy_mem(std::span{ze}.template first<N>(), z);
162template <
typename Rep>
165 static constexpr auto P = Rep::P;
166 static constexpr size_t N = Rep::N;
167 typedef typename Rep::W W;
169 static constexpr auto P_MINUS_2 =
p_minus<2>(P);
212 if constexpr(L == N) {
213 return Self(Rep::to_rep(w));
215 static_assert(L < N);
216 std::array<W, N> ew = {};
217 copy_mem(std::span{ew}.template first<L>(), w);
218 return Self(Rep::to_rep(ew));
241 auto v = Rep::from_rep(m_val);
249 const auto flip = (even != this->
is_even());
269 for(
size_t i = 0; i != N; ++i) {
284 for(
size_t i = 0; i != N; ++i) {
292 for(
size_t i = 0; i != N; ++i) {
309 std::array<W, N> t = value();
317 for(
size_t i = 0; i != N; ++i) {
326 std::array<W, N> t = value();
347 std::array<W, 2 * N> z;
349 return Self(Rep::redc(z));
356 std::array<W, 2 * N> z;
358 m_val = Rep::redc(z);
370 for(
size_t i = 0; i != N; ++i) {
383 for(
size_t i = 0; i != N; ++i) {
398 for(
size_t i = 0; i != N; ++i) {
413 for(
size_t i = 0; i != N; ++i) {
427 std::array<W, 2 * N> z;
429 return Self(Rep::redc(z));
440 std::array<W, 2 * N> z;
441 for(
size_t i = 0; i != n; ++i) {
443 m_val = Rep::redc(z);
453 const W x_is_zero =
~CT::all_zeros(this->data(), N).value();
457 for(
size_t i = 0; i != N; ++i) {
478 constexpr size_t WindowBits = (
Self::BITS <= 256) ? 4 : 5;
479 constexpr size_t WindowElements = (1 << WindowBits) - 1;
481 constexpr size_t Windows = (
Self::BITS + WindowBits - 1) / WindowBits;
489 std::array<Self, WindowElements> tbl;
493 for(
size_t i = 1; i != WindowElements; ++i) {
496 tbl[i] = tbl[i / 2].square();
498 tbl[i] = tbl[i - 1] * tbl[0];
511 for(
size_t i = 1; i != Windows; ++i) {
512 r.square_n(WindowBits);
551 while((a.m_val[0] & 1) != 1) {
600 if(this->
is_zero().as_bool()) {
604 auto x =
Self(std::array<W, N>{1});
619 if(a.m_val == b.m_val) {
624 r.m_val = Rep::to_rep(r.m_val);
671 const CT::Choice correct = (z.square() == *
this);
691 const Self& x = (*this);
700 for(
size_t i = C1_C2.first; i >= 2; i--) {
703 z.conditional_assign(!e, z * c);
705 t.conditional_assign(!e, t * c);
710 const CT::Choice correct = (z.square() == *
this);
723 return CT::is_equal(this->data(), other.data(), N).as_choice();
734 constexpr std::array<W, Self::N>
to_words()
const {
return Rep::from_rep(m_val); }
739 constexpr void serialize_to(std::span<uint8_t, Self::BYTES> bytes)
const {
740 auto v = Rep::from_rep(m_val);
741 std::reverse(v.begin(), v.end());
747 const auto padded_bytes =
store_be(v);
749 copy_mem(bytes, std::span{padded_bytes}.template subspan<extra, Self::BYTES>());
760 static_assert(L >= N);
761 std::array<W, L> stash = {};
762 for(
size_t i = 0; i != N; ++i) {
775 static_assert(L >= N);
776 std::array<W, N> val = {};
777 for(
size_t i = 0; i != N; ++i) {
792 static std::optional<Self>
deserialize(std::span<const uint8_t> bytes) {
818 std::array<uint8_t, 2 * BYTES> padded_bytes = {};
819 copy_mem(std::span{padded_bytes}.template last<L>(), bytes);
835 std::array<uint8_t, 2 * Self::BYTES> padded_bytes = {};
836 copy_mem(std::span{padded_bytes}.last(bytes.size()), bytes);
852 constexpr size_t MAX_ATTEMPTS = 1000;
854 std::array<uint8_t, Self::BYTES> buf{};
856 for(
size_t i = 0; i != MAX_ATTEMPTS; ++i) {
862 constexpr uint8_t mask = 0xFF >> (8 - (
Self::BITS % 8));
868 if(s.value().is_nonzero().as_bool()) {
874 throw Internal_Error(
"Failed to generate random Scalar within bounded number of attempts");
883 std::array<W, 1> v{};
884 v[0] = (x >= 0) ? x : -x;
886 return (x >= 0) ? s : s.negate();
894 constexpr const std::array<W, N>& value()
const {
return m_val; }
896 constexpr const W* data()
const {
return m_val.data(); }
898 explicit constexpr IntMod(std::array<W, N> v) : m_val(v) {}
900 std::array<W, N> m_val;
908template <
typename FieldElement>
911 static constexpr size_t BYTES = 1 + 2 * FieldElement::BYTES;
921 static constexpr Self identity() {
return Self(FieldElement::zero(), FieldElement::zero()); }
925 return Self(FieldElement::zero(), FieldElement::zero());
941 constexpr void serialize_to(std::span<uint8_t, Self::BYTES> bytes)
const {
945 x().serialize_to(pack.next<FieldElement::BYTES>());
946 y().serialize_to(pack.next<FieldElement::BYTES>());
955 static constexpr auto ct_select(std::span<const Self> pts,
size_t idx) {
959 const size_t idx1 =
static_cast<size_t>(idx - 1);
960 for(
size_t i = 0; i != pts.size(); ++i) {
962 result.conditional_assign(found, pts[i]);
971 constexpr const FieldElement&
x()
const {
return m_x; }
976 constexpr const FieldElement&
y()
const {
return m_y; }
982 FieldElement::conditional_assign(m_x, m_y, cond, pt.
x(), pt.
y());
999template <
typename FieldElement,
typename Params>
1005 static constexpr FieldElement
A = FieldElement::from_words(Params::AW);
1008 static constexpr bool A_is_minus_3 = (
A == FieldElement::constant(-3)).as_bool();
1028 auto z = FieldElement::one();
1038 static constexpr Self identity() {
return Self(FieldElement::zero(), FieldElement::one(), FieldElement::zero()); }
1044 m_x(FieldElement::zero()), m_y(FieldElement::one()), m_z(FieldElement::zero()) {}
1050 m_x(
x), m_y(
y), m_z(FieldElement::one()) {}
1056 m_x(
x), m_y(
y), m_z(
z) {}
1071 (*this) = (*this) + other;
1076 (*this) = (*this) + other;
1085 FieldElement::conditional_assign(m_x, m_y, m_z, cond, pt.
x(), pt.
y(), pt.
z());
1148 auto r = FieldElement::random(rng);
1150 auto r2 = r.square();
1162 constexpr const FieldElement&
x()
const {
return m_x; }
1167 constexpr const FieldElement&
y()
const {
return m_y; }
1172 constexpr const FieldElement&
z()
const {
return m_z; }
1190template <StringLiteral PS,
1208 static constexpr int8_t
Z = ZI;
1214template <WordType WI,
size_t NI, std::array<WI, NI> PI>
1218 static constexpr size_t N = NI;
1219 static constexpr auto P = PI;
1227template <
typename Params,
template <
typename FieldParamsT>
typename FieldRep =
MontgomeryRep>
1230 typedef typename Params::W
W;
1234 static constexpr auto PW = Params::PW;
1235 static constexpr auto NW = Params::NW;
1236 static constexpr auto AW = Params::AW;
1239 static_assert(
PW.size() ==
NW.size());
1260 static_assert(
B.is_nonzero().as_bool(),
"B must be non-zero");
1292template <
typename C,
size_t WindowBits>
1295 typedef typename C::W W;
1299 static_assert(BlindingBits < C::Scalar::BITS);
1303 static constexpr size_t Bits = C::Scalar::BITS + BlindingBits;
1305 size_t bits()
const {
return m_bits; }
1308 if(BlindingBits > 0 && rng.
is_seeded()) {
1312 constexpr size_t n_words = C::Words;
1314 uint8_t maskb[MaskBytes + (BlindingBits == 0 ? 1 : 0)] = {0};
1317 W mask[n_words] = {0};
1318 load_le(mask, maskb, MaskWords);
1322 if constexpr(ExcessBits > 0) {
1323 constexpr W ExcessMask = (
static_cast<W
>(1) << (
WordInfo<W>::bits - ExcessBits)) - 1;
1324 mask[MaskWords - 1] &= ExcessMask;
1329 mask[(BlindingBits - 1) /
WordInfo<W>::bits] |=
static_cast<W
>(1) << TopMaskBit;
1332 W mask_n[2 * n_words] = {0};
1334 const auto sw = scalar.to_words();
1338 bigint_add2(mask_n, 2 * n_words, sw.data(), sw.size());
1340 std::reverse(mask_n, mask_n + 2 * n_words);
1342 m_bits = C::Scalar::BITS + BlindingBits;
1345 m_bytes.resize(C::Scalar::BYTES);
1346 scalar.serialize_to(std::span{m_bytes}.template first<C::Scalar::BYTES>());
1347 m_bits = C::Scalar::BITS;
1369 std::vector<uint8_t> m_bytes;
1373template <
typename C,
size_t WindowBits>
1376 static constexpr size_t Bits = C::Scalar::BITS;
1386 std::array<uint8_t, C::Scalar::BYTES> m_bytes;
1389template <
typename C,
size_t W>
1413 std::vector<AffinePoint> m_table;
1421template <
typename C,
size_t W>
1448 std::vector<AffinePoint> m_table;
1454template <
typename C,
size_t W>
1470 return (sb - 1) / wb;
1480 return sb - (sb / wb) * wb;
1492 const size_t scalar_bits = bits.
bits();
1499 auto accum = ProjectivePoint::identity();
1502 for(
size_t i = 0; i != full_windows; ++i) {
1503 const size_t idx = scalar_bits - initial_shift -
WindowBits * i;
1510 accum = ProjectivePoint::from_affine(m_table.ct_select(tidx));
1511 accum.conditional_assign(tneg, accum.negate());
1513 accum = ProjectivePoint::add_or_sub(accum, m_table.ct_select(tidx), tneg);
1520 accum.randomize_rep(rng);
1527 accum = ProjectivePoint::add_or_sub(accum, m_table.ct_select(tidx), tneg);
1537template <
typename C,
size_t W>
1541 static_assert(W >= 1 && W <= 4);
1554 const BlindedScalar bits1(s1, rng);
1555 const BlindedScalar bits2(s2, rng);
1564template <
typename C,
size_t W>
1568 static_assert(W >= 1 && W <= 4);
1594 const bool s1_is_zero = s1.is_zero().as_bool();
1595 const bool s2_is_zero = s2.is_zero().as_bool();
1598 if(s1_is_zero && s2_is_zero) {
1599 return ProjectivePoint::identity();
1602 auto [w_0, first_nonempty_window] = [&]() {
1603 for(
size_t i = 0; i != Windows; ++i) {
1606 const size_t window = w_1 + (w_2 <<
WindowBits);
1609 return std::make_pair(window, i);
1617 auto accum = ProjectivePoint::from_affine(m_table[w_0 - 1]);
1619 for(
size_t i = first_nonempty_window + 1; i < Windows; ++i) {
1625 const size_t window = w_1 + (w_2 <<
WindowBits);
1629 accum += m_table[window - 1];
1637 std::vector<AffinePoint> m_table;
1645template <
typename C>
1647 requires C::ValidForSswuHash
1659template <
typename C>
1661 requires C::ValidForSswuHash
1665 static const typename C::FieldElement C1 = (
SSWU_C2<C>() * C::SSWU_Z).negate();
1674template <
typename C>
1677 const auto z_u2 = C::SSWU_Z * u.square();
1678 const auto z2_u4 = z_u2.square();
1680 auto x1 =
SSWU_C1<C>() * (C::FieldElement::one() + tv1);
1681 x1.conditional_assign(tv1.is_zero(),
SSWU_C2<C>());
1682 const auto x2 = z_u2 * x1;
1690 auto x = C::FieldElement::choose(use_y1, x1, x2);
1691 auto y = C::FieldElement::choose(use_y1, y1.
value_or(C::FieldElement::zero()), y2.
value_or(C::FieldElement::zero()));
1693 auto pt =
typename C::AffinePoint(x, y.correct_sign(u.is_even()));
1710template <
typename C,
bool RO, std::invocable<std::span<u
int8_t>> ExpandMsg>
1711 requires C::ValidForSswuHash
1713 -> std::conditional_t<RO, typename C::ProjectivePoint, typename C::AffinePoint> {
1714 constexpr size_t SecurityLevel = (C::OrderBits + 1) / 2;
1715 constexpr size_t L = (C::PrimeFieldBits + SecurityLevel + 7) / 8;
1716 constexpr size_t Cnt = RO ? 2 : 1;
1718 std::array<uint8_t, L * Cnt> uniform_bytes = {};
1719 expand_message(uniform_bytes);
1722 const auto u0 = C::FieldElement::from_wide_bytes(std::span<const uint8_t, L>(uniform_bytes.data(), L));
1723 const auto u1 = C::FieldElement::from_wide_bytes(std::span<const uint8_t, L>(uniform_bytes.data() + L, L));
1729 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 Self negate() const
constexpr AffineCurvePoint()
constexpr void serialize_to(std::span< uint8_t, Self::BYTES > bytes) const
AffineCurvePoint(Self &&other)=default
constexpr void _const_time_unpoison() const
static constexpr Self identity()
constexpr void _const_time_poison() const
AffineCurvePoint & operator=(const Self &other)=default
constexpr const FieldElement & y() const
static constexpr Self identity(const Self &)
constexpr void conditional_assign(CT::Choice cond, const Self &pt)
AffineCurvePoint< FieldElement > Self
AffineCurvePoint & operator=(Self &&other)=default
constexpr AffineCurvePoint(const FieldElement &x, const FieldElement &y)
static constexpr auto ct_select(std::span< const Self > pts, size_t idx)
constexpr CT::Choice is_identity() const
AffineCurvePoint(const Self &other)=default
~AffineCurvePoint()=default
constexpr const FieldElement & x() const
static constexpr size_t BYTES
BlindedScalarBits(const BlindedScalarBits &other)=delete
BlindedScalarBits & operator=(BlindedScalarBits &&other)=delete
size_t get_window(size_t offset) const
BlindedScalarBits(BlindedScalarBits &&other)=delete
BlindedScalarBits(const typename C::Scalar &scalar, RandomNumberGenerator &rng)
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)
constexpr T into_bitmask() const
static constexpr Mask< T > expand(T v)
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 > AffinePoint
ProjectiveCurvePoint< FieldElement, Params > ProjectivePoint
static constexpr size_t OrderBits
static constexpr AffinePoint G
IntMod< FieldRep< FieldParams > > FieldElement
static constexpr FieldElement B
static constexpr auto P_MOD_4
static constexpr void conditional_assign(Self &x, Self &y, CT::Choice cond, const Self &nx, const Self &ny)
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 BOTAN_FORCE_INLINE Self & operator*=(const Self &other)
constexpr void _const_time_unpoison() const
IntMod(const Self &other)=default
friend constexpr BOTAN_FORCE_INLINE Self operator*(const Self &a, const Self &b)
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
constexpr BOTAN_FORCE_INLINE Self mul2() const
Return (*this) multiplied by 2.
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
static constexpr size_t BYTES
constexpr BOTAN_FORCE_INLINE Self square() const
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.
friend constexpr BOTAN_FORCE_INLINE Self operator+(const Self &a, const Self &b)
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)
friend constexpr BOTAN_FORCE_INLINE Self operator-(const Self &a, const Self &b)
IntMod & operator=(Self &&other)=default
constexpr Self mul4() const
Return (*this) multiplied by 4.
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 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 WindowBits
BlindedScalarBits< C, WindowBits+1 > BlindedScalar
PrecomputedBaseMulTable(const AffinePoint &p)
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
AffineCurvePoint< FieldElement > AffinePoint
friend constexpr Self operator+(const Self &a, const Self &b)
static constexpr FieldElement A
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
consteval StringLiteral(const char(&str)[N])
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
ProjectivePoint mul(const Scalar &s, RandomNumberGenerator &rng) const
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
#define BOTAN_FORCE_INLINE
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)
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 size_t scalar_blinding_bits(size_t scalar_bits)
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)
auto to_affine_batch(std::span< const typename C::ProjectivePoint > projective)
constexpr ProjectivePoint dbl_a_zero(const ProjectivePoint &pt)
C::ProjectivePoint basemul_booth_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 >
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)
std::vector< typename C::AffinePoint > basemul_booth_setup(const typename C::AffinePoint &p, size_t max_scalar_bits)
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 secure_zeroize_buffer(void *ptr, size_t n)
void carry(int64_t &h0, int64_t &h1)
BOTAN_FORCE_INLINE constexpr T choose(T mask, T a, T b)
constexpr std::pair< size_t, CT::Choice > booth_recode(T x)
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)
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