/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 | 314k | ~FE_25519() { secure_scrub_memory(m_fe, sizeof(m_fe)); } |
26 | | |
27 | | /** |
28 | | * Zero element |
29 | | */ |
30 | | FE_25519(int init = 0) |
31 | 151k | { |
32 | 151k | if(init != 0 && init != 1) |
33 | 0 | throw Invalid_Argument("Invalid FE_25519 initial value"); |
34 | 151k | clear_mem(m_fe, 10); |
35 | 151k | m_fe[0] = init; |
36 | 151k | } |
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 | 163k | { |
48 | 163k | m_fe[0] = static_cast<int32_t>(h0); |
49 | 163k | m_fe[1] = static_cast<int32_t>(h1); |
50 | 163k | m_fe[2] = static_cast<int32_t>(h2); |
51 | 163k | m_fe[3] = static_cast<int32_t>(h3); |
52 | 163k | m_fe[4] = static_cast<int32_t>(h4); |
53 | 163k | m_fe[5] = static_cast<int32_t>(h5); |
54 | 163k | m_fe[6] = static_cast<int32_t>(h6); |
55 | 163k | m_fe[7] = static_cast<int32_t>(h7); |
56 | 163k | m_fe[8] = static_cast<int32_t>(h8); |
57 | 163k | m_fe[9] = static_cast<int32_t>(h9); |
58 | 163k | } |
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 | 99 | { |
71 | 99 | uint8_t s[32]; |
72 | 99 | to_bytes(s); |
73 | 99 | |
74 | 99 | uint8_t sum = 0; |
75 | 3.26k | for(size_t i = 0; i != 32; ++i) |
76 | 3.16k | { sum |= s[i]; } |
77 | 99 | |
78 | 99 | // TODO avoid ternary here |
79 | 99 | return (sum == 0) ? 1 : 0; |
80 | 99 | } |
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 | 139 | { |
88 | 139 | // TODO could avoid most of the to_bytes computation here |
89 | 139 | uint8_t s[32]; |
90 | 139 | to_bytes(s); |
91 | 139 | return s[0] & 1; |
92 | 139 | } |
93 | | |
94 | | static FE_25519 add(const FE_25519& a, const FE_25519& b) |
95 | 55.3k | { |
96 | 55.3k | FE_25519 z; |
97 | 608k | for(size_t i = 0; i != 10; ++i) |
98 | 553k | { z[i] = a[i] + b[i]; } |
99 | 55.3k | return z; |
100 | 55.3k | } |
101 | | |
102 | | static FE_25519 sub(const FE_25519& a, const FE_25519& b) |
103 | 67.3k | { |
104 | 67.3k | FE_25519 z; |
105 | 741k | for(size_t i = 0; i != 10; ++i) |
106 | 673k | { z[i] = a[i] - b[i]; } |
107 | 67.3k | return z; |
108 | 67.3k | } |
109 | | |
110 | | static FE_25519 negate(const FE_25519& a) |
111 | 226 | { |
112 | 226 | FE_25519 z; |
113 | 2.48k | for(size_t i = 0; i != 10; ++i) |
114 | 2.26k | { z[i] = -a[i]; } |
115 | 226 | return z; |
116 | 226 | } |
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 | 51.9k | 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.07M | int32_t operator[](size_t i) const { return m_fe[i]; } |
127 | 1.31M | 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 | 69 | { |
146 | 69 | x.from_bytes(b); |
147 | 69 | } |
148 | | |
149 | | inline void fe_tobytes(uint8_t* b, const fe& x) |
150 | 71 | { |
151 | 71 | x.to_bytes(b); |
152 | 71 | } |
153 | | |
154 | | inline void fe_copy(fe& a, const fe& b) |
155 | 544 | { |
156 | 544 | a = b; |
157 | 544 | } |
158 | | |
159 | | inline int fe_isnonzero(const fe& x) |
160 | 99 | { |
161 | 99 | return x.is_zero() ? 0 : 1; |
162 | 99 | } |
163 | | |
164 | | inline int fe_isnegative(const fe& x) |
165 | 139 | { |
166 | 139 | return x.is_negative(); |
167 | 139 | } |
168 | | |
169 | | |
170 | | inline void fe_0(fe& x) |
171 | 266 | { |
172 | 266 | x = FE_25519(); |
173 | 266 | } |
174 | | |
175 | | inline void fe_1(fe& x) |
176 | 595 | { |
177 | 595 | x = FE_25519(1); |
178 | 595 | } |
179 | | |
180 | | inline void fe_add(fe& x, const fe& a, const fe& b) |
181 | 55.3k | { |
182 | 55.3k | x = FE_25519::add(a, b); |
183 | 55.3k | } |
184 | | |
185 | | inline void fe_sub(fe& x, const fe& a, const fe& b) |
186 | 67.3k | { |
187 | 67.3k | x = FE_25519::sub(a, b); |
188 | 67.3k | } |
189 | | |
190 | | inline void fe_neg(fe& x, const fe& z) |
191 | 226 | { |
192 | 226 | x = FE_25519::negate(z); |
193 | 226 | } |
194 | | |
195 | | inline void fe_mul(fe& x, const fe& a, const fe& b) |
196 | 93.4k | { |
197 | 93.4k | x = FE_25519::mul(a, b); |
198 | 93.4k | } |
199 | | |
200 | | inline void fe_sq(fe& x, const fe& z) |
201 | 51.9k | { |
202 | 51.9k | x = FE_25519::sqr(z); |
203 | 51.9k | } |
204 | | |
205 | | inline void fe_sq_iter(fe& x, const fe& z, size_t iter) |
206 | 1.26k | { |
207 | 1.26k | x = FE_25519::sqr_iter(z, iter); |
208 | 1.26k | } |
209 | | |
210 | | inline void fe_sq2(fe& x, const fe& z) |
211 | 17.1k | { |
212 | 17.1k | x = FE_25519::sqr2(z); |
213 | 17.1k | } |
214 | | |
215 | | inline void fe_invert(fe& x, const fe& z) |
216 | 71 | { |
217 | 71 | x = FE_25519::invert(z); |
218 | 71 | } |
219 | | |
220 | | inline void fe_pow22523(fe& x, const fe& y) |
221 | 69 | { |
222 | 69 | x = FE_25519::pow_22523(y); |
223 | 69 | } |
224 | | |
225 | | } |
226 | | |
227 | | #endif |