7#include <botan/internal/pcurves_generic.h> 
    9#include <botan/bigint.h> 
   10#include <botan/exceptn.h> 
   12#include <botan/internal/ct_utils.h> 
   13#include <botan/internal/loadstor.h> 
   14#include <botan/internal/mp_core.h> 
   15#include <botan/internal/pcurves_algos.h> 
   16#include <botan/internal/pcurves_instance.h> 
   17#include <botan/internal/pcurves_mul.h> 
   18#include <botan/internal/primality.h> 
   26constexpr std::optional<std::array<word, N>> 
bytes_to_words(std::span<const uint8_t> bytes) {
 
   27   if(bytes.size() > WordInfo<word>::bytes * N) {
 
   31   std::array<word, N> r{};
 
   33   const size_t full_words = bytes.size() / WordInfo<word>::bytes;
 
   34   const size_t extra_bytes = bytes.size() % WordInfo<word>::bytes;
 
   36   for(
size_t i = 0; i != full_words; ++i) {
 
   41      const size_t shift = extra_bytes * 8;
 
   44      for(
size_t i = 0; i != extra_bytes; ++i) {
 
   45         const word b0 = bytes[WordInfo<word>::bytes * full_words + i];
 
   46         r[0] |= (b0 << (8 * (extra_bytes - 1 - i)));
 
   54T impl_pow_vartime(
const T& elem, 
const T& one, 
size_t bits, std::span<const word> exp) {
 
   55   constexpr size_t WindowBits = 4;
 
   56   constexpr size_t WindowElements = (1 << WindowBits) - 1;
 
   58   const size_t Windows = (bits + WindowBits - 1) / WindowBits;
 
   61   tbl.reserve(WindowElements);
 
   65   for(
size_t i = 1; i != WindowElements; ++i) {
 
   67         tbl.push_back(tbl[i / 2].
square());
 
   69         tbl.push_back(tbl[i - 1] * tbl[0]);
 
   81   for(
size_t i = 1; i != Windows; ++i) {
 
   82      for(
size_t j = 0; j != WindowBits; ++j) {
 
   97class GenericCurveParams final {
 
  102      GenericCurveParams(
const BigInt& p,
 
  105                         const BigInt& base_x,
 
  106                         const BigInt& base_y,
 
  107                         const BigInt& order) :
 
  108            m_words(p.sig_words()),
 
  109            m_order_bits(order.bits()),
 
  110            m_order_bytes(order.bytes()),
 
  111            m_field_bits(p.bits()),
 
  112            m_field_bytes(p.bytes()),
 
  113            m_monty_order(order),
 
  115            m_field(bn_to_fixed(p)),
 
  116            m_field_minus_2(bn_to_fixed_rev(p - 2)),
 
  117            m_field_monty_r1(bn_to_fixed(m_monty_field.R1())),
 
  118            m_field_monty_r2(bn_to_fixed(m_monty_field.R2())),
 
  119            m_field_p_plus_1_over_4(bn_to_fixed_rev((p + 1) / 4)),
 
  120            m_field_inv_2(bn_to_fixed((p / 2) + 1)),
 
  121            m_field_p_dash(m_monty_field.p_dash()),
 
  123            m_order(bn_to_fixed(order)),
 
  124            m_order_minus_2(bn_to_fixed_rev(order - 2)),
 
  125            m_order_monty_r1(bn_to_fixed(m_monty_order.R1())),
 
  126            m_order_monty_r2(bn_to_fixed(m_monty_order.R2())),
 
  127            m_order_monty_r3(bn_to_fixed(m_monty_order.R3())),
 
  128            m_order_inv_2(bn_to_fixed((order / 2) + 1)),
 
  129            m_order_p_dash(m_monty_order.p_dash()),
 
  131            m_a_is_minus_3(a + 3 == p),
 
  132            m_a_is_zero(a.is_zero()),
 
  133            m_order_is_lt_field(order < p) {
 
  135         m_monty_curve_a = bn_to_fixed(m_monty_field.mul(a, m_monty_field.R2(), ws));
 
  136         m_monty_curve_b = bn_to_fixed(m_monty_field.mul(b, m_monty_field.R2(), ws));
 
  138         m_base_x = bn_to_fixed(m_monty_field.mul(base_x, m_monty_field.R2(), ws));
 
  139         m_base_y = bn_to_fixed(m_monty_field.mul(base_y, m_monty_field.R2(), ws));
 
  142      size_t words()
 const { 
return m_words; }
 
  144      size_t order_bits()
 const { 
return m_order_bits; }
 
  146      size_t order_bytes()
 const { 
return m_order_bytes; }
 
  148      size_t field_bits()
 const { 
return m_field_bits; }
 
  150      size_t field_bytes()
 const { 
return m_field_bytes; }
 
  152      const Montgomery_Params& monty_order()
 const { 
return m_monty_order; }
 
  154      const Montgomery_Params& monty_field()
 const { 
return m_monty_field; }
 
  156      const StorageUnit& field()
 const { 
return m_field; }
 
  158      const StorageUnit& field_minus_2()
 const { 
return m_field_minus_2; }
 
  160      const StorageUnit& field_monty_r1()
 const { 
return m_field_monty_r1; }
 
  162      const StorageUnit& field_monty_r2()
 const { 
return m_field_monty_r2; }
 
  164      const StorageUnit& field_p_plus_1_over_4()
 const { 
return m_field_p_plus_1_over_4; }
 
  166      const StorageUnit& field_inv_2()
 const { 
return m_field_inv_2; }
 
  168      word field_p_dash()
 const { 
return m_field_p_dash; }
 
  170      const StorageUnit& order()
 const { 
return m_order; }
 
  172      const StorageUnit& order_minus_2()
 const { 
return m_order_minus_2; }
 
  174      const StorageUnit& order_monty_r1()
 const { 
return m_order_monty_r1; }
 
  176      const StorageUnit& order_monty_r2()
 const { 
return m_order_monty_r2; }
 
  178      const StorageUnit& order_monty_r3()
 const { 
return m_order_monty_r3; }
 
  180      const StorageUnit& order_inv_2()
 const { 
return m_order_inv_2; }
 
  182      word order_p_dash()
 const { 
return m_order_p_dash; }
 
  184      const StorageUnit& monty_curve_a()
 const { 
return m_monty_curve_a; }
 
  186      const StorageUnit& monty_curve_b()
 const { 
return m_monty_curve_b; }
 
  188      const StorageUnit& base_x()
 const { 
return m_base_x; }
 
  190      const StorageUnit& base_y()
 const { 
return m_base_y; }
 
  192      bool a_is_minus_3()
 const { 
return m_a_is_minus_3; }
 
  194      bool a_is_zero()
 const { 
return m_a_is_zero; }
 
  196      bool order_is_less_than_field()
 const { 
return m_order_is_lt_field; }
 
  198      void mul(std::array<word, 2 * N>& z, 
const std::array<word, N>& x, 
const std::array<word, N>& y)
 const {
 
  203         } 
else if(m_words == 6) {
 
  205         } 
else if(m_words == 8) {
 
  207         } 
else if(m_words == 9) {
 
  210            bigint_mul(z.data(), z.size(), x.data(), m_words, m_words, y.data(), m_words, m_words, 
nullptr, 0);
 
  214      void sqr(std::array<word, 2 * N>& z, 
const std::array<word, N>& x)
 const {
 
  219         } 
else if(m_words == 6) {
 
  221         } 
else if(m_words == 8) {
 
  223         } 
else if(m_words == 9) {
 
  226            bigint_sqr(z.data(), z.size(), x.data(), m_words, m_words, 
nullptr, 0);
 
  231      static std::array<word, PrimeOrderCurve::StorageWords> bn_to_fixed(
const BigInt& n) {
 
  232         const size_t n_words = n.sig_words();
 
  235         std::array<word, PrimeOrderCurve::StorageWords> r{};
 
  236         copy_mem(std::span{r}.first(n_words), n._as_span().first(n_words));
 
  240      static std::array<word, PrimeOrderCurve::StorageWords> bn_to_fixed_rev(
const BigInt& n) {
 
  241         auto v = bn_to_fixed(n);
 
  242         std::reverse(v.begin(), v.end());
 
  249      size_t m_order_bytes;
 
  251      size_t m_field_bytes;
 
  253      Montgomery_Params m_monty_order;
 
  254      Montgomery_Params m_monty_field;
 
  257      StorageUnit m_field_minus_2;
 
  258      StorageUnit m_field_monty_r1;
 
  259      StorageUnit m_field_monty_r2;
 
  260      StorageUnit m_field_p_plus_1_over_4;
 
  261      StorageUnit m_field_inv_2;
 
  265      StorageUnit m_order_minus_2;
 
  266      StorageUnit m_order_monty_r1;
 
  267      StorageUnit m_order_monty_r2;
 
  268      StorageUnit m_order_monty_r3;
 
  269      StorageUnit m_order_inv_2;
 
  272      StorageUnit m_monty_curve_a{};
 
  273      StorageUnit m_monty_curve_b{};
 
  275      StorageUnit m_base_x{};
 
  276      StorageUnit m_base_y{};
 
  280      bool m_order_is_lt_field;
 
  283class GenericScalar final {
 
  289      static std::optional<GenericScalar> from_wide_bytes(
const GenericPrimeOrderCurve* curve,
 
  290                                                          std::span<const uint8_t> bytes) {
 
  291         const size_t mlen = curve->_params().order_bytes();
 
  293         if(bytes.size() > 2 * mlen) {
 
  297         std::array<uint8_t, 2 * 
sizeof(
word) * N> padded_bytes{};
 
  298         copy_mem(std::span{padded_bytes}.last(bytes.size()), bytes);
 
  302            auto in_rep = wide_to_rep(curve, words.value());
 
  303            return GenericScalar(curve, in_rep);
 
  309      static std::optional<GenericScalar> deserialize(
const GenericPrimeOrderCurve* curve,
 
  310                                                      std::span<const uint8_t> bytes) {
 
  311         const size_t len = curve->_params().order_bytes();
 
  313         if(bytes.size() != len) {
 
  320            if(!
bigint_ct_is_lt(words->data(), N, curve->_params().order().data(), N).as_bool()) {
 
  325            return GenericScalar(curve, to_rep(curve, *words));
 
  331      static GenericScalar zero(
const GenericPrimeOrderCurve* curve) {
 
  333         return GenericScalar(curve, zeros);
 
  336      static GenericScalar one(
const GenericPrimeOrderCurve* curve) {
 
  337         return GenericScalar(curve, curve->_params().order_monty_r1());
 
  340      static GenericScalar random(
const GenericPrimeOrderCurve* curve, RandomNumberGenerator& rng) {
 
  341         constexpr size_t MAX_ATTEMPTS = 1000;
 
  343         const size_t bits = curve->_params().order_bits();
 
  345         std::vector<uint8_t> buf(curve->_params().order_bytes());
 
  347         for(
size_t i = 0; i != MAX_ATTEMPTS; ++i) {
 
  353               const uint8_t mask = 0xFF >> (8 - (bits % 8));
 
  357            if(
auto s = GenericScalar::deserialize(curve, buf)) {
 
  358               if(s.value().is_nonzero().as_bool()) {
 
  364         throw Internal_Error(
"Failed to generate random Scalar within bounded number of attempts");
 
  367      friend GenericScalar operator+(
const GenericScalar& a, 
const GenericScalar& b) {
 
  368         const auto* curve = check_curve(a, b);
 
  369         const size_t words = curve->_params().words();
 
  376         return GenericScalar(curve, r);
 
  379      friend GenericScalar operator-(
const GenericScalar& a, 
const GenericScalar& b) { 
return a + b.negate(); }
 
  381      friend GenericScalar operator*(
const GenericScalar& a, 
const GenericScalar& b) {
 
  382         const auto* curve = check_curve(a, b);
 
  384         std::array<W, 2 * N> z;  
 
  385         curve->_params().mul(z, a.value(), b.value());
 
  386         return GenericScalar(curve, redc(curve, z));
 
  389      GenericScalar& operator*=(
const GenericScalar& other) {
 
  390         const auto* curve = check_curve(*
this, other);
 
  392         std::array<W, 2 * N> z;  
 
  393         curve->_params().mul(z, value(), other.value());
 
  394         m_val = redc(curve, z);
 
  398      GenericScalar square()
 const {
 
  399         const auto* curve = this->m_curve;
 
  401         std::array<W, 2 * N> z;  
 
  402         curve->_params().sqr(z, value());
 
  403         return GenericScalar(curve, redc(curve, z));
 
  406      GenericScalar pow_vartime(
const StorageUnit& exp)
 const {
 
  407         auto one = GenericScalar::one(curve());
 
  408         auto bits = curve()->_params().order_bits();
 
  409         auto words = curve()->_params().words();
 
  410         return impl_pow_vartime(*
this, one, bits, std::span{exp}.last(words));
 
  413      GenericScalar negate()
 const {
 
  417         bigint_sub3(r.data(), m_curve->_params().order().data(), N, this->data(), N);
 
  418         x_is_zero.if_set_zero_out(r.data(), N);
 
  419         return GenericScalar(m_curve, r);
 
  422      GenericScalar invert()
 const { 
return pow_vartime(m_curve->_params().order_minus_2()); }
 
  431      static void _invert_vartime_div2_helper(GenericScalar& a, GenericScalar& x) {
 
  432         const auto& inv_2 = a.curve()->_params().order_inv_2();
 
  435         while((a.m_val[0] & 1) != 1) {
 
  450      GenericScalar invert_vartime()
 const {
 
  451         if(this->is_zero().as_bool()) {
 
  455         auto x = GenericScalar(m_curve, std::array<W, N>{1});
 
  456         auto b = GenericScalar(m_curve, from_rep(m_curve, m_val));
 
  459         GenericScalar::_invert_vartime_div2_helper(b, x);
 
  466         GenericScalar::_invert_vartime_div2_helper(a, y);
 
  470            if(a.m_val == b.m_val) {
 
  475               return GenericScalar(curve(), to_rep(curve(), r.m_val));
 
  489            std::array<W, N> r{};
 
  497               GenericScalar::_invert_vartime_div2_helper(b, x);
 
  503               GenericScalar::_invert_vartime_div2_helper(a, y);
 
  508      template <concepts::resizable_
byte_buffer T>
 
  509      T serialize()
 const {
 
  510         T bytes(m_curve->_params().order_bytes());
 
  511         this->serialize_to(bytes);
 
  515      void serialize_to(std::span<uint8_t> bytes)
 const {
 
  516         auto v = from_rep(m_curve, m_val);
 
  517         std::reverse(v.begin(), v.end());
 
  519         const size_t flen = m_curve->_params().order_bytes();
 
  520         BOTAN_ARG_CHECK(bytes.size() == flen, 
"Expected output span provided");
 
  523         const auto padded_bytes = 
store_be(v);
 
  524         const size_t extra = N * WordInfo<W>::bytes - flen;
 
  525         copy_mem(bytes, std::span{padded_bytes}.subspan(extra, flen));
 
  528      CT::Choice is_zero()
 const { 
return CT::all_zeros(m_val.data(), m_curve->_params().words()).as_choice(); }
 
  530      CT::Choice is_nonzero()
 const { 
return !is_zero(); }
 
  532      CT::Choice operator==(
const GenericScalar& other)
 const {
 
  533         if(this->m_curve != other.m_curve) {
 
  537         return CT::is_equal(m_val.data(), other.m_val.data(), m_curve->_params().words()).as_choice();
 
  543      StorageUnit to_words()
 const { 
return from_rep(m_curve, m_val); }
 
  545      const StorageUnit& stash_value()
 const { 
return m_val; }
 
  547      const GenericPrimeOrderCurve* curve()
 const { 
return m_curve; }
 
  549      GenericScalar(
const GenericPrimeOrderCurve* curve, StorageUnit val) : m_curve(curve), m_val(val) {}
 
  552      const StorageUnit& value()
 const { 
return m_val; }
 
  554      const W* data()
 const { 
return m_val.data(); }
 
  556      static const GenericPrimeOrderCurve* check_curve(
const GenericScalar& a, 
const GenericScalar& b) {
 
  561      static StorageUnit redc(
const GenericPrimeOrderCurve* curve, std::array<W, 2 * N> z) {
 
  562         const auto& mod = curve->_params().order();
 
  563         const size_t words = curve->_params().words();
 
  567            r.data(), z.data(), mod.data(), words, curve->_params().order_p_dash(), ws.data(), ws.size());
 
  571      static StorageUnit from_rep(
const GenericPrimeOrderCurve* curve, StorageUnit z) {
 
  572         std::array<W, 2 * N> ze{};
 
  573         copy_mem(std::span{ze}.template first<N>(), z);
 
  574         return redc(curve, ze);
 
  577      static StorageUnit to_rep(
const GenericPrimeOrderCurve* curve, StorageUnit x) {
 
  578         std::array<W, 2 * N> z;  
 
  579         curve->_params().mul(z, x, curve->_params().order_monty_r2());
 
  580         return redc(curve, z);
 
  583      static StorageUnit wide_to_rep(
const GenericPrimeOrderCurve* curve, std::array<W, 2 * N> x) {
 
  584         auto redc_x = redc(curve, x);
 
  585         std::array<W, 2 * N> z;  
 
  586         curve->_params().mul(z, redc_x, curve->_params().order_monty_r3());
 
  587         return redc(curve, z);
 
  590      const GenericPrimeOrderCurve* m_curve;
 
  594class GenericField final {
 
  600      static std::optional<GenericField> deserialize(
const GenericPrimeOrderCurve* curve,
 
  601                                                     std::span<const uint8_t> bytes) {
 
  602         const size_t len = curve->_params().field_bytes();
 
  604         if(bytes.size() != len) {
 
  611            if(!
bigint_ct_is_lt(words->data(), N, curve->_params().field().data(), N).as_bool()) {
 
  616            return GenericField::from_words(curve, *words);
 
  622      static GenericField from_words(
const GenericPrimeOrderCurve* curve, 
const std::array<word, N>& words) {
 
  623         return GenericField(curve, to_rep(curve, words));
 
  626      static GenericField zero(
const GenericPrimeOrderCurve* curve) {
 
  628         return GenericField(curve, zeros);
 
  631      static GenericField one(
const GenericPrimeOrderCurve* curve) {
 
  632         return GenericField(curve, curve->_params().field_monty_r1());
 
  635      static GenericField curve_a(
const GenericPrimeOrderCurve* curve) {
 
  636         return GenericField(curve, curve->_params().monty_curve_a());
 
  639      static GenericField curve_b(
const GenericPrimeOrderCurve* curve) {
 
  640         return GenericField(curve, curve->_params().monty_curve_b());
 
  643      static GenericField random(
const GenericPrimeOrderCurve* curve, RandomNumberGenerator& rng) {
 
  644         constexpr size_t MAX_ATTEMPTS = 1000;
 
  646         const size_t bits = curve->_params().field_bits();
 
  648         std::vector<uint8_t> buf(curve->_params().field_bytes());
 
  650         for(
size_t i = 0; i != MAX_ATTEMPTS; ++i) {
 
  656               const uint8_t mask = 0xFF >> (8 - (bits % 8));
 
  660            if(
auto s = GenericField::deserialize(curve, buf)) {
 
  661               if(s.value().is_nonzero().as_bool()) {
 
  667         throw Internal_Error(
"Failed to generate random Scalar within bounded number of attempts");
 
  673      GenericField div2()
 const {
 
  674         StorageUnit t = value();
 
  678         bigint_cnd_add(borrow, t.data(), m_curve->_params().field_inv_2().data(), N);
 
  680         return GenericField(m_curve, t);
 
  684      GenericField mul2()
 const {
 
  685         StorageUnit t = value();
 
  690         return GenericField(m_curve, r);
 
  694      GenericField mul3()
 const { 
return mul2() + (*this); }
 
  697      GenericField mul4()
 const { 
return mul2().mul2(); }
 
  700      GenericField mul8()
 const { 
return mul2().mul2().mul2(); }
 
  702      friend GenericField operator+(
const GenericField& a, 
const GenericField& b) {
 
  703         const auto* curve = check_curve(a, b);
 
  704         const size_t words = curve->_params().words();
 
  711         return GenericField(curve, r);
 
  714      friend GenericField operator-(
const GenericField& a, 
const GenericField& b) { 
return a + b.negate(); }
 
  716      friend GenericField operator*(
const GenericField& a, 
const GenericField& b) {
 
  717         const auto* curve = check_curve(a, b);
 
  719         std::array<W, 2 * N> z;  
 
  720         curve->_params().mul(z, a.value(), b.value());
 
  721         return GenericField(curve, redc(curve, z));
 
  724      GenericField& operator*=(
const GenericField& other) {
 
  725         const auto* curve = check_curve(*
this, other);
 
  727         std::array<W, 2 * N> z;  
 
  728         curve->_params().mul(z, value(), other.value());
 
  729         m_val = redc(curve, z);
 
  733      GenericField square()
 const {
 
  734         std::array<W, 2 * N> z;  
 
  735         m_curve->_params().sqr(z, value());
 
  736         return GenericField(m_curve, redc(m_curve, z));
 
  739      GenericField pow_vartime(
const StorageUnit& exp)
 const {
 
  740         auto one = GenericField::one(curve());
 
  741         auto bits = curve()->_params().field_bits();
 
  742         auto words = curve()->_params().words();
 
  743         return impl_pow_vartime(*
this, one, bits, std::span{exp}.last(words));
 
  746      GenericField negate()
 const {
 
  750         bigint_sub3(r.data(), m_curve->_params().field().data(), N, this->data(), N);
 
  751         x_is_zero.if_set_zero_out(r.data(), N);
 
  752         return GenericField(m_curve, r);
 
  755      GenericField invert()
 const { 
return pow_vartime(m_curve->_params().field_minus_2()); }
 
  757      template <concepts::resizable_
byte_buffer T>
 
  758      T serialize()
 const {
 
  759         T bytes(m_curve->_params().field_bytes());
 
  764      void serialize_to(std::span<uint8_t> bytes)
 const {
 
  765         auto v = from_rep(m_curve, m_val);
 
  766         std::reverse(v.begin(), v.end());
 
  768         const size_t flen = m_curve->_params().field_bytes();
 
  769         BOTAN_ARG_CHECK(bytes.size() == flen, 
"Expected output span provided");
 
  772         const auto padded_bytes = 
store_be(v);
 
  773         const size_t extra = N * WordInfo<W>::bytes - flen;
 
  774         copy_mem(bytes, std::span{padded_bytes}.subspan(extra, flen));
 
  777      CT::Choice is_zero()
 const { 
return CT::all_zeros(m_val.data(), m_curve->_params().words()).as_choice(); }
 
  779      CT::Choice is_nonzero()
 const { 
return !is_zero(); }
 
  781      CT::Choice operator==(
const GenericField& other)
 const {
 
  782         if(this->m_curve != other.m_curve) {
 
  786         return CT::is_equal(m_val.data(), other.m_val.data(), m_curve->_params().words()).as_choice();
 
  789      const StorageUnit& stash_value()
 const { 
return m_val; }
 
  791      const GenericPrimeOrderCurve* curve()
 const { 
return m_curve; }
 
  793      CT::Choice is_even()
 const {
 
  794         auto v = from_rep(m_curve, m_val);
 
  801      StorageUnit to_words()
 const { 
return from_rep(m_curve, m_val); }
 
  803      void _const_time_poison()
 const { 
CT::poison(m_val); }
 
  805      void _const_time_unpoison()
 const { 
CT::unpoison(m_val); }
 
  807      static void conditional_swap(CT::Choice cond, GenericField& x, GenericField& y) {
 
  810         for(
size_t i = 0; i != N; ++i) {
 
  811            auto nx = 
choose(mask, y.m_val[i], x.m_val[i]);
 
  812            auto ny = 
choose(mask, x.m_val[i], y.m_val[i]);
 
  818      void conditional_assign(CT::Choice cond, 
const GenericField& nx) {
 
  821         for(
size_t i = 0; i != N; ++i) {
 
  822            m_val[i] = 
choose(mask, nx.m_val[i], m_val[i]);
 
  831      static void conditional_assign(
 
  832         GenericField& x, GenericField& y, CT::Choice cond, 
const GenericField& nx, 
const GenericField& ny) {
 
  835         for(
size_t i = 0; i != N; ++i) {
 
  836            x.m_val[i] = 
choose(mask, nx.m_val[i], x.m_val[i]);
 
  837            y.m_val[i] = 
choose(mask, ny.m_val[i], y.m_val[i]);
 
  846      static void conditional_assign(GenericField& x,
 
  850                                     const GenericField& nx,
 
  851                                     const GenericField& ny,
 
  852                                     const GenericField& nz) {
 
  855         for(
size_t i = 0; i != N; ++i) {
 
  856            x.m_val[i] = 
choose(mask, nx.m_val[i], x.m_val[i]);
 
  857            y.m_val[i] = 
choose(mask, ny.m_val[i], y.m_val[i]);
 
  858            z.m_val[i] = 
choose(mask, nz.m_val[i], z.m_val[i]);
 
  862      std::pair<GenericField, CT::Choice> sqrt()
 const {
 
  865         auto z = pow_vartime(m_curve->_params().field_p_plus_1_over_4());
 
  866         const CT::Choice correct = (z.square() == *
this);
 
  868         z.conditional_assign(!correct, zero(m_curve));
 
  872      GenericField(
const GenericPrimeOrderCurve* curve, StorageUnit val) : m_curve(curve), m_val(val) {}
 
  875      const StorageUnit& value()
 const { 
return m_val; }
 
  877      const W* data()
 const { 
return m_val.data(); }
 
  879      static const GenericPrimeOrderCurve* check_curve(
const GenericField& a, 
const GenericField& b) {
 
  884      static StorageUnit redc(
const GenericPrimeOrderCurve* curve, std::array<W, 2 * N> z) {
 
  885         const auto& mod = curve->_params().field();
 
  886         const size_t words = curve->_params().words();
 
  890            r.data(), z.data(), mod.data(), words, curve->_params().field_p_dash(), ws.data(), ws.size());
 
  894      static StorageUnit from_rep(
const GenericPrimeOrderCurve* curve, StorageUnit z) {
 
  895         std::array<W, 2 * N> ze{};
 
  896         copy_mem(std::span{ze}.template first<N>(), z);
 
  897         return redc(curve, ze);
 
  900      static StorageUnit to_rep(
const GenericPrimeOrderCurve* curve, StorageUnit x) {
 
  901         std::array<W, 2 * N> z{};
 
  902         curve->_params().mul(z, x, curve->_params().field_monty_r2());
 
  903         return redc(curve, z);
 
  906      const GenericPrimeOrderCurve* m_curve;
 
  915class GenericAffinePoint final {
 
  917      GenericAffinePoint(
const GenericField& x, 
const GenericField& y) : m_x(x), m_y(y) {}
 
  919      explicit GenericAffinePoint(
const GenericPrimeOrderCurve* curve) :
 
  920            m_x(GenericField::zero(curve)), m_y(GenericField::zero(curve)) {}
 
  922      static GenericAffinePoint identity(
const GenericPrimeOrderCurve* curve) {
 
  923         return GenericAffinePoint(GenericField::zero(curve), GenericField::zero(curve));
 
  926      static GenericAffinePoint identity(
const GenericAffinePoint& pt) { 
return identity(pt.curve()); }
 
  928      CT::Choice is_identity()
 const { 
return x().is_zero() && y().is_zero(); }
 
  930      GenericAffinePoint negate()
 const { 
return GenericAffinePoint(x(), y().negate()); }
 
  935      void serialize_to(std::span<uint8_t> bytes)
 const {
 
  936         const size_t fe_bytes = curve()->_params().field_bytes();
 
  937         BOTAN_ARG_CHECK(bytes.size() == 1 + 2 * fe_bytes, 
"Buffer size incorrect");
 
  939         BufferStuffer 
pack(bytes);
 
  941         x().serialize_to(
pack.next(fe_bytes));
 
  942         y().serialize_to(
pack.next(fe_bytes));
 
  951      static auto ct_select(std::span<const GenericAffinePoint> pts, 
size_t idx) {
 
  953         auto result = GenericAffinePoint::identity(pts[0].curve());
 
  956         const size_t idx1 = 
static_cast<size_t>(idx - 1);
 
  957         for(
size_t i = 0; i != pts.size(); ++i) {
 
  959            result.conditional_assign(found, pts[i]);
 
  968      static GenericField x3_ax_b(
const GenericField& x) {
 
  969         return (x.square() + GenericField::curve_a(x.curve())) * x + GenericField::curve_b(x.curve());
 
  977      static std::optional<GenericAffinePoint> deserialize(
const GenericPrimeOrderCurve* curve,
 
  978                                                           std::span<const uint8_t> bytes) {
 
  979         const size_t fe_bytes = curve->_params().field_bytes();
 
  981         if(bytes.size() == 1 + 2 * fe_bytes && bytes[0] == 0x04) {
 
  982            auto x = GenericField::deserialize(curve, bytes.subspan(1, fe_bytes));
 
  983            auto y = GenericField::deserialize(curve, bytes.subspan(1 + fe_bytes, fe_bytes));
 
  986               const auto lhs = (*y).square();
 
  987               const auto rhs = GenericAffinePoint::x3_ax_b(*x);
 
  988               if((lhs == rhs).as_bool()) {
 
  989                  return GenericAffinePoint(*x, *y);
 
  992         } 
else if(bytes.size() == 1 + fe_bytes && (bytes[0] == 0x02 || bytes[0] == 0x03)) {
 
  995            if(
auto x = GenericField::deserialize(curve, bytes.subspan(1, fe_bytes))) {
 
  996               auto [y, is_square] = x3_ax_b(*x).sqrt();
 
  998               if(is_square.as_bool()) {
 
  999                  const auto flip_y = y_is_even != y.is_even();
 
 1000                  y.conditional_assign(flip_y, y.negate());
 
 1001                  return GenericAffinePoint(*x, y);
 
 1004         } 
else if(bytes.size() == 1 && bytes[0] == 0x00) {
 
 1006            return GenericAffinePoint::identity(curve);
 
 1015      const GenericField& x()
 const { 
return m_x; }
 
 1020      const GenericField& y()
 const { 
return m_y; }
 
 1025      void conditional_assign(CT::Choice cond, 
const GenericAffinePoint& pt) {
 
 1026         GenericField::conditional_assign(m_x, m_y, cond, pt.x(), pt.y());
 
 1029      const GenericPrimeOrderCurve* curve()
 const { 
return m_x.curve(); }
 
 1040class GenericProjectivePoint final {
 
 1042      typedef GenericProjectivePoint Self;
 
 1044      using FieldElement = GenericField;
 
 1049      static Self from_affine(
const GenericAffinePoint& pt) {
 
 1052         auto z = GenericField::one(x.curve());
 
 1055         GenericField::conditional_swap(pt.is_identity(), y, z);
 
 1056         return GenericProjectivePoint(x, y, z);
 
 1062      static Self identity(
const GenericPrimeOrderCurve* curve) {
 
 1063         return Self(GenericField::zero(curve), GenericField::one(curve), GenericField::zero(curve));
 
 1069      explicit GenericProjectivePoint(
const GenericPrimeOrderCurve* curve) :
 
 1070            m_x(GenericField::zero(curve)), m_y(GenericField::one(curve)), m_z(GenericField::zero(curve)) {}
 
 1075      GenericProjectivePoint(
const GenericField& x, 
const GenericField& y) :
 
 1076            m_x(x), m_y(y), m_z(GenericField::one(m_x.curve())) {}
 
 1081      GenericProjectivePoint(
const GenericField& x, 
const GenericField& y, 
const GenericField& z) :
 
 1082            m_x(x), m_y(y), m_z(z) {}
 
 1084      friend Self operator+(
const Self& a, 
const Self& b) { 
return Self::add(a, b); }
 
 1086      friend Self operator+(
const Self& a, 
const GenericAffinePoint& b) { 
return Self::add_mixed(a, b); }
 
 1088      friend Self operator+(
const GenericAffinePoint& a, 
const Self& b) { 
return Self::add_mixed(b, a); }
 
 1090      Self& operator+=(
const Self& other) {
 
 1091         (*this) = (*this) + other;
 
 1095      Self& operator+=(
const GenericAffinePoint& other) {
 
 1096         (*this) = (*this) + other;
 
 1100      CT::Choice is_identity()
 const { 
return z().is_zero(); }
 
 1105      static Self add_mixed(
const Self& a, 
const GenericAffinePoint& b) {
 
 1117      Self dbl_n(
size_t n)
 const {
 
 1118         if(curve()->_params().a_is_minus_3()) {
 
 1120         } 
else if(curve()->_params().a_is_zero()) {
 
 1123            const auto A = GenericField::curve_a(curve());
 
 1132         if(curve()->_params().a_is_minus_3()) {
 
 1134         } 
else if(curve()->_params().a_is_zero()) {
 
 1137            const auto A = GenericField::curve_a(curve());
 
 1145      Self negate()
 const { 
return Self(x(), y().negate(), z()); }
 
 1153      void randomize_rep(RandomNumberGenerator& rng) {
 
 1157         if(rng.is_seeded()) {
 
 1158            auto r = GenericField::random(curve(), rng);
 
 1160            auto r2 = r.square();
 
 1172      const GenericField& x()
 const { 
return m_x; }
 
 1177      const GenericField& y()
 const { 
return m_y; }
 
 1182      const GenericField& z()
 const { 
return m_z; }
 
 1184      const GenericPrimeOrderCurve* curve()
 const { 
return m_x.curve(); }
 
 1186      void _const_time_poison()
 const { 
CT::poison_all(m_x, m_y, m_z); }
 
 1196class GenericCurve final {
 
 1198      typedef GenericField FieldElement;
 
 1199      typedef GenericScalar Scalar;
 
 1200      typedef GenericAffinePoint AffinePoint;
 
 1201      typedef GenericProjectivePoint ProjectivePoint;
 
 1203      typedef word WordType;
 
 1207class GenericBlindedScalarBits final {
 
 1209      GenericBlindedScalarBits(
const GenericScalar& scalar, RandomNumberGenerator& rng, 
size_t wb) {
 
 1213         const auto& params = scalar.curve()->_params();
 
 1215         const size_t order_bits = params.order_bits();
 
 1216         const size_t blinder_bits = blinding_bits(order_bits);
 
 1218         const size_t mask_words = blinder_bits / WordInfo<word>::bits;
 
 1219         const size_t mask_bytes = mask_words * WordInfo<word>::bytes;
 
 1221         const size_t words = params.words();
 
 1224         if(rng.is_seeded()) {
 
 1225            rng.randomize(maskb);
 
 1227            auto sbytes = scalar.serialize<std::vector<uint8_t>>();
 
 1228            for(
size_t i = 0; i != sbytes.size(); ++i) {
 
 1229               maskb[i % mask_bytes] ^= sbytes[i];
 
 1233         std::array<word, PrimeOrderCurve::StorageWords> mask{};
 
 1234         load_le(mask.data(), maskb.data(), mask_words);
 
 1235         mask[mask_words - 1] |= WordInfo<word>::top_bit;
 
 1238         std::array<word, 2 * PrimeOrderCurve::StorageWords> mask_n{};
 
 1240         const auto sw = scalar.to_words();
 
 1243         params.mul(mask_n, mask, params.order());
 
 1244         bigint_add2(mask_n.data(), 2 * words, sw.data(), words);
 
 1246         std::reverse(mask_n.begin(), mask_n.end());
 
 1248         m_bits = order_bits + blinder_bits;
 
 1250         m_windows = (order_bits + blinder_bits + wb - 1) / wb;
 
 1253      size_t windows()
 const { 
return m_windows; }
 
 1255      size_t bits()
 const { 
return m_bits; }
 
 1257      size_t get_window(
size_t offset)
 const {
 
 1258         if(m_window_bits == 3) {
 
 1260         } 
else if(m_window_bits == 4) {
 
 1262         } 
else if(m_window_bits == 5) {
 
 1269      static size_t blinding_bits(
size_t order_bits) {
 
 1270         if(order_bits > 512) {
 
 1271            return blinding_bits(512);
 
 1274         const size_t wb = 
sizeof(
word) * 8;
 
 1275         return ((order_bits / 4 + wb - 1) / wb) * wb;
 
 1279      std::vector<uint8_t> m_bytes;
 
 1282      size_t m_window_bits;
 
 1285class GenericWindowedMul final {
 
 1287      static constexpr size_t WindowBits = VarPointWindowBits;
 
 1288      static constexpr size_t TableSize = (1 << WindowBits) - 1;
 
 1290      explicit GenericWindowedMul(
const GenericAffinePoint& pt) :
 
 1293      GenericProjectivePoint mul(
const GenericScalar& s, RandomNumberGenerator& rng) {
 
 1294         GenericBlindedScalarBits bits(s, rng, WindowBits);
 
 1300      AffinePointTable<GenericCurve> m_table;
 
 1303class GenericBaseMulTable final {
 
 1305      static constexpr size_t WindowBits = BasePointWindowBits;
 
 1307      static constexpr size_t WindowElements = (1 << WindowBits) - 1;
 
 1309      explicit GenericBaseMulTable(
const GenericAffinePoint& pt) :
 
 1310            m_table(
basemul_setup<GenericCurve, WindowBits>(pt, blinded_scalar_bits(*pt.curve()))) {}
 
 1312      GenericProjectivePoint mul(
const GenericScalar& s, RandomNumberGenerator& rng) {
 
 1313         GenericBlindedScalarBits scalar(s, rng, WindowBits);
 
 1318      static size_t blinded_scalar_bits(
const GenericPrimeOrderCurve& curve) {
 
 1319         const size_t order_bits = curve.order_bits();
 
 1320         return order_bits + GenericBlindedScalarBits::blinding_bits(order_bits);
 
 1323      std::vector<GenericAffinePoint> m_table;
 
 1326class GenericWindowedMul2 final {
 
 1328      static constexpr size_t WindowBits = Mul2PrecompWindowBits;
 
 1330      GenericWindowedMul2(
const GenericWindowedMul2& other) = 
delete;
 
 1331      GenericWindowedMul2(GenericWindowedMul2&& other) = 
delete;
 
 1332      GenericWindowedMul2& operator=(
const GenericWindowedMul2& other) = 
delete;
 
 1333      GenericWindowedMul2& operator=(GenericWindowedMul2&& other) = 
delete;
 
 1335      ~GenericWindowedMul2() = 
default;
 
 1337      GenericWindowedMul2(
const GenericAffinePoint& p, 
const GenericAffinePoint& q) :
 
 1338            m_table(
mul2_setup<GenericCurve, WindowBits>(p, q)) {}
 
 1340      GenericProjectivePoint mul2(
const GenericScalar& x, 
const GenericScalar& y, RandomNumberGenerator& rng)
 const {
 
 1341         GenericBlindedScalarBits x_bits(x, rng, WindowBits);
 
 1342         GenericBlindedScalarBits y_bits(y, rng, WindowBits);
 
 1347      AffinePointTable<GenericCurve> m_table;
 
 1352      static constexpr size_t WindowBits = Mul2PrecompWindowBits;
 
 1354      GenericVartimeWindowedMul2(
const GenericVartimeWindowedMul2& other) = 
delete;
 
 1355      GenericVartimeWindowedMul2(GenericVartimeWindowedMul2&& other) = 
delete;
 
 1356      GenericVartimeWindowedMul2& operator=(
const GenericVartimeWindowedMul2& other) = 
delete;
 
 1357      GenericVartimeWindowedMul2& operator=(GenericVartimeWindowedMul2&& other) = 
delete;
 
 1359      ~GenericVartimeWindowedMul2() 
override = 
default;
 
 1361      GenericVartimeWindowedMul2(
const GenericAffinePoint& p, 
const GenericAffinePoint& q) :
 
 1364      GenericProjectivePoint mul2_vartime(
const GenericScalar& x, 
const GenericScalar& y)
 const {
 
 1365         const auto x_bits = x.serialize<std::vector<uint8_t>>();
 
 1366         const auto y_bits = y.serialize<std::vector<uint8_t>>();
 
 1368         const auto& curve = m_table[0].curve();
 
 1369         auto accum = GenericProjectivePoint(curve);
 
 1371         const size_t order_bits = curve->order_bits();
 
 1373         const size_t windows = (order_bits + WindowBits - 1) / WindowBits;
 
 1375         for(
size_t i = 0; i != windows; ++i) {
 
 1380               accum = accum.dbl_n(WindowBits);
 
 1383            const size_t idx = (y_i << WindowBits) + x_i;
 
 1386               accum += m_table[idx - 1];
 
 1394      std::vector<GenericAffinePoint> m_table;
 
 1399      m_params(std::make_unique<GenericCurveParams>(p, a, b, base_x, base_y, order)) {}
 
 
 1403   m_basemul = std::make_unique<GenericBaseMulTable>(from_stash(
generator()));
 
 
 1407   return _params().order_bits();
 
 
 1411   return _params().order_bytes();
 
 
 1415   return _params().field_bytes();
 
 
 1421   return stash(m_basemul->mul(from_stash(scalar), rng));
 
 
 1427   auto pt_s = m_basemul->mul(from_stash(scalar), rng);
 
 1429   if(
auto s = GenericScalar::from_wide_bytes(
this, x_bytes)) {
 
 1432      throw Internal_Error(
"Failed to convert x coordinate to integer modulo scalar");
 
 
 1439   GenericWindowedMul pt_table(from_stash(pt));
 
 1440   return stash(pt_table.mul(from_stash(scalar), rng));
 
 
 1446   GenericWindowedMul pt_table(from_stash(pt));
 
 1447   auto pt_s = pt_table.mul(from_stash(scalar), rng);
 
 
 1453   return std::make_unique<GenericVartimeWindowedMul2>(from_stash(
generator()), from_stash(q));
 
 
 1458                                                                                     const Scalar& s2)
 const {
 
 1459   const auto& tbl = 
dynamic_cast<const GenericVartimeWindowedMul2&
>(tableb);
 
 1460   auto pt = tbl.mul2_vartime(from_stash(s1), from_stash(s2));
 
 1461   if(pt.is_identity().as_bool()) {
 
 
 1470   GenericWindowedMul2 table(from_stash(p), from_stash(q));
 
 1471   auto pt = table.mul2(from_stash(x), from_stash(y), rng);
 
 1472   if(pt.is_identity().as_bool()) {
 
 
 1482                                                         const Scalar& s2)
 const {
 
 1483   const auto& tbl = 
dynamic_cast<const GenericVartimeWindowedMul2&
>(tableb);
 
 1484   auto pt = tbl.mul2_vartime(from_stash(s1), from_stash(s2));
 
 1486   if(!pt.is_identity().as_bool()) {
 
 1487      const auto z2 = pt.z().square();
 
 1489      const auto v_bytes = from_stash(v).serialize<std::vector<uint8_t>>();
 
 1491      if(
auto fe_v = GenericField::deserialize(
this, v_bytes)) {
 
 1492         if((*fe_v * z2 == pt.x()).as_bool()) {
 
 1496         if(
_params().order_is_less_than_field()) {
 
 1497            const auto n = GenericField::from_words(
this, 
_params().order());
 
 1498            const auto neg_n = n.negate().to_words();
 
 1500            const auto vw = fe_v->to_words();
 
 1501            if(
bigint_ct_is_lt(vw.data(), vw.size(), neg_n.data(), neg_n.size()).as_bool()) {
 
 1502               return (((*fe_v + n) * z2) == pt.x()).as_bool();
 
 
 1518   const auto y2 = affine.y().square();
 
 1519   const auto x3_ax_b = GenericCurve::AffinePoint::x3_ax_b(affine.x());
 
 1520   const auto valid_point = affine.is_identity() || (y2 == x3_ax_b);
 
 1522   BOTAN_ASSERT(valid_point.as_bool(), 
"Computed point is on the curve");
 
 1524   return stash(affine);
 
 
 1528   return stash(GenericProjectivePoint::from_affine(from_stash(a)) + from_stash(b));
 
 
 1532   return stash(from_stash(pt).negate());
 
 
 1536   return from_stash(pt).is_identity().as_bool();
 
 
 1540   from_stash(pt).serialize_to(bytes);
 
 
 1545   from_stash(scalar).serialize_to(bytes);
 
 
 1549   std::span<const uint8_t> bytes)
 const {
 
 1550   if(
auto s = GenericScalar::deserialize(
this, bytes)) {
 
 1551      return stash(s.value());
 
 
 1558   std::span<const uint8_t> bytes)
 const {
 
 1559   if(
auto s = GenericScalar::from_wide_bytes(
this, bytes)) {
 
 1560      return stash(s.value());
 
 
 1567   std::span<const uint8_t> bytes)
 const {
 
 1568   if(
auto pt = GenericAffinePoint::deserialize(
this, bytes)) {
 
 1569      return stash(pt.value());
 
 
 1576   return stash(from_stash(a) + from_stash(b));
 
 
 1580   return stash(from_stash(a) - from_stash(b));
 
 
 1584   return stash(from_stash(a) * from_stash(b));
 
 
 1588   return stash(from_stash(s).
square());
 
 
 1592   return stash(from_stash(s).invert());
 
 
 1596   return stash(from_stash(s).invert_vartime());
 
 
 1600   return stash(from_stash(s).negate());
 
 
 1604   return from_stash(s).is_zero().as_bool();
 
 
 1608   return (from_stash(a) == from_stash(b)).as_bool();
 
 
 1612   return stash(GenericScalar::one(
this));
 
 
 1616   return stash(GenericScalar::random(
this, rng));
 
 
 1620   return Scalar::_create(shared_from_this(), s.stash_value());
 
 1623GenericScalar GenericPrimeOrderCurve::from_stash(
const PrimeOrderCurve::Scalar& s)
 const {
 
 1625   return GenericScalar(
this, s._value());
 
 1628PrimeOrderCurve::AffinePoint GenericPrimeOrderCurve::stash(
const GenericAffinePoint& pt)
 const {
 
 1629   auto x_w = pt.x().stash_value();
 
 1630   auto y_w = pt.y().stash_value();
 
 1631   return AffinePoint::_create(shared_from_this(), x_w, y_w);
 
 1636   auto x = GenericField(
this, pt._x());
 
 1637   auto y = GenericField(
this, pt._y());
 
 1638   return GenericAffinePoint(x, y);
 
 1642   auto x_w = pt.x().stash_value();
 
 1643   auto y_w = pt.y().stash_value();
 
 1644   auto z_w = pt.z().stash_value();
 
 1645   return ProjectivePoint::_create(shared_from_this(), x_w, y_w, z_w);
 
 1650   auto x = GenericField(
this, pt._x());
 
 1651   auto y = GenericField(
this, pt._y());
 
 1652   auto z = GenericField(
this, pt._z());
 
 1653   return GenericProjectivePoint(x, y, z);
 
 1657   std::function<
void(std::span<uint8_t>)> expand_message)
 const {
 
 1659   throw Not_Implemented(
"Hash to curve is not implemented for this curve");
 
 
 1663   std::function<
void(std::span<uint8_t>)> expand_message)
 const {
 
 1665   throw Not_Implemented(
"Hash to curve is not implemented for this curve");
 
 
 1668std::shared_ptr<const PrimeOrderCurve> PCurveInstance::from_params(
 
 1678   const size_t p_bits = p.
bits();
 
 1687   if(p_bits != 521 && p_bits != 239 && (p_bits < 128 || p_bits > 512 || p_bits % 32 != 0)) {
 
 1697   if(p_bits != order.
bits()) {
 
 1701   auto gpoc = std::make_shared<GenericPrimeOrderCurve>(p, a, b, base_x, base_y, order);
 
 1711   gpoc->_precompute_base_mul();
 
#define BOTAN_ASSERT_NOMSG(expr)
 
#define BOTAN_DEBUG_ASSERT(expr)
 
#define BOTAN_STATE_CHECK(expr)
 
#define BOTAN_ARG_CHECK(expr, msg)
 
#define BOTAN_ASSERT(expr, assertion_made)
 
#define BOTAN_ASSERT_UNREACHABLE()
 
static constexpr Choice from_int(T v)
 
static constexpr Choice no()
 
static constexpr Mask< T > from_choice(Choice c)
 
static constexpr Mask< T > is_equal(T x, T y)
 
Scalar random_scalar(RandomNumberGenerator &rng) const override
 
AffinePoint point_negate(const AffinePoint &pt) const override
 
bool mul2_vartime_x_mod_order_eq(const PrecomputedMul2Table &tableb, const Scalar &v, const Scalar &s1, const Scalar &s2) const override
 
ProjectivePoint mul_by_g(const Scalar &scalar, RandomNumberGenerator &rng) const override
 
std::optional< ProjectivePoint > mul_px_qy(const AffinePoint &p, const Scalar &x, const AffinePoint &q, const Scalar &y, RandomNumberGenerator &rng) const override
 
ProjectivePoint hash_to_curve_ro(std::function< void(std::span< uint8_t >)> expand_message) const override
 
void serialize_scalar(std::span< uint8_t > bytes, const Scalar &scalar) const override
 
Scalar scalar_square(const Scalar &s) const override
Scalar squaring.
 
std::optional< Scalar > deserialize_scalar(std::span< const uint8_t > bytes) const override
 
void _precompute_base_mul()
 
std::optional< Scalar > scalar_from_wide_bytes(std::span< const uint8_t > bytes) const override
 
std::unique_ptr< const PrecomputedMul2Table > mul2_setup_g(const AffinePoint &q) const override
Setup a table for 2-ary multiplication where the first point is the generator.
 
GenericPrimeOrderCurve(const BigInt &p, const BigInt &a, const BigInt &b, const BigInt &base_x, const BigInt &base_y, const BigInt &order)
 
AffinePoint generator() const override
Return the standard generator.
 
const GenericCurveParams & _params() const
 
AffinePoint hash_to_curve_nu(std::function< void(std::span< uint8_t >)> expand_message) const override
 
ProjectivePoint point_add(const AffinePoint &a, const AffinePoint &b) const override
 
Scalar scalar_mul(const Scalar &a, const Scalar &b) const override
Scalar multiplication.
 
Scalar scalar_invert(const Scalar &s) const override
Scalar inversion.
 
std::optional< AffinePoint > deserialize_point(std::span< const uint8_t > bytes) const override
 
std::optional< ProjectivePoint > mul2_vartime(const PrecomputedMul2Table &tableb, const Scalar &x, const Scalar &y) const override
 
void serialize_point(std::span< uint8_t > bytes, const AffinePoint &pt) const override
 
bool scalar_is_zero(const Scalar &s) const override
Test if scalar is zero.
 
Scalar scalar_negate(const Scalar &s) const override
Scalar negation.
 
secure_vector< uint8_t > mul_x_only(const AffinePoint &pt, const Scalar &scalar, RandomNumberGenerator &rng) const override
 
size_t field_element_bytes() const override
 
ProjectivePoint mul(const AffinePoint &pt, const Scalar &scalar, RandomNumberGenerator &rng) const override
 
Scalar scalar_one() const override
 
Scalar base_point_mul_x_mod_order(const Scalar &scalar, RandomNumberGenerator &rng) const override
 
Scalar scalar_invert_vartime(const Scalar &s) const override
Scalar inversion (variable time)
 
bool affine_point_is_identity(const AffinePoint &pt) const override
 
size_t scalar_bytes() const override
Return the byte length of the scalar element.
 
Scalar scalar_sub(const Scalar &a, const Scalar &b) const override
Scalar subtraction.
 
AffinePoint point_to_affine(const ProjectivePoint &pt) const override
 
bool scalar_equal(const Scalar &a, const Scalar &b) const override
Test if two scalars are equal.
 
Scalar scalar_add(const Scalar &a, const Scalar &b) const override
Scalar addition.
 
size_t order_bits() const override
Return the bit length of the group order.
 
static AffinePoint _create(CurvePtr curve, StorageUnit x, StorageUnit y)
 
static constexpr size_t StorageWords
Number of words used to store MaximumByteLength.
 
std::array< word, StorageWords > StorageUnit
 
constexpr void pack(const Polynomial< PolyTrait, D > &p, BufferStuffer &stuffer, MapFnT map)
 
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 to_affine_batch(std::span< const typename C::ProjectivePoint > projective)
 
constexpr auto bigint_add3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
 
auto to_affine_x(const typename C::ProjectivePoint &pt)
 
constexpr auto bytes_to_words(std::span< const uint8_t, L > bytes)
 
constexpr W shift_left(std::array< W, N > &x)
 
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 size_t read_window_bits(std::span< const W, N > words, size_t offset)
 
void bigint_comba_sqr4(word z[8], const word x[4])
 
void bigint_comba_sqr6(word z[12], const word x[6])
 
constexpr ProjectivePoint dbl_a_minus_3(const ProjectivePoint &pt)
 
void bigint_comba_mul4(word z[8], const word x[4], const word y[4])
 
BigInt square(const BigInt &x)
 
void bigint_sqr(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, word workspace[], size_t ws_size)
 
C::ProjectivePoint mul2_exec(const AffinePointTable< C > &table, const BlindedScalar &x, const BlindedScalar &y, RandomNumberGenerator &rng)
 
constexpr auto bigint_sub3(W z[], const W x[], size_t x_size, const W y[], size_t y_size) -> W
 
void bigint_mul(word z[], size_t z_size, const word x[], size_t x_size, size_t x_sw, const word y[], size_t y_size, size_t y_sw, word workspace[], size_t ws_size)
 
void bigint_comba_mul6(word z[12], const word x[6], const word y[6])
 
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)
 
constexpr void bigint_shl1(W x[], size_t x_size, size_t x_words, size_t shift)
 
constexpr auto to_affine(const typename C::ProjectivePoint &pt)
 
constexpr ProjectivePoint point_add_mixed(const ProjectivePoint &a, const AffinePoint &b, const FieldElement &one)
 
void bigint_monty_redc(word r[], const word z[], const word p[], size_t p_size, word p_dash, word ws[], size_t ws_size)
 
constexpr W bigint_cnd_add(W cnd, W x[], const W y[], size_t size)
 
constexpr void bigint_monty_maybe_sub(size_t N, W z[], W x0, const W x[], const W p[])
 
void bigint_comba_mul9(word z[18], const word x[9], const word y[9])
 
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 >
 
std::vector< T, secure_allocator< T > > secure_vector
 
void bigint_comba_sqr8(word z[16], const word x[8])
 
void bigint_comba_sqr9(word z[18], const word x[9])
 
constexpr ProjectivePoint dbl_generic(const ProjectivePoint &pt, const FieldElement &A)
 
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
 
void bigint_comba_mul8(word z[16], const word x[8], const word y[8])
 
constexpr auto store_be(ParamTs &&... params)
 
constexpr void clear_mem(T *ptr, size_t n)
 
constexpr auto load_be(ParamTs &&... params)
 
constexpr W shift_right(std::array< W, N > &x)