ed25519_blake2b 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +23 -0
- data/LICENSE +21 -0
- data/README.md +39 -0
- data/Rakefile +13 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/ed25519_blake2b.gemspec +31 -0
- data/ext/ed25519_blake2b/blake2-config.h +72 -0
- data/ext/ed25519_blake2b/blake2-impl.h +160 -0
- data/ext/ed25519_blake2b/blake2.h +195 -0
- data/ext/ed25519_blake2b/blake2b-load-sse2.h +68 -0
- data/ext/ed25519_blake2b/blake2b-load-sse41.h +402 -0
- data/ext/ed25519_blake2b/blake2b-ref.c +373 -0
- data/ext/ed25519_blake2b/blake2b-round.h +157 -0
- data/ext/ed25519_blake2b/curve25519-donna-32bit.h +579 -0
- data/ext/ed25519_blake2b/curve25519-donna-64bit.h +413 -0
- data/ext/ed25519_blake2b/curve25519-donna-helpers.h +67 -0
- data/ext/ed25519_blake2b/curve25519-donna-sse2.h +1112 -0
- data/ext/ed25519_blake2b/ed25519-donna-32bit-sse2.h +513 -0
- data/ext/ed25519_blake2b/ed25519-donna-32bit-tables.h +61 -0
- data/ext/ed25519_blake2b/ed25519-donna-64bit-sse2.h +436 -0
- data/ext/ed25519_blake2b/ed25519-donna-64bit-tables.h +53 -0
- data/ext/ed25519_blake2b/ed25519-donna-64bit-x86-32bit.h +435 -0
- data/ext/ed25519_blake2b/ed25519-donna-64bit-x86.h +351 -0
- data/ext/ed25519_blake2b/ed25519-donna-basepoint-table.h +259 -0
- data/ext/ed25519_blake2b/ed25519-donna-batchverify.h +275 -0
- data/ext/ed25519_blake2b/ed25519-donna-impl-base.h +364 -0
- data/ext/ed25519_blake2b/ed25519-donna-impl-sse2.h +390 -0
- data/ext/ed25519_blake2b/ed25519-donna-portable-identify.h +103 -0
- data/ext/ed25519_blake2b/ed25519-donna-portable.h +135 -0
- data/ext/ed25519_blake2b/ed25519-donna.h +115 -0
- data/ext/ed25519_blake2b/ed25519-hash-custom.c +28 -0
- data/ext/ed25519_blake2b/ed25519-hash-custom.h +30 -0
- data/ext/ed25519_blake2b/ed25519-hash.h +219 -0
- data/ext/ed25519_blake2b/ed25519-randombytes-custom.h +10 -0
- data/ext/ed25519_blake2b/ed25519-randombytes.h +91 -0
- data/ext/ed25519_blake2b/ed25519.c +150 -0
- data/ext/ed25519_blake2b/ed25519.h +30 -0
- data/ext/ed25519_blake2b/extconf.rb +3 -0
- data/ext/ed25519_blake2b/fuzz/README.md +173 -0
- data/ext/ed25519_blake2b/fuzz/build-nix.php +134 -0
- data/ext/ed25519_blake2b/fuzz/curve25519-ref10.c +1272 -0
- data/ext/ed25519_blake2b/fuzz/curve25519-ref10.h +8 -0
- data/ext/ed25519_blake2b/fuzz/ed25519-donna-sse2.c +3 -0
- data/ext/ed25519_blake2b/fuzz/ed25519-donna.c +1 -0
- data/ext/ed25519_blake2b/fuzz/ed25519-donna.h +34 -0
- data/ext/ed25519_blake2b/fuzz/ed25519-ref10.c +4647 -0
- data/ext/ed25519_blake2b/fuzz/ed25519-ref10.h +9 -0
- data/ext/ed25519_blake2b/fuzz/fuzz-curve25519.c +172 -0
- data/ext/ed25519_blake2b/fuzz/fuzz-ed25519.c +219 -0
- data/ext/ed25519_blake2b/modm-donna-32bit.h +469 -0
- data/ext/ed25519_blake2b/modm-donna-64bit.h +361 -0
- data/ext/ed25519_blake2b/rbext.c +25 -0
- data/ext/ed25519_blake2b/regression.h +1024 -0
- data/lib/ed25519_blake2b/ed25519_blake2b.rb +4 -0
- data/lib/ed25519_blake2b/version.rb +3 -0
- metadata +147 -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
|
+
|