Coverage Report

Created: 2024-11-29 06:10

/src/botan/build/include/public/botan/ec_scalar.h
Line
Count
Source (jump to first uncovered line)
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
13
#include <optional>
14
#include <span>
15
#include <vector>
16
17
namespace Botan {
18
19
class BigInt;
20
class RandomNumberGenerator;
21
class EC_Group;
22
class EC_Group_Data;
23
class EC_Scalar_Data;
24
25
/**
26
* Represents an integer modulo the prime group order of an elliptic curve
27
*/
28
class BOTAN_UNSTABLE_API 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
      * Convert a bytestring to an EC_Scalar
59
      *
60
      * This is similar to deserialize but instead of returning nullopt if the input
61
      * is invalid, it will throw an exception.
62
      */
63
      EC_Scalar(const EC_Group& group, std::span<const uint8_t> bytes);
64
65
      /**
66
      * Deserialize a pair of scalars
67
      *
68
      * Returns nullopt if the length is not 2*bytes(), or if either scalar is
69
      * out of range or zero
70
      */
71
      static std::optional<std::pair<EC_Scalar, EC_Scalar>> deserialize_pair(const EC_Group& group,
72
                                                                             std::span<const uint8_t> bytes);
73
74
      /**
75
      * Return a new random scalar value
76
      */
77
      static EC_Scalar random(const EC_Group& group, RandomNumberGenerator& rng);
78
79
      /**
80
      * Return the scalar value 1
81
      */
82
      static EC_Scalar one(const EC_Group& group);
83
84
      /**
85
      * Convert from the argument BigInt to a EC_Scalar
86
      *
87
      * Throws an exception if the provided bn is negative or too large
88
      */
89
      static EC_Scalar from_bigint(const EC_Group& group, const BigInt& bn);
90
91
      /**
92
      * Compute the elliptic curve scalar multiplication (g*k) where g is the
93
      * standard base point on the curve. Then extract the x coordinate of
94
      * the resulting point, and reduce it modulo the group order.
95
      *
96
      * Workspace argument is transitional
97
      */
98
      static EC_Scalar gk_x_mod_order(const EC_Scalar& scalar, RandomNumberGenerator& rng, std::vector<BigInt>& ws);
99
100
      /**
101
      * Return the byte size of this scalar
102
      */
103
      size_t bytes() const;
104
105
      /**
106
      * Write the fixed length serialization to bytes
107
      *
108
      * The provided span must be exactly bytes() long
109
      */
110
      void serialize_to(std::span<uint8_t> bytes) const;
111
112
      /**
113
      * Return the bytes of the encoded scalar in a container
114
      */
115
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
116
0
      T serialize() const {
117
0
         T s(this->bytes());
118
0
         this->serialize_to(s);
119
0
         return s;
120
0
      }
121
122
      /**
123
      * Write the fixed length serialization to bytes
124
      *
125
      * The provided span must be exactly bytes() long
126
      */
127
      static void serialize_pair_to(std::span<uint8_t> bytes, const EC_Scalar& r, const EC_Scalar& s);
128
129
      /**
130
      * Return the bytes of the encoded scalar in a container
131
      */
132
      template <concepts::resizable_byte_buffer T = std::vector<uint8_t>>
133
0
      static T serialize_pair(const EC_Scalar& r, const EC_Scalar& s) {
134
0
         T bytes(r.bytes() + s.bytes());
135
0
         serialize_pair_to(bytes, r, s);
136
0
         return bytes;
137
0
      }
138
139
      /**
140
      * Return true if this EC_Scalar is zero
141
      */
142
      bool is_zero() const;
143
144
      /**
145
      * Return true if this EC_Scalar is not zero
146
      */
147
1.09k
      bool is_nonzero() const { return !is_zero(); }
148
149
      /**
150
      * Return the modular inverse of this EC_Scalar
151
      *
152
      * If *this is zero, then invert() returns zero
153
      */
154
      EC_Scalar invert() const;
155
156
      /**
157
      */
158
      EC_Scalar negate() const;
159
160
      /**
161
      * Scalar addition (modulo p)
162
      */
163
      EC_Scalar add(const EC_Scalar& x) const;
164
165
      /**
166
      * Scalar subtraction (modulo p)
167
      */
168
      EC_Scalar sub(const EC_Scalar& x) const;
169
170
      /**
171
      * Scalar multiplication (modulo p)
172
      */
173
      EC_Scalar mul(const EC_Scalar& x) const;
174
175
      /**
176
      * Assign a scalar
177
      */
178
      void assign(const EC_Scalar& x);
179
180
      /**
181
      * Set *this to its own square modulo p
182
      */
183
      void square_self();
184
185
      /**
186
      * Test for equality
187
      */
188
      bool is_eq(const EC_Scalar& x) const;
189
190
      /**
191
      * Convert *this to a BigInt
192
      */
193
      BigInt to_bigint() const;
194
195
0
      friend EC_Scalar operator+(const EC_Scalar& x, const EC_Scalar& y) { return x.add(y); }
196
197
0
      friend EC_Scalar operator-(const EC_Scalar& x, const EC_Scalar& y) { return x.sub(y); }
198
199
1.09k
      friend EC_Scalar operator*(const EC_Scalar& x, const EC_Scalar& y) { return x.mul(y); }
200
201
0
      friend bool operator==(const EC_Scalar& x, const EC_Scalar& y) { return x.is_eq(y); }
202
203
      EC_Scalar(const EC_Scalar& other);
204
      EC_Scalar(EC_Scalar&& other) noexcept;
205
206
      EC_Scalar& operator=(const EC_Scalar& other);
207
      EC_Scalar& operator=(EC_Scalar&& other) noexcept;
208
209
      ~EC_Scalar();
210
211
34.2k
      const EC_Scalar_Data& _inner() const { return inner(); }
212
213
      static EC_Scalar _from_inner(std::unique_ptr<EC_Scalar_Data> inner);
214
215
   private:
216
      friend class EC_AffinePoint;
217
218
      EC_Scalar(std::unique_ptr<EC_Scalar_Data> scalar);
219
220
60.6k
      const EC_Scalar_Data& inner() const { return *m_scalar; }
221
222
      std::unique_ptr<EC_Scalar_Data> m_scalar;
223
};
224
225
}  // namespace Botan
226
227
#endif