Coverage Report

Created: 2026-09-14 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/botan/src/lib/pubkey/ed25519/ed25519_fe.cpp
Line
Count
Source
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
#include <botan/internal/ed25519_fe.h>
12
13
#include <botan/internal/ed25519_internal.h>
14
15
namespace Botan {
16
17
//static
18
216
Ed25519_FieldElement Ed25519_FieldElement::invert() const {
19
216
   auto t0 = this->sqr();
20
216
   auto t1 = t0.sqr_iter(2);
21
216
   t1 = *this * t1;
22
216
   t0 = t0 * t1;
23
216
   auto t2 = t0.sqr();
24
216
   t1 = t1 * t2;
25
216
   t2 = t1.sqr_iter(5);
26
216
   t1 = t2 * t1;
27
216
   t2 = t1.sqr_iter(10);
28
216
   t2 = t2 * t1;
29
216
   auto t3 = t2.sqr_iter(20);
30
216
   t2 = t3 * t2;
31
216
   t2 = t2.sqr_iter(10);
32
216
   t1 = t2 * t1;
33
216
   t2 = t1.sqr_iter(50);
34
216
   t2 = t2 * t1;
35
216
   t3 = t2.sqr_iter(100);
36
216
   t2 = t3 * t2;
37
216
   t2 = t2.sqr_iter(50);
38
216
   t1 = t2 * t1;
39
216
   t1 = t1.sqr_iter(5);
40
41
216
   t0 = t1 * t0;
42
216
   return t0;
43
216
}
44
45
117
Ed25519_FieldElement Ed25519_FieldElement::pow_22523() const {
46
117
   auto t0 = this->sqr();
47
117
   auto t1 = t0.sqr_iter(2);
48
117
   t1 = (*this) * t1;
49
117
   t0 = t0 * t1;
50
117
   t0 = t0.sqr();
51
117
   t0 = t1 * t0;
52
117
   t1 = t0.sqr_iter(5);
53
117
   t0 = t1 * t0;
54
117
   t1 = t0.sqr_iter(10);
55
117
   t1 = t1 * t0;
56
117
   auto t2 = t1.sqr_iter(20);
57
117
   t1 = t2 * t1;
58
117
   t1 = t1.sqr_iter(10);
59
117
   t0 = t1 * t0;
60
117
   t1 = t0.sqr_iter(50);
61
117
   t1 = t1 * t0;
62
117
   t2 = t1.sqr_iter(100);
63
117
   t1 = t2 * t1;
64
117
   t1 = t1.sqr_iter(50);
65
117
   t0 = t1 * t0;
66
117
   t0 = t0.sqr_iter(2);
67
68
117
   t0 = t0 * (*this);
69
117
   return t0;
70
117
}
71
72
/*
73
h = f * g
74
Can overlap h with f or g.
75
76
Preconditions:
77
|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
78
|g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
79
80
Postconditions:
81
|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
82
*/
83
84
/*
85
Notes on implementation strategy:
86
87
Using schoolbook multiplication.
88
Karatsuba would save a little in some cost models.
89
90
Most multiplications by 2 and 19 are 32-bit precomputations;
91
cheaper than 64-bit postcomputations.
92
93
There is one remaining multiplication by 19 in the carry chain;
94
one *19 precomputation can be merged into this,
95
but the resulting data flow is considerably less clean.
96
97
There are 12 carries below.
98
10 of them are 2-way parallelizable and vectorizable.
99
Can get away with 11 carries, but then data flow is much deeper.
100
101
With tighter constraints on inputs can squeeze carries into int32.
102
*/
103
104
//static
105
210k
Ed25519_FieldElement Ed25519_FieldElement::mul(const Ed25519_FieldElement& f, const Ed25519_FieldElement& g) {
106
210k
   const int32_t f0 = f.m_fe[0];
107
210k
   const int32_t f1 = f.m_fe[1];
108
210k
   const int32_t f2 = f.m_fe[2];
109
210k
   const int32_t f3 = f.m_fe[3];
110
210k
   const int32_t f4 = f.m_fe[4];
111
210k
   const int32_t f5 = f.m_fe[5];
112
210k
   const int32_t f6 = f.m_fe[6];
113
210k
   const int32_t f7 = f.m_fe[7];
114
210k
   const int32_t f8 = f.m_fe[8];
115
210k
   const int32_t f9 = f.m_fe[9];
116
117
210k
   const int32_t g0 = g.m_fe[0];
118
210k
   const int32_t g1 = g.m_fe[1];
119
210k
   const int32_t g2 = g.m_fe[2];
120
210k
   const int32_t g3 = g.m_fe[3];
121
210k
   const int32_t g4 = g.m_fe[4];
122
210k
   const int32_t g5 = g.m_fe[5];
123
210k
   const int32_t g6 = g.m_fe[6];
124
210k
   const int32_t g7 = g.m_fe[7];
125
210k
   const int32_t g8 = g.m_fe[8];
126
210k
   const int32_t g9 = g.m_fe[9];
127
128
210k
   const int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
129
210k
   const int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
130
210k
   const int32_t g3_19 = 19 * g3;
131
210k
   const int32_t g4_19 = 19 * g4;
132
210k
   const int32_t g5_19 = 19 * g5;
133
210k
   const int32_t g6_19 = 19 * g6;
134
210k
   const int32_t g7_19 = 19 * g7;
135
210k
   const int32_t g8_19 = 19 * g8;
136
210k
   const int32_t g9_19 = 19 * g9;
137
210k
   const int32_t f1_2 = 2 * f1;
138
210k
   const int32_t f3_2 = 2 * f3;
139
210k
   const int32_t f5_2 = 2 * f5;
140
210k
   const int32_t f7_2 = 2 * f7;
141
210k
   const int32_t f9_2 = 2 * f9;
142
143
210k
   const int64_t f0g0 = f0 * static_cast<int64_t>(g0);
144
210k
   const int64_t f0g1 = f0 * static_cast<int64_t>(g1);
145
210k
   const int64_t f0g2 = f0 * static_cast<int64_t>(g2);
146
210k
   const int64_t f0g3 = f0 * static_cast<int64_t>(g3);
147
210k
   const int64_t f0g4 = f0 * static_cast<int64_t>(g4);
148
210k
   const int64_t f0g5 = f0 * static_cast<int64_t>(g5);
149
210k
   const int64_t f0g6 = f0 * static_cast<int64_t>(g6);
150
210k
   const int64_t f0g7 = f0 * static_cast<int64_t>(g7);
151
210k
   const int64_t f0g8 = f0 * static_cast<int64_t>(g8);
152
210k
   const int64_t f0g9 = f0 * static_cast<int64_t>(g9);
153
210k
   const int64_t f1g0 = f1 * static_cast<int64_t>(g0);
154
210k
   const int64_t f1g1_2 = f1_2 * static_cast<int64_t>(g1);
155
210k
   const int64_t f1g2 = f1 * static_cast<int64_t>(g2);
156
210k
   const int64_t f1g3_2 = f1_2 * static_cast<int64_t>(g3);
157
210k
   const int64_t f1g4 = f1 * static_cast<int64_t>(g4);
158
210k
   const int64_t f1g5_2 = f1_2 * static_cast<int64_t>(g5);
159
210k
   const int64_t f1g6 = f1 * static_cast<int64_t>(g6);
160
210k
   const int64_t f1g7_2 = f1_2 * static_cast<int64_t>(g7);
161
210k
   const int64_t f1g8 = f1 * static_cast<int64_t>(g8);
162
210k
   const int64_t f1g9_38 = f1_2 * static_cast<int64_t>(g9_19);
163
210k
   const int64_t f2g0 = f2 * static_cast<int64_t>(g0);
164
210k
   const int64_t f2g1 = f2 * static_cast<int64_t>(g1);
165
210k
   const int64_t f2g2 = f2 * static_cast<int64_t>(g2);
166
210k
   const int64_t f2g3 = f2 * static_cast<int64_t>(g3);
167
210k
   const int64_t f2g4 = f2 * static_cast<int64_t>(g4);
168
210k
   const int64_t f2g5 = f2 * static_cast<int64_t>(g5);
169
210k
   const int64_t f2g6 = f2 * static_cast<int64_t>(g6);
170
210k
   const int64_t f2g7 = f2 * static_cast<int64_t>(g7);
171
210k
   const int64_t f2g8_19 = f2 * static_cast<int64_t>(g8_19);
172
210k
   const int64_t f2g9_19 = f2 * static_cast<int64_t>(g9_19);
173
210k
   const int64_t f3g0 = f3 * static_cast<int64_t>(g0);
174
210k
   const int64_t f3g1_2 = f3_2 * static_cast<int64_t>(g1);
175
210k
   const int64_t f3g2 = f3 * static_cast<int64_t>(g2);
176
210k
   const int64_t f3g3_2 = f3_2 * static_cast<int64_t>(g3);
177
210k
   const int64_t f3g4 = f3 * static_cast<int64_t>(g4);
178
210k
   const int64_t f3g5_2 = f3_2 * static_cast<int64_t>(g5);
179
210k
   const int64_t f3g6 = f3 * static_cast<int64_t>(g6);
180
210k
   const int64_t f3g7_38 = f3_2 * static_cast<int64_t>(g7_19);
181
210k
   const int64_t f3g8_19 = f3 * static_cast<int64_t>(g8_19);
182
210k
   const int64_t f3g9_38 = f3_2 * static_cast<int64_t>(g9_19);
183
210k
   const int64_t f4g0 = f4 * static_cast<int64_t>(g0);
184
210k
   const int64_t f4g1 = f4 * static_cast<int64_t>(g1);
185
210k
   const int64_t f4g2 = f4 * static_cast<int64_t>(g2);
186
210k
   const int64_t f4g3 = f4 * static_cast<int64_t>(g3);
187
210k
   const int64_t f4g4 = f4 * static_cast<int64_t>(g4);
188
210k
   const int64_t f4g5 = f4 * static_cast<int64_t>(g5);
189
210k
   const int64_t f4g6_19 = f4 * static_cast<int64_t>(g6_19);
190
210k
   const int64_t f4g7_19 = f4 * static_cast<int64_t>(g7_19);
191
210k
   const int64_t f4g8_19 = f4 * static_cast<int64_t>(g8_19);
192
210k
   const int64_t f4g9_19 = f4 * static_cast<int64_t>(g9_19);
193
210k
   const int64_t f5g0 = f5 * static_cast<int64_t>(g0);
194
210k
   const int64_t f5g1_2 = f5_2 * static_cast<int64_t>(g1);
195
210k
   const int64_t f5g2 = f5 * static_cast<int64_t>(g2);
196
210k
   const int64_t f5g3_2 = f5_2 * static_cast<int64_t>(g3);
197
210k
   const int64_t f5g4 = f5 * static_cast<int64_t>(g4);
198
210k
   const int64_t f5g5_38 = f5_2 * static_cast<int64_t>(g5_19);
199
210k
   const int64_t f5g6_19 = f5 * static_cast<int64_t>(g6_19);
200
210k
   const int64_t f5g7_38 = f5_2 * static_cast<int64_t>(g7_19);
201
210k
   const int64_t f5g8_19 = f5 * static_cast<int64_t>(g8_19);
202
210k
   const int64_t f5g9_38 = f5_2 * static_cast<int64_t>(g9_19);
203
210k
   const int64_t f6g0 = f6 * static_cast<int64_t>(g0);
204
210k
   const int64_t f6g1 = f6 * static_cast<int64_t>(g1);
205
210k
   const int64_t f6g2 = f6 * static_cast<int64_t>(g2);
206
210k
   const int64_t f6g3 = f6 * static_cast<int64_t>(g3);
207
210k
   const int64_t f6g4_19 = f6 * static_cast<int64_t>(g4_19);
208
210k
   const int64_t f6g5_19 = f6 * static_cast<int64_t>(g5_19);
209
210k
   const int64_t f6g6_19 = f6 * static_cast<int64_t>(g6_19);
210
210k
   const int64_t f6g7_19 = f6 * static_cast<int64_t>(g7_19);
211
210k
   const int64_t f6g8_19 = f6 * static_cast<int64_t>(g8_19);
212
210k
   const int64_t f6g9_19 = f6 * static_cast<int64_t>(g9_19);
213
210k
   const int64_t f7g0 = f7 * static_cast<int64_t>(g0);
214
210k
   const int64_t f7g1_2 = f7_2 * static_cast<int64_t>(g1);
215
210k
   const int64_t f7g2 = f7 * static_cast<int64_t>(g2);
216
210k
   const int64_t f7g3_38 = f7_2 * static_cast<int64_t>(g3_19);
217
210k
   const int64_t f7g4_19 = f7 * static_cast<int64_t>(g4_19);
218
210k
   const int64_t f7g5_38 = f7_2 * static_cast<int64_t>(g5_19);
219
210k
   const int64_t f7g6_19 = f7 * static_cast<int64_t>(g6_19);
220
210k
   const int64_t f7g7_38 = f7_2 * static_cast<int64_t>(g7_19);
221
210k
   const int64_t f7g8_19 = f7 * static_cast<int64_t>(g8_19);
222
210k
   const int64_t f7g9_38 = f7_2 * static_cast<int64_t>(g9_19);
223
210k
   const int64_t f8g0 = f8 * static_cast<int64_t>(g0);
224
210k
   const int64_t f8g1 = f8 * static_cast<int64_t>(g1);
225
210k
   const int64_t f8g2_19 = f8 * static_cast<int64_t>(g2_19);
226
210k
   const int64_t f8g3_19 = f8 * static_cast<int64_t>(g3_19);
227
210k
   const int64_t f8g4_19 = f8 * static_cast<int64_t>(g4_19);
228
210k
   const int64_t f8g5_19 = f8 * static_cast<int64_t>(g5_19);
229
210k
   const int64_t f8g6_19 = f8 * static_cast<int64_t>(g6_19);
230
210k
   const int64_t f8g7_19 = f8 * static_cast<int64_t>(g7_19);
231
210k
   const int64_t f8g8_19 = f8 * static_cast<int64_t>(g8_19);
232
210k
   const int64_t f8g9_19 = f8 * static_cast<int64_t>(g9_19);
233
210k
   const int64_t f9g0 = f9 * static_cast<int64_t>(g0);
234
210k
   const int64_t f9g1_38 = f9_2 * static_cast<int64_t>(g1_19);
235
210k
   const int64_t f9g2_19 = f9 * static_cast<int64_t>(g2_19);
236
210k
   const int64_t f9g3_38 = f9_2 * static_cast<int64_t>(g3_19);
237
210k
   const int64_t f9g4_19 = f9 * static_cast<int64_t>(g4_19);
238
210k
   const int64_t f9g5_38 = f9_2 * static_cast<int64_t>(g5_19);
239
210k
   const int64_t f9g6_19 = f9 * static_cast<int64_t>(g6_19);
240
210k
   const int64_t f9g7_38 = f9_2 * static_cast<int64_t>(g7_19);
241
210k
   const int64_t f9g8_19 = f9 * static_cast<int64_t>(g8_19);
242
210k
   const int64_t f9g9_38 = f9_2 * static_cast<int64_t>(g9_19);
243
244
210k
   int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
245
210k
   int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
246
210k
   int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
247
210k
   int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
248
210k
   int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
249
210k
   int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
250
210k
   int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
251
210k
   int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
252
210k
   int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
253
210k
   int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
254
255
   /*
256
   |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
257
   i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
258
   |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
259
   i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9
260
   */
261
210k
   carry<26>(h0, h1);
262
210k
   carry<26>(h4, h5);
263
264
   /* |h0| <= 2^25 */
265
   /* |h4| <= 2^25 */
266
   /* |h1| <= 1.71*2^59 */
267
   /* |h5| <= 1.71*2^59 */
268
269
210k
   carry<25>(h1, h2);
270
210k
   carry<25>(h5, h6);
271
272
   /* |h1| <= 2^24; from now on fits into int32 */
273
   /* |h5| <= 2^24; from now on fits into int32 */
274
   /* |h2| <= 1.41*2^60 */
275
   /* |h6| <= 1.41*2^60 */
276
277
210k
   carry<26>(h2, h3);
278
210k
   carry<26>(h6, h7);
279
   /* |h2| <= 2^25; from now on fits into int32 unchanged */
280
   /* |h6| <= 2^25; from now on fits into int32 unchanged */
281
   /* |h3| <= 1.71*2^59 */
282
   /* |h7| <= 1.71*2^59 */
283
284
210k
   carry<25>(h3, h4);
285
210k
   carry<25>(h7, h8);
286
   /* |h3| <= 2^24; from now on fits into int32 unchanged */
287
   /* |h7| <= 2^24; from now on fits into int32 unchanged */
288
   /* |h4| <= 1.72*2^34 */
289
   /* |h8| <= 1.41*2^60 */
290
291
210k
   carry<26>(h4, h5);
292
210k
   carry<26>(h8, h9);
293
   /* |h4| <= 2^25; from now on fits into int32 unchanged */
294
   /* |h8| <= 2^25; from now on fits into int32 unchanged */
295
   /* |h5| <= 1.01*2^24 */
296
   /* |h9| <= 1.71*2^59 */
297
298
210k
   carry<25, 19>(h9, h0);
299
300
   /* |h9| <= 2^24; from now on fits into int32 unchanged */
301
   /* |h0| <= 1.1*2^39 */
302
303
210k
   carry<26>(h0, h1);
304
   /* |h0| <= 2^25; from now on fits into int32 unchanged */
305
   /* |h1| <= 1.01*2^24 */
306
307
210k
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
308
210k
}
309
310
/*
311
h = f * f
312
Can overlap h with f.
313
314
Preconditions:
315
|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
316
317
Postconditions:
318
|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
319
*/
320
321
/*
322
See fe_mul.c for discussion of implementation strategy.
323
*/
324
325
//static
326
93.1k
Ed25519_FieldElement Ed25519_FieldElement::sqr_iter(size_t iter) const {
327
93.1k
   int32_t f0 = m_fe[0];
328
93.1k
   int32_t f1 = m_fe[1];
329
93.1k
   int32_t f2 = m_fe[2];
330
93.1k
   int32_t f3 = m_fe[3];
331
93.1k
   int32_t f4 = m_fe[4];
332
93.1k
   int32_t f5 = m_fe[5];
333
93.1k
   int32_t f6 = m_fe[6];
334
93.1k
   int32_t f7 = m_fe[7];
335
93.1k
   int32_t f8 = m_fe[8];
336
93.1k
   int32_t f9 = m_fe[9];
337
338
266k
   for(size_t i = 0; i != iter; ++i) {
339
173k
      const int32_t f0_2 = 2 * f0;
340
173k
      const int32_t f1_2 = 2 * f1;
341
173k
      const int32_t f2_2 = 2 * f2;
342
173k
      const int32_t f3_2 = 2 * f3;
343
173k
      const int32_t f4_2 = 2 * f4;
344
173k
      const int32_t f5_2 = 2 * f5;
345
173k
      const int32_t f6_2 = 2 * f6;
346
173k
      const int32_t f7_2 = 2 * f7;
347
173k
      const int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
348
173k
      const int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
349
173k
      const int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
350
173k
      const int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
351
173k
      const int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
352
353
173k
      const int64_t f0f0 = f0 * static_cast<int64_t>(f0);
354
173k
      const int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
355
173k
      const int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
356
173k
      const int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
357
173k
      const int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
358
173k
      const int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
359
173k
      const int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
360
173k
      const int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
361
173k
      const int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
362
173k
      const int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
363
173k
      const int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
364
173k
      const int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
365
173k
      const int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
366
173k
      const int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
367
173k
      const int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
368
173k
      const int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
369
173k
      const int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
370
173k
      const int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
371
173k
      const int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
372
173k
      const int64_t f2f2 = f2 * static_cast<int64_t>(f2);
373
173k
      const int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
374
173k
      const int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
375
173k
      const int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
376
173k
      const int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
377
173k
      const int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
378
173k
      const int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
379
173k
      const int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
380
173k
      const int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
381
173k
      const int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
382
173k
      const int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
383
173k
      const int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
384
173k
      const int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
385
173k
      const int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
386
173k
      const int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
387
173k
      const int64_t f4f4 = f4 * static_cast<int64_t>(f4);
388
173k
      const int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
389
173k
      const int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
390
173k
      const int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
391
173k
      const int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
392
173k
      const int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
393
173k
      const int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
394
173k
      const int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
395
173k
      const int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
396
173k
      const int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
397
173k
      const int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
398
173k
      const int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
399
173k
      const int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
400
173k
      const int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
401
173k
      const int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
402
173k
      const int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
403
173k
      const int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
404
173k
      const int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
405
173k
      const int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
406
173k
      const int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
407
173k
      const int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
408
409
173k
      int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
410
173k
      int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
411
173k
      int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
412
173k
      int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
413
173k
      int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
414
173k
      int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
415
173k
      int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
416
173k
      int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
417
173k
      int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
418
173k
      int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
419
420
173k
      carry<26>(h0, h1);
421
173k
      carry<26>(h4, h5);
422
173k
      carry<25>(h1, h2);
423
173k
      carry<25>(h5, h6);
424
173k
      carry<26>(h2, h3);
425
173k
      carry<26>(h6, h7);
426
427
173k
      carry<25>(h3, h4);
428
173k
      carry<25>(h7, h8);
429
430
173k
      carry<26>(h4, h5);
431
173k
      carry<26>(h8, h9);
432
173k
      carry<25, 19>(h9, h0);
433
173k
      carry<26>(h0, h1);
434
435
173k
      f0 = static_cast<int32_t>(h0);
436
173k
      f1 = static_cast<int32_t>(h1);
437
173k
      f2 = static_cast<int32_t>(h2);
438
173k
      f3 = static_cast<int32_t>(h3);
439
173k
      f4 = static_cast<int32_t>(h4);
440
173k
      f5 = static_cast<int32_t>(h5);
441
173k
      f6 = static_cast<int32_t>(h6);
442
173k
      f7 = static_cast<int32_t>(h7);
443
173k
      f8 = static_cast<int32_t>(h8);
444
173k
      f9 = static_cast<int32_t>(h9);
445
173k
   }
446
447
93.1k
   return Ed25519_FieldElement(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
448
93.1k
}
449
450
/*
451
h = 2 * f * f
452
Can overlap h with f.
453
454
Preconditions:
455
|f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
456
457
Postconditions:
458
|h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
459
*/
460
461
/*
462
See fe_mul.c for discussion of implementation strategy.
463
*/
464
465
//static
466
29.6k
Ed25519_FieldElement Ed25519_FieldElement::sqr2() const {
467
29.6k
   const int32_t f0 = m_fe[0];
468
29.6k
   const int32_t f1 = m_fe[1];
469
29.6k
   const int32_t f2 = m_fe[2];
470
29.6k
   const int32_t f3 = m_fe[3];
471
29.6k
   const int32_t f4 = m_fe[4];
472
29.6k
   const int32_t f5 = m_fe[5];
473
29.6k
   const int32_t f6 = m_fe[6];
474
29.6k
   const int32_t f7 = m_fe[7];
475
29.6k
   const int32_t f8 = m_fe[8];
476
29.6k
   const int32_t f9 = m_fe[9];
477
478
29.6k
   const int32_t f0_2 = 2 * f0;
479
29.6k
   const int32_t f1_2 = 2 * f1;
480
29.6k
   const int32_t f2_2 = 2 * f2;
481
29.6k
   const int32_t f3_2 = 2 * f3;
482
29.6k
   const int32_t f4_2 = 2 * f4;
483
29.6k
   const int32_t f5_2 = 2 * f5;
484
29.6k
   const int32_t f6_2 = 2 * f6;
485
29.6k
   const int32_t f7_2 = 2 * f7;
486
29.6k
   const int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
487
29.6k
   const int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
488
29.6k
   const int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
489
29.6k
   const int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
490
29.6k
   const int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
491
29.6k
   const int64_t f0f0 = f0 * static_cast<int64_t>(f0);
492
29.6k
   const int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
493
29.6k
   const int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
494
29.6k
   const int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
495
29.6k
   const int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
496
29.6k
   const int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
497
29.6k
   const int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
498
29.6k
   const int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
499
29.6k
   const int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
500
29.6k
   const int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
501
29.6k
   const int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
502
29.6k
   const int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
503
29.6k
   const int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
504
29.6k
   const int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
505
29.6k
   const int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
506
29.6k
   const int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
507
29.6k
   const int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
508
29.6k
   const int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
509
29.6k
   const int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
510
29.6k
   const int64_t f2f2 = f2 * static_cast<int64_t>(f2);
511
29.6k
   const int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
512
29.6k
   const int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
513
29.6k
   const int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
514
29.6k
   const int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
515
29.6k
   const int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
516
29.6k
   const int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
517
29.6k
   const int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
518
29.6k
   const int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
519
29.6k
   const int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
520
29.6k
   const int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
521
29.6k
   const int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
522
29.6k
   const int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
523
29.6k
   const int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
524
29.6k
   const int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
525
29.6k
   const int64_t f4f4 = f4 * static_cast<int64_t>(f4);
526
29.6k
   const int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
527
29.6k
   const int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
528
29.6k
   const int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
529
29.6k
   const int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
530
29.6k
   const int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
531
29.6k
   const int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
532
29.6k
   const int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
533
29.6k
   const int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
534
29.6k
   const int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
535
29.6k
   const int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
536
29.6k
   const int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
537
29.6k
   const int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
538
29.6k
   const int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
539
29.6k
   const int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
540
29.6k
   const int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
541
29.6k
   const int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
542
29.6k
   const int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
543
29.6k
   const int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
544
29.6k
   const int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
545
29.6k
   const int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
546
547
29.6k
   int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
548
29.6k
   int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
549
29.6k
   int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
550
29.6k
   int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
551
29.6k
   int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
552
29.6k
   int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
553
29.6k
   int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
554
29.6k
   int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
555
29.6k
   int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
556
29.6k
   int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
557
558
29.6k
   h0 += h0;
559
29.6k
   h1 += h1;
560
29.6k
   h2 += h2;
561
29.6k
   h3 += h3;
562
29.6k
   h4 += h4;
563
29.6k
   h5 += h5;
564
29.6k
   h6 += h6;
565
29.6k
   h7 += h7;
566
29.6k
   h8 += h8;
567
29.6k
   h9 += h9;
568
569
29.6k
   carry<26>(h0, h1);
570
29.6k
   carry<26>(h4, h5);
571
572
29.6k
   carry<25>(h1, h2);
573
29.6k
   carry<25>(h5, h6);
574
575
29.6k
   carry<26>(h2, h3);
576
29.6k
   carry<26>(h6, h7);
577
578
29.6k
   carry<25>(h3, h4);
579
29.6k
   carry<25>(h7, h8);
580
29.6k
   carry<26>(h4, h5);
581
29.6k
   carry<26>(h8, h9);
582
29.6k
   carry<25, 19>(h9, h0);
583
29.6k
   carry<26>(h0, h1);
584
585
29.6k
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
586
29.6k
}
587
588
/*
589
Ignores top bit of h.
590
*/
591
117
Ed25519_FieldElement Ed25519_FieldElement::deserialize(const uint8_t s[32]) {
592
117
   int64_t h0 = load_4(s);
593
117
   int64_t h1 = load_3(s + 4) << 6;
594
117
   int64_t h2 = load_3(s + 7) << 5;
595
117
   int64_t h3 = load_3(s + 10) << 3;
596
117
   int64_t h4 = load_3(s + 13) << 2;
597
117
   int64_t h5 = load_4(s + 16);
598
117
   int64_t h6 = load_3(s + 20) << 7;
599
117
   int64_t h7 = load_3(s + 23) << 5;
600
117
   int64_t h8 = load_3(s + 26) << 4;
601
117
   int64_t h9 = (load_3(s + 29) & 0x7fffff) << 2;
602
603
117
   carry<25, 19>(h9, h0);
604
117
   carry<25>(h1, h2);
605
117
   carry<25>(h3, h4);
606
117
   carry<25>(h5, h6);
607
117
   carry<25>(h7, h8);
608
609
117
   carry<26>(h0, h1);
610
117
   carry<26>(h2, h3);
611
117
   carry<26>(h4, h5);
612
117
   carry<26>(h6, h7);
613
117
   carry<26>(h8, h9);
614
615
117
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
616
117
}
617
618
/*
619
Preconditions:
620
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
621
622
Write p=2^255-19; q=floor(h/p).
623
Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
624
625
Proof:
626
Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
627
Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
628
629
Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
630
Then 0<y<1.
631
632
Write r=h-pq.
633
Have 0<=r<=p-1=2^255-20.
634
Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
635
636
Write x=r+19(2^-255)r+y.
637
Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
638
639
Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
640
so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
641
*/
642
643
712
void Ed25519_FieldElement::serialize_to(std::span<uint8_t, 32> s) const {
644
712
   const int32_t X25 = (1 << 25);
645
646
712
   int32_t h0 = m_fe[0];
647
712
   int32_t h1 = m_fe[1];
648
712
   int32_t h2 = m_fe[2];
649
712
   int32_t h3 = m_fe[3];
650
712
   int32_t h4 = m_fe[4];
651
712
   int32_t h5 = m_fe[5];
652
712
   int32_t h6 = m_fe[6];
653
712
   int32_t h7 = m_fe[7];
654
712
   int32_t h8 = m_fe[8];
655
712
   int32_t h9 = m_fe[9];
656
657
712
   int32_t q = (19 * h9 + ((static_cast<int32_t>(1) << 24))) >> 25;
658
712
   q = (h0 + q) >> 26;
659
712
   q = (h1 + q) >> 25;
660
712
   q = (h2 + q) >> 26;
661
712
   q = (h3 + q) >> 25;
662
712
   q = (h4 + q) >> 26;
663
712
   q = (h5 + q) >> 25;
664
712
   q = (h6 + q) >> 26;
665
712
   q = (h7 + q) >> 25;
666
712
   q = (h8 + q) >> 26;
667
712
   q = (h9 + q) >> 25;
668
669
   /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
670
712
   h0 += 19 * q;
671
   /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
672
673
712
   carry0<26>(h0, h1);
674
712
   carry0<25>(h1, h2);
675
712
   carry0<26>(h2, h3);
676
712
   carry0<25>(h3, h4);
677
712
   carry0<26>(h4, h5);
678
712
   carry0<25>(h5, h6);
679
712
   carry0<26>(h6, h7);
680
712
   carry0<25>(h7, h8);
681
712
   carry0<26>(h8, h9);
682
683
712
   int32_t carry9 = h9 >> 25;
684
712
   h9 -= carry9 * X25;
685
   /* h10 = carry9 */
686
687
   /*
688
   Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
689
   Have h0+...+2^230 h9 between 0 and 2^255-1;
690
   evidently 2^255 h10-2^255 q = 0.
691
   Goal: Output h0+...+2^230 h9.
692
   */
693
694
712
   s[0] = static_cast<uint8_t>(h0 >> 0);
695
712
   s[1] = static_cast<uint8_t>(h0 >> 8);
696
712
   s[2] = static_cast<uint8_t>(h0 >> 16);
697
712
   s[3] = static_cast<uint8_t>((h0 >> 24) | (h1 << 2));
698
712
   s[4] = static_cast<uint8_t>(h1 >> 6);
699
712
   s[5] = static_cast<uint8_t>(h1 >> 14);
700
712
   s[6] = static_cast<uint8_t>((h1 >> 22) | (h2 << 3));
701
712
   s[7] = static_cast<uint8_t>(h2 >> 5);
702
712
   s[8] = static_cast<uint8_t>(h2 >> 13);
703
712
   s[9] = static_cast<uint8_t>((h2 >> 21) | (h3 << 5));
704
712
   s[10] = static_cast<uint8_t>(h3 >> 3);
705
712
   s[11] = static_cast<uint8_t>(h3 >> 11);
706
712
   s[12] = static_cast<uint8_t>((h3 >> 19) | (h4 << 6));
707
712
   s[13] = static_cast<uint8_t>(h4 >> 2);
708
712
   s[14] = static_cast<uint8_t>(h4 >> 10);
709
712
   s[15] = static_cast<uint8_t>(h4 >> 18);
710
712
   s[16] = static_cast<uint8_t>(h5 >> 0);
711
712
   s[17] = static_cast<uint8_t>(h5 >> 8);
712
712
   s[18] = static_cast<uint8_t>(h5 >> 16);
713
712
   s[19] = static_cast<uint8_t>((h5 >> 24) | (h6 << 1));
714
712
   s[20] = static_cast<uint8_t>(h6 >> 7);
715
712
   s[21] = static_cast<uint8_t>(h6 >> 15);
716
712
   s[22] = static_cast<uint8_t>((h6 >> 23) | (h7 << 3));
717
712
   s[23] = static_cast<uint8_t>(h7 >> 5);
718
712
   s[24] = static_cast<uint8_t>(h7 >> 13);
719
712
   s[25] = static_cast<uint8_t>((h7 >> 21) | (h8 << 4));
720
712
   s[26] = static_cast<uint8_t>(h8 >> 4);
721
712
   s[27] = static_cast<uint8_t>(h8 >> 12);
722
712
   s[28] = static_cast<uint8_t>((h8 >> 20) | (h9 << 6));
723
712
   s[29] = static_cast<uint8_t>(h9 >> 2);
724
712
   s[30] = static_cast<uint8_t>(h9 >> 10);
725
712
   s[31] = static_cast<uint8_t>(h9 >> 18);
726
712
}
727
728
}  // namespace Botan