nanocurrency 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }