Coverage Report

Created: 2026-08-05 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/build/include/public/botan/ec_scalar.h
Line
Count
Source
1
/*
2
* (C) 2024 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#ifndef BOTAN_EC_SCALAR_H_
8
#define BOTAN_EC_SCALAR_H_
9
10
#include <botan/concepts.h>
11
#include <botan/types.h>
12
#include <memory>
13
#include <optional>
14
#include <span>
15
#include <string_view>
16
#include <vector>
17
18
namespace Botan {
19
20
class BigInt;
21
class RandomNumberGenerator;
22
class EC_Group;
23
class EC_Scalar_Data;
24
25
/**
26
* Represents an integer modulo the prime group order of an elliptic curve
27
*/
28
class BOTAN_PUBLIC_API(3, 6) EC_Scalar final {
29
   public:
30
      /**
31
      * Deserialize a scalar
32
      *
33
      * The span must be exactly bytes() long; this function does not accept
34
      * either short inputs (eg [1] to encode the integer 1) or inputs with
35
      * excess leading zero bytes.
36
      *
37
      * Returns nullopt if the length is incorrect or if the integer is not
38
      * within the range [0,n) where n is the group order.
39
      */
40
      static std::optional<EC_Scalar> deserialize(const EC_Group& group, std::span<const uint8_t> bytes);
41
42
      /**
43
      * Convert a bytestring to an EC_Scalar
44
      *
45
      * This uses the truncation rules from ECDSA
46
      */
47
      static EC_Scalar from_bytes_with_trunc(const EC_Group& group, std::span<const uint8_t> bytes);
48
49
      /**
50
      * Convert a bytestring to an EC_Scalar
51
      *
52
      * This reduces the bytes modulo the group order. The input can be at most
53
      * 2*bytes() long
54
      */
55
      static EC_Scalar from_bytes_mod_order(const EC_Group& group, std::span<const uint8_t> bytes);
56
57
      /**
58
      * Hash to scalar following RFC 9380
59
      *
60
      * This requires XMD. Unlike hash2curve, any group is supported
61
      */
62
      static EC_Scalar hash(const EC_Group& group,
63
                            std::string_view hash_fn,
64
                            std::span<const uint8_t> input,
65
                            std::span<const uint8_t> domain_sep);
66
67
      /**
68
      * Convert a bytestring to an EC_Scalar
69
      *
70
      * This is similar to deserialize but instead of returning nullopt if the input
71
      * is invalid, it will throw an exception.
72
      */
73
      BOTAN_DEPRECATED("Use EC_Scalar::deserialize") EC_Scalar(const EC_Group& group, std::span<const uint8_t> bytes);
74
75
      /**
76
      * Deserialize a pair of scalars
77
      *
78
      * Returns nullopt if the length is not 2*bytes(), or if either scalar is
79
      * out of range or zero
80
      */
81
      static std::optional<std::pair<EC_Scalar, EC_Scalar>> deserialize_pair(const EC_Group& group,
82
                                                                             std::span<const uint8_t> bytes);
83
84
      /**
85
      * Return a new random scalar value
86
      */
87
      static EC_Scalar random(const EC_Group& group, RandomNumberGenerator& rng);
88
89
      /**
90
      * Return the scalar value 1
91
      */
92
      static EC_Scalar one(const EC_Group& group);
93
94
      /**
95
      * Convert from the argument BigInt to a EC_Scalar
96
      *
97
      * Throws an exception if the provided bn is negative or too large
98
      */
99
      static EC_Scalar from_bigint(const EC_Group& group, const BigInt& bn);
100
101
      /**
102
      * Compute the elliptic curve scalar multiplication (g*k) where g is the
103
      * standard base point on the curve. Then extract the x coordinate of
104
      * the resulting point, and reduce it modulo the group order.
105
      */
106
      static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng);
107
108
      /**
109
      * Compute the elliptic curve scalar multiplication (g*k) where g is the
110
      * standard base point on the curve. Then extract the x coordinate of
111
      * the resulting point, and reduce it modulo the group order.
112
      *
113
      * @param scalar the scalar k to multiply the base point by
114
      * @param rng a random number generator, used for blinding
115
      * @return the x coordinate of g*k reduced modulo the group order
116
      */
117
      BOTAN_DEPRECATED("Use version without workspace arg")
118
      static EC_Scalar
119
0
         gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& /*ws*/) {
120
0
         return EC_Scalar::gk_x_mod_order(scalar, rng);
121
0
      }
122
123
      /**
124
      * Return the byte size of this scalar
125
      */
126
      size_t bytes() const;
127
128
      /**
129
      * Write the fixed length serialization to bytes
130
      *
131
      * The provided span must be exactly bytes() long
132
      */
133
      void serialize_to(std::span<uint8_t> bytes) const;
134
135
      /**
136
      * Return the bytes of the encoded scalar in a container
137
      */
138
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
139
0
      T serialize() const {
140
0
         T s(this->bytes());
141
0
         this->serialize_to(s);
142
0
         return s;
143
0
      }
144
145
      /**
146
      * Write the fixed length serialization to bytes
147
      *
148
      * The provided span must be exactly 2*bytes() long
149
      */
150
      static void serialize_pair_to(std::span<uint8_t> bytes, const EC_Scalar& r, const EC_Scalar& s);
151
152
      /**
153
      * Return the bytes of the encoded scalar in a container
154
      */
155
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
156
0
      static T serialize_pair(const EC_Scalar& r, const EC_Scalar& s) {
157
0
         T bytes(r.bytes() + s.bytes());
158
0
         serialize_pair_to(bytes, r, s);
159
0
         return bytes;
160
0
      }
161
162
      /**
163
      * Return true if this EC_Scalar is zero
164
      */
165
      bool is_zero() const;
166
167
      /**
168
      * Return true if this EC_Scalar is not zero
169
      */
170
14.3k
      bool is_nonzero() const { return !is_zero(); }
171
172
      /**
173
      * Constant time modular inversion
174
      *
175
      * Return the modular inverse of this EC_Scalar
176
      *
177
      * If *this is zero, then invert() returns zero
178
      */
179
      EC_Scalar invert() const;
180
181
      /**
182
      * Variable time modular inversion
183
      *
184
      * Return the modular inverse of this EC_Scalar
185
      *
186
      * If *this is zero, then invert_vartime() returns zero
187
      */
188
      EC_Scalar invert_vartime() const;
189
190
      /**
191
      * Return the additive inverse of *this
192
      */
193
      EC_Scalar negate() const;
194
195
      /**
196
      * Scalar addition (modulo group order)
197
      */
198
      EC_Scalar add(const EC_Scalar& x) const;
199
200
      /**
201
      * Scalar subtraction (modulo group order)
202
      */
203
      EC_Scalar sub(const EC_Scalar& x) const;
204
205
      /**
206
      * Scalar multiplication (modulo group order)
207
      */
208
      EC_Scalar mul(const EC_Scalar& x) const;
209
210
      /**
211
      * Assign a scalar
212
      */
213
      void assign(const EC_Scalar& x);
214
215
      /**
216
      * Equivalent to assigning a zero value, but also does so in a way that
217
      * attempts to ensure the write always occurs even if a compiler can deduce
218
      * the assignment is otherwise unnecessary.
219
      */
220
      void zeroize();
221
222
      /**
223
      * Set *this to its own square modulo the group order
224
      */
225
      void square_self();
226
227
      /**
228
      * Test for equality
229
      */
230
      bool is_eq(const EC_Scalar& x) const;
231
232
      /**
233
      * Convert *this to a BigInt
234
      */
235
      BigInt to_bigint() const;
236
237
13.6k
      friend EC_Scalar operator+(const EC_Scalar& x, const EC_Scalar& y) { return x.add(y); }
238
239
2.05k
      friend EC_Scalar operator-(const EC_Scalar& x, const EC_Scalar& y) { return x.sub(y); }
240
241
21.1k
      friend EC_Scalar operator*(const EC_Scalar& x, const EC_Scalar& y) { return x.mul(y); }
242
243
24.2k
      friend bool operator==(const EC_Scalar& x, const EC_Scalar& y) { return x.is_eq(y); }
244
245
      /**
246
      * Copy constructor
247
      * @param other the scalar to copy
248
      */
249
      EC_Scalar(const EC_Scalar& other);
250
251
      /**
252
      * Move constructor
253
      * @param other the scalar to move from
254
      */
255
      EC_Scalar(EC_Scalar&& other) noexcept;
256
257
      /**
258
      * Copy assignment
259
      * @param other the scalar to copy
260
      * @return reference to this
261
      */
262
      EC_Scalar& operator=(const EC_Scalar& other);
263
264
      /**
265
      * Move assignment
266
      * @param other the scalar to move from
267
      * @return reference to this
268
      */
269
      EC_Scalar& operator=(EC_Scalar&& other) noexcept;
270
271
      ~EC_Scalar();
272
273
      /**
274
      * For internal use only
275
      * @return the inner representation of this scalar
276
      */
277
30.1k
      const EC_Scalar_Data& _inner() const { return inner(); }
278
279
      /**
280
      * For internal use only
281
      * @param inner the inner representation to wrap
282
      * @return a scalar wrapping the provided inner representation
283
      */
284
      static EC_Scalar _from_inner(std::unique_ptr<EC_Scalar_Data> inner);
285
286
   private:
287
      friend class EC_AffinePoint;
288
289
      explicit EC_Scalar(std::unique_ptr<EC_Scalar_Data> scalar);
290
291
359k
      const EC_Scalar_Data& inner() const { return *m_scalar; }
292
293
      std::unique_ptr<EC_Scalar_Data> m_scalar;
294
};
295
296
}  // namespace Botan
297
298
#endif