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,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
+