Coverage Report

Created: 2026-02-07 06:16

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
175
Ed25519_FieldElement Ed25519_FieldElement::invert() const {
19
175
   auto t0 = this->sqr();
20
175
   auto t1 = t0.sqr_iter(2);
21
175
   t1 = *this * t1;
22
175
   t0 = t0 * t1;
23
175
   auto t2 = t0.sqr();
24
175
   t1 = t1 * t2;
25
175
   t2 = t1.sqr_iter(5);
26
175
   t1 = t2 * t1;
27
175
   t2 = t1.sqr_iter(10);
28
175
   t2 = t2 * t1;
29
175
   auto t3 = t2.sqr_iter(20);
30
175
   t2 = t3 * t2;
31
175
   t2 = t2.sqr_iter(10);
32
175
   t1 = t2 * t1;
33
175
   t2 = t1.sqr_iter(50);
34
175
   t2 = t2 * t1;
35
175
   t3 = t2.sqr_iter(100);
36
175
   t2 = t3 * t2;
37
175
   t2 = t2.sqr_iter(50);
38
175
   t1 = t2 * t1;
39
175
   t1 = t1.sqr_iter(5);
40
41
175
   t0 = t1 * t0;
42
175
   return t0;
43
175
}
44
45
86
Ed25519_FieldElement Ed25519_FieldElement::pow_22523() const {
46
86
   auto t0 = this->sqr();
47
86
   auto t1 = t0.sqr_iter(2);
48
86
   t1 = (*this) * t1;
49
86
   t0 = t0 * t1;
50
86
   t0 = t0.sqr();
51
86
   t0 = t1 * t0;
52
86
   t1 = t0.sqr_iter(5);
53
86
   t0 = t1 * t0;
54
86
   t1 = t0.sqr_iter(10);
55
86
   t1 = t1 * t0;
56
86
   auto t2 = t1.sqr_iter(20);
57
86
   t1 = t2 * t1;
58
86
   t1 = t1.sqr_iter(10);
59
86
   t0 = t1 * t0;
60
86
   t1 = t0.sqr_iter(50);
61
86
   t1 = t1 * t0;
62
86
   t2 = t1.sqr_iter(100);
63
86
   t1 = t2 * t1;
64
86
   t1 = t1.sqr_iter(50);
65
86
   t0 = t1 * t0;
66
86
   t0 = t0.sqr_iter(2);
67
68
86
   t0 = t0 * (*this);
69
86
   return t0;
70
86
}
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
160k
Ed25519_FieldElement Ed25519_FieldElement::mul(const Ed25519_FieldElement& f, const Ed25519_FieldElement& g) {
106
160k
   const int32_t f0 = f.m_fe[0];
107
160k
   const int32_t f1 = f.m_fe[1];
108
160k
   const int32_t f2 = f.m_fe[2];
109
160k
   const int32_t f3 = f.m_fe[3];
110
160k
   const int32_t f4 = f.m_fe[4];
111
160k
   const int32_t f5 = f.m_fe[5];
112
160k
   const int32_t f6 = f.m_fe[6];
113
160k
   const int32_t f7 = f.m_fe[7];
114
160k
   const int32_t f8 = f.m_fe[8];
115
160k
   const int32_t f9 = f.m_fe[9];
116
117
160k
   const int32_t g0 = g.m_fe[0];
118
160k
   const int32_t g1 = g.m_fe[1];
119
160k
   const int32_t g2 = g.m_fe[2];
120
160k
   const int32_t g3 = g.m_fe[3];
121
160k
   const int32_t g4 = g.m_fe[4];
122
160k
   const int32_t g5 = g.m_fe[5];
123
160k
   const int32_t g6 = g.m_fe[6];
124
160k
   const int32_t g7 = g.m_fe[7];
125
160k
   const int32_t g8 = g.m_fe[8];
126
160k
   const int32_t g9 = g.m_fe[9];
127
128
160k
   const int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
129
160k
   const int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
130
160k
   const int32_t g3_19 = 19 * g3;
131
160k
   const int32_t g4_19 = 19 * g4;
132
160k
   const int32_t g5_19 = 19 * g5;
133
160k
   const int32_t g6_19 = 19 * g6;
134
160k
   const int32_t g7_19 = 19 * g7;
135
160k
   const int32_t g8_19 = 19 * g8;
136
160k
   const int32_t g9_19 = 19 * g9;
137
160k
   const int32_t f1_2 = 2 * f1;
138
160k
   const int32_t f3_2 = 2 * f3;
139
160k
   const int32_t f5_2 = 2 * f5;
140
160k
   const int32_t f7_2 = 2 * f7;
141
160k
   const int32_t f9_2 = 2 * f9;
142
143
160k
   const int64_t f0g0 = f0 * static_cast<int64_t>(g0);
144
160k
   const int64_t f0g1 = f0 * static_cast<int64_t>(g1);
145
160k
   const int64_t f0g2 = f0 * static_cast<int64_t>(g2);
146
160k
   const int64_t f0g3 = f0 * static_cast<int64_t>(g3);
147
160k
   const int64_t f0g4 = f0 * static_cast<int64_t>(g4);
148
160k
   const int64_t f0g5 = f0 * static_cast<int64_t>(g5);
149
160k
   const int64_t f0g6 = f0 * static_cast<int64_t>(g6);
150
160k
   const int64_t f0g7 = f0 * static_cast<int64_t>(g7);
151
160k
   const int64_t f0g8 = f0 * static_cast<int64_t>(g8);
152
160k
   const int64_t f0g9 = f0 * static_cast<int64_t>(g9);
153
160k
   const int64_t f1g0 = f1 * static_cast<int64_t>(g0);
154
160k
   const int64_t f1g1_2 = f1_2 * static_cast<int64_t>(g1);
155
160k
   const int64_t f1g2 = f1 * static_cast<int64_t>(g2);
156
160k
   const int64_t f1g3_2 = f1_2 * static_cast<int64_t>(g3);
157
160k
   const int64_t f1g4 = f1 * static_cast<int64_t>(g4);
158
160k
   const int64_t f1g5_2 = f1_2 * static_cast<int64_t>(g5);
159
160k
   const int64_t f1g6 = f1 * static_cast<int64_t>(g6);
160
160k
   const int64_t f1g7_2 = f1_2 * static_cast<int64_t>(g7);
161
160k
   const int64_t f1g8 = f1 * static_cast<int64_t>(g8);
162
160k
   const int64_t f1g9_38 = f1_2 * static_cast<int64_t>(g9_19);
163
160k
   const int64_t f2g0 = f2 * static_cast<int64_t>(g0);
164
160k
   const int64_t f2g1 = f2 * static_cast<int64_t>(g1);
165
160k
   const int64_t f2g2 = f2 * static_cast<int64_t>(g2);
166
160k
   const int64_t f2g3 = f2 * static_cast<int64_t>(g3);
167
160k
   const int64_t f2g4 = f2 * static_cast<int64_t>(g4);
168
160k
   const int64_t f2g5 = f2 * static_cast<int64_t>(g5);
169
160k
   const int64_t f2g6 = f2 * static_cast<int64_t>(g6);
170
160k
   const int64_t f2g7 = f2 * static_cast<int64_t>(g7);
171
160k
   const int64_t f2g8_19 = f2 * static_cast<int64_t>(g8_19);
172
160k
   const int64_t f2g9_19 = f2 * static_cast<int64_t>(g9_19);
173
160k
   const int64_t f3g0 = f3 * static_cast<int64_t>(g0);
174
160k
   const int64_t f3g1_2 = f3_2 * static_cast<int64_t>(g1);
175
160k
   const int64_t f3g2 = f3 * static_cast<int64_t>(g2);
176
160k
   const int64_t f3g3_2 = f3_2 * static_cast<int64_t>(g3);
177
160k
   const int64_t f3g4 = f3 * static_cast<int64_t>(g4);
178
160k
   const int64_t f3g5_2 = f3_2 * static_cast<int64_t>(g5);
179
160k
   const int64_t f3g6 = f3 * static_cast<int64_t>(g6);
180
160k
   const int64_t f3g7_38 = f3_2 * static_cast<int64_t>(g7_19);
181
160k
   const int64_t f3g8_19 = f3 * static_cast<int64_t>(g8_19);
182
160k
   const int64_t f3g9_38 = f3_2 * static_cast<int64_t>(g9_19);
183
160k
   const int64_t f4g0 = f4 * static_cast<int64_t>(g0);
184
160k
   const int64_t f4g1 = f4 * static_cast<int64_t>(g1);
185
160k
   const int64_t f4g2 = f4 * static_cast<int64_t>(g2);
186
160k
   const int64_t f4g3 = f4 * static_cast<int64_t>(g3);
187
160k
   const int64_t f4g4 = f4 * static_cast<int64_t>(g4);
188
160k
   const int64_t f4g5 = f4 * static_cast<int64_t>(g5);
189
160k
   const int64_t f4g6_19 = f4 * static_cast<int64_t>(g6_19);
190
160k
   const int64_t f4g7_19 = f4 * static_cast<int64_t>(g7_19);
191
160k
   const int64_t f4g8_19 = f4 * static_cast<int64_t>(g8_19);
192
160k
   const int64_t f4g9_19 = f4 * static_cast<int64_t>(g9_19);
193
160k
   const int64_t f5g0 = f5 * static_cast<int64_t>(g0);
194
160k
   const int64_t f5g1_2 = f5_2 * static_cast<int64_t>(g1);
195
160k
   const int64_t f5g2 = f5 * static_cast<int64_t>(g2);
196
160k
   const int64_t f5g3_2 = f5_2 * static_cast<int64_t>(g3);
197
160k
   const int64_t f5g4 = f5 * static_cast<int64_t>(g4);
198
160k
   const int64_t f5g5_38 = f5_2 * static_cast<int64_t>(g5_19);
199
160k
   const int64_t f5g6_19 = f5 * static_cast<int64_t>(g6_19);
200
160k
   const int64_t f5g7_38 = f5_2 * static_cast<int64_t>(g7_19);
201
160k
   const int64_t f5g8_19 = f5 * static_cast<int64_t>(g8_19);
202
160k
   const int64_t f5g9_38 = f5_2 * static_cast<int64_t>(g9_19);
203
160k
   const int64_t f6g0 = f6 * static_cast<int64_t>(g0);
204
160k
   const int64_t f6g1 = f6 * static_cast<int64_t>(g1);
205
160k
   const int64_t f6g2 = f6 * static_cast<int64_t>(g2);
206
160k
   const int64_t f6g3 = f6 * static_cast<int64_t>(g3);
207
160k
   const int64_t f6g4_19 = f6 * static_cast<int64_t>(g4_19);
208
160k
   const int64_t f6g5_19 = f6 * static_cast<int64_t>(g5_19);
209
160k
   const int64_t f6g6_19 = f6 * static_cast<int64_t>(g6_19);
210
160k
   const int64_t f6g7_19 = f6 * static_cast<int64_t>(g7_19);
211
160k
   const int64_t f6g8_19 = f6 * static_cast<int64_t>(g8_19);
212
160k
   const int64_t f6g9_19 = f6 * static_cast<int64_t>(g9_19);
213
160k
   const int64_t f7g0 = f7 * static_cast<int64_t>(g0);
214
160k
   const int64_t f7g1_2 = f7_2 * static_cast<int64_t>(g1);
215
160k
   const int64_t f7g2 = f7 * static_cast<int64_t>(g2);
216
160k
   const int64_t f7g3_38 = f7_2 * static_cast<int64_t>(g3_19);
217
160k
   const int64_t f7g4_19 = f7 * static_cast<int64_t>(g4_19);
218
160k
   const int64_t f7g5_38 = f7_2 * static_cast<int64_t>(g5_19);
219
160k
   const int64_t f7g6_19 = f7 * static_cast<int64_t>(g6_19);
220
160k
   const int64_t f7g7_38 = f7_2 * static_cast<int64_t>(g7_19);
221
160k
   const int64_t f7g8_19 = f7 * static_cast<int64_t>(g8_19);
222
160k
   const int64_t f7g9_38 = f7_2 * static_cast<int64_t>(g9_19);
223
160k
   const int64_t f8g0 = f8 * static_cast<int64_t>(g0);
224
160k
   const int64_t f8g1 = f8 * static_cast<int64_t>(g1);
225
160k
   const int64_t f8g2_19 = f8 * static_cast<int64_t>(g2_19);
226
160k
   const int64_t f8g3_19 = f8 * static_cast<int64_t>(g3_19);
227
160k
   const int64_t f8g4_19 = f8 * static_cast<int64_t>(g4_19);
228
160k
   const int64_t f8g5_19 = f8 * static_cast<int64_t>(g5_19);
229
160k
   const int64_t f8g6_19 = f8 * static_cast<int64_t>(g6_19);
230
160k
   const int64_t f8g7_19 = f8 * static_cast<int64_t>(g7_19);
231
160k
   const int64_t f8g8_19 = f8 * static_cast<int64_t>(g8_19);
232
160k
   const int64_t f8g9_19 = f8 * static_cast<int64_t>(g9_19);
233
160k
   const int64_t f9g0 = f9 * static_cast<int64_t>(g0);
234
160k
   const int64_t f9g1_38 = f9_2 * static_cast<int64_t>(g1_19);
235
160k
   const int64_t f9g2_19 = f9 * static_cast<int64_t>(g2_19);
236
160k
   const int64_t f9g3_38 = f9_2 * static_cast<int64_t>(g3_19);
237
160k
   const int64_t f9g4_19 = f9 * static_cast<int64_t>(g4_19);
238
160k
   const int64_t f9g5_38 = f9_2 * static_cast<int64_t>(g5_19);
239
160k
   const int64_t f9g6_19 = f9 * static_cast<int64_t>(g6_19);
240
160k
   const int64_t f9g7_38 = f9_2 * static_cast<int64_t>(g7_19);
241
160k
   const int64_t f9g8_19 = f9 * static_cast<int64_t>(g8_19);
242
160k
   const int64_t f9g9_38 = f9_2 * static_cast<int64_t>(g9_19);
243
244
160k
   int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
245
160k
   int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
246
160k
   int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
247
160k
   int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
248
160k
   int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
249
160k
   int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
250
160k
   int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
251
160k
   int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
252
160k
   int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
253
160k
   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
160k
   carry<26>(h0, h1);
262
160k
   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
160k
   carry<25>(h1, h2);
270
160k
   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
160k
   carry<26>(h2, h3);
278
160k
   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
160k
   carry<25>(h3, h4);
285
160k
   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
160k
   carry<26>(h4, h5);
292
160k
   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
160k
   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
160k
   carry<26>(h0, h1);
304
   /* |h0| <= 2^25; from now on fits into int32 unchanged */
305
   /* |h1| <= 1.01*2^24 */
306
307
160k
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
308
160k
}
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
68.6k
Ed25519_FieldElement Ed25519_FieldElement::sqr_iter(size_t iter) const {
327
68.6k
   int32_t f0 = m_fe[0];
328
68.6k
   int32_t f1 = m_fe[1];
329
68.6k
   int32_t f2 = m_fe[2];
330
68.6k
   int32_t f3 = m_fe[3];
331
68.6k
   int32_t f4 = m_fe[4];
332
68.6k
   int32_t f5 = m_fe[5];
333
68.6k
   int32_t f6 = m_fe[6];
334
68.6k
   int32_t f7 = m_fe[7];
335
68.6k
   int32_t f8 = m_fe[8];
336
68.6k
   int32_t f9 = m_fe[9];
337
338
200k
   for(size_t i = 0; i != iter; ++i) {
339
131k
      const int32_t f0_2 = 2 * f0;
340
131k
      const int32_t f1_2 = 2 * f1;
341
131k
      const int32_t f2_2 = 2 * f2;
342
131k
      const int32_t f3_2 = 2 * f3;
343
131k
      const int32_t f4_2 = 2 * f4;
344
131k
      const int32_t f5_2 = 2 * f5;
345
131k
      const int32_t f6_2 = 2 * f6;
346
131k
      const int32_t f7_2 = 2 * f7;
347
131k
      const int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
348
131k
      const int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
349
131k
      const int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
350
131k
      const int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
351
131k
      const int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
352
353
131k
      const int64_t f0f0 = f0 * static_cast<int64_t>(f0);
354
131k
      const int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
355
131k
      const int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
356
131k
      const int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
357
131k
      const int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
358
131k
      const int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
359
131k
      const int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
360
131k
      const int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
361
131k
      const int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
362
131k
      const int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
363
131k
      const int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
364
131k
      const int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
365
131k
      const int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
366
131k
      const int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
367
131k
      const int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
368
131k
      const int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
369
131k
      const int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
370
131k
      const int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
371
131k
      const int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
372
131k
      const int64_t f2f2 = f2 * static_cast<int64_t>(f2);
373
131k
      const int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
374
131k
      const int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
375
131k
      const int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
376
131k
      const int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
377
131k
      const int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
378
131k
      const int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
379
131k
      const int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
380
131k
      const int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
381
131k
      const int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
382
131k
      const int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
383
131k
      const int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
384
131k
      const int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
385
131k
      const int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
386
131k
      const int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
387
131k
      const int64_t f4f4 = f4 * static_cast<int64_t>(f4);
388
131k
      const int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
389
131k
      const int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
390
131k
      const int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
391
131k
      const int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
392
131k
      const int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
393
131k
      const int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
394
131k
      const int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
395
131k
      const int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
396
131k
      const int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
397
131k
      const int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
398
131k
      const int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
399
131k
      const int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
400
131k
      const int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
401
131k
      const int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
402
131k
      const int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
403
131k
      const int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
404
131k
      const int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
405
131k
      const int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
406
131k
      const int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
407
131k
      const int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
408
409
131k
      int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
410
131k
      int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
411
131k
      int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
412
131k
      int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
413
131k
      int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
414
131k
      int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
415
131k
      int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
416
131k
      int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
417
131k
      int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
418
131k
      int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
419
420
131k
      carry<26>(h0, h1);
421
131k
      carry<26>(h4, h5);
422
131k
      carry<25>(h1, h2);
423
131k
      carry<25>(h5, h6);
424
131k
      carry<26>(h2, h3);
425
131k
      carry<26>(h6, h7);
426
427
131k
      carry<25>(h3, h4);
428
131k
      carry<25>(h7, h8);
429
430
131k
      carry<26>(h4, h5);
431
131k
      carry<26>(h8, h9);
432
131k
      carry<25, 19>(h9, h0);
433
131k
      carry<26>(h0, h1);
434
435
131k
      f0 = static_cast<int32_t>(h0);
436
131k
      f1 = static_cast<int32_t>(h1);
437
131k
      f2 = static_cast<int32_t>(h2);
438
131k
      f3 = static_cast<int32_t>(h3);
439
131k
      f4 = static_cast<int32_t>(h4);
440
131k
      f5 = static_cast<int32_t>(h5);
441
131k
      f6 = static_cast<int32_t>(h6);
442
131k
      f7 = static_cast<int32_t>(h7);
443
131k
      f8 = static_cast<int32_t>(h8);
444
131k
      f9 = static_cast<int32_t>(h9);
445
131k
   }
446
447
68.6k
   return Ed25519_FieldElement(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
448
68.6k
}
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
21.8k
Ed25519_FieldElement Ed25519_FieldElement::sqr2() const {
467
21.8k
   const int32_t f0 = m_fe[0];
468
21.8k
   const int32_t f1 = m_fe[1];
469
21.8k
   const int32_t f2 = m_fe[2];
470
21.8k
   const int32_t f3 = m_fe[3];
471
21.8k
   const int32_t f4 = m_fe[4];
472
21.8k
   const int32_t f5 = m_fe[5];
473
21.8k
   const int32_t f6 = m_fe[6];
474
21.8k
   const int32_t f7 = m_fe[7];
475
21.8k
   const int32_t f8 = m_fe[8];
476
21.8k
   const int32_t f9 = m_fe[9];
477
478
21.8k
   const int32_t f0_2 = 2 * f0;
479
21.8k
   const int32_t f1_2 = 2 * f1;
480
21.8k
   const int32_t f2_2 = 2 * f2;
481
21.8k
   const int32_t f3_2 = 2 * f3;
482
21.8k
   const int32_t f4_2 = 2 * f4;
483
21.8k
   const int32_t f5_2 = 2 * f5;
484
21.8k
   const int32_t f6_2 = 2 * f6;
485
21.8k
   const int32_t f7_2 = 2 * f7;
486
21.8k
   const int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
487
21.8k
   const int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
488
21.8k
   const int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
489
21.8k
   const int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
490
21.8k
   const int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
491
21.8k
   const int64_t f0f0 = f0 * static_cast<int64_t>(f0);
492
21.8k
   const int64_t f0f1_2 = f0_2 * static_cast<int64_t>(f1);
493
21.8k
   const int64_t f0f2_2 = f0_2 * static_cast<int64_t>(f2);
494
21.8k
   const int64_t f0f3_2 = f0_2 * static_cast<int64_t>(f3);
495
21.8k
   const int64_t f0f4_2 = f0_2 * static_cast<int64_t>(f4);
496
21.8k
   const int64_t f0f5_2 = f0_2 * static_cast<int64_t>(f5);
497
21.8k
   const int64_t f0f6_2 = f0_2 * static_cast<int64_t>(f6);
498
21.8k
   const int64_t f0f7_2 = f0_2 * static_cast<int64_t>(f7);
499
21.8k
   const int64_t f0f8_2 = f0_2 * static_cast<int64_t>(f8);
500
21.8k
   const int64_t f0f9_2 = f0_2 * static_cast<int64_t>(f9);
501
21.8k
   const int64_t f1f1_2 = f1_2 * static_cast<int64_t>(f1);
502
21.8k
   const int64_t f1f2_2 = f1_2 * static_cast<int64_t>(f2);
503
21.8k
   const int64_t f1f3_4 = f1_2 * static_cast<int64_t>(f3_2);
504
21.8k
   const int64_t f1f4_2 = f1_2 * static_cast<int64_t>(f4);
505
21.8k
   const int64_t f1f5_4 = f1_2 * static_cast<int64_t>(f5_2);
506
21.8k
   const int64_t f1f6_2 = f1_2 * static_cast<int64_t>(f6);
507
21.8k
   const int64_t f1f7_4 = f1_2 * static_cast<int64_t>(f7_2);
508
21.8k
   const int64_t f1f8_2 = f1_2 * static_cast<int64_t>(f8);
509
21.8k
   const int64_t f1f9_76 = f1_2 * static_cast<int64_t>(f9_38);
510
21.8k
   const int64_t f2f2 = f2 * static_cast<int64_t>(f2);
511
21.8k
   const int64_t f2f3_2 = f2_2 * static_cast<int64_t>(f3);
512
21.8k
   const int64_t f2f4_2 = f2_2 * static_cast<int64_t>(f4);
513
21.8k
   const int64_t f2f5_2 = f2_2 * static_cast<int64_t>(f5);
514
21.8k
   const int64_t f2f6_2 = f2_2 * static_cast<int64_t>(f6);
515
21.8k
   const int64_t f2f7_2 = f2_2 * static_cast<int64_t>(f7);
516
21.8k
   const int64_t f2f8_38 = f2_2 * static_cast<int64_t>(f8_19);
517
21.8k
   const int64_t f2f9_38 = f2 * static_cast<int64_t>(f9_38);
518
21.8k
   const int64_t f3f3_2 = f3_2 * static_cast<int64_t>(f3);
519
21.8k
   const int64_t f3f4_2 = f3_2 * static_cast<int64_t>(f4);
520
21.8k
   const int64_t f3f5_4 = f3_2 * static_cast<int64_t>(f5_2);
521
21.8k
   const int64_t f3f6_2 = f3_2 * static_cast<int64_t>(f6);
522
21.8k
   const int64_t f3f7_76 = f3_2 * static_cast<int64_t>(f7_38);
523
21.8k
   const int64_t f3f8_38 = f3_2 * static_cast<int64_t>(f8_19);
524
21.8k
   const int64_t f3f9_76 = f3_2 * static_cast<int64_t>(f9_38);
525
21.8k
   const int64_t f4f4 = f4 * static_cast<int64_t>(f4);
526
21.8k
   const int64_t f4f5_2 = f4_2 * static_cast<int64_t>(f5);
527
21.8k
   const int64_t f4f6_38 = f4_2 * static_cast<int64_t>(f6_19);
528
21.8k
   const int64_t f4f7_38 = f4 * static_cast<int64_t>(f7_38);
529
21.8k
   const int64_t f4f8_38 = f4_2 * static_cast<int64_t>(f8_19);
530
21.8k
   const int64_t f4f9_38 = f4 * static_cast<int64_t>(f9_38);
531
21.8k
   const int64_t f5f5_38 = f5 * static_cast<int64_t>(f5_38);
532
21.8k
   const int64_t f5f6_38 = f5_2 * static_cast<int64_t>(f6_19);
533
21.8k
   const int64_t f5f7_76 = f5_2 * static_cast<int64_t>(f7_38);
534
21.8k
   const int64_t f5f8_38 = f5_2 * static_cast<int64_t>(f8_19);
535
21.8k
   const int64_t f5f9_76 = f5_2 * static_cast<int64_t>(f9_38);
536
21.8k
   const int64_t f6f6_19 = f6 * static_cast<int64_t>(f6_19);
537
21.8k
   const int64_t f6f7_38 = f6 * static_cast<int64_t>(f7_38);
538
21.8k
   const int64_t f6f8_38 = f6_2 * static_cast<int64_t>(f8_19);
539
21.8k
   const int64_t f6f9_38 = f6 * static_cast<int64_t>(f9_38);
540
21.8k
   const int64_t f7f7_38 = f7 * static_cast<int64_t>(f7_38);
541
21.8k
   const int64_t f7f8_38 = f7_2 * static_cast<int64_t>(f8_19);
542
21.8k
   const int64_t f7f9_76 = f7_2 * static_cast<int64_t>(f9_38);
543
21.8k
   const int64_t f8f8_19 = f8 * static_cast<int64_t>(f8_19);
544
21.8k
   const int64_t f8f9_38 = f8 * static_cast<int64_t>(f9_38);
545
21.8k
   const int64_t f9f9_38 = f9 * static_cast<int64_t>(f9_38);
546
547
21.8k
   int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
548
21.8k
   int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
549
21.8k
   int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
550
21.8k
   int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
551
21.8k
   int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
552
21.8k
   int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
553
21.8k
   int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
554
21.8k
   int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
555
21.8k
   int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
556
21.8k
   int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
557
558
21.8k
   h0 += h0;
559
21.8k
   h1 += h1;
560
21.8k
   h2 += h2;
561
21.8k
   h3 += h3;
562
21.8k
   h4 += h4;
563
21.8k
   h5 += h5;
564
21.8k
   h6 += h6;
565
21.8k
   h7 += h7;
566
21.8k
   h8 += h8;
567
21.8k
   h9 += h9;
568
569
21.8k
   carry<26>(h0, h1);
570
21.8k
   carry<26>(h4, h5);
571
572
21.8k
   carry<25>(h1, h2);
573
21.8k
   carry<25>(h5, h6);
574
575
21.8k
   carry<26>(h2, h3);
576
21.8k
   carry<26>(h6, h7);
577
578
21.8k
   carry<25>(h3, h4);
579
21.8k
   carry<25>(h7, h8);
580
21.8k
   carry<26>(h4, h5);
581
21.8k
   carry<26>(h8, h9);
582
21.8k
   carry<25, 19>(h9, h0);
583
21.8k
   carry<26>(h0, h1);
584
585
21.8k
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
586
21.8k
}
587
588
/*
589
Ignores top bit of h.
590
*/
591
86
Ed25519_FieldElement Ed25519_FieldElement::deserialize(const uint8_t s[32]) {
592
86
   int64_t h0 = load_4(s);
593
86
   int64_t h1 = load_3(s + 4) << 6;
594
86
   int64_t h2 = load_3(s + 7) << 5;
595
86
   int64_t h3 = load_3(s + 10) << 3;
596
86
   int64_t h4 = load_3(s + 13) << 2;
597
86
   int64_t h5 = load_4(s + 16);
598
86
   int64_t h6 = load_3(s + 20) << 7;
599
86
   int64_t h7 = load_3(s + 23) << 5;
600
86
   int64_t h8 = load_3(s + 26) << 4;
601
86
   int64_t h9 = (load_3(s + 29) & 0x7fffff) << 2;
602
603
86
   carry<25, 19>(h9, h0);
604
86
   carry<25>(h1, h2);
605
86
   carry<25>(h3, h4);
606
86
   carry<25>(h5, h6);
607
86
   carry<25>(h7, h8);
608
609
86
   carry<26>(h0, h1);
610
86
   carry<26>(h2, h3);
611
86
   carry<26>(h4, h5);
612
86
   carry<26>(h6, h7);
613
86
   carry<26>(h8, h9);
614
615
86
   return Ed25519_FieldElement(h0, h1, h2, h3, h4, h5, h6, h7, h8, h9);
616
86
}
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
566
void Ed25519_FieldElement::serialize_to(std::span<uint8_t, 32> s) const {
644
566
   const int32_t X25 = (1 << 25);
645
646
566
   int32_t h0 = m_fe[0];
647
566
   int32_t h1 = m_fe[1];
648
566
   int32_t h2 = m_fe[2];
649
566
   int32_t h3 = m_fe[3];
650
566
   int32_t h4 = m_fe[4];
651
566
   int32_t h5 = m_fe[5];
652
566
   int32_t h6 = m_fe[6];
653
566
   int32_t h7 = m_fe[7];
654
566
   int32_t h8 = m_fe[8];
655
566
   int32_t h9 = m_fe[9];
656
657
566
   int32_t q = (19 * h9 + ((static_cast<int32_t>(1) << 24))) >> 25;
658
566
   q = (h0 + q) >> 26;
659
566
   q = (h1 + q) >> 25;
660
566
   q = (h2 + q) >> 26;
661
566
   q = (h3 + q) >> 25;
662
566
   q = (h4 + q) >> 26;
663
566
   q = (h5 + q) >> 25;
664
566
   q = (h6 + q) >> 26;
665
566
   q = (h7 + q) >> 25;
666
566
   q = (h8 + q) >> 26;
667
566
   q = (h9 + q) >> 25;
668
669
   /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
670
566
   h0 += 19 * q;
671
   /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
672
673
566
   carry0<26>(h0, h1);
674
566
   carry0<25>(h1, h2);
675
566
   carry0<26>(h2, h3);
676
566
   carry0<25>(h3, h4);
677
566
   carry0<26>(h4, h5);
678
566
   carry0<25>(h5, h6);
679
566
   carry0<26>(h6, h7);
680
566
   carry0<25>(h7, h8);
681
566
   carry0<26>(h8, h9);
682
683
566
   const int32_t carry9 = h9 >> 25;
684
566
   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
566
   s[0] = static_cast<uint8_t>(h0 >> 0);
695
566
   s[1] = static_cast<uint8_t>(h0 >> 8);
696
566
   s[2] = static_cast<uint8_t>(h0 >> 16);
697
566
   s[3] = static_cast<uint8_t>((h0 >> 24) | (h1 << 2));
698
566
   s[4] = static_cast<uint8_t>(h1 >> 6);
699
566
   s[5] = static_cast<uint8_t>(h1 >> 14);
700
566
   s[6] = static_cast<uint8_t>((h1 >> 22) | (h2 << 3));
701
566
   s[7] = static_cast<uint8_t>(h2 >> 5);
702
566
   s[8] = static_cast<uint8_t>(h2 >> 13);
703
566
   s[9] = static_cast<uint8_t>((h2 >> 21) | (h3 << 5));
704
566
   s[10] = static_cast<uint8_t>(h3 >> 3);
705
566
   s[11] = static_cast<uint8_t>(h3 >> 11);
706
566
   s[12] = static_cast<uint8_t>((h3 >> 19) | (h4 << 6));
707
566
   s[13] = static_cast<uint8_t>(h4 >> 2);
708
566
   s[14] = static_cast<uint8_t>(h4 >> 10);
709
566
   s[15] = static_cast<uint8_t>(h4 >> 18);
710
566
   s[16] = static_cast<uint8_t>(h5 >> 0);
711
566
   s[17] = static_cast<uint8_t>(h5 >> 8);
712
566
   s[18] = static_cast<uint8_t>(h5 >> 16);
713
566
   s[19] = static_cast<uint8_t>((h5 >> 24) | (h6 << 1));
714
566
   s[20] = static_cast<uint8_t>(h6 >> 7);
715
566
   s[21] = static_cast<uint8_t>(h6 >> 15);
716
566
   s[22] = static_cast<uint8_t>((h6 >> 23) | (h7 << 3));
717
566
   s[23] = static_cast<uint8_t>(h7 >> 5);
718
566
   s[24] = static_cast<uint8_t>(h7 >> 13);
719
566
   s[25] = static_cast<uint8_t>((h7 >> 21) | (h8 << 4));
720
566
   s[26] = static_cast<uint8_t>(h8 >> 4);
721
566
   s[27] = static_cast<uint8_t>(h8 >> 12);
722
566
   s[28] = static_cast<uint8_t>((h8 >> 20) | (h9 << 6));
723
566
   s[29] = static_cast<uint8_t>(h9 >> 2);
724
566
   s[30] = static_cast<uint8_t>(h9 >> 10);
725
566
   s[31] = static_cast<uint8_t>(h9 >> 18);
726
566
}
727
728
}  // namespace Botan