nanocurrency 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +6 -0
  7. data/Gemfile.lock +40 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +43 -0
  10. data/Rakefile +16 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/ext/.DS_Store +0 -0
  14. data/ext/nanocurrency_ext/blake2-config.h +72 -0
  15. data/ext/nanocurrency_ext/blake2-impl.h +160 -0
  16. data/ext/nanocurrency_ext/blake2.h +195 -0
  17. data/ext/nanocurrency_ext/blake2b-load-sse2.h +68 -0
  18. data/ext/nanocurrency_ext/blake2b-load-sse41.h +402 -0
  19. data/ext/nanocurrency_ext/blake2b-ref.c +373 -0
  20. data/ext/nanocurrency_ext/blake2b-round.h +157 -0
  21. data/ext/nanocurrency_ext/curve25519-donna-32bit.h +579 -0
  22. data/ext/nanocurrency_ext/curve25519-donna-64bit.h +413 -0
  23. data/ext/nanocurrency_ext/curve25519-donna-helpers.h +67 -0
  24. data/ext/nanocurrency_ext/curve25519-donna-sse2.h +1112 -0
  25. data/ext/nanocurrency_ext/ed25519-donna-32bit-sse2.h +513 -0
  26. data/ext/nanocurrency_ext/ed25519-donna-32bit-tables.h +61 -0
  27. data/ext/nanocurrency_ext/ed25519-donna-64bit-sse2.h +436 -0
  28. data/ext/nanocurrency_ext/ed25519-donna-64bit-tables.h +53 -0
  29. data/ext/nanocurrency_ext/ed25519-donna-64bit-x86-32bit.h +435 -0
  30. data/ext/nanocurrency_ext/ed25519-donna-64bit-x86.h +351 -0
  31. data/ext/nanocurrency_ext/ed25519-donna-basepoint-table.h +259 -0
  32. data/ext/nanocurrency_ext/ed25519-donna-batchverify.h +275 -0
  33. data/ext/nanocurrency_ext/ed25519-donna-impl-base.h +364 -0
  34. data/ext/nanocurrency_ext/ed25519-donna-impl-sse2.h +390 -0
  35. data/ext/nanocurrency_ext/ed25519-donna-portable-identify.h +103 -0
  36. data/ext/nanocurrency_ext/ed25519-donna-portable.h +135 -0
  37. data/ext/nanocurrency_ext/ed25519-donna.h +115 -0
  38. data/ext/nanocurrency_ext/ed25519-hash-custom.c +28 -0
  39. data/ext/nanocurrency_ext/ed25519-hash-custom.h +30 -0
  40. data/ext/nanocurrency_ext/ed25519-hash.h +219 -0
  41. data/ext/nanocurrency_ext/ed25519-randombytes-custom.h +10 -0
  42. data/ext/nanocurrency_ext/ed25519-randombytes.h +91 -0
  43. data/ext/nanocurrency_ext/ed25519.c +150 -0
  44. data/ext/nanocurrency_ext/ed25519.h +30 -0
  45. data/ext/nanocurrency_ext/extconf.rb +3 -0
  46. data/ext/nanocurrency_ext/fuzz/README.md +173 -0
  47. data/ext/nanocurrency_ext/fuzz/build-nix.php +134 -0
  48. data/ext/nanocurrency_ext/fuzz/curve25519-ref10.c +1272 -0
  49. data/ext/nanocurrency_ext/fuzz/curve25519-ref10.h +8 -0
  50. data/ext/nanocurrency_ext/fuzz/ed25519-donna-sse2.c +3 -0
  51. data/ext/nanocurrency_ext/fuzz/ed25519-donna.c +1 -0
  52. data/ext/nanocurrency_ext/fuzz/ed25519-donna.h +34 -0
  53. data/ext/nanocurrency_ext/fuzz/ed25519-ref10.c +4647 -0
  54. data/ext/nanocurrency_ext/fuzz/ed25519-ref10.h +9 -0
  55. data/ext/nanocurrency_ext/fuzz/fuzz-curve25519.c +172 -0
  56. data/ext/nanocurrency_ext/fuzz/fuzz-ed25519.c +219 -0
  57. data/ext/nanocurrency_ext/modm-donna-32bit.h +469 -0
  58. data/ext/nanocurrency_ext/modm-donna-64bit.h +361 -0
  59. data/ext/nanocurrency_ext/rbext.c +164 -0
  60. data/ext/nanocurrency_ext/regression.h +1024 -0
  61. data/lib/nano/account.rb +59 -0
  62. data/lib/nano/base32.rb +87 -0
  63. data/lib/nano/block.rb +142 -0
  64. data/lib/nano/check.rb +65 -0
  65. data/lib/nano/conversion.rb +102 -0
  66. data/lib/nano/hash.rb +43 -0
  67. data/lib/nano/key.rb +69 -0
  68. data/lib/nano/utils.rb +45 -0
  69. data/lib/nano/work.rb +51 -0
  70. data/lib/nanocurrency.rb +7 -0
  71. data/lib/nanocurrency/version.rb +3 -0
  72. data/lib/nanocurrency_ext.bundle +0 -0
  73. data/nanocurrency.gemspec +44 -0
  74. metadata +192 -0
@@ -0,0 +1,413 @@
1
+ /*
2
+ Public domain by Adam Langley <agl@imperialviolet.org> &
3
+ Andrew M. <liquidsun@gmail.com>
4
+ See: https://github.com/floodyberry/curve25519-donna
5
+
6
+ 64bit integer curve25519 implementation
7
+ */
8
+
9
+ typedef uint64_t bignum25519[5];
10
+
11
+ static const uint64_t reduce_mask_40 = ((uint64_t)1 << 40) - 1;
12
+ static const uint64_t reduce_mask_51 = ((uint64_t)1 << 51) - 1;
13
+ static const uint64_t reduce_mask_56 = ((uint64_t)1 << 56) - 1;
14
+
15
+ /* out = in */
16
+ DONNA_INLINE static void
17
+ curve25519_copy(bignum25519 out, const bignum25519 in) {
18
+ out[0] = in[0];
19
+ out[1] = in[1];
20
+ out[2] = in[2];
21
+ out[3] = in[3];
22
+ out[4] = in[4];
23
+ }
24
+
25
+ /* out = a + b */
26
+ DONNA_INLINE static void
27
+ curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) {
28
+ out[0] = a[0] + b[0];
29
+ out[1] = a[1] + b[1];
30
+ out[2] = a[2] + b[2];
31
+ out[3] = a[3] + b[3];
32
+ out[4] = a[4] + b[4];
33
+ }
34
+
35
+ /* out = a + b, where a and/or b are the result of a basic op (add,sub) */
36
+ DONNA_INLINE static void
37
+ curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
38
+ out[0] = a[0] + b[0];
39
+ out[1] = a[1] + b[1];
40
+ out[2] = a[2] + b[2];
41
+ out[3] = a[3] + b[3];
42
+ out[4] = a[4] + b[4];
43
+ }
44
+
45
+ DONNA_INLINE static void
46
+ curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
47
+ uint64_t c;
48
+ out[0] = a[0] + b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
49
+ out[1] = a[1] + b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
50
+ out[2] = a[2] + b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
51
+ out[3] = a[3] + b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
52
+ out[4] = a[4] + b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
53
+ out[0] += c * 19;
54
+ }
55
+
56
+ /* multiples of p */
57
+ static const uint64_t twoP0 = 0x0fffffffffffda;
58
+ static const uint64_t twoP1234 = 0x0ffffffffffffe;
59
+ static const uint64_t fourP0 = 0x1fffffffffffb4;
60
+ static const uint64_t fourP1234 = 0x1ffffffffffffc;
61
+
62
+ /* out = a - b */
63
+ DONNA_INLINE static void
64
+ curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) {
65
+ out[0] = a[0] + twoP0 - b[0];
66
+ out[1] = a[1] + twoP1234 - b[1];
67
+ out[2] = a[2] + twoP1234 - b[2];
68
+ out[3] = a[3] + twoP1234 - b[3];
69
+ out[4] = a[4] + twoP1234 - b[4];
70
+ }
71
+
72
+ /* out = a - b, where a and/or b are the result of a basic op (add,sub) */
73
+ DONNA_INLINE static void
74
+ curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
75
+ out[0] = a[0] + fourP0 - b[0];
76
+ out[1] = a[1] + fourP1234 - b[1];
77
+ out[2] = a[2] + fourP1234 - b[2];
78
+ out[3] = a[3] + fourP1234 - b[3];
79
+ out[4] = a[4] + fourP1234 - b[4];
80
+ }
81
+
82
+ DONNA_INLINE static void
83
+ curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
84
+ uint64_t c;
85
+ out[0] = a[0] + fourP0 - b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
86
+ out[1] = a[1] + fourP1234 - b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
87
+ out[2] = a[2] + fourP1234 - b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
88
+ out[3] = a[3] + fourP1234 - b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
89
+ out[4] = a[4] + fourP1234 - b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
90
+ out[0] += c * 19;
91
+ }
92
+
93
+ /* out = -a */
94
+ DONNA_INLINE static void
95
+ curve25519_neg(bignum25519 out, const bignum25519 a) {
96
+ uint64_t c;
97
+ out[0] = twoP0 - a[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
98
+ out[1] = twoP1234 - a[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
99
+ out[2] = twoP1234 - a[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
100
+ out[3] = twoP1234 - a[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
101
+ out[4] = twoP1234 - a[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
102
+ out[0] += c * 19;
103
+ }
104
+
105
+ /* out = a * b */
106
+ DONNA_INLINE static void
107
+ curve25519_mul(bignum25519 out, const bignum25519 in2, const bignum25519 in) {
108
+ #if !defined(HAVE_NATIVE_UINT128)
109
+ uint128_t mul;
110
+ #endif
111
+ uint128_t t[5];
112
+ uint64_t r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c;
113
+
114
+ r0 = in[0];
115
+ r1 = in[1];
116
+ r2 = in[2];
117
+ r3 = in[3];
118
+ r4 = in[4];
119
+
120
+ s0 = in2[0];
121
+ s1 = in2[1];
122
+ s2 = in2[2];
123
+ s3 = in2[3];
124
+ s4 = in2[4];
125
+
126
+ #if defined(HAVE_NATIVE_UINT128)
127
+ t[0] = ((uint128_t) r0) * s0;
128
+ t[1] = ((uint128_t) r0) * s1 + ((uint128_t) r1) * s0;
129
+ t[2] = ((uint128_t) r0) * s2 + ((uint128_t) r2) * s0 + ((uint128_t) r1) * s1;
130
+ t[3] = ((uint128_t) r0) * s3 + ((uint128_t) r3) * s0 + ((uint128_t) r1) * s2 + ((uint128_t) r2) * s1;
131
+ t[4] = ((uint128_t) r0) * s4 + ((uint128_t) r4) * s0 + ((uint128_t) r3) * s1 + ((uint128_t) r1) * s3 + ((uint128_t) r2) * s2;
132
+ #else
133
+ mul64x64_128(t[0], r0, s0)
134
+ mul64x64_128(t[1], r0, s1) mul64x64_128(mul, r1, s0) add128(t[1], mul)
135
+ mul64x64_128(t[2], r0, s2) mul64x64_128(mul, r2, s0) add128(t[2], mul) mul64x64_128(mul, r1, s1) add128(t[2], mul)
136
+ mul64x64_128(t[3], r0, s3) mul64x64_128(mul, r3, s0) add128(t[3], mul) mul64x64_128(mul, r1, s2) add128(t[3], mul) mul64x64_128(mul, r2, s1) add128(t[3], mul)
137
+ mul64x64_128(t[4], r0, s4) mul64x64_128(mul, r4, s0) add128(t[4], mul) mul64x64_128(mul, r3, s1) add128(t[4], mul) mul64x64_128(mul, r1, s3) add128(t[4], mul) mul64x64_128(mul, r2, s2) add128(t[4], mul)
138
+ #endif
139
+
140
+ r1 *= 19;
141
+ r2 *= 19;
142
+ r3 *= 19;
143
+ r4 *= 19;
144
+
145
+ #if defined(HAVE_NATIVE_UINT128)
146
+ t[0] += ((uint128_t) r4) * s1 + ((uint128_t) r1) * s4 + ((uint128_t) r2) * s3 + ((uint128_t) r3) * s2;
147
+ t[1] += ((uint128_t) r4) * s2 + ((uint128_t) r2) * s4 + ((uint128_t) r3) * s3;
148
+ t[2] += ((uint128_t) r4) * s3 + ((uint128_t) r3) * s4;
149
+ t[3] += ((uint128_t) r4) * s4;
150
+ #else
151
+ mul64x64_128(mul, r4, s1) add128(t[0], mul) mul64x64_128(mul, r1, s4) add128(t[0], mul) mul64x64_128(mul, r2, s3) add128(t[0], mul) mul64x64_128(mul, r3, s2) add128(t[0], mul)
152
+ mul64x64_128(mul, r4, s2) add128(t[1], mul) mul64x64_128(mul, r2, s4) add128(t[1], mul) mul64x64_128(mul, r3, s3) add128(t[1], mul)
153
+ mul64x64_128(mul, r4, s3) add128(t[2], mul) mul64x64_128(mul, r3, s4) add128(t[2], mul)
154
+ mul64x64_128(mul, r4, s4) add128(t[3], mul)
155
+ #endif
156
+
157
+
158
+ r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51);
159
+ add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51);
160
+ add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51);
161
+ add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51);
162
+ add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51);
163
+ r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51;
164
+ r1 += c;
165
+
166
+ out[0] = r0;
167
+ out[1] = r1;
168
+ out[2] = r2;
169
+ out[3] = r3;
170
+ out[4] = r4;
171
+ }
172
+
173
+ DONNA_NOINLINE static void
174
+ curve25519_mul_noinline(bignum25519 out, const bignum25519 in2, const bignum25519 in) {
175
+ curve25519_mul(out, in2, in);
176
+ }
177
+
178
+ /* out = in^(2 * count) */
179
+ DONNA_NOINLINE static void
180
+ curve25519_square_times(bignum25519 out, const bignum25519 in, uint64_t count) {
181
+ #if !defined(HAVE_NATIVE_UINT128)
182
+ uint128_t mul;
183
+ #endif
184
+ uint128_t t[5];
185
+ uint64_t r0,r1,r2,r3,r4,c;
186
+ uint64_t d0,d1,d2,d4,d419;
187
+
188
+ r0 = in[0];
189
+ r1 = in[1];
190
+ r2 = in[2];
191
+ r3 = in[3];
192
+ r4 = in[4];
193
+
194
+ do {
195
+ d0 = r0 * 2;
196
+ d1 = r1 * 2;
197
+ d2 = r2 * 2 * 19;
198
+ d419 = r4 * 19;
199
+ d4 = d419 * 2;
200
+
201
+ #if defined(HAVE_NATIVE_UINT128)
202
+ t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 ));
203
+ t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19));
204
+ t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 ));
205
+ t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 ));
206
+ t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 ));
207
+ #else
208
+ mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul)
209
+ mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul)
210
+ mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul)
211
+ mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul)
212
+ mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul)
213
+ #endif
214
+
215
+ r0 = lo128(t[0]) & reduce_mask_51;
216
+ r1 = lo128(t[1]) & reduce_mask_51; shl128(c, t[0], 13); r1 += c;
217
+ r2 = lo128(t[2]) & reduce_mask_51; shl128(c, t[1], 13); r2 += c;
218
+ r3 = lo128(t[3]) & reduce_mask_51; shl128(c, t[2], 13); r3 += c;
219
+ r4 = lo128(t[4]) & reduce_mask_51; shl128(c, t[3], 13); r4 += c;
220
+ shl128(c, t[4], 13); r0 += c * 19;
221
+ c = r0 >> 51; r0 &= reduce_mask_51;
222
+ r1 += c ; c = r1 >> 51; r1 &= reduce_mask_51;
223
+ r2 += c ; c = r2 >> 51; r2 &= reduce_mask_51;
224
+ r3 += c ; c = r3 >> 51; r3 &= reduce_mask_51;
225
+ r4 += c ; c = r4 >> 51; r4 &= reduce_mask_51;
226
+ r0 += c * 19;
227
+ } while(--count);
228
+
229
+ out[0] = r0;
230
+ out[1] = r1;
231
+ out[2] = r2;
232
+ out[3] = r3;
233
+ out[4] = r4;
234
+ }
235
+
236
+ DONNA_INLINE static void
237
+ curve25519_square(bignum25519 out, const bignum25519 in) {
238
+ #if !defined(HAVE_NATIVE_UINT128)
239
+ uint128_t mul;
240
+ #endif
241
+ uint128_t t[5];
242
+ uint64_t r0,r1,r2,r3,r4,c;
243
+ uint64_t d0,d1,d2,d4,d419;
244
+
245
+ r0 = in[0];
246
+ r1 = in[1];
247
+ r2 = in[2];
248
+ r3 = in[3];
249
+ r4 = in[4];
250
+
251
+ d0 = r0 * 2;
252
+ d1 = r1 * 2;
253
+ d2 = r2 * 2 * 19;
254
+ d419 = r4 * 19;
255
+ d4 = d419 * 2;
256
+
257
+ #if defined(HAVE_NATIVE_UINT128)
258
+ t[0] = ((uint128_t) r0) * r0 + ((uint128_t) d4) * r1 + (((uint128_t) d2) * (r3 ));
259
+ t[1] = ((uint128_t) d0) * r1 + ((uint128_t) d4) * r2 + (((uint128_t) r3) * (r3 * 19));
260
+ t[2] = ((uint128_t) d0) * r2 + ((uint128_t) r1) * r1 + (((uint128_t) d4) * (r3 ));
261
+ t[3] = ((uint128_t) d0) * r3 + ((uint128_t) d1) * r2 + (((uint128_t) r4) * (d419 ));
262
+ t[4] = ((uint128_t) d0) * r4 + ((uint128_t) d1) * r3 + (((uint128_t) r2) * (r2 ));
263
+ #else
264
+ mul64x64_128(t[0], r0, r0) mul64x64_128(mul, d4, r1) add128(t[0], mul) mul64x64_128(mul, d2, r3) add128(t[0], mul)
265
+ mul64x64_128(t[1], d0, r1) mul64x64_128(mul, d4, r2) add128(t[1], mul) mul64x64_128(mul, r3, r3 * 19) add128(t[1], mul)
266
+ mul64x64_128(t[2], d0, r2) mul64x64_128(mul, r1, r1) add128(t[2], mul) mul64x64_128(mul, d4, r3) add128(t[2], mul)
267
+ mul64x64_128(t[3], d0, r3) mul64x64_128(mul, d1, r2) add128(t[3], mul) mul64x64_128(mul, r4, d419) add128(t[3], mul)
268
+ mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul)
269
+ #endif
270
+
271
+ r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51);
272
+ add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51);
273
+ add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51);
274
+ add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51);
275
+ add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51);
276
+ r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51;
277
+ r1 += c;
278
+
279
+ out[0] = r0;
280
+ out[1] = r1;
281
+ out[2] = r2;
282
+ out[3] = r3;
283
+ out[4] = r4;
284
+ }
285
+
286
+ /* Take a little-endian, 32-byte number and expand it into polynomial form */
287
+ DONNA_INLINE static void
288
+ curve25519_expand(bignum25519 out, const unsigned char *in) {
289
+ static const union { uint8_t b[2]; uint16_t s; } endian_check = {{1,0}};
290
+ uint64_t x0,x1,x2,x3;
291
+
292
+ if (endian_check.s == 1) {
293
+ x0 = *(uint64_t *)(in + 0);
294
+ x1 = *(uint64_t *)(in + 8);
295
+ x2 = *(uint64_t *)(in + 16);
296
+ x3 = *(uint64_t *)(in + 24);
297
+ } else {
298
+ #define F_curve25519_expand(s) \
299
+ ((((uint64_t)in[s + 0]) ) | \
300
+ (((uint64_t)in[s + 1]) << 8) | \
301
+ (((uint64_t)in[s + 2]) << 16) | \
302
+ (((uint64_t)in[s + 3]) << 24) | \
303
+ (((uint64_t)in[s + 4]) << 32) | \
304
+ (((uint64_t)in[s + 5]) << 40) | \
305
+ (((uint64_t)in[s + 6]) << 48) | \
306
+ (((uint64_t)in[s + 7]) << 56))
307
+
308
+ x0 = F_curve25519_expand(0);
309
+ x1 = F_curve25519_expand(8);
310
+ x2 = F_curve25519_expand(16);
311
+ x3 = F_curve25519_expand(24);
312
+ }
313
+
314
+ out[0] = x0 & reduce_mask_51; x0 = (x0 >> 51) | (x1 << 13);
315
+ out[1] = x0 & reduce_mask_51; x1 = (x1 >> 38) | (x2 << 26);
316
+ out[2] = x1 & reduce_mask_51; x2 = (x2 >> 25) | (x3 << 39);
317
+ out[3] = x2 & reduce_mask_51; x3 = (x3 >> 12);
318
+ out[4] = x3 & reduce_mask_51;
319
+ }
320
+
321
+ /* Take a fully reduced polynomial form number and contract it into a
322
+ * little-endian, 32-byte array
323
+ */
324
+ DONNA_INLINE static void
325
+ curve25519_contract(unsigned char *out, const bignum25519 input) {
326
+ uint64_t t[5];
327
+ uint64_t f, i;
328
+
329
+ t[0] = input[0];
330
+ t[1] = input[1];
331
+ t[2] = input[2];
332
+ t[3] = input[3];
333
+ t[4] = input[4];
334
+
335
+ #define curve25519_contract_carry() \
336
+ t[1] += t[0] >> 51; t[0] &= reduce_mask_51; \
337
+ t[2] += t[1] >> 51; t[1] &= reduce_mask_51; \
338
+ t[3] += t[2] >> 51; t[2] &= reduce_mask_51; \
339
+ t[4] += t[3] >> 51; t[3] &= reduce_mask_51;
340
+
341
+ #define curve25519_contract_carry_full() curve25519_contract_carry() \
342
+ t[0] += 19 * (t[4] >> 51); t[4] &= reduce_mask_51;
343
+
344
+ #define curve25519_contract_carry_final() curve25519_contract_carry() \
345
+ t[4] &= reduce_mask_51;
346
+
347
+ curve25519_contract_carry_full()
348
+ curve25519_contract_carry_full()
349
+
350
+ /* now t is between 0 and 2^255-1, properly carried. */
351
+ /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */
352
+ t[0] += 19;
353
+ curve25519_contract_carry_full()
354
+
355
+ /* now between 19 and 2^255-1 in both cases, and offset by 19. */
356
+ t[0] += (reduce_mask_51 + 1) - 19;
357
+ t[1] += (reduce_mask_51 + 1) - 1;
358
+ t[2] += (reduce_mask_51 + 1) - 1;
359
+ t[3] += (reduce_mask_51 + 1) - 1;
360
+ t[4] += (reduce_mask_51 + 1) - 1;
361
+
362
+ /* now between 2^255 and 2^256-20, and offset by 2^255. */
363
+ curve25519_contract_carry_final()
364
+
365
+ #define write51full(n,shift) \
366
+ f = ((t[n] >> shift) | (t[n+1] << (51 - shift))); \
367
+ for (i = 0; i < 8; i++, f >>= 8) *out++ = (unsigned char)f;
368
+ #define write51(n) write51full(n,13*n)
369
+ write51(0)
370
+ write51(1)
371
+ write51(2)
372
+ write51(3)
373
+ }
374
+
375
+ #if !defined(ED25519_GCC_64BIT_CHOOSE)
376
+
377
+ /* out = (flag) ? in : out */
378
+ DONNA_INLINE static void
379
+ curve25519_move_conditional_bytes(uint8_t out[96], const uint8_t in[96], uint64_t flag) {
380
+ const uint64_t nb = flag - 1, b = ~nb;
381
+ const uint64_t *inq = (const uint64_t *)in;
382
+ uint64_t *outq = (uint64_t *)out;
383
+ outq[0] = (outq[0] & nb) | (inq[0] & b);
384
+ outq[1] = (outq[1] & nb) | (inq[1] & b);
385
+ outq[2] = (outq[2] & nb) | (inq[2] & b);
386
+ outq[3] = (outq[3] & nb) | (inq[3] & b);
387
+ outq[4] = (outq[4] & nb) | (inq[4] & b);
388
+ outq[5] = (outq[5] & nb) | (inq[5] & b);
389
+ outq[6] = (outq[6] & nb) | (inq[6] & b);
390
+ outq[7] = (outq[7] & nb) | (inq[7] & b);
391
+ outq[8] = (outq[8] & nb) | (inq[8] & b);
392
+ outq[9] = (outq[9] & nb) | (inq[9] & b);
393
+ outq[10] = (outq[10] & nb) | (inq[10] & b);
394
+ outq[11] = (outq[11] & nb) | (inq[11] & b);
395
+ }
396
+
397
+ /* if (iswap) swap(a, b) */
398
+ DONNA_INLINE static void
399
+ curve25519_swap_conditional(bignum25519 a, bignum25519 b, uint64_t iswap) {
400
+ const uint64_t swap = (uint64_t)(-(int64_t)iswap);
401
+ uint64_t x0,x1,x2,x3,x4;
402
+
403
+ x0 = swap & (a[0] ^ b[0]); a[0] ^= x0; b[0] ^= x0;
404
+ x1 = swap & (a[1] ^ b[1]); a[1] ^= x1; b[1] ^= x1;
405
+ x2 = swap & (a[2] ^ b[2]); a[2] ^= x2; b[2] ^= x2;
406
+ x3 = swap & (a[3] ^ b[3]); a[3] ^= x3; b[3] ^= x3;
407
+ x4 = swap & (a[4] ^ b[4]); a[4] ^= x4; b[4] ^= x4;
408
+ }
409
+
410
+ #endif /* ED25519_GCC_64BIT_CHOOSE */
411
+
412
+ #define ED25519_64BIT_TABLES
413
+
@@ -0,0 +1,67 @@
1
+ /*
2
+ Public domain by Andrew M. <liquidsun@gmail.com>
3
+ See: https://github.com/floodyberry/curve25519-donna
4
+
5
+ Curve25519 implementation agnostic helpers
6
+ */
7
+
8
+ /*
9
+ * In: b = 2^5 - 2^0
10
+ * Out: b = 2^250 - 2^0
11
+ */
12
+ static void
13
+ curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) {
14
+ bignum25519 ALIGN(16) t0,c;
15
+
16
+ /* 2^5 - 2^0 */ /* b */
17
+ /* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5);
18
+ /* 2^10 - 2^0 */ curve25519_mul_noinline(b, t0, b);
19
+ /* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10);
20
+ /* 2^20 - 2^0 */ curve25519_mul_noinline(c, t0, b);
21
+ /* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20);
22
+ /* 2^40 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
23
+ /* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10);
24
+ /* 2^50 - 2^0 */ curve25519_mul_noinline(b, t0, b);
25
+ /* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50);
26
+ /* 2^100 - 2^0 */ curve25519_mul_noinline(c, t0, b);
27
+ /* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100);
28
+ /* 2^200 - 2^0 */ curve25519_mul_noinline(t0, t0, c);
29
+ /* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50);
30
+ /* 2^250 - 2^0 */ curve25519_mul_noinline(b, t0, b);
31
+ }
32
+
33
+ /*
34
+ * z^(p - 2) = z(2^255 - 21)
35
+ */
36
+ static void
37
+ curve25519_recip(bignum25519 out, const bignum25519 z) {
38
+ bignum25519 ALIGN(16) a,t0,b;
39
+
40
+ /* 2 */ curve25519_square_times(a, z, 1); /* a = 2 */
41
+ /* 8 */ curve25519_square_times(t0, a, 2);
42
+ /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
43
+ /* 11 */ curve25519_mul_noinline(a, b, a); /* a = 11 */
44
+ /* 22 */ curve25519_square_times(t0, a, 1);
45
+ /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
46
+ /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
47
+ /* 2^255 - 2^5 */ curve25519_square_times(b, b, 5);
48
+ /* 2^255 - 21 */ curve25519_mul_noinline(out, b, a);
49
+ }
50
+
51
+ /*
52
+ * z^((p-5)/8) = z^(2^252 - 3)
53
+ */
54
+ static void
55
+ curve25519_pow_two252m3(bignum25519 two252m3, const bignum25519 z) {
56
+ bignum25519 ALIGN(16) b,c,t0;
57
+
58
+ /* 2 */ curve25519_square_times(c, z, 1); /* c = 2 */
59
+ /* 8 */ curve25519_square_times(t0, c, 2); /* t0 = 8 */
60
+ /* 9 */ curve25519_mul_noinline(b, t0, z); /* b = 9 */
61
+ /* 11 */ curve25519_mul_noinline(c, b, c); /* c = 11 */
62
+ /* 22 */ curve25519_square_times(t0, c, 1);
63
+ /* 2^5 - 2^0 = 31 */ curve25519_mul_noinline(b, t0, b);
64
+ /* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
65
+ /* 2^252 - 2^2 */ curve25519_square_times(b, b, 2);
66
+ /* 2^252 - 3 */ curve25519_mul_noinline(two252m3, b, z);
67
+ }