Coverage Report

Created: 2025-04-11 06:34

/src/botan/build/include/internal/botan/internal/curve448_gf.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
* X448 Gf Modulo 2^448 - 2^224 - 1
3
* (C) 2024 Jack Lloyd
4
*     2024 Fabian Albert - Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
#ifndef BOTAN_CURVE_448_GF_H_
9
#define BOTAN_CURVE_448_GF_H_
10
11
#include <botan/mem_ops.h>
12
#include <botan/types.h>
13
#include <botan/internal/bit_ops.h>
14
15
#include <array>
16
#include <span>
17
18
namespace Botan {
19
20
constexpr size_t BYTES_448 = ceil_tobytes(448);
21
/* uint64_t words to store a 448 bit value */
22
constexpr size_t WORDS_448 = 7;
23
24
/**
25
 * This class represents a GF element in the field GF(2^448 - 2^224 - 1). Computations are
26
 * performed using optimized operations as defined in the paper:
27
 * "Reduction Modulo 2^448 - 2^224 - 1" by Kaushik Nath and Palash Sarkar
28
 * (https://eprint.iacr.org/2019/1304).
29
 *
30
 * The representation of the field element is a 448-bit uint, stored in little-endian order
31
 * as 7*64bit words. Note that the internal representation is not necessarily canonical, i.e.
32
 * the value might be larger than the prime modulus. When calling the to_bytes() method, the
33
 * canonical representation is returned.
34
 */
35
class Gf448Elem final {
36
   public:
37
      /**
38
       * @brief Construct a GF element from a 448-bit integer gives as 56 bytes @p x in
39
       * little-endian order.
40
       */
41
      Gf448Elem(std::span<const uint8_t, BYTES_448> x);
42
43
      /**
44
       * @brief Construct a GF element from a 448-bit integer gives as 7 uint64_t words @p x in
45
       * little-endian order.
46
       */
47
320
      Gf448Elem(std::span<const uint64_t, WORDS_448> data) { copy_mem(m_x, data); }
48
49
      /**
50
       * @brief Construct a GF element by passing the least significant 64 bits as a word.
51
       * All other become zero.
52
       */
53
      Gf448Elem(uint64_t least_sig_word);
54
55
      /**
56
       * @brief Store the canonical representation of the GF element as 56 bytes in little-endian
57
       * order.
58
       *
59
       * @param out The 56 byte output buffer.
60
       */
61
      void to_bytes(std::span<uint8_t, BYTES_448> out) const;
62
63
      /**
64
       * @brief Return the canonical representation of the GF element as 56 bytes in little-endian
65
       * order.
66
       */
67
      std::array<uint8_t, BYTES_448> to_bytes() const;
68
69
      /**
70
       * @brief Swap this and other if b == true. Constant time for any b.
71
       */
72
      void ct_cond_swap(bool b, Gf448Elem& other);
73
74
      /**
75
       * @brief Set this to @p other if b is true. Constant time for any b.
76
       */
77
      void ct_cond_assign(bool b, const Gf448Elem& other);
78
79
      Gf448Elem operator+(const Gf448Elem& other) const;
80
81
      Gf448Elem operator-(const Gf448Elem& other) const;
82
83
      Gf448Elem operator-() const;
84
85
      Gf448Elem operator*(const Gf448Elem& other) const;
86
87
      Gf448Elem operator/(const Gf448Elem& other) const;
88
89
      bool operator==(const Gf448Elem& other) const;
90
91
0
      bool operator!=(const Gf448Elem& other) const = default;
92
93
      /**
94
       * @brief Return true iff this element is zero. Constant time.
95
       */
96
      bool is_zero() const;
97
98
      /**
99
       * @brief Return true iff this element is odd. Constant time.
100
       */
101
      bool is_odd() const;
102
103
      /**
104
       * @brief Accessor to the internal words of the GF element.
105
       *
106
       * Note that the internal representation is not necessarily canonical, i.e.
107
       * the value might be larger than the prime modulus.
108
       */
109
5.31M
      std::span<uint64_t, WORDS_448> words() { return m_x; }
110
111
      /**
112
       * @brief Constant accessor to the internal words of the GF element.
113
       *
114
       * Note that the internal representation is not necessarily canonical, i.e.
115
       * the value might be larger than the prime modulus.
116
       */
117
5.31M
      std::span<const uint64_t, WORDS_448> words() const { return m_x; }
118
119
      /**
120
       * @brief Given 56 bytes, checks that the (little endian) number from this
121
       * bytes is a valid GF element, i.e. is smaller than the prime modulus.
122
       */
123
      static bool bytes_are_canonical_representation(std::span<const uint8_t, BYTES_448> x);
124
125
   private:
126
      std::array<uint64_t, WORDS_448> m_x;
127
};
128
129
/**
130
 * @brief Computes elem^2. Faster than operator*.
131
 */
132
Gf448Elem square(const Gf448Elem& elem);
133
134
/**
135
 * @brief Compute the root of @p elem in the field.
136
 *
137
 * The root of a in GF(p) is computed as r = a^((p+1)/4) mod p.
138
 * Note that the root is not unique, i.e. r and p-r are both roots.
139
 *
140
 * @return GfPElem The root of this element.
141
 */
142
Gf448Elem root(const Gf448Elem& elem);
143
144
}  // namespace Botan
145
146
#endif  // BOTAN_CURVE_448_GF_H_