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,275 @@
1
+ /*
2
+ Ed25519 batch verification
3
+ */
4
+
5
+ #define max_batch_size 64
6
+ #define heap_batch_size ((max_batch_size * 2) + 1)
7
+
8
+ /* which limb is the 128th bit in? */
9
+ static const size_t limb128bits = (128 + bignum256modm_bits_per_limb - 1) / bignum256modm_bits_per_limb;
10
+
11
+ typedef size_t heap_index_t;
12
+
13
+ typedef struct batch_heap_t {
14
+ unsigned char r[heap_batch_size][16]; /* 128 bit random values */
15
+ ge25519 points[heap_batch_size];
16
+ bignum256modm scalars[heap_batch_size];
17
+ heap_index_t heap[heap_batch_size];
18
+ size_t size;
19
+ } batch_heap;
20
+
21
+ /* swap two values in the heap */
22
+ static void
23
+ heap_swap(heap_index_t *heap, size_t a, size_t b) {
24
+ heap_index_t temp;
25
+ temp = heap[a];
26
+ heap[a] = heap[b];
27
+ heap[b] = temp;
28
+ }
29
+
30
+ /* add the scalar at the end of the list to the heap */
31
+ static void
32
+ heap_insert_next(batch_heap *heap) {
33
+ size_t node = heap->size, parent;
34
+ heap_index_t *pheap = heap->heap;
35
+ bignum256modm *scalars = heap->scalars;
36
+
37
+ /* insert at the bottom */
38
+ pheap[node] = (heap_index_t)node;
39
+
40
+ /* sift node up to its sorted spot */
41
+ parent = (node - 1) / 2;
42
+ while (node && lt256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], bignum256modm_limb_size - 1)) {
43
+ heap_swap(pheap, parent, node);
44
+ node = parent;
45
+ parent = (node - 1) / 2;
46
+ }
47
+ heap->size++;
48
+ }
49
+
50
+ /* update the heap when the root element is updated */
51
+ static void
52
+ heap_updated_root(batch_heap *heap, size_t limbsize) {
53
+ size_t node, parent, childr, childl;
54
+ heap_index_t *pheap = heap->heap;
55
+ bignum256modm *scalars = heap->scalars;
56
+
57
+ /* sift root to the bottom */
58
+ parent = 0;
59
+ node = 1;
60
+ childl = 1;
61
+ childr = 2;
62
+ while ((childr < heap->size)) {
63
+ node = lt256_modm_batch(scalars[pheap[childl]], scalars[pheap[childr]], limbsize) ? childr : childl;
64
+ heap_swap(pheap, parent, node);
65
+ parent = node;
66
+ childl = (parent * 2) + 1;
67
+ childr = childl + 1;
68
+ }
69
+
70
+ /* sift root back up to its sorted spot */
71
+ parent = (node - 1) / 2;
72
+ while (node && lte256_modm_batch(scalars[pheap[parent]], scalars[pheap[node]], limbsize)) {
73
+ heap_swap(pheap, parent, node);
74
+ node = parent;
75
+ parent = (node - 1) / 2;
76
+ }
77
+ }
78
+
79
+ /* build the heap with count elements, count must be >= 3 */
80
+ static void
81
+ heap_build(batch_heap *heap, size_t count) {
82
+ heap->heap[0] = 0;
83
+ heap->size = 0;
84
+ while (heap->size < count)
85
+ heap_insert_next(heap);
86
+ }
87
+
88
+ /* extend the heap to contain new_count elements */
89
+ static void
90
+ heap_extend(batch_heap *heap, size_t new_count) {
91
+ while (heap->size < new_count)
92
+ heap_insert_next(heap);
93
+ }
94
+
95
+ /* get the top 2 elements of the heap */
96
+ static void
97
+ heap_get_top2(batch_heap *heap, heap_index_t *max1, heap_index_t *max2, size_t limbsize) {
98
+ heap_index_t h0 = heap->heap[0], h1 = heap->heap[1], h2 = heap->heap[2];
99
+ if (lt256_modm_batch(heap->scalars[h1], heap->scalars[h2], limbsize))
100
+ h1 = h2;
101
+ *max1 = h0;
102
+ *max2 = h1;
103
+ }
104
+
105
+ /* */
106
+ static void
107
+ ge25519_multi_scalarmult_vartime_final(ge25519 *r, ge25519 *point, bignum256modm scalar) {
108
+ const bignum256modm_element_t topbit = ((bignum256modm_element_t)1 << (bignum256modm_bits_per_limb - 1));
109
+ size_t limb = limb128bits;
110
+ bignum256modm_element_t flag;
111
+
112
+ if (isone256_modm_batch(scalar)) {
113
+ /* this will happen most of the time after bos-carter */
114
+ *r = *point;
115
+ return;
116
+ } else if (iszero256_modm_batch(scalar)) {
117
+ /* this will only happen if all scalars == 0 */
118
+ memset(r, 0, sizeof(*r));
119
+ r->y[0] = 1;
120
+ r->z[0] = 1;
121
+ return;
122
+ }
123
+
124
+ *r = *point;
125
+
126
+ /* find the limb where first bit is set */
127
+ while (!scalar[limb])
128
+ limb--;
129
+
130
+ /* find the first bit */
131
+ flag = topbit;
132
+ while ((scalar[limb] & flag) == 0)
133
+ flag >>= 1;
134
+
135
+ /* exponentiate */
136
+ for (;;) {
137
+ ge25519_double(r, r);
138
+ if (scalar[limb] & flag)
139
+ ge25519_add(r, r, point);
140
+
141
+ flag >>= 1;
142
+ if (!flag) {
143
+ if (!limb--)
144
+ break;
145
+ flag = topbit;
146
+ }
147
+ }
148
+ }
149
+
150
+ /* count must be >= 5 */
151
+ static void
152
+ ge25519_multi_scalarmult_vartime(ge25519 *r, batch_heap *heap, size_t count) {
153
+ heap_index_t max1, max2;
154
+
155
+ /* start with the full limb size */
156
+ size_t limbsize = bignum256modm_limb_size - 1;
157
+
158
+ /* whether the heap has been extended to include the 128 bit scalars */
159
+ int extended = 0;
160
+
161
+ /* grab an odd number of scalars to build the heap, unknown limb sizes */
162
+ heap_build(heap, ((count + 1) / 2) | 1);
163
+
164
+ for (;;) {
165
+ heap_get_top2(heap, &max1, &max2, limbsize);
166
+
167
+ /* only one scalar remaining, we're done */
168
+ if (iszero256_modm_batch(heap->scalars[max2]))
169
+ break;
170
+
171
+ /* exhausted another limb? */
172
+ if (!heap->scalars[max1][limbsize])
173
+ limbsize -= 1;
174
+
175
+ /* can we extend to the 128 bit scalars? */
176
+ if (!extended && isatmost128bits256_modm_batch(heap->scalars[max1])) {
177
+ heap_extend(heap, count);
178
+ heap_get_top2(heap, &max1, &max2, limbsize);
179
+ extended = 1;
180
+ }
181
+
182
+ sub256_modm_batch(heap->scalars[max1], heap->scalars[max1], heap->scalars[max2], limbsize);
183
+ ge25519_add(&heap->points[max2], &heap->points[max2], &heap->points[max1]);
184
+ heap_updated_root(heap, limbsize);
185
+ }
186
+
187
+ ge25519_multi_scalarmult_vartime_final(r, &heap->points[max1], heap->scalars[max1]);
188
+ }
189
+
190
+ /* not actually used for anything other than testing */
191
+ unsigned char batch_point_buffer[3][32];
192
+
193
+ static int
194
+ ge25519_is_neutral_vartime(const ge25519 *p) {
195
+ static const unsigned char zero[32] = {0};
196
+ unsigned char point_buffer[3][32];
197
+ curve25519_contract(point_buffer[0], p->x);
198
+ curve25519_contract(point_buffer[1], p->y);
199
+ curve25519_contract(point_buffer[2], p->z);
200
+ memcpy(batch_point_buffer[1], point_buffer[1], 32);
201
+ return (memcmp(point_buffer[0], zero, 32) == 0) && (memcmp(point_buffer[1], point_buffer[2], 32) == 0);
202
+ }
203
+
204
+ int
205
+ ED25519_FN(ed25519_sign_open_batch) (const unsigned char **m, size_t *mlen, const unsigned char **pk, const unsigned char **RS, size_t num, int *valid) {
206
+ batch_heap ALIGN(16) batch;
207
+ ge25519 ALIGN(16) p;
208
+ bignum256modm *r_scalars;
209
+ size_t i, batchsize;
210
+ unsigned char hram[64];
211
+ int ret = 0;
212
+
213
+ for (i = 0; i < num; i++)
214
+ valid[i] = 1;
215
+
216
+ while (num > 3) {
217
+ batchsize = (num > max_batch_size) ? max_batch_size : num;
218
+
219
+ /* generate r (scalars[batchsize+1]..scalars[2*batchsize] */
220
+ ED25519_FN(ed25519_randombytes_unsafe) (batch.r, batchsize * 16);
221
+ r_scalars = &batch.scalars[batchsize + 1];
222
+ for (i = 0; i < batchsize; i++)
223
+ expand256_modm(r_scalars[i], batch.r[i], 16);
224
+
225
+ /* compute scalars[0] = ((r1s1 + r2s2 + ...)) */
226
+ for (i = 0; i < batchsize; i++) {
227
+ expand256_modm(batch.scalars[i], RS[i] + 32, 32);
228
+ mul256_modm(batch.scalars[i], batch.scalars[i], r_scalars[i]);
229
+ }
230
+ for (i = 1; i < batchsize; i++)
231
+ add256_modm(batch.scalars[0], batch.scalars[0], batch.scalars[i]);
232
+
233
+ /* compute scalars[1]..scalars[batchsize] as r[i]*H(R[i],A[i],m[i]) */
234
+ for (i = 0; i < batchsize; i++) {
235
+ ed25519_hram(hram, RS[i], pk[i], m[i], mlen[i]);
236
+ expand256_modm(batch.scalars[i+1], hram, 64);
237
+ mul256_modm(batch.scalars[i+1], batch.scalars[i+1], r_scalars[i]);
238
+ }
239
+
240
+ /* compute points */
241
+ batch.points[0] = ge25519_basepoint;
242
+ for (i = 0; i < batchsize; i++)
243
+ if (!ge25519_unpack_negative_vartime(&batch.points[i+1], pk[i]))
244
+ goto fallback;
245
+ for (i = 0; i < batchsize; i++)
246
+ if (!ge25519_unpack_negative_vartime(&batch.points[batchsize+i+1], RS[i]))
247
+ goto fallback;
248
+
249
+ ge25519_multi_scalarmult_vartime(&p, &batch, (batchsize * 2) + 1);
250
+ if (!ge25519_is_neutral_vartime(&p)) {
251
+ ret |= 2;
252
+
253
+ fallback:
254
+ for (i = 0; i < batchsize; i++) {
255
+ valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1;
256
+ ret |= (valid[i] ^ 1);
257
+ }
258
+ }
259
+
260
+ m += batchsize;
261
+ mlen += batchsize;
262
+ pk += batchsize;
263
+ RS += batchsize;
264
+ num -= batchsize;
265
+ valid += batchsize;
266
+ }
267
+
268
+ for (i = 0; i < num; i++) {
269
+ valid[i] = ED25519_FN(ed25519_sign_open) (m[i], mlen[i], pk[i], RS[i]) ? 0 : 1;
270
+ ret |= (valid[i] ^ 1);
271
+ }
272
+
273
+ return ret;
274
+ }
275
+
@@ -0,0 +1,364 @@
1
+ /*
2
+ conversions
3
+ */
4
+
5
+ DONNA_INLINE static void
6
+ ge25519_p1p1_to_partial(ge25519 *r, const ge25519_p1p1 *p) {
7
+ curve25519_mul(r->x, p->x, p->t);
8
+ curve25519_mul(r->y, p->y, p->z);
9
+ curve25519_mul(r->z, p->z, p->t);
10
+ }
11
+
12
+ DONNA_INLINE static void
13
+ ge25519_p1p1_to_full(ge25519 *r, const ge25519_p1p1 *p) {
14
+ curve25519_mul(r->x, p->x, p->t);
15
+ curve25519_mul(r->y, p->y, p->z);
16
+ curve25519_mul(r->z, p->z, p->t);
17
+ curve25519_mul(r->t, p->x, p->y);
18
+ }
19
+
20
+ static void
21
+ ge25519_full_to_pniels(ge25519_pniels *p, const ge25519 *r) {
22
+ curve25519_sub(p->ysubx, r->y, r->x);
23
+ curve25519_add(p->xaddy, r->y, r->x);
24
+ curve25519_copy(p->z, r->z);
25
+ curve25519_mul(p->t2d, r->t, ge25519_ec2d);
26
+ }
27
+
28
+ /*
29
+ adding & doubling
30
+ */
31
+
32
+ static void
33
+ ge25519_add_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519 *q) {
34
+ bignum25519 a,b,c,d,t,u;
35
+
36
+ curve25519_sub(a, p->y, p->x);
37
+ curve25519_add(b, p->y, p->x);
38
+ curve25519_sub(t, q->y, q->x);
39
+ curve25519_add(u, q->y, q->x);
40
+ curve25519_mul(a, a, t);
41
+ curve25519_mul(b, b, u);
42
+ curve25519_mul(c, p->t, q->t);
43
+ curve25519_mul(c, c, ge25519_ec2d);
44
+ curve25519_mul(d, p->z, q->z);
45
+ curve25519_add(d, d, d);
46
+ curve25519_sub(r->x, b, a);
47
+ curve25519_add(r->y, b, a);
48
+ curve25519_add_after_basic(r->z, d, c);
49
+ curve25519_sub_after_basic(r->t, d, c);
50
+ }
51
+
52
+
53
+ static void
54
+ ge25519_double_p1p1(ge25519_p1p1 *r, const ge25519 *p) {
55
+ bignum25519 a,b,c;
56
+
57
+ curve25519_square(a, p->x);
58
+ curve25519_square(b, p->y);
59
+ curve25519_square(c, p->z);
60
+ curve25519_add_reduce(c, c, c);
61
+ curve25519_add(r->x, p->x, p->y);
62
+ curve25519_square(r->x, r->x);
63
+ curve25519_add(r->y, b, a);
64
+ curve25519_sub(r->z, b, a);
65
+ curve25519_sub_after_basic(r->x, r->x, r->y);
66
+ curve25519_sub_after_basic(r->t, c, r->z);
67
+ }
68
+
69
+ static void
70
+ ge25519_nielsadd2_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_niels *q, unsigned char signbit) {
71
+ const bignum25519 *qb = (const bignum25519 *)q;
72
+ bignum25519 *rb = (bignum25519 *)r;
73
+ bignum25519 a,b,c;
74
+
75
+ curve25519_sub(a, p->y, p->x);
76
+ curve25519_add(b, p->y, p->x);
77
+ curve25519_mul(a, a, qb[signbit]); /* x for +, y for - */
78
+ curve25519_mul(r->x, b, qb[signbit^1]); /* y for +, x for - */
79
+ curve25519_add(r->y, r->x, a);
80
+ curve25519_sub(r->x, r->x, a);
81
+ curve25519_mul(c, p->t, q->t2d);
82
+ curve25519_add_reduce(r->t, p->z, p->z);
83
+ curve25519_copy(r->z, r->t);
84
+ curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
85
+ curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
86
+ }
87
+
88
+ static void
89
+ ge25519_pnielsadd_p1p1(ge25519_p1p1 *r, const ge25519 *p, const ge25519_pniels *q, unsigned char signbit) {
90
+ const bignum25519 *qb = (const bignum25519 *)q;
91
+ bignum25519 *rb = (bignum25519 *)r;
92
+ bignum25519 a,b,c;
93
+
94
+ curve25519_sub(a, p->y, p->x);
95
+ curve25519_add(b, p->y, p->x);
96
+ curve25519_mul(a, a, qb[signbit]); /* ysubx for +, xaddy for - */
97
+ curve25519_mul(r->x, b, qb[signbit^1]); /* xaddy for +, ysubx for - */
98
+ curve25519_add(r->y, r->x, a);
99
+ curve25519_sub(r->x, r->x, a);
100
+ curve25519_mul(c, p->t, q->t2d);
101
+ curve25519_mul(r->t, p->z, q->z);
102
+ curve25519_add_reduce(r->t, r->t, r->t);
103
+ curve25519_copy(r->z, r->t);
104
+ curve25519_add(rb[2+signbit], rb[2+signbit], c); /* z for +, t for - */
105
+ curve25519_sub(rb[2+(signbit^1)], rb[2+(signbit^1)], c); /* t for +, z for - */
106
+ }
107
+
108
+ static void
109
+ ge25519_double_partial(ge25519 *r, const ge25519 *p) {
110
+ ge25519_p1p1 t;
111
+ ge25519_double_p1p1(&t, p);
112
+ ge25519_p1p1_to_partial(r, &t);
113
+ }
114
+
115
+ static void
116
+ ge25519_double(ge25519 *r, const ge25519 *p) {
117
+ ge25519_p1p1 t;
118
+ ge25519_double_p1p1(&t, p);
119
+ ge25519_p1p1_to_full(r, &t);
120
+ }
121
+
122
+ static void
123
+ ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q) {
124
+ ge25519_p1p1 t;
125
+ ge25519_add_p1p1(&t, p, q);
126
+ ge25519_p1p1_to_full(r, &t);
127
+ }
128
+
129
+ static void
130
+ ge25519_nielsadd2(ge25519 *r, const ge25519_niels *q) {
131
+ bignum25519 a,b,c,e,f,g,h;
132
+
133
+ curve25519_sub(a, r->y, r->x);
134
+ curve25519_add(b, r->y, r->x);
135
+ curve25519_mul(a, a, q->ysubx);
136
+ curve25519_mul(e, b, q->xaddy);
137
+ curve25519_add(h, e, a);
138
+ curve25519_sub(e, e, a);
139
+ curve25519_mul(c, r->t, q->t2d);
140
+ curve25519_add(f, r->z, r->z);
141
+ curve25519_add_after_basic(g, f, c);
142
+ curve25519_sub_after_basic(f, f, c);
143
+ curve25519_mul(r->x, e, f);
144
+ curve25519_mul(r->y, h, g);
145
+ curve25519_mul(r->z, g, f);
146
+ curve25519_mul(r->t, e, h);
147
+ }
148
+
149
+ static void
150
+ ge25519_pnielsadd(ge25519_pniels *r, const ge25519 *p, const ge25519_pniels *q) {
151
+ bignum25519 a,b,c,x,y,z,t;
152
+
153
+ curve25519_sub(a, p->y, p->x);
154
+ curve25519_add(b, p->y, p->x);
155
+ curve25519_mul(a, a, q->ysubx);
156
+ curve25519_mul(x, b, q->xaddy);
157
+ curve25519_add(y, x, a);
158
+ curve25519_sub(x, x, a);
159
+ curve25519_mul(c, p->t, q->t2d);
160
+ curve25519_mul(t, p->z, q->z);
161
+ curve25519_add(t, t, t);
162
+ curve25519_add_after_basic(z, t, c);
163
+ curve25519_sub_after_basic(t, t, c);
164
+ curve25519_mul(r->xaddy, x, t);
165
+ curve25519_mul(r->ysubx, y, z);
166
+ curve25519_mul(r->z, z, t);
167
+ curve25519_mul(r->t2d, x, y);
168
+ curve25519_copy(y, r->ysubx);
169
+ curve25519_sub(r->ysubx, r->ysubx, r->xaddy);
170
+ curve25519_add(r->xaddy, r->xaddy, y);
171
+ curve25519_mul(r->t2d, r->t2d, ge25519_ec2d);
172
+ }
173
+
174
+
175
+ /*
176
+ pack & unpack
177
+ */
178
+
179
+ static void
180
+ ge25519_pack(unsigned char r[32], const ge25519 *p) {
181
+ bignum25519 tx, ty, zi;
182
+ unsigned char parity[32];
183
+ curve25519_recip(zi, p->z);
184
+ curve25519_mul(tx, p->x, zi);
185
+ curve25519_mul(ty, p->y, zi);
186
+ curve25519_contract(r, ty);
187
+ curve25519_contract(parity, tx);
188
+ r[31] ^= ((parity[0] & 1) << 7);
189
+ }
190
+
191
+ static int
192
+ ge25519_unpack_negative_vartime(ge25519 *r, const unsigned char p[32]) {
193
+ static const unsigned char zero[32] = {0};
194
+ static const bignum25519 one = {1};
195
+ unsigned char parity = p[31] >> 7;
196
+ unsigned char check[32];
197
+ bignum25519 t, root, num, den, d3;
198
+
199
+ curve25519_expand(r->y, p);
200
+ curve25519_copy(r->z, one);
201
+ curve25519_square(num, r->y); /* x = y^2 */
202
+ curve25519_mul(den, num, ge25519_ecd); /* den = dy^2 */
203
+ curve25519_sub_reduce(num, num, r->z); /* x = y^1 - 1 */
204
+ curve25519_add(den, den, r->z); /* den = dy^2 + 1 */
205
+
206
+ /* Computation of sqrt(num/den) */
207
+ /* 1.: computation of num^((p-5)/8)*den^((7p-35)/8) = (num*den^7)^((p-5)/8) */
208
+ curve25519_square(t, den);
209
+ curve25519_mul(d3, t, den);
210
+ curve25519_square(r->x, d3);
211
+ curve25519_mul(r->x, r->x, den);
212
+ curve25519_mul(r->x, r->x, num);
213
+ curve25519_pow_two252m3(r->x, r->x);
214
+
215
+ /* 2. computation of r->x = num * den^3 * (num*den^7)^((p-5)/8) */
216
+ curve25519_mul(r->x, r->x, d3);
217
+ curve25519_mul(r->x, r->x, num);
218
+
219
+ /* 3. Check if either of the roots works: */
220
+ curve25519_square(t, r->x);
221
+ curve25519_mul(t, t, den);
222
+ curve25519_sub_reduce(root, t, num);
223
+ curve25519_contract(check, root);
224
+ if (!ed25519_verify(check, zero, 32)) {
225
+ curve25519_add_reduce(t, t, num);
226
+ curve25519_contract(check, t);
227
+ if (!ed25519_verify(check, zero, 32))
228
+ return 0;
229
+ curve25519_mul(r->x, r->x, ge25519_sqrtneg1);
230
+ }
231
+
232
+ curve25519_contract(check, r->x);
233
+ if ((check[0] & 1) == parity) {
234
+ curve25519_copy(t, r->x);
235
+ curve25519_neg(r->x, t);
236
+ }
237
+ curve25519_mul(r->t, r->x, r->y);
238
+ return 1;
239
+ }
240
+
241
+
242
+ /*
243
+ scalarmults
244
+ */
245
+
246
+ #define S1_SWINDOWSIZE 5
247
+ #define S1_TABLE_SIZE (1<<(S1_SWINDOWSIZE-2))
248
+ #define S2_SWINDOWSIZE 7
249
+ #define S2_TABLE_SIZE (1<<(S2_SWINDOWSIZE-2))
250
+
251
+ /* computes [s1]p1 + [s2]basepoint */
252
+ static void
253
+ ge25519_double_scalarmult_vartime(ge25519 *r, const ge25519 *p1, const bignum256modm s1, const bignum256modm s2) {
254
+ signed char slide1[256], slide2[256];
255
+ ge25519_pniels pre1[S1_TABLE_SIZE];
256
+ ge25519 d1;
257
+ ge25519_p1p1 t;
258
+ int32_t i;
259
+
260
+ contract256_slidingwindow_modm(slide1, s1, S1_SWINDOWSIZE);
261
+ contract256_slidingwindow_modm(slide2, s2, S2_SWINDOWSIZE);
262
+
263
+ ge25519_double(&d1, p1);
264
+ ge25519_full_to_pniels(pre1, p1);
265
+ for (i = 0; i < S1_TABLE_SIZE - 1; i++)
266
+ ge25519_pnielsadd(&pre1[i+1], &d1, &pre1[i]);
267
+
268
+ /* set neutral */
269
+ memset(r, 0, sizeof(ge25519));
270
+ r->y[0] = 1;
271
+ r->z[0] = 1;
272
+
273
+ i = 255;
274
+ while ((i >= 0) && !(slide1[i] | slide2[i]))
275
+ i--;
276
+
277
+ for (; i >= 0; i--) {
278
+ ge25519_double_p1p1(&t, r);
279
+
280
+ if (slide1[i]) {
281
+ ge25519_p1p1_to_full(r, &t);
282
+ ge25519_pnielsadd_p1p1(&t, r, &pre1[abs(slide1[i]) / 2], (unsigned char)slide1[i] >> 7);
283
+ }
284
+
285
+ if (slide2[i]) {
286
+ ge25519_p1p1_to_full(r, &t);
287
+ ge25519_nielsadd2_p1p1(&t, r, &ge25519_niels_sliding_multiples[abs(slide2[i]) / 2], (unsigned char)slide2[i] >> 7);
288
+ }
289
+
290
+ ge25519_p1p1_to_partial(r, &t);
291
+ }
292
+ }
293
+
294
+
295
+
296
+ #if !defined(HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS)
297
+
298
+ static uint32_t
299
+ ge25519_windowb_equal(uint32_t b, uint32_t c) {
300
+ return ((b ^ c) - 1) >> 31;
301
+ }
302
+
303
+ static void
304
+ ge25519_scalarmult_base_choose_niels(ge25519_niels *t, const uint8_t table[256][96], uint32_t pos, signed char b) {
305
+ bignum25519 neg;
306
+ uint32_t sign = (uint32_t)((unsigned char)b >> 7);
307
+ uint32_t mask = ~(sign - 1);
308
+ uint32_t u = (b + mask) ^ mask;
309
+ uint32_t i;
310
+
311
+ /* ysubx, xaddy, t2d in packed form. initialize to ysubx = 1, xaddy = 1, t2d = 0 */
312
+ uint8_t packed[96] = {0};
313
+ packed[0] = 1;
314
+ packed[32] = 1;
315
+
316
+ for (i = 0; i < 8; i++)
317
+ curve25519_move_conditional_bytes(packed, table[(pos * 8) + i], ge25519_windowb_equal(u, i + 1));
318
+
319
+ /* expand in to t */
320
+ curve25519_expand(t->ysubx, packed + 0);
321
+ curve25519_expand(t->xaddy, packed + 32);
322
+ curve25519_expand(t->t2d , packed + 64);
323
+
324
+ /* adjust for sign */
325
+ curve25519_swap_conditional(t->ysubx, t->xaddy, sign);
326
+ curve25519_neg(neg, t->t2d);
327
+ curve25519_swap_conditional(t->t2d, neg, sign);
328
+ }
329
+
330
+ #endif /* HAVE_GE25519_SCALARMULT_BASE_CHOOSE_NIELS */
331
+
332
+
333
+ /* computes [s]basepoint */
334
+ static void
335
+ ge25519_scalarmult_base_niels(ge25519 *r, const uint8_t basepoint_table[256][96], const bignum256modm s) {
336
+ signed char b[64];
337
+ uint32_t i;
338
+ ge25519_niels t;
339
+
340
+ contract256_window4_modm(b, s);
341
+
342
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[1]);
343
+ curve25519_sub_reduce(r->x, t.xaddy, t.ysubx);
344
+ curve25519_add_reduce(r->y, t.xaddy, t.ysubx);
345
+ memset(r->z, 0, sizeof(bignum25519));
346
+ curve25519_copy(r->t, t.t2d);
347
+ r->z[0] = 2;
348
+ for (i = 3; i < 64; i += 2) {
349
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
350
+ ge25519_nielsadd2(r, &t);
351
+ }
352
+ ge25519_double_partial(r, r);
353
+ ge25519_double_partial(r, r);
354
+ ge25519_double_partial(r, r);
355
+ ge25519_double(r, r);
356
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, 0, b[0]);
357
+ curve25519_mul(t.t2d, t.t2d, ge25519_ecd);
358
+ ge25519_nielsadd2(r, &t);
359
+ for(i = 2; i < 64; i += 2) {
360
+ ge25519_scalarmult_base_choose_niels(&t, basepoint_table, i / 2, b[i]);
361
+ ge25519_nielsadd2(r, &t);
362
+ }
363
+ }
364
+