/src/botan/build/include/botan/internal/ed25519_fe.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Ed25519 field element |
3 | | * (C) 2017 Ribose Inc |
4 | | * |
5 | | * Based on the public domain code from SUPERCOP ref10 by |
6 | | * Peter Schwabe, Daniel J. Bernstein, Niels Duif, Tanja Lange, Bo-Yin Yang |
7 | | * |
8 | | * Botan is released under the Simplified BSD License (see license.txt) |
9 | | */ |
10 | | |
11 | | #ifndef BOTAN_ED25519_FE_H_ |
12 | | #define BOTAN_ED25519_FE_H_ |
13 | | |
14 | | #include <botan/mem_ops.h> |
15 | | #include <botan/exceptn.h> |
16 | | |
17 | | namespace Botan { |
18 | | |
19 | | /** |
20 | | * An element of the field \\Z/(2^255-19) |
21 | | */ |
22 | | class FE_25519 |
23 | | { |
24 | | public: |
25 | 329k | ~FE_25519() { secure_scrub_memory(m_fe, sizeof(m_fe)); } |
26 | | |
27 | | /** |
28 | | * Zero element |
29 | | */ |
30 | | FE_25519(int init = 0) |
31 | 158k | { |
32 | 158k | if(init != 0 && init != 1) |
33 | 0 | throw Invalid_Argument("Invalid FE_25519 initial value"); |
34 | 158k | clear_mem(m_fe, 10); |
35 | 158k | m_fe[0] = init; |
36 | 158k | } |
37 | | |
38 | | FE_25519(std::initializer_list<int32_t> x) |
39 | 9.24k | { |
40 | 9.24k | if(x.size() != 10) |
41 | 0 | throw Invalid_Argument("Invalid FE_25519 initializer list"); |
42 | 9.24k | copy_mem(m_fe, x.begin(), 10); |
43 | 9.24k | } |
44 | | |
45 | | FE_25519(int64_t h0, int64_t h1, int64_t h2, int64_t h3, int64_t h4, |
46 | | int64_t h5, int64_t h6, int64_t h7, int64_t h8, int64_t h9) |
47 | 171k | { |
48 | 171k | m_fe[0] = static_cast<int32_t>(h0); |
49 | 171k | m_fe[1] = static_cast<int32_t>(h1); |
50 | 171k | m_fe[2] = static_cast<int32_t>(h2); |
51 | 171k | m_fe[3] = static_cast<int32_t>(h3); |
52 | 171k | m_fe[4] = static_cast<int32_t>(h4); |
53 | 171k | m_fe[5] = static_cast<int32_t>(h5); |
54 | 171k | m_fe[6] = static_cast<int32_t>(h6); |
55 | 171k | m_fe[7] = static_cast<int32_t>(h7); |
56 | 171k | m_fe[8] = static_cast<int32_t>(h8); |
57 | 171k | m_fe[9] = static_cast<int32_t>(h9); |
58 | 171k | } |
59 | | |
60 | | FE_25519(const FE_25519& other) = default; |
61 | | FE_25519& operator=(const FE_25519& other) = default; |
62 | | |
63 | | FE_25519(FE_25519&& other) = default; |
64 | | FE_25519& operator=(FE_25519&& other) = default; |
65 | | |
66 | | void from_bytes(const uint8_t b[32]); |
67 | | void to_bytes(uint8_t b[32]) const; |
68 | | |
69 | | bool is_zero() const |
70 | 118 | { |
71 | 118 | uint8_t s[32]; |
72 | 118 | to_bytes(s); |
73 | 118 | |
74 | 118 | uint8_t sum = 0; |
75 | 3.89k | for(size_t i = 0; i != 32; ++i) |
76 | 3.77k | { sum |= s[i]; } |
77 | 118 | |
78 | | // TODO avoid ternary here |
79 | 71 | return (sum == 0) ? 1 : 0; |
80 | 118 | } |
81 | | |
82 | | /* |
83 | | return 1 if f is in {1,3,5,...,q-2} |
84 | | return 0 if f is in {0,2,4,...,q-1} |
85 | | */ |
86 | | bool is_negative() const |
87 | 146 | { |
88 | | // TODO could avoid most of the to_bytes computation here |
89 | 146 | uint8_t s[32]; |
90 | 146 | to_bytes(s); |
91 | 146 | return s[0] & 1; |
92 | 146 | } |
93 | | |
94 | | static FE_25519 add(const FE_25519& a, const FE_25519& b) |
95 | 57.7k | { |
96 | 57.7k | FE_25519 z; |
97 | 635k | for(size_t i = 0; i != 10; ++i) |
98 | 577k | { z[i] = a[i] + b[i]; } |
99 | 57.7k | return z; |
100 | 57.7k | } |
101 | | |
102 | | static FE_25519 sub(const FE_25519& a, const FE_25519& b) |
103 | 70.3k | { |
104 | 70.3k | FE_25519 z; |
105 | 774k | for(size_t i = 0; i != 10; ++i) |
106 | 703k | { z[i] = a[i] - b[i]; } |
107 | 70.3k | return z; |
108 | 70.3k | } |
109 | | |
110 | | static FE_25519 negate(const FE_25519& a) |
111 | 292 | { |
112 | 292 | FE_25519 z; |
113 | 3.21k | for(size_t i = 0; i != 10; ++i) |
114 | 2.92k | { z[i] = -a[i]; } |
115 | 292 | return z; |
116 | 292 | } |
117 | | |
118 | | static FE_25519 mul(const FE_25519& a, const FE_25519& b); |
119 | | static FE_25519 sqr_iter(const FE_25519& a, size_t iter); |
120 | 54.2k | static FE_25519 sqr(const FE_25519& a) { return sqr_iter(a, 1); } |
121 | | static FE_25519 sqr2(const FE_25519& a); |
122 | | static FE_25519 pow_22523(const FE_25519& a); |
123 | | static FE_25519 invert(const FE_25519& a); |
124 | | |
125 | | // TODO remove |
126 | 5.31M | int32_t operator[](size_t i) const { return m_fe[i]; } |
127 | 1.39M | int32_t& operator[](size_t i) { return m_fe[i]; } |
128 | | |
129 | | private: |
130 | | |
131 | | int32_t m_fe[10]; |
132 | | }; |
133 | | |
134 | | typedef FE_25519 fe; |
135 | | |
136 | | /* |
137 | | fe means field element. |
138 | | Here the field is |
139 | | An element t, entries t[0]...t[9], represents the integer |
140 | | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. |
141 | | Bounds on each t[i] vary depending on context. |
142 | | */ |
143 | | |
144 | | inline void fe_frombytes(fe& x, const uint8_t* b) |
145 | 73 | { |
146 | 73 | x.from_bytes(b); |
147 | 73 | } |
148 | | |
149 | | inline void fe_tobytes(uint8_t* b, const fe& x) |
150 | 75 | { |
151 | 75 | x.to_bytes(b); |
152 | 75 | } |
153 | | |
154 | | inline void fe_copy(fe& a, const fe& b) |
155 | 568 | { |
156 | 568 | a = b; |
157 | 568 | } |
158 | | |
159 | | inline int fe_isnonzero(const fe& x) |
160 | 118 | { |
161 | 71 | return x.is_zero() ? 0 : 1; |
162 | 118 | } |
163 | | |
164 | | inline int fe_isnegative(const fe& x) |
165 | 146 | { |
166 | 146 | return x.is_negative(); |
167 | 146 | } |
168 | | |
169 | | |
170 | | inline void fe_0(fe& x) |
171 | 335 | { |
172 | 335 | x = FE_25519(); |
173 | 335 | } |
174 | | |
175 | | inline void fe_1(fe& x) |
176 | 735 | { |
177 | 735 | x = FE_25519(1); |
178 | 735 | } |
179 | | |
180 | | inline void fe_add(fe& x, const fe& a, const fe& b) |
181 | 57.7k | { |
182 | 57.7k | x = FE_25519::add(a, b); |
183 | 57.7k | } |
184 | | |
185 | | inline void fe_sub(fe& x, const fe& a, const fe& b) |
186 | 70.3k | { |
187 | 70.3k | x = FE_25519::sub(a, b); |
188 | 70.3k | } |
189 | | |
190 | | inline void fe_neg(fe& x, const fe& z) |
191 | 292 | { |
192 | 292 | x = FE_25519::negate(z); |
193 | 292 | } |
194 | | |
195 | | inline void fe_mul(fe& x, const fe& a, const fe& b) |
196 | 97.5k | { |
197 | 97.5k | x = FE_25519::mul(a, b); |
198 | 97.5k | } |
199 | | |
200 | | inline void fe_sq(fe& x, const fe& z) |
201 | 54.2k | { |
202 | 54.2k | x = FE_25519::sqr(z); |
203 | 54.2k | } |
204 | | |
205 | | inline void fe_sq_iter(fe& x, const fe& z, size_t iter) |
206 | 1.33k | { |
207 | 1.33k | x = FE_25519::sqr_iter(z, iter); |
208 | 1.33k | } |
209 | | |
210 | | inline void fe_sq2(fe& x, const fe& z) |
211 | 17.8k | { |
212 | 17.8k | x = FE_25519::sqr2(z); |
213 | 17.8k | } |
214 | | |
215 | | inline void fe_invert(fe& x, const fe& z) |
216 | 75 | { |
217 | 75 | x = FE_25519::invert(z); |
218 | 75 | } |
219 | | |
220 | | inline void fe_pow22523(fe& x, const fe& y) |
221 | 73 | { |
222 | 73 | x = FE_25519::pow_22523(y); |
223 | 73 | } |
224 | | |
225 | | } |
226 | | |
227 | | #endif |