9#include <botan/internal/ed448_internal.h> 
   11#include <botan/exceptn.h> 
   12#include <botan/types.h> 
   13#include <botan/internal/ct_utils.h> 
   14#include <botan/internal/loadstor.h> 
   15#include <botan/internal/shake_xof.h> 
   16#include <botan/internal/stl_util.h> 
   21constexpr uint64_t MINUS_D = 39081;
 
   23std::vector<uint8_t> dom4(uint8_t x, std::span<const uint8_t> y) {
 
   32                                       store_le(
static_cast<uint8_t
>(y.size())),
 
   37std::array<uint8_t, 2 * ED448_LEN> shake(
bool f, std::span<const uint8_t> context, Ts... xs) {
 
   39   shake_xof.update(dom4(
static_cast<uint8_t
>(f), context));
 
   40   (shake_xof.update(std::span(xs)), ...);
 
   41   std::array<uint8_t, 2 * ED448_LEN> res{};
 
   42   shake_xof.output(res);
 
   46std::pair<std::span<const uint8_t, 57>, std::span<const uint8_t, 57>> split(std::span<const uint8_t, 114> arr) {
 
   48   auto lhs = bs.take<57>();
 
   49   auto rhs = bs.take<57>();
 
   59   std::array<uint8_t, ED448_LEN> raw_s{};
 
   60   shake_xof.output(raw_s);
 
   80   if((enc.back() & 0x7F) != 0) {  
 
   81      throw Decoding_Error(
"Ed448 point has unacceptable x-distinguisher");
 
   83   const bool x_distinguisher = enc.back() != 0;
 
   84   const auto y_data = std::span(enc).first<56>();
 
  106   if(v * 
square(maybe_x) != u) {
 
  112   if(maybe_x.is_zero() && x_distinguisher) {
 
  115   bool maybe_x_parity = maybe_x.
is_odd();
 
  116   std::array<uint64_t, WORDS_448> x_data{};
 
  118      .select_n(x_data.data(), maybe_x.words().data(), (-maybe_x).words().data(), 
WORDS_448);
 
 
  124   constexpr std::array<const uint64_t, WORDS_448> 
x = {0x2626a82bc70cc05e,
 
  131   constexpr std::array<const uint64_t, WORDS_448> 
y = {0x9808795bf230fa14,
 
 
  142   std::array<uint8_t, ED448_LEN> res_buf = {0};
 
  149   y().
to_bytes(std::span(res_buf).first<56>());
 
  153   res_buf.back() = (
static_cast<uint8_t
>(
x().
is_odd()) << 7);
 
 
  167   const Gf448Elem H = (m_x + m_y) * (other.m_x + other.m_y);
 
  168   const Gf448Elem X3 = A * F * (H - C - D);
 
 
  197   for(int16_t i = 445; i >= 0; --i) {
 
  198      res = res.double_point();
 
  200      auto add_sum = res + *
this;
 
  201      res.ct_conditional_assign(s.
get_bit(i), add_sum);
 
 
  211   return (mask_x & mask_y).as_bool();
 
 
  215   m_x.ct_cond_assign(cond, other.m_x);
 
  216   m_y.ct_cond_assign(cond, other.m_y);
 
  217   m_z.ct_cond_assign(cond, other.m_z);
 
 
  228   shake_xof.update(sk);
 
  230   const Scalar448 s = scalar_from_xof(shake_xof);
 
 
  237std::array<uint8_t, 2 * ED448_LEN> 
sign_message(std::span<const uint8_t, ED448_LEN> sk,
 
  238                                                std::span<const uint8_t, ED448_LEN> pk,
 
  240                                                std::span<const uint8_t> context,
 
  241                                                std::span<const uint8_t> msg) {
 
  252   shake_xof.update(sk);
 
  253   const Scalar448 s = scalar_from_xof(shake_xof);
 
  254   std::array<uint8_t, ED448_LEN> prefix{};
 
  255   shake_xof.output(prefix);
 
  260   const Scalar448 r(shake(pgflag, context, prefix, msg));
 
  267   const Scalar448 k(shake(pgflag, context, big_r, pk, msg));
 
  270   const auto big_s = r + k * s;  
 
  274   std::array<uint8_t, 2 * ED448_LEN> sig{};
 
 
  285                      std::span<const uint8_t> context,
 
  286                      std::span<const uint8_t> sig,
 
  287                      std::span<const uint8_t> msg) {
 
  300   const auto [big_r_bytes, big_s_bytes] = split(sig.first<2 * 
ED448_LEN>());
 
  309   const Scalar448 k(shake(phflag, context, big_r_bytes, pk, msg));
 
 
#define BOTAN_ARG_CHECK(expr, msg)
 
#define BOTAN_ASSERT(expr, assertion_made)
 
Helper class to ease in-place marshalling of concatenated fixed-length values.
 
constexpr void append(std::span< const uint8_t > buffer)
 
constexpr bool full() const
 
static constexpr Mask< T > expand_bool(bool v)
 
Representation of a point on the Ed448 curve.
 
Gf448Elem y() const
Getter for point coordinate y.
 
static Ed448Point identity()
Return the identity element.
 
Ed448Point(const Gf448Elem &x, const Gf448Elem &y, const Gf448Elem &z)
Create a point from its projective coordinates X, Y, Z.
 
static Ed448Point decode(std::span< const uint8_t, ED448_LEN > enc)
Decode a point from its 57-byte encoding (RFC 8032 5.2.3)
 
Ed448Point scalar_mul(const Scalar448 &scalar) const
Scalar multiplication.
 
Ed448Point double_point() const
Double a point (RFC 8032 5.2.4)
 
void ct_conditional_assign(bool cond, const Ed448Point &other)
Assign other to this if cond is true (constant time)
 
static Ed448Point base_point()
Create the curve's base point ('B' in RFC 8032 5.2)
 
bool operator==(const Ed448Point &other) const
Check if two points are equal (constant time)
 
Ed448Point operator+(const Ed448Point &other) const
Add two points (RFC 8032 5.2.4)
 
Gf448Elem x() const
Getter for point coordinate x.
 
std::array< uint8_t, ED448_LEN > encode() const
Encode the point to its 57-byte representation (RFC 8032 5.2.2)
 
void to_bytes(std::span< uint8_t, BYTES_448 > out) const
Store the canonical representation of the GF element as 56 bytes in little-endian order.
 
static bool bytes_are_canonical_representation(std::span< const uint8_t, BYTES_448 > x)
Given 56 bytes, checks that the (little endian) number from this bytes is a valid GF element,...
 
bool is_odd() const
Return true iff this element is odd. Constant time.
 
Representation of a scalar for X448.
 
static bool bytes_are_reduced(std::span< const uint8_t > x)
 
bool get_bit(size_t i) const
Access the i-th bit of the scalar. From 0 (lsb) to 445 (msb).
 
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
 
BigInt operator*(const BigInt &x, const BigInt &y)
 
std::array< uint8_t, ED448_LEN > create_pk_from_sk(std::span< const uint8_t, ED448_LEN > sk)
Create a public key point from a secret key (RFC 8032 5.2.5)
 
BigInt square(const BigInt &x)
 
constexpr size_t ED448_LEN
 
constexpr auto store_le(ParamTs &&... params)
 
constexpr auto concat(Rs &&... ranges)
 
bool verify_signature(std::span< const uint8_t, ED448_LEN > pk, bool phflag, std::span< const uint8_t > context, std::span< const uint8_t > sig, std::span< const uint8_t > msg)
Verify a signature(RFC 8032 5.2.7)
 
constexpr size_t WORDS_448
 
std::array< uint8_t, 2 *ED448_LEN > sign_message(std::span< const uint8_t, ED448_LEN > sk, std::span< const uint8_t, ED448_LEN > pk, bool pgflag, std::span< const uint8_t > context, std::span< const uint8_t > msg)
Sign a message using a keypair (RFC 8032 5.2.6)