comparison NaCl/crypto_sign/ed25519.cs @ 73:6aca18ee4ec6

NaCl: improved ed25519 implementation, added simple API for ed25519 and sha512
author Ivo Smits <Ivo@UCIS.nl>
date Sat, 02 Nov 2013 16:01:09 +0100
parents 7e9d1cfcc562
children
comparison
equal deleted inserted replaced
72:b7d981ccd434 73:6aca18ee4ec6
1 using System; 1 using System;
2 using System.Text; 2 using System.Text;
3 using UCIS.NaCl.crypto_hash;
3 4
4 namespace UCIS.NaCl.crypto_sign { 5 namespace UCIS.NaCl.crypto_sign {
5 public static class ed25519 { 6 public static class ed25519 {
6 public const int SECRETKEYBYTES = 64; 7 public const int SECRETKEYBYTES = 64;
7 public const int PUBLICKEYBYTES = 32; 8 public const int PUBLICKEYBYTES = 32;
8 public const int SEEDBYTES = 32; 9 public const int SEEDBYTES = 32;
9 public const int BYTES = 64; 10 public const int BYTES = 64;
10 11
11 unsafe struct fe { 12 unsafe struct fe {
12 fixed Int32 v[10]; 13 Int32 v0, v1, v2, v3, v4, v5, v6, v7, v8, v9;
13 public int this[int index] {
14 get { fixed (Int32* vp = v) return vp[index]; }
15 set { fixed (Int32* vp = v) vp[index] = value; }
16 }
17 public override string ToString() { 14 public override string ToString() {
18 return String.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}", this[0], this[1], this[2], this[3], this[4], this[5], this[6], this[7], this[8], this[9]); 15 return String.Format("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}", v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
16 }
17 public fe(int offset, Int32[] data) {
18 v0 = data[offset + 0];
19 v1 = data[offset + 1];
20 v2 = data[offset + 2];
21 v3 = data[offset + 3];
22 v4 = data[offset + 4];
23 v5 = data[offset + 5];
24 v6 = data[offset + 6];
25 v7 = data[offset + 7];
26 v8 = data[offset + 8];
27 v9 = data[offset + 9];
28 }
29 public void set_zero() {
30 v0 = v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = 0;
31 }
32 public void set_one() {
33 v0 = 1;
34 v1 = v2 = v3 = v4 = v5 = v6 = v7 = v8 = v9 = 0;
35 }
36 public void cmov(ref fe g, Int32 b) {
37 b = -b;
38 v0 ^= (v0 ^ g.v0) & b;
39 v1 ^= (v1 ^ g.v1) & b;
40 v2 ^= (v2 ^ g.v2) & b;
41 v3 ^= (v3 ^ g.v3) & b;
42 v4 ^= (v4 ^ g.v4) & b;
43 v5 ^= (v5 ^ g.v5) & b;
44 v6 ^= (v6 ^ g.v6) & b;
45 v7 ^= (v7 ^ g.v7) & b;
46 v8 ^= (v8 ^ g.v8) & b;
47 v9 ^= (v9 ^ g.v9) & b;
48 }
49 public void neg() {
50 v0 = -v0;
51 v1 = -v1;
52 v2 = -v2;
53 v3 = -v3;
54 v4 = -v4;
55 v5 = -v5;
56 v6 = -v6;
57 v7 = -v7;
58 v8 = -v8;
59 v9 = -v9;
60 }
61 public void add(ref fe g) {
62 v0 += g.v0;
63 v1 += g.v1;
64 v2 += g.v2;
65 v3 += g.v3;
66 v4 += g.v4;
67 v5 += g.v5;
68 v6 += g.v6;
69 v7 += g.v7;
70 v8 += g.v8;
71 v9 += g.v9;
72 }
73 public void sub(ref fe g) {
74 v0 -= g.v0;
75 v1 -= g.v1;
76 v2 -= g.v2;
77 v3 -= g.v3;
78 v4 -= g.v4;
79 v5 -= g.v5;
80 v6 -= g.v6;
81 v7 -= g.v7;
82 v8 -= g.v8;
83 v9 -= g.v9;
84 }
85 public void mul(ref fe g) {
86 Int32 f0 = v0;
87 Int32 f1 = v1;
88 Int32 f2 = v2;
89 Int32 f3 = v3;
90 Int32 f4 = v4;
91 Int32 f5 = v5;
92 Int32 f6 = v6;
93 Int32 f7 = v7;
94 Int32 f8 = v8;
95 Int32 f9 = v9;
96 Int32 g0 = g.v0;
97 Int32 g1 = g.v1;
98 Int32 g2 = g.v2;
99 Int32 g3 = g.v3;
100 Int32 g4 = g.v4;
101 Int32 g5 = g.v5;
102 Int32 g6 = g.v6;
103 Int32 g7 = g.v7;
104 Int32 g8 = g.v8;
105 Int32 g9 = g.v9;
106 Int32 g1_19 = 19 * g1; /* 1.959375*2^29 */
107 Int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
108 Int32 g3_19 = 19 * g3;
109 Int32 g4_19 = 19 * g4;
110 Int32 g5_19 = 19 * g5;
111 Int32 g6_19 = 19 * g6;
112 Int32 g7_19 = 19 * g7;
113 Int32 g8_19 = 19 * g8;
114 Int32 g9_19 = 19 * g9;
115 Int32 f1_2 = 2 * f1;
116 Int32 f3_2 = 2 * f3;
117 Int32 f5_2 = 2 * f5;
118 Int32 f7_2 = 2 * f7;
119 Int32 f9_2 = 2 * f9;
120 Int64 f0g0 = f0 * (Int64)g0;
121 Int64 f0g1 = f0 * (Int64)g1;
122 Int64 f0g2 = f0 * (Int64)g2;
123 Int64 f0g3 = f0 * (Int64)g3;
124 Int64 f0g4 = f0 * (Int64)g4;
125 Int64 f0g5 = f0 * (Int64)g5;
126 Int64 f0g6 = f0 * (Int64)g6;
127 Int64 f0g7 = f0 * (Int64)g7;
128 Int64 f0g8 = f0 * (Int64)g8;
129 Int64 f0g9 = f0 * (Int64)g9;
130 Int64 f1g0 = f1 * (Int64)g0;
131 Int64 f1g1_2 = f1_2 * (Int64)g1;
132 Int64 f1g2 = f1 * (Int64)g2;
133 Int64 f1g3_2 = f1_2 * (Int64)g3;
134 Int64 f1g4 = f1 * (Int64)g4;
135 Int64 f1g5_2 = f1_2 * (Int64)g5;
136 Int64 f1g6 = f1 * (Int64)g6;
137 Int64 f1g7_2 = f1_2 * (Int64)g7;
138 Int64 f1g8 = f1 * (Int64)g8;
139 Int64 f1g9_38 = f1_2 * (Int64)g9_19;
140 Int64 f2g0 = f2 * (Int64)g0;
141 Int64 f2g1 = f2 * (Int64)g1;
142 Int64 f2g2 = f2 * (Int64)g2;
143 Int64 f2g3 = f2 * (Int64)g3;
144 Int64 f2g4 = f2 * (Int64)g4;
145 Int64 f2g5 = f2 * (Int64)g5;
146 Int64 f2g6 = f2 * (Int64)g6;
147 Int64 f2g7 = f2 * (Int64)g7;
148 Int64 f2g8_19 = f2 * (Int64)g8_19;
149 Int64 f2g9_19 = f2 * (Int64)g9_19;
150 Int64 f3g0 = f3 * (Int64)g0;
151 Int64 f3g1_2 = f3_2 * (Int64)g1;
152 Int64 f3g2 = f3 * (Int64)g2;
153 Int64 f3g3_2 = f3_2 * (Int64)g3;
154 Int64 f3g4 = f3 * (Int64)g4;
155 Int64 f3g5_2 = f3_2 * (Int64)g5;
156 Int64 f3g6 = f3 * (Int64)g6;
157 Int64 f3g7_38 = f3_2 * (Int64)g7_19;
158 Int64 f3g8_19 = f3 * (Int64)g8_19;
159 Int64 f3g9_38 = f3_2 * (Int64)g9_19;
160 Int64 f4g0 = f4 * (Int64)g0;
161 Int64 f4g1 = f4 * (Int64)g1;
162 Int64 f4g2 = f4 * (Int64)g2;
163 Int64 f4g3 = f4 * (Int64)g3;
164 Int64 f4g4 = f4 * (Int64)g4;
165 Int64 f4g5 = f4 * (Int64)g5;
166 Int64 f4g6_19 = f4 * (Int64)g6_19;
167 Int64 f4g7_19 = f4 * (Int64)g7_19;
168 Int64 f4g8_19 = f4 * (Int64)g8_19;
169 Int64 f4g9_19 = f4 * (Int64)g9_19;
170 Int64 f5g0 = f5 * (Int64)g0;
171 Int64 f5g1_2 = f5_2 * (Int64)g1;
172 Int64 f5g2 = f5 * (Int64)g2;
173 Int64 f5g3_2 = f5_2 * (Int64)g3;
174 Int64 f5g4 = f5 * (Int64)g4;
175 Int64 f5g5_38 = f5_2 * (Int64)g5_19;
176 Int64 f5g6_19 = f5 * (Int64)g6_19;
177 Int64 f5g7_38 = f5_2 * (Int64)g7_19;
178 Int64 f5g8_19 = f5 * (Int64)g8_19;
179 Int64 f5g9_38 = f5_2 * (Int64)g9_19;
180 Int64 f6g0 = f6 * (Int64)g0;
181 Int64 f6g1 = f6 * (Int64)g1;
182 Int64 f6g2 = f6 * (Int64)g2;
183 Int64 f6g3 = f6 * (Int64)g3;
184 Int64 f6g4_19 = f6 * (Int64)g4_19;
185 Int64 f6g5_19 = f6 * (Int64)g5_19;
186 Int64 f6g6_19 = f6 * (Int64)g6_19;
187 Int64 f6g7_19 = f6 * (Int64)g7_19;
188 Int64 f6g8_19 = f6 * (Int64)g8_19;
189 Int64 f6g9_19 = f6 * (Int64)g9_19;
190 Int64 f7g0 = f7 * (Int64)g0;
191 Int64 f7g1_2 = f7_2 * (Int64)g1;
192 Int64 f7g2 = f7 * (Int64)g2;
193 Int64 f7g3_38 = f7_2 * (Int64)g3_19;
194 Int64 f7g4_19 = f7 * (Int64)g4_19;
195 Int64 f7g5_38 = f7_2 * (Int64)g5_19;
196 Int64 f7g6_19 = f7 * (Int64)g6_19;
197 Int64 f7g7_38 = f7_2 * (Int64)g7_19;
198 Int64 f7g8_19 = f7 * (Int64)g8_19;
199 Int64 f7g9_38 = f7_2 * (Int64)g9_19;
200 Int64 f8g0 = f8 * (Int64)g0;
201 Int64 f8g1 = f8 * (Int64)g1;
202 Int64 f8g2_19 = f8 * (Int64)g2_19;
203 Int64 f8g3_19 = f8 * (Int64)g3_19;
204 Int64 f8g4_19 = f8 * (Int64)g4_19;
205 Int64 f8g5_19 = f8 * (Int64)g5_19;
206 Int64 f8g6_19 = f8 * (Int64)g6_19;
207 Int64 f8g7_19 = f8 * (Int64)g7_19;
208 Int64 f8g8_19 = f8 * (Int64)g8_19;
209 Int64 f8g9_19 = f8 * (Int64)g9_19;
210 Int64 f9g0 = f9 * (Int64)g0;
211 Int64 f9g1_38 = f9_2 * (Int64)g1_19;
212 Int64 f9g2_19 = f9 * (Int64)g2_19;
213 Int64 f9g3_38 = f9_2 * (Int64)g3_19;
214 Int64 f9g4_19 = f9 * (Int64)g4_19;
215 Int64 f9g5_38 = f9_2 * (Int64)g5_19;
216 Int64 f9g6_19 = f9 * (Int64)g6_19;
217 Int64 f9g7_38 = f9_2 * (Int64)g7_19;
218 Int64 f9g8_19 = f9 * (Int64)g8_19;
219 Int64 f9g9_38 = f9_2 * (Int64)g9_19;
220 Int64 h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
221 Int64 h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
222 Int64 h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
223 Int64 h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
224 Int64 h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
225 Int64 h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
226 Int64 h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
227 Int64 h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
228 Int64 h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
229 Int64 h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
230 Int64 carry0;
231 Int64 carry1;
232 Int64 carry2;
233 Int64 carry3;
234 Int64 carry4;
235 Int64 carry5;
236 Int64 carry6;
237 Int64 carry7;
238 Int64 carry8;
239 Int64 carry9;
240 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
241 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
242 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
243 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
244 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
245 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
246 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
247 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
248 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
249 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
250 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
251 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
252 v0 = (Int32)h0;
253 v1 = (Int32)h1;
254 v2 = (Int32)h2;
255 v3 = (Int32)h3;
256 v4 = (Int32)h4;
257 v5 = (Int32)h5;
258 v6 = (Int32)h6;
259 v7 = (Int32)h7;
260 v8 = (Int32)h8;
261 v9 = (Int32)h9;
262 }
263 public void sq() {
264 Int32 f0 = v0;
265 Int32 f1 = v1;
266 Int32 f2 = v2;
267 Int32 f3 = v3;
268 Int32 f4 = v4;
269 Int32 f5 = v5;
270 Int32 f6 = v6;
271 Int32 f7 = v7;
272 Int32 f8 = v8;
273 Int32 f9 = v9;
274 Int32 f0_2 = 2 * f0;
275 Int32 f1_2 = 2 * f1;
276 Int32 f2_2 = 2 * f2;
277 Int32 f3_2 = 2 * f3;
278 Int32 f4_2 = 2 * f4;
279 Int32 f5_2 = 2 * f5;
280 Int32 f6_2 = 2 * f6;
281 Int32 f7_2 = 2 * f7;
282 Int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
283 Int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
284 Int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
285 Int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
286 Int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
287 Int64 f0f0 = f0 * (Int64)f0;
288 Int64 f0f1_2 = f0_2 * (Int64)f1;
289 Int64 f0f2_2 = f0_2 * (Int64)f2;
290 Int64 f0f3_2 = f0_2 * (Int64)f3;
291 Int64 f0f4_2 = f0_2 * (Int64)f4;
292 Int64 f0f5_2 = f0_2 * (Int64)f5;
293 Int64 f0f6_2 = f0_2 * (Int64)f6;
294 Int64 f0f7_2 = f0_2 * (Int64)f7;
295 Int64 f0f8_2 = f0_2 * (Int64)f8;
296 Int64 f0f9_2 = f0_2 * (Int64)f9;
297 Int64 f1f1_2 = f1_2 * (Int64)f1;
298 Int64 f1f2_2 = f1_2 * (Int64)f2;
299 Int64 f1f3_4 = f1_2 * (Int64)f3_2;
300 Int64 f1f4_2 = f1_2 * (Int64)f4;
301 Int64 f1f5_4 = f1_2 * (Int64)f5_2;
302 Int64 f1f6_2 = f1_2 * (Int64)f6;
303 Int64 f1f7_4 = f1_2 * (Int64)f7_2;
304 Int64 f1f8_2 = f1_2 * (Int64)f8;
305 Int64 f1f9_76 = f1_2 * (Int64)f9_38;
306 Int64 f2f2 = f2 * (Int64)f2;
307 Int64 f2f3_2 = f2_2 * (Int64)f3;
308 Int64 f2f4_2 = f2_2 * (Int64)f4;
309 Int64 f2f5_2 = f2_2 * (Int64)f5;
310 Int64 f2f6_2 = f2_2 * (Int64)f6;
311 Int64 f2f7_2 = f2_2 * (Int64)f7;
312 Int64 f2f8_38 = f2_2 * (Int64)f8_19;
313 Int64 f2f9_38 = f2 * (Int64)f9_38;
314 Int64 f3f3_2 = f3_2 * (Int64)f3;
315 Int64 f3f4_2 = f3_2 * (Int64)f4;
316 Int64 f3f5_4 = f3_2 * (Int64)f5_2;
317 Int64 f3f6_2 = f3_2 * (Int64)f6;
318 Int64 f3f7_76 = f3_2 * (Int64)f7_38;
319 Int64 f3f8_38 = f3_2 * (Int64)f8_19;
320 Int64 f3f9_76 = f3_2 * (Int64)f9_38;
321 Int64 f4f4 = f4 * (Int64)f4;
322 Int64 f4f5_2 = f4_2 * (Int64)f5;
323 Int64 f4f6_38 = f4_2 * (Int64)f6_19;
324 Int64 f4f7_38 = f4 * (Int64)f7_38;
325 Int64 f4f8_38 = f4_2 * (Int64)f8_19;
326 Int64 f4f9_38 = f4 * (Int64)f9_38;
327 Int64 f5f5_38 = f5 * (Int64)f5_38;
328 Int64 f5f6_38 = f5_2 * (Int64)f6_19;
329 Int64 f5f7_76 = f5_2 * (Int64)f7_38;
330 Int64 f5f8_38 = f5_2 * (Int64)f8_19;
331 Int64 f5f9_76 = f5_2 * (Int64)f9_38;
332 Int64 f6f6_19 = f6 * (Int64)f6_19;
333 Int64 f6f7_38 = f6 * (Int64)f7_38;
334 Int64 f6f8_38 = f6_2 * (Int64)f8_19;
335 Int64 f6f9_38 = f6 * (Int64)f9_38;
336 Int64 f7f7_38 = f7 * (Int64)f7_38;
337 Int64 f7f8_38 = f7_2 * (Int64)f8_19;
338 Int64 f7f9_76 = f7_2 * (Int64)f9_38;
339 Int64 f8f8_19 = f8 * (Int64)f8_19;
340 Int64 f8f9_38 = f8 * (Int64)f9_38;
341 Int64 f9f9_38 = f9 * (Int64)f9_38;
342 Int64 h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
343 Int64 h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
344 Int64 h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
345 Int64 h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
346 Int64 h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
347 Int64 h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
348 Int64 h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
349 Int64 h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
350 Int64 h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
351 Int64 h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
352 Int64 carry0;
353 Int64 carry1;
354 Int64 carry2;
355 Int64 carry3;
356 Int64 carry4;
357 Int64 carry5;
358 Int64 carry6;
359 Int64 carry7;
360 Int64 carry8;
361 Int64 carry9;
362
363 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
364 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
365
366 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
367 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
368
369 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
370 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
371
372 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
373 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
374
375 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
376 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
377
378 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
379
380 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
381
382 v0 = (Int32)h0;
383 v1 = (Int32)h1;
384 v2 = (Int32)h2;
385 v3 = (Int32)h3;
386 v4 = (Int32)h4;
387 v5 = (Int32)h5;
388 v6 = (Int32)h6;
389 v7 = (Int32)h7;
390 v8 = (Int32)h8;
391 v9 = (Int32)h9;
392 }
393 public void sq2() {
394 Int32 f0 = v0;
395 Int32 f1 = v1;
396 Int32 f2 = v2;
397 Int32 f3 = v3;
398 Int32 f4 = v4;
399 Int32 f5 = v5;
400 Int32 f6 = v6;
401 Int32 f7 = v7;
402 Int32 f8 = v8;
403 Int32 f9 = v9;
404 Int32 f0_2 = 2 * f0;
405 Int32 f1_2 = 2 * f1;
406 Int32 f2_2 = 2 * f2;
407 Int32 f3_2 = 2 * f3;
408 Int32 f4_2 = 2 * f4;
409 Int32 f5_2 = 2 * f5;
410 Int32 f6_2 = 2 * f6;
411 Int32 f7_2 = 2 * f7;
412 Int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
413 Int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
414 Int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
415 Int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
416 Int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
417 Int64 f0f0 = f0 * (Int64)f0;
418 Int64 f0f1_2 = f0_2 * (Int64)f1;
419 Int64 f0f2_2 = f0_2 * (Int64)f2;
420 Int64 f0f3_2 = f0_2 * (Int64)f3;
421 Int64 f0f4_2 = f0_2 * (Int64)f4;
422 Int64 f0f5_2 = f0_2 * (Int64)f5;
423 Int64 f0f6_2 = f0_2 * (Int64)f6;
424 Int64 f0f7_2 = f0_2 * (Int64)f7;
425 Int64 f0f8_2 = f0_2 * (Int64)f8;
426 Int64 f0f9_2 = f0_2 * (Int64)f9;
427 Int64 f1f1_2 = f1_2 * (Int64)f1;
428 Int64 f1f2_2 = f1_2 * (Int64)f2;
429 Int64 f1f3_4 = f1_2 * (Int64)f3_2;
430 Int64 f1f4_2 = f1_2 * (Int64)f4;
431 Int64 f1f5_4 = f1_2 * (Int64)f5_2;
432 Int64 f1f6_2 = f1_2 * (Int64)f6;
433 Int64 f1f7_4 = f1_2 * (Int64)f7_2;
434 Int64 f1f8_2 = f1_2 * (Int64)f8;
435 Int64 f1f9_76 = f1_2 * (Int64)f9_38;
436 Int64 f2f2 = f2 * (Int64)f2;
437 Int64 f2f3_2 = f2_2 * (Int64)f3;
438 Int64 f2f4_2 = f2_2 * (Int64)f4;
439 Int64 f2f5_2 = f2_2 * (Int64)f5;
440 Int64 f2f6_2 = f2_2 * (Int64)f6;
441 Int64 f2f7_2 = f2_2 * (Int64)f7;
442 Int64 f2f8_38 = f2_2 * (Int64)f8_19;
443 Int64 f2f9_38 = f2 * (Int64)f9_38;
444 Int64 f3f3_2 = f3_2 * (Int64)f3;
445 Int64 f3f4_2 = f3_2 * (Int64)f4;
446 Int64 f3f5_4 = f3_2 * (Int64)f5_2;
447 Int64 f3f6_2 = f3_2 * (Int64)f6;
448 Int64 f3f7_76 = f3_2 * (Int64)f7_38;
449 Int64 f3f8_38 = f3_2 * (Int64)f8_19;
450 Int64 f3f9_76 = f3_2 * (Int64)f9_38;
451 Int64 f4f4 = f4 * (Int64)f4;
452 Int64 f4f5_2 = f4_2 * (Int64)f5;
453 Int64 f4f6_38 = f4_2 * (Int64)f6_19;
454 Int64 f4f7_38 = f4 * (Int64)f7_38;
455 Int64 f4f8_38 = f4_2 * (Int64)f8_19;
456 Int64 f4f9_38 = f4 * (Int64)f9_38;
457 Int64 f5f5_38 = f5 * (Int64)f5_38;
458 Int64 f5f6_38 = f5_2 * (Int64)f6_19;
459 Int64 f5f7_76 = f5_2 * (Int64)f7_38;
460 Int64 f5f8_38 = f5_2 * (Int64)f8_19;
461 Int64 f5f9_76 = f5_2 * (Int64)f9_38;
462 Int64 f6f6_19 = f6 * (Int64)f6_19;
463 Int64 f6f7_38 = f6 * (Int64)f7_38;
464 Int64 f6f8_38 = f6_2 * (Int64)f8_19;
465 Int64 f6f9_38 = f6 * (Int64)f9_38;
466 Int64 f7f7_38 = f7 * (Int64)f7_38;
467 Int64 f7f8_38 = f7_2 * (Int64)f8_19;
468 Int64 f7f9_76 = f7_2 * (Int64)f9_38;
469 Int64 f8f8_19 = f8 * (Int64)f8_19;
470 Int64 f8f9_38 = f8 * (Int64)f9_38;
471 Int64 f9f9_38 = f9 * (Int64)f9_38;
472 Int64 h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
473 Int64 h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
474 Int64 h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
475 Int64 h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
476 Int64 h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
477 Int64 h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
478 Int64 h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
479 Int64 h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
480 Int64 h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
481 Int64 h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
482 Int64 carry0;
483 Int64 carry1;
484 Int64 carry2;
485 Int64 carry3;
486 Int64 carry4;
487 Int64 carry5;
488 Int64 carry6;
489 Int64 carry7;
490 Int64 carry8;
491 Int64 carry9;
492
493 h0 += h0;
494 h1 += h1;
495 h2 += h2;
496 h3 += h3;
497 h4 += h4;
498 h5 += h5;
499 h6 += h6;
500 h7 += h7;
501 h8 += h8;
502 h9 += h9;
503
504 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
505 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
506
507 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
508 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
509
510 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
511 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
512
513 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
514 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
515
516 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
517 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
518
519 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
520
521 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
522
523 v0 = (Int32)h0;
524 v1 = (Int32)h1;
525 v2 = (Int32)h2;
526 v3 = (Int32)h3;
527 v4 = (Int32)h4;
528 v5 = (Int32)h5;
529 v6 = (Int32)h6;
530 v7 = (Int32)h7;
531 v8 = (Int32)h8;
532 v9 = (Int32)h9;
533 }
534 public void invert() {
535 fe t0 = this;
536 t0.sq();
537 fe t1 = t0;
538 t1.sq();
539 t1.sq();
540 mul(ref t1);
541 t0.mul(ref this);
542 fe t2 = t0;
543 t2.sq();
544 mul(ref t2);
545 t1 = this;
546 for (int i = 1; i < 6; i++) sq();
547 mul(ref t1);
548 t1 = this;
549 for (int i = 1; i < 11; i++) sq();
550 mul(ref t1);
551 t2 = this;
552 for (int i = 1; i < 21; i++) sq();
553 mul(ref t2);
554 for (int i = 1; i < 11; ++i) sq();
555 this.mul(ref t1);
556 t1 = this;
557 for (int i = 1; i < 51; i++) sq();
558 mul(ref t1);
559 t2 = this;
560 for (int i = 1; i < 101; i++) sq();
561 mul(ref t2);
562 for (int i = 1; i < 51; i++) sq();
563 mul(ref t1);
564 for (int i = 1; i < 6; i++) sq();
565 mul(ref t0);
566 }
567 public unsafe void tobytes(Byte* s) {
568 Int32 h0 = v0, h1 = v1, h2 = v2, h3 = v3, h4 = v4, h5 = v5, h6 = v6, h7 = v7, h8 = v8, h9 = v9;
569 Int32 q = (19 * h9 + (((Int32)1) << 24)) >> 25;
570 q = (h0 + q) >> 26;
571 q = (h1 + q) >> 25;
572 q = (h2 + q) >> 26;
573 q = (h3 + q) >> 25;
574 q = (h4 + q) >> 26;
575 q = (h5 + q) >> 25;
576 q = (h6 + q) >> 26;
577 q = (h7 + q) >> 25;
578 q = (h8 + q) >> 26;
579 q = (h9 + q) >> 25;
580 h0 += 19 * q;
581 Int32 carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
582 Int32 carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
583 Int32 carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
584 Int32 carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
585 Int32 carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
586 Int32 carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
587 Int32 carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
588 Int32 carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
589 Int32 carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
590 Int32 carry9 = h9 >> 25; h9 -= carry9 << 25;
591 s[0] = (Byte)(h0 >> 0);
592 s[1] = (Byte)(h0 >> 8);
593 s[2] = (Byte)(h0 >> 16);
594 s[3] = (Byte)((h0 >> 24) | (h1 << 2));
595 s[4] = (Byte)(h1 >> 6);
596 s[5] = (Byte)(h1 >> 14);
597 s[6] = (Byte)((h1 >> 22) | (h2 << 3));
598 s[7] = (Byte)(h2 >> 5);
599 s[8] = (Byte)(h2 >> 13);
600 s[9] = (Byte)((h2 >> 21) | (h3 << 5));
601 s[10] = (Byte)(h3 >> 3);
602 s[11] = (Byte)(h3 >> 11);
603 s[12] = (Byte)((h3 >> 19) | (h4 << 6));
604 s[13] = (Byte)(h4 >> 2);
605 s[14] = (Byte)(h4 >> 10);
606 s[15] = (Byte)(h4 >> 18);
607 s[16] = (Byte)(h5 >> 0);
608 s[17] = (Byte)(h5 >> 8);
609 s[18] = (Byte)(h5 >> 16);
610 s[19] = (Byte)((h5 >> 24) | (h6 << 1));
611 s[20] = (Byte)(h6 >> 7);
612 s[21] = (Byte)(h6 >> 15);
613 s[22] = (Byte)((h6 >> 23) | (h7 << 3));
614 s[23] = (Byte)(h7 >> 5);
615 s[24] = (Byte)(h7 >> 13);
616 s[25] = (Byte)((h7 >> 21) | (h8 << 4));
617 s[26] = (Byte)(h8 >> 4);
618 s[27] = (Byte)(h8 >> 12);
619 s[28] = (Byte)((h8 >> 20) | (h9 << 6));
620 s[29] = (Byte)(h9 >> 2);
621 s[30] = (Byte)(h9 >> 10);
622 s[31] = (Byte)(h9 >> 18);
623 }
624 public int isnegative() {
625 Int32 h0 = v0, h9 = v9;
626 Int32 q = (19 * h9 + (1 << 24)) >> 25;
627 q = (h0 + q) >> 26;
628 q = (v1 + q) >> 25;
629 q = (v2 + q) >> 26;
630 q = (v3 + q) >> 25;
631 q = (v4 + q) >> 26;
632 q = (v5 + q) >> 25;
633 q = (v6 + q) >> 26;
634 q = (v7 + q) >> 25;
635 q = (v8 + q) >> 26;
636 q = (h9 + q) >> 25;
637 h0 += 19 * q;
638 h0 -= (h0 >> 26) << 26;
639 return (h0 >> 0) & 1;
640 }
641 public unsafe void frombytes(Byte* s) {
642 Int64 h0 = load_4(s);
643 Int64 h1 = load_3(s + 4) << 6;
644 Int64 h2 = load_3(s + 7) << 5;
645 Int64 h3 = load_3(s + 10) << 3;
646 Int64 h4 = load_3(s + 13) << 2;
647 Int64 h5 = load_4(s + 16);
648 Int64 h6 = load_3(s + 20) << 7;
649 Int64 h7 = load_3(s + 23) << 5;
650 Int64 h8 = load_3(s + 26) << 4;
651 Int64 h9 = (load_3(s + 29) & 8388607) << 2;
652
653 Int64 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
654 Int64 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
655 Int64 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
656 Int64 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
657 Int64 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
658
659 Int64 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
660 Int64 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
661 Int64 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
662 Int64 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
663 Int64 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
664
665 v0 = (Int32)h0;
666 v1 = (Int32)h1;
667 v2 = (Int32)h2;
668 v3 = (Int32)h3;
669 v4 = (Int32)h4;
670 v5 = (Int32)h5;
671 v6 = (Int32)h6;
672 v7 = (Int32)h7;
673 v8 = (Int32)h8;
674 v9 = (Int32)h9;
675 }
676 public int isnonzero() {
677 Int32 h0 = v0, h1 = v1, h2 = v2, h3 = v3, h4 = v4, h5 = v5, h6 = v6, h7 = v7, h8 = v8, h9 = v9;
678 Int32 q = (19 * h9 + (((Int32)1) << 24)) >> 25;
679 q = (h0 + q) >> 26;
680 q = (h1 + q) >> 25;
681 q = (h2 + q) >> 26;
682 q = (h3 + q) >> 25;
683 q = (h4 + q) >> 26;
684 q = (h5 + q) >> 25;
685 q = (h6 + q) >> 26;
686 q = (h7 + q) >> 25;
687 q = (h8 + q) >> 26;
688 q = (h9 + q) >> 25;
689 h0 += 19 * q;
690 Int32 carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
691 Int32 carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
692 Int32 carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
693 Int32 carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
694 Int32 carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
695 Int32 carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
696 Int32 carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
697 Int32 carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
698 Int32 carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
699 Int32 carry9 = h9 >> 25; h9 -= carry9 << 25;
700 Int32 b = h0 | h1 | h2 | h3 | h4 | h5 | h6 | h7 | h8 | h9;
701 b = (b | (b >> 8) | (b >> 16) | (b >> 24)) & 0xff;
702 return (1 & ((b - 1) >> 8)) - 1;
703 }
704 public void pow22523() {
705 fe t0 = this;
706 t0.sq();
707 fe t1 = t0;
708 for (int i = 1; i < 3; i++) t1.sq();
709 fe t2 = this;
710 mul(ref t1);
711 t0.mul(ref this);
712 t0.sq();
713 mul(ref t0);
714 t0 = this;
715 for (int i = 1; i < 6; i++) sq();
716 mul(ref t0);
717 t0 = this;
718 for (int i = 1; i < 11; i++) sq();
719 mul(ref t0);
720 t1 = this;
721 for (int i = 1; i < 21; i++) sq();
722 mul(ref t1);
723 for (int i = 1; i < 11; i++) sq();
724 mul(ref t0);
725 t0 = this;
726 for (int i = 1; i < 51; i++) sq();
727 mul(ref t0);
728 t1 = this;
729 for (int i = 1; i < 101; i++) sq();
730 mul(ref t1);
731 for (int i = 1; i < 51; i++) sq();
732 mul(ref t0);
733 for (int i = 1; i < 3; i++) sq();
734 mul(ref t2);
19 } 735 }
20 } 736 }
21 struct ge_precomp { 737 struct ge_precomp {
22 public fe yplusx; 738 public fe yplusx;
23 public fe yminusx; 739 public fe yminusx;
24 public fe xy2d; 740 public fe xy2d;
25 public ge_precomp(Int32[] data, int offset) 741 public ge_precomp(Int32[] data, int offset)
26 : this() { 742 : this() {
27 yplusx = fe_unpack(offset + 0 * 10, data); 743 yplusx = new fe(offset + 0 * 10, data);
28 yminusx = fe_unpack(offset + 1 * 10, data); 744 yminusx = new fe(offset + 1 * 10, data);
29 xy2d = fe_unpack(offset + 2 * 10, data); 745 xy2d = new fe(offset + 2 * 10, data);
746 }
747 public void set_zero() {
748 yplusx.set_one();
749 yminusx.set_one();
750 xy2d.set_zero();
751 }
752 public void cmov(ref ge_precomp u, Byte b) {
753 yplusx.cmov(ref u.yplusx, b);
754 yminusx.cmov(ref u.yminusx, b);
755 xy2d.cmov(ref u.xy2d, b);
30 } 756 }
31 } 757 }
32 struct ge_p1p1 { 758 struct ge_p1p1 {
33 public fe X; 759 public fe X;
34 public fe Y; 760 public fe Y;
37 } 763 }
38 struct ge_p2 { 764 struct ge_p2 {
39 public fe X; 765 public fe X;
40 public fe Y; 766 public fe Y;
41 public fe Z; 767 public fe Z;
768 public void set_zero() {
769 X.set_zero();
770 Y.set_one();
771 Z.set_one();
772 }
42 } 773 }
43 struct ge_p3 { 774 struct ge_p3 {
44 public fe X; 775 public fe X;
45 public fe Y; 776 public fe Y;
46 public fe Z; 777 public fe Z;
47 public fe T; 778 public fe T;
48 } 779 public void set_zero() {
49 780 X.set_zero();
50 static fe fe_unpack(int offset, Int32[] data) { 781 Y.set_one();
51 fe ret = new fe(); 782 Z.set_one();
52 for (int i = 0; i < 10; i++) ret[i] = data[offset + i]; 783 T.set_zero();
784 }
785 }
786 struct ge_cached {
787 public fe YplusX;
788 public fe YminusX;
789 public fe Z;
790 public fe T2d;
791 }
792
793 static ge_precomp[] base_unpack(int n, Int32[] data) {
794 ge_precomp[] ret = new ge_precomp[n];
795 for (int i = 0; i < n; i++) ret[i] = new ge_precomp(data, i * 3 * 10);
53 return ret; 796 return ret;
54 } 797 }
55 static ge_precomp[] base_unpack(int n, int offset, Int32[] data) { 798 static ge_precomp[] basev = base_unpack(32 * 8,
56 ge_precomp[] ret = new ge_precomp[n];
57 for (int i = 0; i < n; i++) ret[i] = new ge_precomp(data, offset + i * 3 * 10);
58 return ret;
59 }
60 static ge_precomp[][] base_unpack_a(int a, int b, Int32[] data) {
61 ge_precomp[][] ret = new ge_precomp[a][];
62 for (int i = 0; i < a; i++) ret[i] = base_unpack(b, i * b * 3 * 10, data);
63 return ret;
64 }
65 static ge_precomp[][] basev = base_unpack_a(32, 8,
66 new Int32[32 * 8 * 3 * 10] { 799 new Int32[32 * 8 * 3 * 10] {
67 #region base point data 800 #region base point data
68 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605, 801 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605,
69 -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378, 802 -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378,
70 -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546, 803 -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546,
834 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684, 1567 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684,
835 -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476, 1568 -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476,
836 #endregion 1569 #endregion
837 }); 1570 });
838 1571
839 static void fe_0(out fe h) {
840 h = new fe();
841 h[0] = 0;
842 h[1] = 0;
843 h[2] = 0;
844 h[3] = 0;
845 h[4] = 0;
846 h[5] = 0;
847 h[6] = 0;
848 h[7] = 0;
849 h[8] = 0;
850 h[9] = 0;
851 }
852 static void fe_1(out fe h) {
853 h = new fe();
854 h[0] = 1;
855 h[1] = 0;
856 h[2] = 0;
857 h[3] = 0;
858 h[4] = 0;
859 h[5] = 0;
860 h[6] = 0;
861 h[7] = 0;
862 h[8] = 0;
863 h[9] = 0;
864 }
865 static void ge_p3_0(out ge_p3 h) {
866 fe_0(out h.X);
867 fe_1(out h.Y);
868 fe_1(out h.Z);
869 fe_0(out h.T);
870 }
871 static Byte negative(SByte b) { 1572 static Byte negative(SByte b) {
872 UInt64 x = (UInt64)(Int64)b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */ 1573 UInt64 x = (UInt64)(Int64)b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
873 x >>= 63; /* 1: yes; 0: no */ 1574 x >>= 63; /* 1: yes; 0: no */
874 return (Byte)x; 1575 return (Byte)x;
875 } 1576 }
876 static void ge_precomp_0(out ge_precomp h) { 1577 static Byte equal(Byte b, Byte c) {
877 fe_1(out h.yplusx); 1578 UInt32 y = (UInt32)(b ^ c); /* 0: yes; 1..255: no */
878 fe_1(out h.yminusx);
879 fe_0(out h.xy2d);
880 }
881 static void fe_cmov(ref fe f, ref fe g, Int32 b) {
882 Int32 f0 = f[0];
883 Int32 f1 = f[1];
884 Int32 f2 = f[2];
885 Int32 f3 = f[3];
886 Int32 f4 = f[4];
887 Int32 f5 = f[5];
888 Int32 f6 = f[6];
889 Int32 f7 = f[7];
890 Int32 f8 = f[8];
891 Int32 f9 = f[9];
892 Int32 g0 = g[0];
893 Int32 g1 = g[1];
894 Int32 g2 = g[2];
895 Int32 g3 = g[3];
896 Int32 g4 = g[4];
897 Int32 g5 = g[5];
898 Int32 g6 = g[6];
899 Int32 g7 = g[7];
900 Int32 g8 = g[8];
901 Int32 g9 = g[9];
902 Int32 x0 = f0 ^ g0;
903 Int32 x1 = f1 ^ g1;
904 Int32 x2 = f2 ^ g2;
905 Int32 x3 = f3 ^ g3;
906 Int32 x4 = f4 ^ g4;
907 Int32 x5 = f5 ^ g5;
908 Int32 x6 = f6 ^ g6;
909 Int32 x7 = f7 ^ g7;
910 Int32 x8 = f8 ^ g8;
911 Int32 x9 = f9 ^ g9;
912 b = -b;
913 x0 &= b;
914 x1 &= b;
915 x2 &= b;
916 x3 &= b;
917 x4 &= b;
918 x5 &= b;
919 x6 &= b;
920 x7 &= b;
921 x8 &= b;
922 x9 &= b;
923 f[0] = f0 ^ x0;
924 f[1] = f1 ^ x1;
925 f[2] = f2 ^ x2;
926 f[3] = f3 ^ x3;
927 f[4] = f4 ^ x4;
928 f[5] = f5 ^ x5;
929 f[6] = f6 ^ x6;
930 f[7] = f7 ^ x7;
931 f[8] = f8 ^ x8;
932 f[9] = f9 ^ x9;
933 }
934 static void cmov(ref ge_precomp t, ref ge_precomp u, Byte b) {
935 fe_cmov(ref t.yplusx, ref u.yplusx, b);
936 fe_cmov(ref t.yminusx, ref u.yminusx, b);
937 fe_cmov(ref t.xy2d, ref u.xy2d, b);
938 }
939 static Byte equal(Byte b, SByte c) {
940 Byte ub = (Byte)b;
941 Byte uc = (Byte)c;
942 Byte x = (Byte)(ub ^ uc); /* 0: yes; 1..255: no */
943 UInt32 y = x; /* 0: yes; 1..255: no */
944 y -= 1; /* 4294967295: yes; 0..254: no */ 1579 y -= 1; /* 4294967295: yes; 0..254: no */
945 y >>= 31; /* 1: yes; 0: no */ 1580 y >>= 31; /* 1: yes; 0: no */
946 return (Byte)y; 1581 return (Byte)y;
947 }
948 static void fe_copy(out fe h, ref fe f) {
949 Int32 f0 = f[0];
950 Int32 f1 = f[1];
951 Int32 f2 = f[2];
952 Int32 f3 = f[3];
953 Int32 f4 = f[4];
954 Int32 f5 = f[5];
955 Int32 f6 = f[6];
956 Int32 f7 = f[7];
957 Int32 f8 = f[8];
958 Int32 f9 = f[9];
959 h = new fe();
960 h[0] = f0;
961 h[1] = f1;
962 h[2] = f2;
963 h[3] = f3;
964 h[4] = f4;
965 h[5] = f5;
966 h[6] = f6;
967 h[7] = f7;
968 h[8] = f8;
969 h[9] = f9;
970 }
971 static void fe_neg(out fe h, ref fe f) {
972 Int32 f0 = f[0];
973 Int32 f1 = f[1];
974 Int32 f2 = f[2];
975 Int32 f3 = f[3];
976 Int32 f4 = f[4];
977 Int32 f5 = f[5];
978 Int32 f6 = f[6];
979 Int32 f7 = f[7];
980 Int32 f8 = f[8];
981 Int32 f9 = f[9];
982 Int32 h0 = -f0;
983 Int32 h1 = -f1;
984 Int32 h2 = -f2;
985 Int32 h3 = -f3;
986 Int32 h4 = -f4;
987 Int32 h5 = -f5;
988 Int32 h6 = -f6;
989 Int32 h7 = -f7;
990 Int32 h8 = -f8;
991 Int32 h9 = -f9;
992 h = new fe();
993 h[0] = h0;
994 h[1] = h1;
995 h[2] = h2;
996 h[3] = h3;
997 h[4] = h4;
998 h[5] = h5;
999 h[6] = h6;
1000 h[7] = h7;
1001 h[8] = h8;
1002 h[9] = h9;
1003 } 1582 }
1004 static void select(out ge_precomp t, int pos, SByte b) { 1583 static void select(out ge_precomp t, int pos, SByte b) {
1005 ge_precomp minust; 1584 ge_precomp minust;
1006 Byte bnegative = negative(b); 1585 Byte bnegative = negative(b);
1007 Byte babs = (Byte)(b - (((-bnegative) & b) << 1)); 1586 Byte babs = (Byte)(b - (((-bnegative) & b) << 1));
1008 ge_precomp_0(out t); 1587 t = new ge_precomp();
1009 cmov(ref t, ref basev[pos][0], equal(babs, 1)); 1588 t.set_zero();
1010 cmov(ref t, ref basev[pos][1], equal(babs, 2)); 1589 int basei = pos * 8;
1011 cmov(ref t, ref basev[pos][2], equal(babs, 3)); 1590 t.cmov(ref basev[basei + 0], equal(babs, 1));
1012 cmov(ref t, ref basev[pos][3], equal(babs, 4)); 1591 t.cmov(ref basev[basei + 1], equal(babs, 2));
1013 cmov(ref t, ref basev[pos][4], equal(babs, 5)); 1592 t.cmov(ref basev[basei + 2], equal(babs, 3));
1014 cmov(ref t, ref basev[pos][5], equal(babs, 6)); 1593 t.cmov(ref basev[basei + 3], equal(babs, 4));
1015 cmov(ref t, ref basev[pos][6], equal(babs, 7)); 1594 t.cmov(ref basev[basei + 4], equal(babs, 5));
1016 cmov(ref t, ref basev[pos][7], equal(babs, 8)); 1595 t.cmov(ref basev[basei + 5], equal(babs, 6));
1017 fe_copy(out minust.yplusx, ref t.yminusx); 1596 t.cmov(ref basev[basei + 6], equal(babs, 7));
1018 fe_copy(out minust.yminusx, ref t.yplusx); 1597 t.cmov(ref basev[basei + 7], equal(babs, 8));
1019 fe_neg(out minust.xy2d, ref t.xy2d); 1598 minust.yplusx = t.yminusx;
1020 cmov(ref t, ref minust, bnegative); 1599 minust.yminusx = t.yplusx;
1600 minust.xy2d = t.xy2d; minust.xy2d.neg();
1601 t.cmov(ref minust, bnegative);
1021 } 1602 }
1022 static void fe_add(out fe h, ref fe f, ref fe g) { 1603 static void fe_add(out fe h, ref fe f, ref fe g) {
1023 Int32 f0 = f[0]; 1604 fe r = f;
1024 Int32 f1 = f[1]; 1605 r.add(ref g);
1025 Int32 f2 = f[2]; 1606 h = r;
1026 Int32 f3 = f[3];
1027 Int32 f4 = f[4];
1028 Int32 f5 = f[5];
1029 Int32 f6 = f[6];
1030 Int32 f7 = f[7];
1031 Int32 f8 = f[8];
1032 Int32 f9 = f[9];
1033 Int32 g0 = g[0];
1034 Int32 g1 = g[1];
1035 Int32 g2 = g[2];
1036 Int32 g3 = g[3];
1037 Int32 g4 = g[4];
1038 Int32 g5 = g[5];
1039 Int32 g6 = g[6];
1040 Int32 g7 = g[7];
1041 Int32 g8 = g[8];
1042 Int32 g9 = g[9];
1043 Int32 h0 = f0 + g0;
1044 Int32 h1 = f1 + g1;
1045 Int32 h2 = f2 + g2;
1046 Int32 h3 = f3 + g3;
1047 Int32 h4 = f4 + g4;
1048 Int32 h5 = f5 + g5;
1049 Int32 h6 = f6 + g6;
1050 Int32 h7 = f7 + g7;
1051 Int32 h8 = f8 + g8;
1052 Int32 h9 = f9 + g9;
1053 h = new fe();
1054 h[0] = h0;
1055 h[1] = h1;
1056 h[2] = h2;
1057 h[3] = h3;
1058 h[4] = h4;
1059 h[5] = h5;
1060 h[6] = h6;
1061 h[7] = h7;
1062 h[8] = h8;
1063 h[9] = h9;
1064 } 1607 }
1065 static void fe_sub(out fe h, ref fe f, ref fe g) { 1608 static void fe_sub(out fe h, ref fe f, ref fe g) {
1066 Int32 f0 = f[0]; 1609 fe r = f;
1067 Int32 f1 = f[1]; 1610 r.sub(ref g);
1068 Int32 f2 = f[2]; 1611 h = r;
1069 Int32 f3 = f[3];
1070 Int32 f4 = f[4];
1071 Int32 f5 = f[5];
1072 Int32 f6 = f[6];
1073 Int32 f7 = f[7];
1074 Int32 f8 = f[8];
1075 Int32 f9 = f[9];
1076 Int32 g0 = g[0];
1077 Int32 g1 = g[1];
1078 Int32 g2 = g[2];
1079 Int32 g3 = g[3];
1080 Int32 g4 = g[4];
1081 Int32 g5 = g[5];
1082 Int32 g6 = g[6];
1083 Int32 g7 = g[7];
1084 Int32 g8 = g[8];
1085 Int32 g9 = g[9];
1086 Int32 h0 = f0 - g0;
1087 Int32 h1 = f1 - g1;
1088 Int32 h2 = f2 - g2;
1089 Int32 h3 = f3 - g3;
1090 Int32 h4 = f4 - g4;
1091 Int32 h5 = f5 - g5;
1092 Int32 h6 = f6 - g6;
1093 Int32 h7 = f7 - g7;
1094 Int32 h8 = f8 - g8;
1095 Int32 h9 = f9 - g9;
1096 h = new fe();
1097 h[0] = h0;
1098 h[1] = h1;
1099 h[2] = h2;
1100 h[3] = h3;
1101 h[4] = h4;
1102 h[5] = h5;
1103 h[6] = h6;
1104 h[7] = h7;
1105 h[8] = h8;
1106 h[9] = h9;
1107 } 1612 }
1108 static void fe_mul(out fe h, ref fe f, ref fe g) { 1613 static void fe_mul(out fe h, ref fe f, ref fe g) {
1109 Int32 f0 = f[0]; 1614 fe r = f;
1110 Int32 f1 = f[1]; 1615 r.mul(ref g);
1111 Int32 f2 = f[2]; 1616 h = r;
1112 Int32 f3 = f[3];
1113 Int32 f4 = f[4];
1114 Int32 f5 = f[5];
1115 Int32 f6 = f[6];
1116 Int32 f7 = f[7];
1117 Int32 f8 = f[8];
1118 Int32 f9 = f[9];
1119 Int32 g0 = g[0];
1120 Int32 g1 = g[1];
1121 Int32 g2 = g[2];
1122 Int32 g3 = g[3];
1123 Int32 g4 = g[4];
1124 Int32 g5 = g[5];
1125 Int32 g6 = g[6];
1126 Int32 g7 = g[7];
1127 Int32 g8 = g[8];
1128 Int32 g9 = g[9];
1129 Int32 g1_19 = 19 * g1; /* 1.959375*2^29 */
1130 Int32 g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
1131 Int32 g3_19 = 19 * g3;
1132 Int32 g4_19 = 19 * g4;
1133 Int32 g5_19 = 19 * g5;
1134 Int32 g6_19 = 19 * g6;
1135 Int32 g7_19 = 19 * g7;
1136 Int32 g8_19 = 19 * g8;
1137 Int32 g9_19 = 19 * g9;
1138 Int32 f1_2 = 2 * f1;
1139 Int32 f3_2 = 2 * f3;
1140 Int32 f5_2 = 2 * f5;
1141 Int32 f7_2 = 2 * f7;
1142 Int32 f9_2 = 2 * f9;
1143 Int64 f0g0 = f0 * (Int64)g0;
1144 Int64 f0g1 = f0 * (Int64)g1;
1145 Int64 f0g2 = f0 * (Int64)g2;
1146 Int64 f0g3 = f0 * (Int64)g3;
1147 Int64 f0g4 = f0 * (Int64)g4;
1148 Int64 f0g5 = f0 * (Int64)g5;
1149 Int64 f0g6 = f0 * (Int64)g6;
1150 Int64 f0g7 = f0 * (Int64)g7;
1151 Int64 f0g8 = f0 * (Int64)g8;
1152 Int64 f0g9 = f0 * (Int64)g9;
1153 Int64 f1g0 = f1 * (Int64)g0;
1154 Int64 f1g1_2 = f1_2 * (Int64)g1;
1155 Int64 f1g2 = f1 * (Int64)g2;
1156 Int64 f1g3_2 = f1_2 * (Int64)g3;
1157 Int64 f1g4 = f1 * (Int64)g4;
1158 Int64 f1g5_2 = f1_2 * (Int64)g5;
1159 Int64 f1g6 = f1 * (Int64)g6;
1160 Int64 f1g7_2 = f1_2 * (Int64)g7;
1161 Int64 f1g8 = f1 * (Int64)g8;
1162 Int64 f1g9_38 = f1_2 * (Int64)g9_19;
1163 Int64 f2g0 = f2 * (Int64)g0;
1164 Int64 f2g1 = f2 * (Int64)g1;
1165 Int64 f2g2 = f2 * (Int64)g2;
1166 Int64 f2g3 = f2 * (Int64)g3;
1167 Int64 f2g4 = f2 * (Int64)g4;
1168 Int64 f2g5 = f2 * (Int64)g5;
1169 Int64 f2g6 = f2 * (Int64)g6;
1170 Int64 f2g7 = f2 * (Int64)g7;
1171 Int64 f2g8_19 = f2 * (Int64)g8_19;
1172 Int64 f2g9_19 = f2 * (Int64)g9_19;
1173 Int64 f3g0 = f3 * (Int64)g0;
1174 Int64 f3g1_2 = f3_2 * (Int64)g1;
1175 Int64 f3g2 = f3 * (Int64)g2;
1176 Int64 f3g3_2 = f3_2 * (Int64)g3;
1177 Int64 f3g4 = f3 * (Int64)g4;
1178 Int64 f3g5_2 = f3_2 * (Int64)g5;
1179 Int64 f3g6 = f3 * (Int64)g6;
1180 Int64 f3g7_38 = f3_2 * (Int64)g7_19;
1181 Int64 f3g8_19 = f3 * (Int64)g8_19;
1182 Int64 f3g9_38 = f3_2 * (Int64)g9_19;
1183 Int64 f4g0 = f4 * (Int64)g0;
1184 Int64 f4g1 = f4 * (Int64)g1;
1185 Int64 f4g2 = f4 * (Int64)g2;
1186 Int64 f4g3 = f4 * (Int64)g3;
1187 Int64 f4g4 = f4 * (Int64)g4;
1188 Int64 f4g5 = f4 * (Int64)g5;
1189 Int64 f4g6_19 = f4 * (Int64)g6_19;
1190 Int64 f4g7_19 = f4 * (Int64)g7_19;
1191 Int64 f4g8_19 = f4 * (Int64)g8_19;
1192 Int64 f4g9_19 = f4 * (Int64)g9_19;
1193 Int64 f5g0 = f5 * (Int64)g0;
1194 Int64 f5g1_2 = f5_2 * (Int64)g1;
1195 Int64 f5g2 = f5 * (Int64)g2;
1196 Int64 f5g3_2 = f5_2 * (Int64)g3;
1197 Int64 f5g4 = f5 * (Int64)g4;
1198 Int64 f5g5_38 = f5_2 * (Int64)g5_19;
1199 Int64 f5g6_19 = f5 * (Int64)g6_19;
1200 Int64 f5g7_38 = f5_2 * (Int64)g7_19;
1201 Int64 f5g8_19 = f5 * (Int64)g8_19;
1202 Int64 f5g9_38 = f5_2 * (Int64)g9_19;
1203 Int64 f6g0 = f6 * (Int64)g0;
1204 Int64 f6g1 = f6 * (Int64)g1;
1205 Int64 f6g2 = f6 * (Int64)g2;
1206 Int64 f6g3 = f6 * (Int64)g3;
1207 Int64 f6g4_19 = f6 * (Int64)g4_19;
1208 Int64 f6g5_19 = f6 * (Int64)g5_19;
1209 Int64 f6g6_19 = f6 * (Int64)g6_19;
1210 Int64 f6g7_19 = f6 * (Int64)g7_19;
1211 Int64 f6g8_19 = f6 * (Int64)g8_19;
1212 Int64 f6g9_19 = f6 * (Int64)g9_19;
1213 Int64 f7g0 = f7 * (Int64)g0;
1214 Int64 f7g1_2 = f7_2 * (Int64)g1;
1215 Int64 f7g2 = f7 * (Int64)g2;
1216 Int64 f7g3_38 = f7_2 * (Int64)g3_19;
1217 Int64 f7g4_19 = f7 * (Int64)g4_19;
1218 Int64 f7g5_38 = f7_2 * (Int64)g5_19;
1219 Int64 f7g6_19 = f7 * (Int64)g6_19;
1220 Int64 f7g7_38 = f7_2 * (Int64)g7_19;
1221 Int64 f7g8_19 = f7 * (Int64)g8_19;
1222 Int64 f7g9_38 = f7_2 * (Int64)g9_19;
1223 Int64 f8g0 = f8 * (Int64)g0;
1224 Int64 f8g1 = f8 * (Int64)g1;
1225 Int64 f8g2_19 = f8 * (Int64)g2_19;
1226 Int64 f8g3_19 = f8 * (Int64)g3_19;
1227 Int64 f8g4_19 = f8 * (Int64)g4_19;
1228 Int64 f8g5_19 = f8 * (Int64)g5_19;
1229 Int64 f8g6_19 = f8 * (Int64)g6_19;
1230 Int64 f8g7_19 = f8 * (Int64)g7_19;
1231 Int64 f8g8_19 = f8 * (Int64)g8_19;
1232 Int64 f8g9_19 = f8 * (Int64)g9_19;
1233 Int64 f9g0 = f9 * (Int64)g0;
1234 Int64 f9g1_38 = f9_2 * (Int64)g1_19;
1235 Int64 f9g2_19 = f9 * (Int64)g2_19;
1236 Int64 f9g3_38 = f9_2 * (Int64)g3_19;
1237 Int64 f9g4_19 = f9 * (Int64)g4_19;
1238 Int64 f9g5_38 = f9_2 * (Int64)g5_19;
1239 Int64 f9g6_19 = f9 * (Int64)g6_19;
1240 Int64 f9g7_38 = f9_2 * (Int64)g7_19;
1241 Int64 f9g8_19 = f9 * (Int64)g8_19;
1242 Int64 f9g9_38 = f9_2 * (Int64)g9_19;
1243 Int64 h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
1244 Int64 h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
1245 Int64 h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
1246 Int64 h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
1247 Int64 h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
1248 Int64 h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
1249 Int64 h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
1250 Int64 h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
1251 Int64 h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
1252 Int64 h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0;
1253 Int64 carry0;
1254 Int64 carry1;
1255 Int64 carry2;
1256 Int64 carry3;
1257 Int64 carry4;
1258 Int64 carry5;
1259 Int64 carry6;
1260 Int64 carry7;
1261 Int64 carry8;
1262 Int64 carry9;
1263 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1264 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1265 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
1266 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
1267 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
1268 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
1269 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
1270 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
1271 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1272 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
1273 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
1274 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1275 h = new fe();
1276 h[0] = (Int32)h0;
1277 h[1] = (Int32)h1;
1278 h[2] = (Int32)h2;
1279 h[3] = (Int32)h3;
1280 h[4] = (Int32)h4;
1281 h[5] = (Int32)h5;
1282 h[6] = (Int32)h6;
1283 h[7] = (Int32)h7;
1284 h[8] = (Int32)h8;
1285 h[9] = (Int32)h9;
1286 } 1617 }
1287 static void ge_madd(out ge_p1p1 r, ref ge_p3 p, ref ge_precomp q) { 1618 static void ge_madd(out ge_p1p1 r, ref ge_p3 p, ref ge_precomp q) {
1288 fe t0; 1619 fe t0;
1289 fe_add(out r.X, ref p.Y, ref p.X); 1620 fe_add(out r.X, ref p.Y, ref p.X);
1290 fe_sub(out r.Y, ref p.Y, ref p.X); 1621 fe_sub(out r.Y, ref p.Y, ref p.X);
1302 fe_mul(out r.Y, ref p.Y, ref p.Z); 1633 fe_mul(out r.Y, ref p.Y, ref p.Z);
1303 fe_mul(out r.Z, ref p.Z, ref p.T); 1634 fe_mul(out r.Z, ref p.Z, ref p.T);
1304 fe_mul(out r.T, ref p.X, ref p.Y); 1635 fe_mul(out r.T, ref p.X, ref p.Y);
1305 } 1636 }
1306 static void ge_p3_to_p2(out ge_p2 r, ref ge_p3 p) { 1637 static void ge_p3_to_p2(out ge_p2 r, ref ge_p3 p) {
1307 fe_copy(out r.X, ref p.X); 1638 r.X = p.X;
1308 fe_copy(out r.Y, ref p.Y); 1639 r.Y = p.Y;
1309 fe_copy(out r.Z, ref p.Z); 1640 r.Z = p.Z;
1310 } 1641 }
1311 static void fe_sq(out fe h, ref fe f) { 1642 static void fe_sq(out fe h, ref fe f) {
1312 Int32 f0 = f[0]; 1643 h = f;
1313 Int32 f1 = f[1]; 1644 h.sq();
1314 Int32 f2 = f[2];
1315 Int32 f3 = f[3];
1316 Int32 f4 = f[4];
1317 Int32 f5 = f[5];
1318 Int32 f6 = f[6];
1319 Int32 f7 = f[7];
1320 Int32 f8 = f[8];
1321 Int32 f9 = f[9];
1322 Int32 f0_2 = 2 * f0;
1323 Int32 f1_2 = 2 * f1;
1324 Int32 f2_2 = 2 * f2;
1325 Int32 f3_2 = 2 * f3;
1326 Int32 f4_2 = 2 * f4;
1327 Int32 f5_2 = 2 * f5;
1328 Int32 f6_2 = 2 * f6;
1329 Int32 f7_2 = 2 * f7;
1330 Int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
1331 Int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
1332 Int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
1333 Int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
1334 Int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
1335 Int64 f0f0 = f0 * (Int64)f0;
1336 Int64 f0f1_2 = f0_2 * (Int64)f1;
1337 Int64 f0f2_2 = f0_2 * (Int64)f2;
1338 Int64 f0f3_2 = f0_2 * (Int64)f3;
1339 Int64 f0f4_2 = f0_2 * (Int64)f4;
1340 Int64 f0f5_2 = f0_2 * (Int64)f5;
1341 Int64 f0f6_2 = f0_2 * (Int64)f6;
1342 Int64 f0f7_2 = f0_2 * (Int64)f7;
1343 Int64 f0f8_2 = f0_2 * (Int64)f8;
1344 Int64 f0f9_2 = f0_2 * (Int64)f9;
1345 Int64 f1f1_2 = f1_2 * (Int64)f1;
1346 Int64 f1f2_2 = f1_2 * (Int64)f2;
1347 Int64 f1f3_4 = f1_2 * (Int64)f3_2;
1348 Int64 f1f4_2 = f1_2 * (Int64)f4;
1349 Int64 f1f5_4 = f1_2 * (Int64)f5_2;
1350 Int64 f1f6_2 = f1_2 * (Int64)f6;
1351 Int64 f1f7_4 = f1_2 * (Int64)f7_2;
1352 Int64 f1f8_2 = f1_2 * (Int64)f8;
1353 Int64 f1f9_76 = f1_2 * (Int64)f9_38;
1354 Int64 f2f2 = f2 * (Int64)f2;
1355 Int64 f2f3_2 = f2_2 * (Int64)f3;
1356 Int64 f2f4_2 = f2_2 * (Int64)f4;
1357 Int64 f2f5_2 = f2_2 * (Int64)f5;
1358 Int64 f2f6_2 = f2_2 * (Int64)f6;
1359 Int64 f2f7_2 = f2_2 * (Int64)f7;
1360 Int64 f2f8_38 = f2_2 * (Int64)f8_19;
1361 Int64 f2f9_38 = f2 * (Int64)f9_38;
1362 Int64 f3f3_2 = f3_2 * (Int64)f3;
1363 Int64 f3f4_2 = f3_2 * (Int64)f4;
1364 Int64 f3f5_4 = f3_2 * (Int64)f5_2;
1365 Int64 f3f6_2 = f3_2 * (Int64)f6;
1366 Int64 f3f7_76 = f3_2 * (Int64)f7_38;
1367 Int64 f3f8_38 = f3_2 * (Int64)f8_19;
1368 Int64 f3f9_76 = f3_2 * (Int64)f9_38;
1369 Int64 f4f4 = f4 * (Int64)f4;
1370 Int64 f4f5_2 = f4_2 * (Int64)f5;
1371 Int64 f4f6_38 = f4_2 * (Int64)f6_19;
1372 Int64 f4f7_38 = f4 * (Int64)f7_38;
1373 Int64 f4f8_38 = f4_2 * (Int64)f8_19;
1374 Int64 f4f9_38 = f4 * (Int64)f9_38;
1375 Int64 f5f5_38 = f5 * (Int64)f5_38;
1376 Int64 f5f6_38 = f5_2 * (Int64)f6_19;
1377 Int64 f5f7_76 = f5_2 * (Int64)f7_38;
1378 Int64 f5f8_38 = f5_2 * (Int64)f8_19;
1379 Int64 f5f9_76 = f5_2 * (Int64)f9_38;
1380 Int64 f6f6_19 = f6 * (Int64)f6_19;
1381 Int64 f6f7_38 = f6 * (Int64)f7_38;
1382 Int64 f6f8_38 = f6_2 * (Int64)f8_19;
1383 Int64 f6f9_38 = f6 * (Int64)f9_38;
1384 Int64 f7f7_38 = f7 * (Int64)f7_38;
1385 Int64 f7f8_38 = f7_2 * (Int64)f8_19;
1386 Int64 f7f9_76 = f7_2 * (Int64)f9_38;
1387 Int64 f8f8_19 = f8 * (Int64)f8_19;
1388 Int64 f8f9_38 = f8 * (Int64)f9_38;
1389 Int64 f9f9_38 = f9 * (Int64)f9_38;
1390 Int64 h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
1391 Int64 h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
1392 Int64 h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
1393 Int64 h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
1394 Int64 h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
1395 Int64 h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
1396 Int64 h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
1397 Int64 h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
1398 Int64 h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
1399 Int64 h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
1400 Int64 carry0;
1401 Int64 carry1;
1402 Int64 carry2;
1403 Int64 carry3;
1404 Int64 carry4;
1405 Int64 carry5;
1406 Int64 carry6;
1407 Int64 carry7;
1408 Int64 carry8;
1409 Int64 carry9;
1410
1411 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1412 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1413
1414 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
1415 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
1416
1417 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
1418 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
1419
1420 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
1421 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
1422
1423 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1424 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
1425
1426 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
1427
1428 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1429
1430 h = new fe();
1431 h[0] = (Int32)h0;
1432 h[1] = (Int32)h1;
1433 h[2] = (Int32)h2;
1434 h[3] = (Int32)h3;
1435 h[4] = (Int32)h4;
1436 h[5] = (Int32)h5;
1437 h[6] = (Int32)h6;
1438 h[7] = (Int32)h7;
1439 h[8] = (Int32)h8;
1440 h[9] = (Int32)h9;
1441 }
1442 static void fe_sq2(out fe h, ref fe f) {
1443 Int32 f0 = f[0];
1444 Int32 f1 = f[1];
1445 Int32 f2 = f[2];
1446 Int32 f3 = f[3];
1447 Int32 f4 = f[4];
1448 Int32 f5 = f[5];
1449 Int32 f6 = f[6];
1450 Int32 f7 = f[7];
1451 Int32 f8 = f[8];
1452 Int32 f9 = f[9];
1453 Int32 f0_2 = 2 * f0;
1454 Int32 f1_2 = 2 * f1;
1455 Int32 f2_2 = 2 * f2;
1456 Int32 f3_2 = 2 * f3;
1457 Int32 f4_2 = 2 * f4;
1458 Int32 f5_2 = 2 * f5;
1459 Int32 f6_2 = 2 * f6;
1460 Int32 f7_2 = 2 * f7;
1461 Int32 f5_38 = 38 * f5; /* 1.959375*2^30 */
1462 Int32 f6_19 = 19 * f6; /* 1.959375*2^30 */
1463 Int32 f7_38 = 38 * f7; /* 1.959375*2^30 */
1464 Int32 f8_19 = 19 * f8; /* 1.959375*2^30 */
1465 Int32 f9_38 = 38 * f9; /* 1.959375*2^30 */
1466 Int64 f0f0 = f0 * (Int64)f0;
1467 Int64 f0f1_2 = f0_2 * (Int64)f1;
1468 Int64 f0f2_2 = f0_2 * (Int64)f2;
1469 Int64 f0f3_2 = f0_2 * (Int64)f3;
1470 Int64 f0f4_2 = f0_2 * (Int64)f4;
1471 Int64 f0f5_2 = f0_2 * (Int64)f5;
1472 Int64 f0f6_2 = f0_2 * (Int64)f6;
1473 Int64 f0f7_2 = f0_2 * (Int64)f7;
1474 Int64 f0f8_2 = f0_2 * (Int64)f8;
1475 Int64 f0f9_2 = f0_2 * (Int64)f9;
1476 Int64 f1f1_2 = f1_2 * (Int64)f1;
1477 Int64 f1f2_2 = f1_2 * (Int64)f2;
1478 Int64 f1f3_4 = f1_2 * (Int64)f3_2;
1479 Int64 f1f4_2 = f1_2 * (Int64)f4;
1480 Int64 f1f5_4 = f1_2 * (Int64)f5_2;
1481 Int64 f1f6_2 = f1_2 * (Int64)f6;
1482 Int64 f1f7_4 = f1_2 * (Int64)f7_2;
1483 Int64 f1f8_2 = f1_2 * (Int64)f8;
1484 Int64 f1f9_76 = f1_2 * (Int64)f9_38;
1485 Int64 f2f2 = f2 * (Int64)f2;
1486 Int64 f2f3_2 = f2_2 * (Int64)f3;
1487 Int64 f2f4_2 = f2_2 * (Int64)f4;
1488 Int64 f2f5_2 = f2_2 * (Int64)f5;
1489 Int64 f2f6_2 = f2_2 * (Int64)f6;
1490 Int64 f2f7_2 = f2_2 * (Int64)f7;
1491 Int64 f2f8_38 = f2_2 * (Int64)f8_19;
1492 Int64 f2f9_38 = f2 * (Int64)f9_38;
1493 Int64 f3f3_2 = f3_2 * (Int64)f3;
1494 Int64 f3f4_2 = f3_2 * (Int64)f4;
1495 Int64 f3f5_4 = f3_2 * (Int64)f5_2;
1496 Int64 f3f6_2 = f3_2 * (Int64)f6;
1497 Int64 f3f7_76 = f3_2 * (Int64)f7_38;
1498 Int64 f3f8_38 = f3_2 * (Int64)f8_19;
1499 Int64 f3f9_76 = f3_2 * (Int64)f9_38;
1500 Int64 f4f4 = f4 * (Int64)f4;
1501 Int64 f4f5_2 = f4_2 * (Int64)f5;
1502 Int64 f4f6_38 = f4_2 * (Int64)f6_19;
1503 Int64 f4f7_38 = f4 * (Int64)f7_38;
1504 Int64 f4f8_38 = f4_2 * (Int64)f8_19;
1505 Int64 f4f9_38 = f4 * (Int64)f9_38;
1506 Int64 f5f5_38 = f5 * (Int64)f5_38;
1507 Int64 f5f6_38 = f5_2 * (Int64)f6_19;
1508 Int64 f5f7_76 = f5_2 * (Int64)f7_38;
1509 Int64 f5f8_38 = f5_2 * (Int64)f8_19;
1510 Int64 f5f9_76 = f5_2 * (Int64)f9_38;
1511 Int64 f6f6_19 = f6 * (Int64)f6_19;
1512 Int64 f6f7_38 = f6 * (Int64)f7_38;
1513 Int64 f6f8_38 = f6_2 * (Int64)f8_19;
1514 Int64 f6f9_38 = f6 * (Int64)f9_38;
1515 Int64 f7f7_38 = f7 * (Int64)f7_38;
1516 Int64 f7f8_38 = f7_2 * (Int64)f8_19;
1517 Int64 f7f9_76 = f7_2 * (Int64)f9_38;
1518 Int64 f8f8_19 = f8 * (Int64)f8_19;
1519 Int64 f8f9_38 = f8 * (Int64)f9_38;
1520 Int64 f9f9_38 = f9 * (Int64)f9_38;
1521 Int64 h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
1522 Int64 h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
1523 Int64 h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
1524 Int64 h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
1525 Int64 h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
1526 Int64 h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
1527 Int64 h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
1528 Int64 h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
1529 Int64 h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
1530 Int64 h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
1531 Int64 carry0;
1532 Int64 carry1;
1533 Int64 carry2;
1534 Int64 carry3;
1535 Int64 carry4;
1536 Int64 carry5;
1537 Int64 carry6;
1538 Int64 carry7;
1539 Int64 carry8;
1540 Int64 carry9;
1541
1542 h0 += h0;
1543 h1 += h1;
1544 h2 += h2;
1545 h3 += h3;
1546 h4 += h4;
1547 h5 += h5;
1548 h6 += h6;
1549 h7 += h7;
1550 h8 += h8;
1551 h9 += h9;
1552
1553 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1554 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1555
1556 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
1557 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
1558
1559 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
1560 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
1561
1562 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
1563 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
1564
1565 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
1566 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
1567
1568 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
1569
1570 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
1571
1572 h = new fe();
1573 h[0] = (Int32)h0;
1574 h[1] = (Int32)h1;
1575 h[2] = (Int32)h2;
1576 h[3] = (Int32)h3;
1577 h[4] = (Int32)h4;
1578 h[5] = (Int32)h5;
1579 h[6] = (Int32)h6;
1580 h[7] = (Int32)h7;
1581 h[8] = (Int32)h8;
1582 h[9] = (Int32)h9;
1583 } 1645 }
1584 static void ge_p2_dbl(out ge_p1p1 r, ref ge_p2 p) { 1646 static void ge_p2_dbl(out ge_p1p1 r, ref ge_p2 p) {
1585 fe t0; 1647 r.X = p.X; r.X.sq();
1586 fe_sq(out r.X, ref p.X); 1648 r.Z = p.Y; r.Z.sq();
1587 fe_sq(out r.Z, ref p.Y); 1649 r.T = p.Z; r.T.sq2();
1588 fe_sq2(out r.T, ref p.Z); 1650 r.Y = p.X; r.Y.add(ref p.Y);
1589 fe_add(out r.Y, ref p.X, ref p.Y); 1651 fe t0 = r.Y; t0.sq();
1590 fe_sq(out t0, ref r.Y); 1652 r.Y = r.Z; r.Y.add(ref r.X);
1591 fe_add(out r.Y, ref r.Z, ref r.X); 1653 r.Z.sub(ref r.X);
1592 fe_sub(out r.Z, ref r.Z, ref r.X); 1654 r.X = t0; r.X.sub(ref r.Y);
1593 fe_sub(out r.X, ref t0, ref r.Y); 1655 r.T.sub(ref r.Z);
1594 fe_sub(out r.T, ref r.T, ref r.Z);
1595 } 1656 }
1596 static void ge_p3_dbl(out ge_p1p1 r, ref ge_p3 p) { 1657 static void ge_p3_dbl(out ge_p1p1 r, ref ge_p3 p) {
1597 ge_p2 q; 1658 ge_p2 q;
1598 ge_p3_to_p2(out q, ref p); 1659 ge_p3_to_p2(out q, ref p);
1599 ge_p2_dbl(out r, ref q); 1660 ge_p2_dbl(out r, ref q);
1618 carry >>= 4; 1679 carry >>= 4;
1619 e[i] -= (sbyte)(carry << 4); 1680 e[i] -= (sbyte)(carry << 4);
1620 } 1681 }
1621 e[63] += carry; 1682 e[63] += carry;
1622 1683
1623 ge_p3_0(out h); 1684 h = new ge_p3();
1685 h.set_zero();
1624 ge_precomp t; 1686 ge_precomp t;
1625 ge_p1p1 r; 1687 ge_p1p1 r;
1626 for (int i = 1; i < 64; i += 2) { 1688 for (int i = 1; i < 64; i += 2) {
1627 select(out t, i / 2, e[i]); 1689 select(out t, i / 2, e[i]);
1628 ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r); 1690 ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r);
1637 for (int i = 0; i < 64; i += 2) { 1699 for (int i = 0; i < 64; i += 2) {
1638 select(out t, i / 2, e[i]); 1700 select(out t, i / 2, e[i]);
1639 ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r); 1701 ge_madd(out r, ref h, ref t); ge_p1p1_to_p3(out h, ref r);
1640 } 1702 }
1641 } 1703 }
1642 static void fe_invert(out fe outv, ref fe z) {
1643 fe t0;
1644 fe t1;
1645 fe t2;
1646 fe t3;
1647 fe_sq(out t0, ref z); for (int i = 1; i < 1; ++i) fe_sq(out t0, ref t0);
1648 fe_sq(out t1, ref t0); for (int i = 1; i < 2; ++i) fe_sq(out t1, ref t1);
1649 fe_mul(out t1, ref z, ref t1);
1650 fe_mul(out t0, ref t0, ref t1);
1651 fe_sq(out t2, ref t0); for (int i = 1; i < 1; ++i) fe_sq(out t2, ref t2);
1652 fe_mul(out t1, ref t1, ref t2);
1653 fe_sq(out t2, ref t1); for (int i = 1; i < 5; ++i) fe_sq(out t2, ref t2);
1654 fe_mul(out t1, ref t2, ref t1);
1655 fe_sq(out t2, ref t1); for (int i = 1; i < 10; ++i) fe_sq(out t2, ref t2);
1656 fe_mul(out t2, ref t2, ref t1);
1657 fe_sq(out t3, ref t2); for (int i = 1; i < 20; ++i) fe_sq(out t3, ref t3);
1658 fe_mul(out t2, ref t3, ref t2);
1659 fe_sq(out t2, ref t2); for (int i = 1; i < 10; ++i) fe_sq(out t2, ref t2);
1660 fe_mul(out t1, ref t2, ref t1);
1661 fe_sq(out t2, ref t1); for (int i = 1; i < 50; ++i) fe_sq(out t2, ref t2);
1662 fe_mul(out t2, ref t2, ref t1);
1663 fe_sq(out t3, ref t2); for (int i = 1; i < 100; ++i) fe_sq(out t3, ref t3);
1664 fe_mul(out t2, ref t3, ref t2);
1665 fe_sq(out t2, ref t2); for (int i = 1; i < 50; ++i) fe_sq(out t2, ref t2);
1666 fe_mul(out t1, ref t2, ref t1);
1667 fe_sq(out t1, ref t1); for (int i = 1; i < 5; ++i) fe_sq(out t1, ref t1);
1668 fe_mul(out outv, ref t1, ref t0);
1669 }
1670 static unsafe void fe_tobytes(Byte* s, ref fe h) {
1671 Int32 h0 = h[0];
1672 Int32 h1 = h[1];
1673 Int32 h2 = h[2];
1674 Int32 h3 = h[3];
1675 Int32 h4 = h[4];
1676 Int32 h5 = h[5];
1677 Int32 h6 = h[6];
1678 Int32 h7 = h[7];
1679 Int32 h8 = h[8];
1680 Int32 h9 = h[9];
1681 Int32 q;
1682 Int32 carry0;
1683 Int32 carry1;
1684 Int32 carry2;
1685 Int32 carry3;
1686 Int32 carry4;
1687 Int32 carry5;
1688 Int32 carry6;
1689 Int32 carry7;
1690 Int32 carry8;
1691 Int32 carry9;
1692
1693 q = (19 * h9 + (((Int32)1) << 24)) >> 25;
1694 q = (h0 + q) >> 26;
1695 q = (h1 + q) >> 25;
1696 q = (h2 + q) >> 26;
1697 q = (h3 + q) >> 25;
1698 q = (h4 + q) >> 26;
1699 q = (h5 + q) >> 25;
1700 q = (h6 + q) >> 26;
1701 q = (h7 + q) >> 25;
1702 q = (h8 + q) >> 26;
1703 q = (h9 + q) >> 25;
1704
1705 h0 += 19 * q;
1706
1707 carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
1708 carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
1709 carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
1710 carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
1711 carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
1712 carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
1713 carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
1714 carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
1715 carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
1716 carry9 = h9 >> 25; h9 -= carry9 << 25;
1717 /* h10 = carry9 */
1718
1719 s[0] = (Byte)(h0 >> 0);
1720 s[1] = (Byte)(h0 >> 8);
1721 s[2] = (Byte)(h0 >> 16);
1722 s[3] = (Byte)((h0 >> 24) | (h1 << 2));
1723 s[4] = (Byte)(h1 >> 6);
1724 s[5] = (Byte)(h1 >> 14);
1725 s[6] = (Byte)((h1 >> 22) | (h2 << 3));
1726 s[7] = (Byte)(h2 >> 5);
1727 s[8] = (Byte)(h2 >> 13);
1728 s[9] = (Byte)((h2 >> 21) | (h3 << 5));
1729 s[10] = (Byte)(h3 >> 3);
1730 s[11] = (Byte)(h3 >> 11);
1731 s[12] = (Byte)((h3 >> 19) | (h4 << 6));
1732 s[13] = (Byte)(h4 >> 2);
1733 s[14] = (Byte)(h4 >> 10);
1734 s[15] = (Byte)(h4 >> 18);
1735 s[16] = (Byte)(h5 >> 0);
1736 s[17] = (Byte)(h5 >> 8);
1737 s[18] = (Byte)(h5 >> 16);
1738 s[19] = (Byte)((h5 >> 24) | (h6 << 1));
1739 s[20] = (Byte)(h6 >> 7);
1740 s[21] = (Byte)(h6 >> 15);
1741 s[22] = (Byte)((h6 >> 23) | (h7 << 3));
1742 s[23] = (Byte)(h7 >> 5);
1743 s[24] = (Byte)(h7 >> 13);
1744 s[25] = (Byte)((h7 >> 21) | (h8 << 4));
1745 s[26] = (Byte)(h8 >> 4);
1746 s[27] = (Byte)(h8 >> 12);
1747 s[28] = (Byte)((h8 >> 20) | (h9 << 6));
1748 s[29] = (Byte)(h9 >> 2);
1749 s[30] = (Byte)(h9 >> 10);
1750 s[31] = (Byte)(h9 >> 18);
1751 }
1752 static unsafe int fe_isnegative(ref fe f) {
1753 Byte* s = stackalloc Byte[32];
1754 fe_tobytes(s, ref f);
1755 return s[0] & 1;
1756 }
1757 static unsafe void ge_p3_tobytes(Byte* s, ref ge_p3 h) { 1704 static unsafe void ge_p3_tobytes(Byte* s, ref ge_p3 h) {
1758 fe recip; 1705 fe recip = h.Z; recip.invert();
1759 fe x; 1706 fe x = h.X; x.mul(ref recip);
1760 fe y; 1707 fe y = h.Y; y.mul(ref recip);
1761 fe_invert(out recip, ref h.Z); 1708 y.tobytes(s);
1762 fe_mul(out x, ref h.X, ref recip); 1709 s[31] ^= (Byte)(x.isnegative() << 7);
1763 fe_mul(out y, ref h.Y, ref recip);
1764 fe_tobytes(s, ref y);
1765 s[31] ^= (Byte)(fe_isnegative(ref x) << 7);
1766 } 1710 }
1767 1711
1768 public static unsafe void crypto_sign_seed_keypair(out Byte[] pk, out Byte[] sk, Byte[] seed) { 1712 public static unsafe void crypto_sign_seed_keypair(out Byte[] pk, out Byte[] sk, Byte[] seed) {
1769 if (seed.Length < SEEDBYTES) throw new ArgumentException("seed.Length < SEEDBYTES"); 1713 if (seed.Length < SEEDBYTES) throw new ArgumentException("seed.Length < SEEDBYTES");
1770 sk = new Byte[SECRETKEYBYTES]; 1714 sk = new Byte[SECRETKEYBYTES];
1789 1733
1790 public static unsafe void crypto_sign_getpublickey(out Byte[] pk, Byte[] sk) { 1734 public static unsafe void crypto_sign_getpublickey(out Byte[] pk, Byte[] sk) {
1791 pk = UCIS.Util.ArrayUtil.Slice(sk, 32, 32); 1735 pk = UCIS.Util.ArrayUtil.Slice(sk, 32, 32);
1792 } 1736 }
1793 1737
1794 static unsafe Int64 load_3(Byte* inv) { 1738 static unsafe UInt32 load_3(Byte* inv) {
1795 UInt64 result; 1739 return (UInt32)inv[0] | ((UInt32)inv[1] << 8) | ((UInt32)inv[2] << 16);
1796 result = (UInt64)inv[0]; 1740 }
1797 result |= ((UInt64)inv[1]) << 8; 1741 static unsafe UInt32 load_4(Byte* inv) {
1798 result |= ((UInt64)inv[2]) << 16; 1742 return (UInt32)inv[0] | ((UInt32)inv[1] << 8) | ((UInt32)inv[2] << 16) | ((UInt32)inv[3] << 24);
1799 return (Int64)result;
1800 }
1801 static unsafe Int64 load_4(Byte* inv) {
1802 UInt64 result;
1803 result = (UInt64)inv[0];
1804 result |= ((UInt64)inv[1]) << 8;
1805 result |= ((UInt64)inv[2]) << 16;
1806 result |= ((UInt64)inv[3]) << 24;
1807 return (Int64)result;
1808 } 1743 }
1809 static unsafe void sc_reduce(Byte* s) { 1744 static unsafe void sc_reduce(Byte* s) {
1810 Int64 s0 = 2097151 & load_3(s); 1745 Int64 s0 = 2097151 & load_3(s);
1811 Int64 s1 = 2097151 & (load_4(s + 2) >> 5); 1746 Int64 s1 = 2097151 & (load_4(s + 2) >> 5);
1812 Int64 s2 = 2097151 & (load_3(s + 5) >> 2); 1747 Int64 s2 = 2097151 & (load_3(s + 5) >> 2);
1829 Int64 s19 = 2097151 & (load_4(s + 49) >> 7); 1764 Int64 s19 = 2097151 & (load_4(s + 49) >> 7);
1830 Int64 s20 = 2097151 & (load_4(s + 52) >> 4); 1765 Int64 s20 = 2097151 & (load_4(s + 52) >> 4);
1831 Int64 s21 = 2097151 & (load_3(s + 55) >> 1); 1766 Int64 s21 = 2097151 & (load_3(s + 55) >> 1);
1832 Int64 s22 = 2097151 & (load_4(s + 57) >> 6); 1767 Int64 s22 = 2097151 & (load_4(s + 57) >> 6);
1833 Int64 s23 = (load_4(s + 60) >> 3); 1768 Int64 s23 = (load_4(s + 60) >> 3);
1834 Int64 carry0;
1835 Int64 carry1;
1836 Int64 carry2;
1837 Int64 carry3;
1838 Int64 carry4;
1839 Int64 carry5;
1840 Int64 carry6;
1841 Int64 carry7;
1842 Int64 carry8;
1843 Int64 carry9;
1844 Int64 carry10;
1845 Int64 carry11;
1846 Int64 carry12;
1847 Int64 carry13;
1848 Int64 carry14;
1849 Int64 carry15;
1850 Int64 carry16;
1851 1769
1852 s11 += s23 * 666643; 1770 s11 += s23 * 666643;
1853 s12 += s23 * 470296; 1771 s12 += s23 * 470296;
1854 s13 += s23 * 654183; 1772 s13 += s23 * 654183;
1855 s14 -= s23 * 997805; 1773 s14 -= s23 * 997805;
1862 s12 += s22 * 654183; 1780 s12 += s22 * 654183;
1863 s13 -= s22 * 997805; 1781 s13 -= s22 * 997805;
1864 s14 += s22 * 136657; 1782 s14 += s22 * 136657;
1865 s15 -= s22 * 683901; 1783 s15 -= s22 * 683901;
1866 1784
1867
1868 s9 += s21 * 666643; 1785 s9 += s21 * 666643;
1869 s10 += s21 * 470296; 1786 s10 += s21 * 470296;
1870 s11 += s21 * 654183; 1787 s11 += s21 * 654183;
1871 s12 -= s21 * 997805; 1788 s12 -= s21 * 997805;
1872 s13 += s21 * 136657; 1789 s13 += s21 * 136657;
1873 s14 -= s21 * 683901; 1790 s14 -= s21 * 683901;
1874 1791
1875
1876 s8 += s20 * 666643; 1792 s8 += s20 * 666643;
1877 s9 += s20 * 470296; 1793 s9 += s20 * 470296;
1878 s10 += s20 * 654183; 1794 s10 += s20 * 654183;
1879 s11 -= s20 * 997805; 1795 s11 -= s20 * 997805;
1880 s12 += s20 * 136657; 1796 s12 += s20 * 136657;
1881 s13 -= s20 * 683901; 1797 s13 -= s20 * 683901;
1882 1798
1883
1884 s7 += s19 * 666643; 1799 s7 += s19 * 666643;
1885 s8 += s19 * 470296; 1800 s8 += s19 * 470296;
1886 s9 += s19 * 654183; 1801 s9 += s19 * 654183;
1887 s10 -= s19 * 997805; 1802 s10 -= s19 * 997805;
1888 s11 += s19 * 136657; 1803 s11 += s19 * 136657;
1893 s8 += s18 * 654183; 1808 s8 += s18 * 654183;
1894 s9 -= s18 * 997805; 1809 s9 -= s18 * 997805;
1895 s10 += s18 * 136657; 1810 s10 += s18 * 136657;
1896 s11 -= s18 * 683901; 1811 s11 -= s18 * 683901;
1897 1812
1898 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 1813 Int64 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
1899 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 1814 Int64 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
1900 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 1815 Int64 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
1901 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; 1816 Int64 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
1902 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; 1817 Int64 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
1903 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; 1818 Int64 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
1904 1819
1905 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 1820 Int64 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
1906 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 1821 Int64 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
1907 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 1822 Int64 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
1908 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; 1823 Int64 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
1909 carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21; 1824 Int64 carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
1910 1825
1911 s5 += s17 * 666643; 1826 s5 += s17 * 666643;
1912 s6 += s17 * 470296; 1827 s6 += s17 * 470296;
1913 s7 += s17 * 654183; 1828 s7 += s17 * 654183;
1914 s8 -= s17 * 997805; 1829 s8 -= s17 * 997805;
1949 s3 -= s12 * 997805; 1864 s3 -= s12 * 997805;
1950 s4 += s12 * 136657; 1865 s4 += s12 * 136657;
1951 s5 -= s12 * 683901; 1866 s5 -= s12 * 683901;
1952 s12 = 0; 1867 s12 = 0;
1953 1868
1954 carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; 1869 Int64 carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
1955 carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; 1870 Int64 carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
1956 carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; 1871 Int64 carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
1957 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 1872 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
1958 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 1873 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
1959 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 1874 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
1960 1875
1961 carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21; 1876 Int64 carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
1962 carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21; 1877 Int64 carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
1963 carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21; 1878 Int64 carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
1964 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 1879 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
1965 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 1880 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
1966 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 1881 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
1967 1882
1968 s0 += s12 * 666643; 1883 s0 += s12 * 666643;
1990 s1 += s12 * 470296; 1905 s1 += s12 * 470296;
1991 s2 += s12 * 654183; 1906 s2 += s12 * 654183;
1992 s3 -= s12 * 997805; 1907 s3 -= s12 * 997805;
1993 s4 += s12 * 136657; 1908 s4 += s12 * 136657;
1994 s5 -= s12 * 683901; 1909 s5 -= s12 * 683901;
1995 1910
1996
1997 carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 1911 carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
1998 carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 1912 carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
1999 carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 1913 carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
2000 carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 1914 carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
2001 carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 1915 carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
2074 Int64 c7 = 2097151 & (load_3(c + 18) >> 3); 1988 Int64 c7 = 2097151 & (load_3(c + 18) >> 3);
2075 Int64 c8 = 2097151 & load_3(c + 21); 1989 Int64 c8 = 2097151 & load_3(c + 21);
2076 Int64 c9 = 2097151 & (load_4(c + 23) >> 5); 1990 Int64 c9 = 2097151 & (load_4(c + 23) >> 5);
2077 Int64 c10 = 2097151 & (load_3(c + 26) >> 2); 1991 Int64 c10 = 2097151 & (load_3(c + 26) >> 2);
2078 Int64 c11 = (load_4(c + 28) >> 7); 1992 Int64 c11 = (load_4(c + 28) >> 7);
2079 Int64 s0; 1993
2080 Int64 s1; 1994 Int64 s0 = c0 + a0 * b0;
2081 Int64 s2; 1995 Int64 s1 = c1 + a0 * b1 + a1 * b0;
2082 Int64 s3; 1996 Int64 s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
2083 Int64 s4; 1997 Int64 s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
2084 Int64 s5; 1998 Int64 s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
2085 Int64 s6; 1999 Int64 s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
2086 Int64 s7; 2000 Int64 s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
2087 Int64 s8; 2001 Int64 s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
2088 Int64 s9; 2002 Int64 s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0;
2089 Int64 s10; 2003 Int64 s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
2090 Int64 s11; 2004 Int64 s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
2091 Int64 s12; 2005 Int64 s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
2092 Int64 s13; 2006 Int64 s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
2093 Int64 s14; 2007 Int64 s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
2094 Int64 s15; 2008 Int64 s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3;
2095 Int64 s16; 2009 Int64 s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
2096 Int64 s17; 2010 Int64 s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
2097 Int64 s18; 2011 Int64 s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
2098 Int64 s19; 2012 Int64 s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
2099 Int64 s20; 2013 Int64 s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
2100 Int64 s21; 2014 Int64 s20 = a9 * b11 + a10 * b10 + a11 * b9;
2101 Int64 s22; 2015 Int64 s21 = a10 * b11 + a11 * b10;
2102 Int64 s23; 2016 Int64 s22 = a11 * b11;
2103 Int64 carry0; 2017 Int64 s23 = 0;
2104 Int64 carry1; 2018
2105 Int64 carry2; 2019 Int64 carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21;
2106 Int64 carry3; 2020 Int64 carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21;
2107 Int64 carry4; 2021 Int64 carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21;
2108 Int64 carry5; 2022 Int64 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
2109 Int64 carry6; 2023 Int64 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
2110 Int64 carry7; 2024 Int64 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
2111 Int64 carry8; 2025 Int64 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
2112 Int64 carry9; 2026 Int64 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
2113 Int64 carry10; 2027 Int64 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
2114 Int64 carry11; 2028 Int64 carry18 = (s18 + (1 << 20)) >> 21; s19 += carry18; s18 -= carry18 << 21;
2115 Int64 carry12; 2029 Int64 carry20 = (s20 + (1 << 20)) >> 21; s21 += carry20; s20 -= carry20 << 21;
2116 Int64 carry13; 2030 Int64 carry22 = (s22 + (1 << 20)) >> 21; s23 += carry22; s22 -= carry22 << 21;
2117 Int64 carry14; 2031
2118 Int64 carry15; 2032 Int64 carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
2119 Int64 carry16; 2033 Int64 carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
2120 Int64 carry17; 2034 Int64 carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
2121 Int64 carry18; 2035 Int64 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
2122 Int64 carry19; 2036 Int64 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
2123 Int64 carry20; 2037 Int64 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
2124 Int64 carry21; 2038 Int64 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
2125 Int64 carry22; 2039 Int64 carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
2126 2040 Int64 carry17 = (s17 + (1 << 20)) >> 21; s18 += carry17; s17 -= carry17 << 21;
2127 s0 = c0 + a0 * b0; 2041 Int64 carry19 = (s19 + (1 << 20)) >> 21; s20 += carry19; s19 -= carry19 << 21;
2128 s1 = c1 + a0 * b1 + a1 * b0; 2042 Int64 carry21 = (s21 + (1 << 20)) >> 21; s22 += carry21; s21 -= carry21 << 21;
2129 s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0; 2043
2130 s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0; 2044 s11 += s23 * 666643;
2131 s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0; 2045 s12 += s23 * 470296;
2132 s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0; 2046 s13 += s23 * 654183;
2133 s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0; 2047 s14 -= s23 * 997805;
2134 s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0; 2048 s15 += s23 * 136657;
2135 s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0; 2049 s16 -= s23 * 683901;
2136 s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0; 2050
2137 s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0; 2051 s10 += s22 * 666643;
2138 s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0; 2052 s11 += s22 * 470296;
2139 s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1; 2053 s12 += s22 * 654183;
2140 s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2; 2054 s13 -= s22 * 997805;
2141 s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3; 2055 s14 += s22 * 136657;
2142 s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4; 2056 s15 -= s22 * 683901;
2143 s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5; 2057
2144 s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6; 2058 s9 += s21 * 666643;
2145 s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7; 2059 s10 += s21 * 470296;
2146 s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8; 2060 s11 += s21 * 654183;
2147 s20 = a9 * b11 + a10 * b10 + a11 * b9; 2061 s12 -= s21 * 997805;
2148 s21 = a10 * b11 + a11 * b10; 2062 s13 += s21 * 136657;
2149 s22 = a11 * b11; 2063 s14 -= s21 * 683901;
2150 s23 = 0; 2064
2151 2065 s8 += s20 * 666643;
2152 carry0 = (s0 + (1 << 20)) >> 21; s1 += carry0; s0 -= carry0 << 21; 2066 s9 += s20 * 470296;
2153 carry2 = (s2 + (1 << 20)) >> 21; s3 += carry2; s2 -= carry2 << 21; 2067 s10 += s20 * 654183;
2154 carry4 = (s4 + (1 << 20)) >> 21; s5 += carry4; s4 -= carry4 << 21; 2068 s11 -= s20 * 997805;
2069 s12 += s20 * 136657;
2070 s13 -= s20 * 683901;
2071
2072 s7 += s19 * 666643;
2073 s8 += s19 * 470296;
2074 s9 += s19 * 654183;
2075 s10 -= s19 * 997805;
2076 s11 += s19 * 136657;
2077 s12 -= s19 * 683901;
2078
2079 s6 += s18 * 666643;
2080 s7 += s18 * 470296;
2081 s8 += s18 * 654183;
2082 s9 -= s18 * 997805;
2083 s10 += s18 * 136657;
2084 s11 -= s18 * 683901;
2085
2155 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21; 2086 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
2156 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21; 2087 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
2157 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21; 2088 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
2158 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21; 2089 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
2159 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21; 2090 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
2160 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21; 2091 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
2161 carry18 = (s18 + (1 << 20)) >> 21; s19 += carry18; s18 -= carry18 << 21;
2162 carry20 = (s20 + (1 << 20)) >> 21; s21 += carry20; s20 -= carry20 << 21;
2163 carry22 = (s22 + (1 << 20)) >> 21; s23 += carry22; s22 -= carry22 << 21;
2164
2165 carry1 = (s1 + (1 << 20)) >> 21; s2 += carry1; s1 -= carry1 << 21;
2166 carry3 = (s3 + (1 << 20)) >> 21; s4 += carry3; s3 -= carry3 << 21;
2167 carry5 = (s5 + (1 << 20)) >> 21; s6 += carry5; s5 -= carry5 << 21;
2168 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
2169 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
2170 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
2171 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
2172 carry15 = (s15 + (1 << 20)) >> 21; s16 += carry15; s15 -= carry15 << 21;
2173 carry17 = (s17 + (1 << 20)) >> 21; s18 += carry17; s17 -= carry17 << 21;
2174 carry19 = (s19 + (1 << 20)) >> 21; s20 += carry19; s19 -= carry19 << 21;
2175 carry21 = (s21 + (1 << 20)) >> 21; s22 += carry21; s21 -= carry21 << 21;
2176
2177 s11 += s23 * 666643;
2178 s12 += s23 * 470296;
2179 s13 += s23 * 654183;
2180 s14 -= s23 * 997805;
2181 s15 += s23 * 136657;
2182 s16 -= s23 * 683901;
2183
2184
2185 s10 += s22 * 666643;
2186 s11 += s22 * 470296;
2187 s12 += s22 * 654183;
2188 s13 -= s22 * 997805;
2189 s14 += s22 * 136657;
2190 s15 -= s22 * 683901;
2191
2192
2193 s9 += s21 * 666643;
2194 s10 += s21 * 470296;
2195 s11 += s21 * 654183;
2196 s12 -= s21 * 997805;
2197 s13 += s21 * 136657;
2198 s14 -= s21 * 683901;
2199
2200
2201 s8 += s20 * 666643;
2202 s9 += s20 * 470296;
2203 s10 += s20 * 654183;
2204 s11 -= s20 * 997805;
2205 s12 += s20 * 136657;
2206 s13 -= s20 * 683901;
2207
2208
2209 s7 += s19 * 666643;
2210 s8 += s19 * 470296;
2211 s9 += s19 * 654183;
2212 s10 -= s19 * 997805;
2213 s11 += s19 * 136657;
2214 s12 -= s19 * 683901;
2215
2216
2217 s6 += s18 * 666643;
2218 s7 += s18 * 470296;
2219 s8 += s18 * 654183;
2220 s9 -= s18 * 997805;
2221 s10 += s18 * 136657;
2222 s11 -= s18 * 683901;
2223
2224
2225 carry6 = (s6 + (1 << 20)) >> 21; s7 += carry6; s6 -= carry6 << 21;
2226 carry8 = (s8 + (1 << 20)) >> 21; s9 += carry8; s8 -= carry8 << 21;
2227 carry10 = (s10 + (1 << 20)) >> 21; s11 += carry10; s10 -= carry10 << 21;
2228 carry12 = (s12 + (1 << 20)) >> 21; s13 += carry12; s12 -= carry12 << 21;
2229 carry14 = (s14 + (1 << 20)) >> 21; s15 += carry14; s14 -= carry14 << 21;
2230 carry16 = (s16 + (1 << 20)) >> 21; s17 += carry16; s16 -= carry16 << 21;
2231 2092
2232 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21; 2093 carry7 = (s7 + (1 << 20)) >> 21; s8 += carry7; s7 -= carry7 << 21;
2233 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21; 2094 carry9 = (s9 + (1 << 20)) >> 21; s10 += carry9; s9 -= carry9 << 21;
2234 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21; 2095 carry11 = (s11 + (1 << 20)) >> 21; s12 += carry11; s11 -= carry11 << 21;
2235 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21; 2096 carry13 = (s13 + (1 << 20)) >> 21; s14 += carry13; s13 -= carry13 << 21;
2239 s6 += s17 * 470296; 2100 s6 += s17 * 470296;
2240 s7 += s17 * 654183; 2101 s7 += s17 * 654183;
2241 s8 -= s17 * 997805; 2102 s8 -= s17 * 997805;
2242 s9 += s17 * 136657; 2103 s9 += s17 * 136657;
2243 s10 -= s17 * 683901; 2104 s10 -= s17 * 683901;
2244 2105
2245
2246 s4 += s16 * 666643; 2106 s4 += s16 * 666643;
2247 s5 += s16 * 470296; 2107 s5 += s16 * 470296;
2248 s6 += s16 * 654183; 2108 s6 += s16 * 654183;
2249 s7 -= s16 * 997805; 2109 s7 -= s16 * 997805;
2250 s8 += s16 * 136657; 2110 s8 += s16 * 136657;
2251 s9 -= s16 * 683901; 2111 s9 -= s16 * 683901;
2252 2112
2253
2254 s3 += s15 * 666643; 2113 s3 += s15 * 666643;
2255 s4 += s15 * 470296; 2114 s4 += s15 * 470296;
2256 s5 += s15 * 654183; 2115 s5 += s15 * 654183;
2257 s6 -= s15 * 997805; 2116 s6 -= s15 * 997805;
2258 s7 += s15 * 136657; 2117 s7 += s15 * 136657;
2259 s8 -= s15 * 683901; 2118 s8 -= s15 * 683901;
2260 2119
2261
2262 s2 += s14 * 666643; 2120 s2 += s14 * 666643;
2263 s3 += s14 * 470296; 2121 s3 += s14 * 470296;
2264 s4 += s14 * 654183; 2122 s4 += s14 * 654183;
2265 s5 -= s14 * 997805; 2123 s5 -= s14 * 997805;
2266 s6 += s14 * 136657; 2124 s6 += s14 * 136657;
2267 s7 -= s14 * 683901; 2125 s7 -= s14 * 683901;
2268 2126
2269
2270 s1 += s13 * 666643; 2127 s1 += s13 * 666643;
2271 s2 += s13 * 470296; 2128 s2 += s13 * 470296;
2272 s3 += s13 * 654183; 2129 s3 += s13 * 654183;
2273 s4 -= s13 * 997805; 2130 s4 -= s13 * 997805;
2274 s5 += s13 * 136657; 2131 s5 += s13 * 136657;
2275 s6 -= s13 * 683901; 2132 s6 -= s13 * 683901;
2276 2133
2277
2278 s0 += s12 * 666643; 2134 s0 += s12 * 666643;
2279 s1 += s12 * 470296; 2135 s1 += s12 * 470296;
2280 s2 += s12 * 654183; 2136 s2 += s12 * 654183;
2281 s3 -= s12 * 997805; 2137 s3 -= s12 * 997805;
2282 s4 += s12 * 136657; 2138 s4 += s12 * 136657;
2322 s1 += s12 * 470296; 2178 s1 += s12 * 470296;
2323 s2 += s12 * 654183; 2179 s2 += s12 * 654183;
2324 s3 -= s12 * 997805; 2180 s3 -= s12 * 997805;
2325 s4 += s12 * 136657; 2181 s4 += s12 * 136657;
2326 s5 -= s12 * 683901; 2182 s5 -= s12 * 683901;
2327 2183
2328
2329 carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21; 2184 carry0 = s0 >> 21; s1 += carry0; s0 -= carry0 << 21;
2330 carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21; 2185 carry1 = s1 >> 21; s2 += carry1; s1 -= carry1 << 21;
2331 carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21; 2186 carry2 = s2 >> 21; s3 += carry2; s2 -= carry2 << 21;
2332 carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21; 2187 carry3 = s3 >> 21; s4 += carry3; s3 -= carry3 << 21;
2333 carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21; 2188 carry4 = s4 >> 21; s5 += carry4; s4 -= carry4 << 21;
2369 s[28] = (Byte)((s10 >> 14) | (s11 << 7)); 2224 s[28] = (Byte)((s10 >> 14) | (s11 << 7));
2370 s[29] = (Byte)(s11 >> 1); 2225 s[29] = (Byte)(s11 >> 1);
2371 s[30] = (Byte)(s11 >> 9); 2226 s[30] = (Byte)(s11 >> 9);
2372 s[31] = (Byte)(s11 >> 17); 2227 s[31] = (Byte)(s11 >> 17);
2373 } 2228 }
2374 public static unsafe void crypto_sign(Byte[] sm, int smoffset, out UInt64 smlen, Byte[] m, int moffset, UInt64 mlen, Byte[] sk) { 2229 public static unsafe void crypto_sign(Byte[] sm, int smoffset, out int smlen, Byte[] m, int moffset, int mlen, Byte[] sk) {
2375 if (smoffset + (int)mlen + 64 > sm.Length) throw new ArgumentException("signed message buffer is too small"); 2230 if (smoffset + (int)mlen + 64 > sm.Length) throw new ArgumentException("signed message buffer is too small");
2376 if (moffset + (int)mlen > m.Length) throw new ArgumentException("message buffer is too small"); 2231 if (moffset + (int)mlen > m.Length) throw new ArgumentException("message buffer is too small");
2377 if (64 > sk.Length) throw new ArgumentException("key buffer is too small"); 2232 if (64 > sk.Length) throw new ArgumentException("key buffer is too small");
2378 fixed (Byte* smp = sm, mp = m, skp = sk) crypto_sign(smp + smoffset, out smlen, mp + moffset, mlen, skp); 2233 fixed (Byte* smp = sm, mp = m, skp = sk) crypto_sign(smp + smoffset, out smlen, mp + moffset, mlen, skp);
2379 } 2234 }
2380 public static unsafe void crypto_sign(Byte* sm, out UInt64 smlen, Byte* m, UInt64 mlen, Byte* sk) { 2235 public static unsafe void crypto_sign(Byte* sm, out int smlen, Byte* m, int mlen, Byte* sk) {
2236 smlen = mlen + 64;
2237 for (int i = 0; i < mlen; ++i) sm[64 + i] = m[i];
2238 crypto_getsignature(sm, m, mlen, sk);
2239 }
2240 public static unsafe void crypto_getsignature(Byte* sig, Byte* m, int mlen, Byte* sk) {
2381 Byte* az = stackalloc Byte[64]; 2241 Byte* az = stackalloc Byte[64];
2382 Byte* r = stackalloc Byte[64]; 2242 sha512.crypto_hash(az, sk, 32);
2383 Byte* hram = stackalloc Byte[64];
2384
2385 crypto_hash.sha512.crypto_hash(az, sk, 32);
2386 az[0] &= 248; 2243 az[0] &= 248;
2387 az[31] &= 63; 2244 az[31] &= 63;
2388 az[31] |= 64; 2245 az[31] |= 64;
2389 2246
2390 smlen = mlen + 64; 2247 sha512.sha512state hashstate = new sha512.sha512state();
2391 for (UInt64 i = 0; i < mlen; ++i) sm[64 + i] = m[i]; 2248 hashstate.init();
2392 for (UInt64 i = 0; i < 32; ++i) sm[32 + i] = az[32 + i]; 2249 hashstate.process(az + 32, 32);
2393 crypto_hash.sha512.crypto_hash(r, sm + 32, mlen + 32); 2250 hashstate.process(m, (int)mlen);
2394 for (UInt64 i = 0; i < 32; ++i) sm[32 + i] = sk[32 + i]; 2251 Byte* r = stackalloc Byte[64];
2252 hashstate.finish(r);
2395 2253
2396 sc_reduce(r); 2254 sc_reduce(r);
2397 ge_p3 R; 2255 ge_p3 R;
2398 ge_scalarmult_base(out R, r); 2256 ge_scalarmult_base(out R, r);
2399 ge_p3_tobytes(sm, ref R); 2257 ge_p3_tobytes(sig, ref R);
2400 2258
2401 crypto_hash.sha512.crypto_hash(hram, sm, mlen + 64); 2259 hashstate.init();
2260 hashstate.process(sig, 32);
2261 hashstate.process(sk + 32, 32);
2262 hashstate.process(m, (int)mlen);
2263 Byte* hram = stackalloc Byte[64];
2264 hashstate.finish(hram);
2402 sc_reduce(hram); 2265 sc_reduce(hram);
2403 sc_muladd(sm + 32, hram, az, r); 2266 sc_muladd(sig + 32, hram, az, r);
2404 } 2267 }
2405 2268
2406 static unsafe void fe_frombytes(out fe h, Byte* s) { 2269 static fe d = new fe(0, new Int32[10] { -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 });
2407 Int64 h0 = load_4(s); 2270 static fe sqrtm1 = new fe(0, new Int32[10] { -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 });
2408 Int64 h1 = load_3(s + 4) << 6; 2271
2409 Int64 h2 = load_3(s + 7) << 5;
2410 Int64 h3 = load_3(s + 10) << 3;
2411 Int64 h4 = load_3(s + 13) << 2;
2412 Int64 h5 = load_4(s + 16);
2413 Int64 h6 = load_3(s + 20) << 7;
2414 Int64 h7 = load_3(s + 23) << 5;
2415 Int64 h8 = load_3(s + 26) << 4;
2416 Int64 h9 = (load_3(s + 29) & 8388607) << 2;
2417 Int64 carry0;
2418 Int64 carry1;
2419 Int64 carry2;
2420 Int64 carry3;
2421 Int64 carry4;
2422 Int64 carry5;
2423 Int64 carry6;
2424 Int64 carry7;
2425 Int64 carry8;
2426 Int64 carry9;
2427
2428 carry9 = (h9 + (Int64)(1 << 24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
2429 carry1 = (h1 + (Int64)(1 << 24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
2430 carry3 = (h3 + (Int64)(1 << 24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
2431 carry5 = (h5 + (Int64)(1 << 24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
2432 carry7 = (h7 + (Int64)(1 << 24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
2433
2434 carry0 = (h0 + (Int64)(1 << 25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
2435 carry2 = (h2 + (Int64)(1 << 25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
2436 carry4 = (h4 + (Int64)(1 << 25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
2437 carry6 = (h6 + (Int64)(1 << 25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
2438 carry8 = (h8 + (Int64)(1 << 25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
2439
2440 h = new fe();
2441 h[0] = (Int32)h0;
2442 h[1] = (Int32)h1;
2443 h[2] = (Int32)h2;
2444 h[3] = (Int32)h3;
2445 h[4] = (Int32)h4;
2446 h[5] = (Int32)h5;
2447 h[6] = (Int32)h6;
2448 h[7] = (Int32)h7;
2449 h[8] = (Int32)h8;
2450 h[9] = (Int32)h9;
2451 }
2452 static Byte[] zero = new Byte[32];
2453 static unsafe int fe_isnonzero(ref fe f) {
2454 Byte* s = stackalloc Byte[32];
2455 fe_tobytes(s, ref f);
2456 fixed (Byte* zerop = zero) return crypto_verify._32.crypto_verify(s, zerop);
2457 }
2458 static fe d = fe_unpack(0, new Int32[10] { -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116 });
2459 static fe sqrtm1 = fe_unpack(0, new Int32[10] { -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482 });
2460 static void fe_pow22523(out fe outv, ref fe z) {
2461 fe t0;
2462 fe t1;
2463 fe t2;
2464 fe_sq(out t0, ref z); for (int i = 1; i < 1; ++i) fe_sq(out t0, ref t0);
2465 fe_sq(out t1, ref t0); for (int i = 1; i < 2; ++i) fe_sq(out t1, ref t1);
2466 fe_mul(out t1, ref z, ref t1);
2467 fe_mul(out t0, ref t0, ref t1);
2468 fe_sq(out t0, ref t0); for (int i = 1; i < 1; ++i) fe_sq(out t0, ref t0);
2469 fe_mul(out t0, ref t1, ref t0);
2470 fe_sq(out t1, ref t0); for (int i = 1; i < 5; ++i) fe_sq(out t1, ref t1);
2471 fe_mul(out t0, ref t1, ref t0);
2472 fe_sq(out t1, ref t0); for (int i = 1; i < 10; ++i) fe_sq(out t1, ref t1);
2473 fe_mul(out t1, ref t1, ref t0);
2474 fe_sq(out t2, ref t1); for (int i = 1; i < 20; ++i) fe_sq(out t2, ref t2);
2475 fe_mul(out t1, ref t2, ref t1);
2476 fe_sq(out t1, ref t1); for (int i = 1; i < 10; ++i) fe_sq(out t1, ref t1);
2477 fe_mul(out t0, ref t1, ref t0);
2478 fe_sq(out t1, ref t0); for (int i = 1; i < 50; ++i) fe_sq(out t1, ref t1);
2479 fe_mul(out t1, ref t1, ref t0);
2480 fe_sq(out t2, ref t1); for (int i = 1; i < 100; ++i) fe_sq(out t2, ref t2);
2481 fe_mul(out t1, ref t2, ref t1);
2482 fe_sq(out t1, ref t1); for (int i = 1; i < 50; ++i) fe_sq(out t1, ref t1);
2483 fe_mul(out t0, ref t1, ref t0);
2484 fe_sq(out t0, ref t0); for (int i = 1; i < 2; ++i) fe_sq(out t0, ref t0);
2485 fe_mul(out outv, ref t0, ref z);
2486 }
2487 static unsafe Boolean ge_frombytes_negate_vartime(out ge_p3 h, Byte* s) { 2272 static unsafe Boolean ge_frombytes_negate_vartime(out ge_p3 h, Byte* s) {
2488 fe u; 2273 fe u;
2489 fe v; 2274 fe v;
2490 fe v3; 2275 fe v3;
2491 fe vxx; 2276 fe vxx;
2492 fe check; 2277 fe check;
2493 2278
2494 fe_frombytes(out h.Y, s); 2279 h = new ge_p3();
2495 fe_1(out h.Z); 2280
2281 h.Y.frombytes(s);
2282 h.Z.set_one();
2496 fe_sq(out u, ref h.Y); 2283 fe_sq(out u, ref h.Y);
2497 fe_mul(out v, ref u, ref d); 2284 fe_mul(out v, ref u, ref d);
2498 fe_sub(out u, ref u, ref h.Z); /* u = y^2-1 */ 2285 u.sub(ref h.Z); /* u = y^2-1 */
2499 fe_add(out v, ref v, ref h.Z); /* v = dy^2+1 */ 2286 v.add(ref h.Z); /* v = dy^2+1 */
2500 2287
2501 fe_sq(out v3, ref v); 2288 fe_sq(out v3, ref v);
2502 fe_mul(out v3, ref v3, ref v); /* v3 = v^3 */ 2289 v3.mul(ref v); /* v3 = v^3 */
2503 fe_sq(out h.X, ref v3); 2290 fe_sq(out h.X, ref v3);
2504 fe_mul(out h.X, ref h.X, ref v); 2291 h.X.mul(ref v);
2505 fe_mul(out h.X, ref h.X, ref u); /* x = uv^7 */ 2292 h.X.mul(ref u); /* x = uv^7 */
2506 2293
2507 fe_pow22523(out h.X, ref h.X); /* x = (uv^7)^((q-5)/8) */ 2294 h.X.pow22523(); /* x = (uv^7)^((q-5)/8) */
2508 fe_mul(out h.X, ref h.X, ref v3); 2295 h.X.mul(ref v3);
2509 fe_mul(out h.X, ref h.X, ref u); /* x = uv^3(uv^7)^((q-5)/8) */ 2296 h.X.mul(ref u); /* x = uv^3(uv^7)^((q-5)/8) */
2510 2297
2511 fe_sq(out vxx, ref h.X); 2298 fe_sq(out vxx, ref h.X);
2512 fe_mul(out vxx, ref vxx, ref v); 2299 vxx.mul(ref v);
2513 fe_sub(out check, ref vxx, ref u); /* vx^2-u */ 2300 fe_sub(out check, ref vxx, ref u); /* vx^2-u */
2514 if (fe_isnonzero(ref check) != 0) { 2301 if (check.isnonzero() != 0) {
2515 fe_add(out check, ref vxx, ref u); /* vx^2+u */ 2302 fe_add(out check, ref vxx, ref u); /* vx^2+u */
2516 if (fe_isnonzero(ref check) != 0) return false; 2303 if (check.isnonzero() != 0) return false;
2517 fe_mul(out h.X, ref h.X, ref sqrtm1); 2304 h.X.mul(ref sqrtm1);
2518 } 2305 }
2519 2306
2520 if (fe_isnegative(ref h.X) == (s[31] >> 7)) 2307 if (h.X.isnegative() == (s[31] >> 7)) h.X.neg();
2521 fe_neg(out h.X, ref h.X);
2522 2308
2523 fe_mul(out h.T, ref h.X, ref h.Y); 2309 fe_mul(out h.T, ref h.X, ref h.Y);
2524 return true; 2310 return true;
2525 }
2526 struct ge_cached {
2527 public fe YplusX;
2528 public fe YminusX;
2529 public fe Z;
2530 public fe T2d;
2531 } 2311 }
2532 static unsafe void slide(SByte* r, Byte* a) { 2312 static unsafe void slide(SByte* r, Byte* a) {
2533 for (int i = 0; i < 256; ++i) r[i] = (SByte)(1 & (a[i >> 3] >> (i & 7))); 2313 for (int i = 0; i < 256; ++i) r[i] = (SByte)(1 & (a[i >> 3] >> (i & 7)));
2534 2314
2535 for (int i = 0; i < 256; ++i) 2315 for (int i = 0; i < 256; ++i)
2551 break; 2331 break;
2552 } 2332 }
2553 } 2333 }
2554 } 2334 }
2555 } 2335 }
2556 static ge_precomp[] Bi = base_unpack(8, 0, new Int32[8 * 3 * 10] { 2336 static ge_precomp[] Bi = base_unpack(8, new Int32[8 * 3 * 10] {
2557 #region Base number 2337 #region Base number
2558 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605, 2338 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605,
2559 -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378, 2339 -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378,
2560 -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546, 2340 -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546,
2561 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024, 2341 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024,
2579 -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876, 2359 -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876,
2580 -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619, 2360 -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619,
2581 -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683, 2361 -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683,
2582 #endregion 2362 #endregion
2583 }); 2363 });
2584 static fe d2 = fe_unpack(0, new Int32[10] { -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 }); 2364 static fe d2 = new fe(0, new Int32[10] { -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199 });
2585 static void ge_p3_to_cached(out ge_cached r, ref ge_p3 p) { 2365 static void ge_p3_to_cached(out ge_cached r, ref ge_p3 p) {
2586 fe_add(out r.YplusX, ref p.Y, ref p.X); 2366 fe_add(out r.YplusX, ref p.Y, ref p.X);
2587 fe_sub(out r.YminusX, ref p.Y, ref p.X); 2367 fe_sub(out r.YminusX, ref p.Y, ref p.X);
2588 fe_copy(out r.Z, ref p.Z); 2368 r.Z = p.Z;
2589 fe_mul(out r.T2d, ref p.T, ref d2); 2369 fe_mul(out r.T2d, ref p.T, ref d2);
2590 } 2370 }
2591 static void ge_add(out ge_p1p1 r, ref ge_p3 p, ref ge_cached q) { 2371 static void ge_add(out ge_p1p1 r, ref ge_p3 p, ref ge_cached q) {
2592 fe t0; 2372 fe t0;
2593 fe_add(out r.X, ref p.Y, ref p.X); 2373 fe_add(out r.X, ref p.Y, ref p.X);
2600 fe_sub(out r.X, ref r.Z, ref r.Y); 2380 fe_sub(out r.X, ref r.Z, ref r.Y);
2601 fe_add(out r.Y, ref r.Z, ref r.Y); 2381 fe_add(out r.Y, ref r.Z, ref r.Y);
2602 fe_add(out r.Z, ref t0, ref r.T); 2382 fe_add(out r.Z, ref t0, ref r.T);
2603 fe_sub(out r.T, ref t0, ref r.T); 2383 fe_sub(out r.T, ref t0, ref r.T);
2604 } 2384 }
2605 static void ge_p2_0(out ge_p2 h) {
2606 fe_0(out h.X);
2607 fe_1(out h.Y);
2608 fe_1(out h.Z);
2609 }
2610 static void ge_sub(out ge_p1p1 r, ref ge_p3 p, ref ge_cached q) { 2385 static void ge_sub(out ge_p1p1 r, ref ge_p3 p, ref ge_cached q) {
2611 fe t0; 2386 fe t0;
2612 fe_add(out r.X, ref p.Y, ref p.X); 2387 fe_add(out r.X, ref p.Y, ref p.X);
2613 fe_sub(out r.Y, ref p.Y, ref p.X); 2388 fe_sub(out r.Y, ref p.Y, ref p.X);
2614 fe_mul(out r.Z, ref r.X, ref q.YminusX); 2389 fe_mul(out r.Z, ref r.X, ref q.YminusX);
2639 SByte* bslide = stackalloc SByte[256]; 2414 SByte* bslide = stackalloc SByte[256];
2640 ge_cached* Ai = stackalloc ge_cached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ 2415 ge_cached* Ai = stackalloc ge_cached[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
2641 ge_p1p1 t; 2416 ge_p1p1 t;
2642 ge_p3 u; 2417 ge_p3 u;
2643 ge_p3 A2; 2418 ge_p3 A2;
2644 int i;
2645 2419
2646 slide(aslide, a); 2420 slide(aslide, a);
2647 slide(bslide, b); 2421 slide(bslide, b);
2648 2422
2649 ge_p3_to_cached(out Ai[0], ref A); 2423 ge_p3_to_cached(out Ai[0], ref A);
2654 ge_add(out t, ref A2, ref Ai[3]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[4], ref u); 2428 ge_add(out t, ref A2, ref Ai[3]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[4], ref u);
2655 ge_add(out t, ref A2, ref Ai[4]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[5], ref u); 2429 ge_add(out t, ref A2, ref Ai[4]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[5], ref u);
2656 ge_add(out t, ref A2, ref Ai[5]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[6], ref u); 2430 ge_add(out t, ref A2, ref Ai[5]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[6], ref u);
2657 ge_add(out t, ref A2, ref Ai[6]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[7], ref u); 2431 ge_add(out t, ref A2, ref Ai[6]); ge_p1p1_to_p3(out u, ref t); ge_p3_to_cached(out Ai[7], ref u);
2658 2432
2659 ge_p2_0(out r); 2433 r = new ge_p2(); r.set_zero();
2660 2434
2661 for (i = 255; i >= 0; --i) { 2435 int i;
2662 if ((aslide[i] != 0) || (bslide[i] != 0)) break; 2436 for (i = 255; i >= 0 && aslide[i] == 0 && bslide[i] == 0; i--);
2663 } 2437 for (; i >= 0; i--) {
2664
2665 for (; i >= 0; --i) {
2666 ge_p2_dbl(out t, ref r); 2438 ge_p2_dbl(out t, ref r);
2667 2439
2668 if (aslide[i] > 0) { 2440 if (aslide[i] > 0) {
2669 ge_p1p1_to_p3(out u, ref t); 2441 ge_p1p1_to_p3(out u, ref t);
2670 ge_add(out t, ref u, ref Ai[aslide[i] / 2]); 2442 ge_add(out t, ref u, ref Ai[aslide[i] / 2]);
2683 2455
2684 ge_p1p1_to_p2(out r, ref t); 2456 ge_p1p1_to_p2(out r, ref t);
2685 } 2457 }
2686 } 2458 }
2687 static unsafe void ge_tobytes(Byte* s, ref ge_p2 h) { 2459 static unsafe void ge_tobytes(Byte* s, ref ge_p2 h) {
2688 fe recip; 2460 fe recip = h.Z; recip.invert();
2689 fe x; 2461 fe x = h.X; x.mul(ref recip);
2690 fe y; 2462 fe y = h.Y; y.mul(ref recip);
2691 fe_invert(out recip, ref h.Z); 2463 y.tobytes(s);
2692 fe_mul(out x, ref h.X, ref recip); 2464 s[31] ^= (Byte)(x.isnegative() << 7);
2693 fe_mul(out y, ref h.Y, ref recip); 2465 }
2694 fe_tobytes(s, ref y); 2466 public static unsafe Boolean crypto_sign_open(Byte[] m, int moffset, out int mlen, Byte[] sm, int smoffset, int smlen, Byte[] pk) {
2695 s[31] ^= (Byte)(fe_isnegative(ref x) << 7);
2696 }
2697 public static unsafe Boolean crypto_sign_open(Byte[] m, int moffset, out UInt64 mlen, Byte[] sm, int smoffset, UInt64 smlen, Byte[] pk) {
2698 if (smoffset + (int)smlen > sm.Length) throw new ArgumentException("signed message buffer is too small"); 2467 if (smoffset + (int)smlen > sm.Length) throw new ArgumentException("signed message buffer is too small");
2699 if (moffset + (int)smlen > m.Length) throw new ArgumentException("message buffer is too small"); 2468 if (moffset + (int)smlen > m.Length) throw new ArgumentException("message buffer is too small");
2700 if (32 > pk.Length) throw new ArgumentException("key buffer is too small"); 2469 if (32 > pk.Length) throw new ArgumentException("key buffer is too small");
2701 fixed (Byte* mp = m, smp = sm, pkp = pk) return crypto_sign_open(mp + moffset, out mlen, smp + smoffset, smlen, pkp); 2470 fixed (Byte* mp = m, smp = sm, pkp = pk) return crypto_sign_open(mp + moffset, out mlen, smp + smoffset, smlen, pkp);
2702 } 2471 }
2703 public static unsafe Boolean crypto_sign_open(Byte* m, out UInt64 mlen, Byte* sm, UInt64 smlen, Byte* pk) { 2472 public static unsafe Boolean crypto_sign_open(Byte* m, out int mlen, Byte* sm, int smlen, Byte* pk) {
2704 Byte* h = stackalloc Byte[64]; 2473 mlen = 0;
2705 Byte* checkr = stackalloc Byte[32]; 2474 if (!crypto_sign_verify(sm, sm + 64, (int)smlen - 64, pk)) return false;
2706 ge_p3 A; 2475 for (int i = 0; i < smlen - 64; ++i) m[i] = sm[64 + i];
2707 ge_p2 R;
2708
2709 mlen = unchecked((UInt64)(-1));
2710 if (smlen < 64) return false;
2711 if ((sm[63] & 224) != 0) return false;
2712 if (!ge_frombytes_negate_vartime(out A, pk)) return false;
2713
2714 for (UInt64 i = 0; i < smlen; ++i) m[i] = sm[i];
2715 for (UInt64 i = 0; i < 32; ++i) m[32 + i] = pk[i];
2716 crypto_hash.sha512.crypto_hash(h, m, smlen);
2717 sc_reduce(h);
2718
2719 ge_double_scalarmult_vartime(out R, h, ref A, sm + 32);
2720 ge_tobytes(checkr, ref R);
2721 if (crypto_verify._32.crypto_verify(checkr, sm) != 0) {
2722 for (UInt64 i = 0; i < smlen; ++i) m[i] = 0;
2723 return false;
2724 }
2725
2726 for (UInt64 i = 0; i < smlen - 64; ++i) m[i] = sm[64 + i];
2727 for (UInt64 i = smlen - 64; i < smlen; ++i) m[i] = 0;
2728 mlen = smlen - 64; 2476 mlen = smlen - 64;
2729 return true; 2477 return true;
2730 } 2478 }
2479 public static unsafe Boolean crypto_sign_verify(Byte* sig, Byte* m, int mlen, Byte* pk) {
2480 if (mlen < 0) return false;
2481 if ((sig[63] & 224) != 0) return false;
2482 ge_p3 A;
2483 if (!ge_frombytes_negate_vartime(out A, pk)) return false;
2484
2485 sha512.sha512state hashstate = new sha512.sha512state();
2486 hashstate.init();
2487 hashstate.process(sig, 32);
2488 hashstate.process(pk, 32);
2489 hashstate.process(m, mlen);
2490 Byte* h = stackalloc Byte[64];
2491 hashstate.finish(h);
2492 sc_reduce(h);
2493
2494 ge_p2 R;
2495 ge_double_scalarmult_vartime(out R, h, ref A, sig + 32);
2496 ge_tobytes(h, ref R);
2497 return crypto_verify._32.crypto_verify(h, sig) == 0;
2498 }
2731 } 2499 }
2732 } 2500 }