GNUnet 0.28.0-dev.2-5-gff43856e1
 
Loading...
Searching...
No Matches
crypto_elligator.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2002-2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19
20
21 Portions of this code are derived from the Elligator-2 project,
22 which is licensed under the Creative Commons CC0 1.0 Universal Public Domain Dedication.
23 The Elligator-2 project can be found at: https://github.com/Kleshni/Elligator-2
24
25 Note that gmp is already a dependency of GnuTLS
26
27*/
28
29#include "platform.h"
30#include "gnunet_common.h"
31#include <sodium.h>
32#include "gnunet_util_lib.h"
33#include "benchmark.h"
34
35#include <stdint.h>
36#include <stdbool.h>
37#include <string.h>
38#include <gmp.h>
39
40// Ed25519 subgroup of points with a low order
41static const uint8_t lookupTable[8][crypto_scalarmult_SCALARBYTES] = {
42 {
43 0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0,
44 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0,
45 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39,
46 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x05
47 },
48 {
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
53 },
54 {
55 0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F,
56 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F,
57 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6,
58 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0x7A
59 },
60 {
61 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
62 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
64 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F
65 }, {
66 0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F,
67 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F,
68 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6,
69 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0xFA
70 }, {
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
75 }, {
76 0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0,
77 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0,
78 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39,
79 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x85
80 },{
81 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
85 }
86};
87
88// main.h from Kleshnis's elligator implementation
89#include <limits.h>
90
91#define P_BITS (256) // 255 significant bits + 1 for carry
92#define P_BYTES ((P_BITS + CHAR_BIT - 1) / CHAR_BIT)
93#define P_LIMBS ((P_BITS + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
94
95
96// main.c from Kleshnis's elligator implementation
97static const unsigned char p_bytes[P_BYTES] = {
98 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
102};
103
104static const unsigned char negative_1_bytes[P_BYTES] = {
105 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
109};
110
111static const unsigned char negative_2_bytes[P_BYTES] = {
112 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
113 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
116};
117
118static const unsigned char divide_negative_1_2_bytes[P_BYTES] = {
119 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
120 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
123};
124
125static const unsigned char divide_plus_p_3_8_bytes[P_BYTES] = {
126 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f
130};
131
132static const unsigned char divide_minus_p_1_2_bytes[P_BYTES] = {
133 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
137};
138
139static const unsigned char square_root_negative_1_bytes[P_BYTES] = {
140 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
141 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
142 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
143 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b
144};
145
146static const unsigned char A_bytes[P_BYTES] = {
147 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
151};
152
153static const unsigned char negative_A_bytes[P_BYTES] = {
154 0xe7, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
158};
159
160static const unsigned char u_bytes[P_BYTES] = {
161 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
165};
166
167static const unsigned char inverted_u_bytes[P_BYTES] = {
168 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
169 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
172};
173
174static const unsigned char d_bytes[P_BYTES] = {
175 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
176 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
177 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
178 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
179};
180
181static mp_limb_t p[P_LIMBS];
182static mp_limb_t negative_1[P_LIMBS];
183static mp_limb_t negative_2[P_LIMBS];
184static mp_limb_t divide_negative_1_2[P_LIMBS];
185static mp_limb_t divide_plus_p_3_8[P_LIMBS];
186static mp_limb_t divide_minus_p_1_2[P_LIMBS];
188static mp_limb_t A[P_LIMBS];
189static mp_limb_t negative_A[P_LIMBS];
190static mp_limb_t u[P_LIMBS];
191static mp_limb_t inverted_u[P_LIMBS];
192static mp_limb_t d[P_LIMBS];
193
194static mp_size_t scratch_space_length;
195
203static void
204decode_bytes (mp_limb_t *number, const uint8_t *bytes)
205{
206 mp_limb_t scratch_space[1];
207
208 for (size_t i = 0; i < P_BYTES; ++i)
209 {
210 mpn_lshift (number, number, P_LIMBS, 8);
211 mpn_sec_add_1 (number, number, 1, bytes[P_BYTES - i - 1], scratch_space);
212 }
213}
214
215
223static void
224encode_bytes (uint8_t *bytes, mp_limb_t *number)
225{
226 for (size_t i = 0; i < P_BYTES; ++i)
227 {
228 bytes[P_BYTES - i - 1] = mpn_lshift (number, number, P_LIMBS, 8);
229 }
230}
231
232
233void
235
239void __attribute__ ((constructor))
241{
242 static bool initialized = false;
243
244 mp_size_t scratch_space_lengths[] = {
245 // For least_square_root
246
247 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
248 mpn_sec_sqr_itch (P_LIMBS),
249 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
250 mpn_sec_sub_1_itch (P_LIMBS),
251 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
252
253 // For Elligator_2_Curve25519_encode
254
255 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
256 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
257 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
258 mpn_sec_sqr_itch (P_LIMBS),
259 mpn_sec_sub_1_itch (P_LIMBS),
260
261 // For Elligator_2_Curve25519_decode
262
263 mpn_sec_sqr_itch (P_LIMBS),
264 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
265 mpn_sec_div_r_itch (P_LIMBS, P_LIMBS),
266 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
267 mpn_sec_add_1_itch (P_LIMBS),
268 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
269
270 // For Elligator_2_Curve25519_convert_from_Ed25519
271 mpn_sec_sqr_itch (P_LIMBS),
272 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
273 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
274 mpn_sec_add_1_itch (P_LIMBS),
275 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
276 mpn_sec_sub_1_itch (P_LIMBS)
277 };
278
279 if (initialized)
280 {
281 return;
282 }
283
296
297
298 for (size_t i = 0; i < sizeof scratch_space_lengths
299 / sizeof *scratch_space_lengths; ++i)
300 {
301 if (scratch_space_lengths[i] > scratch_space_length)
302 {
303 scratch_space_length = scratch_space_lengths[i];
304 }
305 }
306
307 initialized = true;
308}
309
310
319static void
320least_square_root (mp_limb_t *root,
321 const mp_limb_t *number,
322 mp_limb_t *scratch_space)
323{
324 mp_limb_t a[P_LIMBS + P_LIMBS];
325 mp_limb_t b[P_LIMBS];
326 mp_limb_t condition;
327
328 // root := number ^ ((p + 3) / 8)
329
330 mpn_add_n (b, number, p, P_LIMBS); // The next function requires a nonzero input
331 mpn_sec_powm (root, b, P_LIMBS, divide_plus_p_3_8, P_BITS - 1, p, P_LIMBS,
332 scratch_space);
333
334 // If root ^ 2 != number, root := root * square_root(-1)
335
336 mpn_sec_sqr (a, root, P_LIMBS, scratch_space);
337 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
338 mpn_sub_n (b, a, number, P_LIMBS);
339
340 condition = mpn_sec_sub_1 (b, b, P_LIMBS, 1, scratch_space) ^ 1;
341
342 mpn_sec_mul (a, root, P_LIMBS, square_root_negative_1, P_LIMBS,
343 scratch_space);
344 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
345
346 mpn_cnd_swap (condition, root, a, P_LIMBS);
347
348 // If root > (p - 1) / 2, root := -root
349
350 condition = mpn_sub_n (a, divide_minus_p_1_2, root, P_LIMBS);
351
352 mpn_sub_n (a, p, root, P_LIMBS); // If root = 0, a := p
353
354 mpn_cnd_swap (condition, root, a, P_LIMBS);
355}
356
357
358bool
360 uint8_t random_tweak,
362 const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
363{
364 bool high_y;
365 bool msb_set;
366 bool smsb_set;
367
368
369 uint8_t *representative = r->r;
370 uint8_t *point = (uint8_t *) pub->q_y;
371
372 mp_limb_t scratch_space[scratch_space_length];
373
374 mp_limb_t a[P_LIMBS + P_LIMBS];
375 mp_limb_t b[P_LIMBS + P_LIMBS];
376 mp_limb_t c[P_LIMBS + P_LIMBS];
377
378 high_y = random_tweak & 1;
379
380 // a := point
381
382 decode_bytes (a, point);
383
384 // b := -a / (a + A), or b := p if a = 0
385
386 mpn_add_n (b, a, A, P_LIMBS);
387 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
388 scratch_space);
389 mpn_sec_mul (b, c, P_LIMBS, a, P_LIMBS, scratch_space);
390 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
391 mpn_sub_n (b, p, b, P_LIMBS);
392
393 // If high_y = true, b := 1 / b or b := 0 if it was = p
394
395 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
396 scratch_space);
397 mpn_cnd_swap (high_y, b, c, P_LIMBS);
398
399 // c := b / u
400
401 mpn_sec_mul (c, b, P_LIMBS, inverted_u, P_LIMBS, scratch_space);
402 mpn_sec_div_r (c, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
403
404 // If c is a square modulo p, b := least_square_root(c)
405
406 least_square_root (b, c, scratch_space);
407
408 // Determine, whether b ^ 2 = c
409
410 mpn_sec_sqr (a, b, P_LIMBS, scratch_space);
411 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
412 mpn_sub_n (a, a, c, P_LIMBS);
413
414 {
415 bool result = mpn_sec_sub_1 (a, a, P_LIMBS, 1, scratch_space);
416
417 encode_bytes (representative, b);
418
419 // Setting most significant bit and second most significant bit randomly
420 msb_set = (random_tweak >> 1) & 1;
421 smsb_set = (random_tweak >> 2) & 1;
422 if (msb_set)
423 {
424 r->r[31] |= 128;
425 }
426 if (smsb_set)
427 {
428 r->r[31] |= 64;
429 }
430 return result;
431 }
432}
433
434
446static bool
447elligator_direct_map (uint8_t *point,
448 bool *high_y,
449 uint8_t *representative)
450{
451 mp_limb_t scratch_space[scratch_space_length];
452
453 mp_limb_t a[P_LIMBS + P_LIMBS];
454 mp_limb_t b[P_LIMBS + P_LIMBS];
455 mp_limb_t c[P_LIMBS];
456 mp_limb_t e[P_LIMBS + P_LIMBS];
457 bool result;
458
459 // a := representative
460
461 decode_bytes (a, representative);
462
463 // Determine whether a < (p - 1) / 2
464
465 result = mpn_sub_n (b, divide_minus_p_1_2, a, P_LIMBS) ^ 1;
466
467 // b := -A / (1 + u * a ^ 2)
468
469 mpn_sec_sqr (b, a, P_LIMBS, scratch_space);
470 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
471 mpn_sec_mul (a, u, P_LIMBS, b, P_LIMBS, scratch_space);
472 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
473 mpn_sec_add_1 (b, a, P_LIMBS, 1, scratch_space);
474 mpn_sec_powm (a, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
475 scratch_space);
476 mpn_sec_mul (b, a, P_LIMBS, negative_A, P_LIMBS, scratch_space);
477 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
478
479 // a := b ^ 3 + A * b ^ 2 + b (with 1-bit overflow)
480
481 mpn_sec_sqr (a, b, P_LIMBS, scratch_space);
482 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
483 mpn_add_n (c, b, A, P_LIMBS);
484 mpn_sec_mul (e, c, P_LIMBS, a, P_LIMBS, scratch_space);
485 mpn_sec_div_r (e, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
486 mpn_add_n (a, e, b, P_LIMBS);
487
488 // If a is a quadratic residue modulo p, point := b and high_y := 1
489 // Otherwise point := -b - A and high_y := 0
490
491 mpn_sub_n (c, p, b, P_LIMBS);
492 mpn_add_n (c, c, negative_A, P_LIMBS);
493 mpn_sec_div_r (c, P_LIMBS, p, P_LIMBS, scratch_space);
494
495 mpn_sec_powm (e, a, P_LIMBS, divide_minus_p_1_2, P_BITS - 1, p, P_LIMBS,
496 scratch_space);
497 *high_y = mpn_sub_n (e, e, divide_minus_p_1_2, P_LIMBS);
498
499 mpn_cnd_swap (*high_y, b, c, P_LIMBS);
500
501 encode_bytes (point, c);
502
503 return result;
504}
505
506
507void
509 struct GNUNET_CRYPTO_EcdhePublicKey *point,
510 bool *high_y,
511 const struct GNUNET_CRYPTO_ElligatorRepresentative *representative)
512{
513 // if sign of direct map transformation not needed throw it away
515 bool high_y_local;
516 bool *high_y_ptr;
517 if (NULL == high_y)
518 high_y_ptr = &high_y_local;
519 else
520 high_y_ptr = high_y;
521
522 memcpy (&r_tmp.r, &representative->r, sizeof(r_tmp.r));
523 r_tmp.r[31] &= 63;
524 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Print high_y\n");
525 elligator_direct_map ((uint8_t *) point->q_y,
526 high_y_ptr,
527 (uint8_t *) r_tmp.r);
528}
529
530
541static bool
543 const uint8_t *source)
544{
545 mp_limb_t scratch_space[scratch_space_length];
546
547 mp_limb_t y[P_LIMBS];
548 mp_limb_t a[P_LIMBS + P_LIMBS];
549 mp_limb_t b[P_LIMBS + P_LIMBS];
550 mp_limb_t c[P_LIMBS + P_LIMBS];
551
552 uint8_t y_bytes[P_BYTES];
553 bool result;
554
555 memcpy (y_bytes, source, 31);
556
557 y_bytes[31] = source[31] & 0x7f;
558
559 decode_bytes (y, y_bytes);
560
561 // Check if y < p
562
563 result = mpn_sub_n (a, y, p, P_LIMBS);
564
565 // a := (y ^ 2 - 1) / (1 + d * y ^ 2)
566
567 mpn_sec_sqr (a, y, P_LIMBS, scratch_space);
568 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
569 mpn_sec_mul (b, a, P_LIMBS, d, P_LIMBS, scratch_space);
570 mpn_sec_add_1 (b, b, P_LIMBS, 1, scratch_space);
571 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
572 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
573 scratch_space);
574 mpn_add_n (b, a, negative_1, P_LIMBS);
575 mpn_sec_mul (a, b, P_LIMBS, c, P_LIMBS, scratch_space);
576 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
577
578 // Check, whether a is a square modulo p (including a = 0)
579
580 mpn_add_n (a, a, p, P_LIMBS);
581 mpn_sec_powm (b, a, P_LIMBS, divide_negative_1_2, P_BITS - 1, p, P_LIMBS,
582 scratch_space);
583
584 result &= mpn_sub_n (c, b, divide_minus_p_1_2, P_LIMBS);
585
586 // If a = p, the parity bit must be 0
587
588 mpn_sub_n (a, a, p, P_LIMBS);
589
590 result ^= mpn_sec_sub_1 (a, a, P_LIMBS, 1, scratch_space) & source[31] >> 7;
591
592 // If y != 1, c := (1 + y) / (1 - y), otherwise c := 0
593
594 mpn_sub_n (a, p, y, P_LIMBS);
595 mpn_sec_add_1 (a, a, P_LIMBS, 1, scratch_space);
596 mpn_sec_powm (b, a, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
597 scratch_space);
598 mpn_sec_add_1 (a, y, P_LIMBS, 1, scratch_space);
599 mpn_sec_mul (c, a, P_LIMBS, b, P_LIMBS, scratch_space);
600 mpn_sec_div_r (c, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
601
602 encode_bytes (point, c);
603
604 return result;
605}
606
607
612{
613 // eHigh
614 // crypto_scalarmult_ed25519_base clamps the scalar pk->d and return only 0 if pk->d is zero
615 unsigned char eHigh[crypto_scalarmult_SCALARBYTES] = {0};
616 int sLow = (pk->d)[0] % 8;
617 unsigned char eLow[crypto_scalarmult_SCALARBYTES] = {0};
618 unsigned char edPub[crypto_scalarmult_SCALARBYTES] = {0};
619 GNUNET_assert (0 == crypto_scalarmult_ed25519_base (eHigh, pk->d));
620
621 // eLow: choose a random point of low order
622 memcpy (eLow, lookupTable[sLow], crypto_scalarmult_SCALARBYTES);
623
624 // eHigh + eLow
625 if (crypto_core_ed25519_add (edPub, eLow, eHigh) == -1)
626 {
627 return GNUNET_SYSERR;
628 }
629
630 if (convert_from_ed_to_curve (pub->q_y, edPub) == false)
631 {
632 return GNUNET_SYSERR;
633 }
634 return GNUNET_OK;
635}
636
637
640 uint8_t random_tweak,
644{
646 if (GNUNET_SYSERR ==
648 return GNUNET_SYSERR;
649
650 if (NULL == repr)
651 return GNUNET_OK;
652 if (! GNUNET_CRYPTO_ecdhe_elligator_encoding (random_tweak,
653 repr,
654 &pub))
655 return GNUNET_SYSERR;
656 memcpy (pk->q_y, pub.q_y, sizeof(pk->q_y));
657 return GNUNET_OK;
658}
659
660
666{
667 uint8_t random_tweak;
669 &random_tweak,
670 sizeof(uint8_t));
671
673 sk,
674 pk,
675 repr);
676}
677
678
679void
682{
685 // inverse map can fail for some public keys generated by GNUNET_CRYPTO_ecdhe_elligator_generate_public_key
686 while (true)
687 {
689 sk,
690 sizeof (struct
692 ;
694 &repr))
695 break;
696 }
697
698}
benchmarking for various operations
static bool elligator_direct_map(uint8_t *point, bool *high_y, uint8_t *representative)
Takes a number of the underlying finite field of Curve25519 and projects it into a valid point on tha...
static void decode_bytes(mp_limb_t *number, const uint8_t *bytes)
This function decodes the byte buffer into the MPI limb.
static void encode_bytes(uint8_t *bytes, mp_limb_t *number)
This function encodes the MPI limb into a byte buffer.
static mp_limb_t divide_minus_p_1_2[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t negative_A[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t negative_2[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static const uint8_t lookupTable[8][crypto_scalarmult_SCALARBYTES]
#define P_BITS
static mp_limb_t square_root_negative_1[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t p[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static const unsigned char divide_minus_p_1_2_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static const unsigned char negative_A_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static mp_limb_t d[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static const unsigned char u_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
#define P_BYTES
#define P_LIMBS
static const unsigned char p_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static const unsigned char negative_1_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static void least_square_root(mp_limb_t *root, const mp_limb_t *number, mp_limb_t *scratch_space)
Calculates the root of a given number.
static bool convert_from_ed_to_curve(uint8_t *point, const uint8_t *source)
Takes a number of the underlying finite field of Curve25519 and projects it into a valid point on tha...
static enum GNUNET_GenericReturnValue elligator_generate_public_key(const struct GNUNET_CRYPTO_ElligatorEcdhePrivateKey *pk, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
static const unsigned char negative_2_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static mp_size_t scratch_space_length
static const unsigned char A_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
void GNUNET_CRYPTO_ecdhe_elligator_initialize(void)
static const unsigned char square_root_negative_1_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static const unsigned char d_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static mp_limb_t negative_1[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static const unsigned char divide_plus_p_3_8_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static const unsigned char divide_negative_1_2_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static mp_limb_t A[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t inverted_u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t divide_plus_p_3_8[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static mp_limb_t u[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static const unsigned char inverted_u_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static mp_limb_t divide_negative_1_2[(((256)+GMP_NUMB_BITS - 1)/GMP_NUMB_BITS)]
static GstElement * source
Appsrc instance into which we write data for the pipeline.
struct GNUNET_CRYPTO_BlindablePrivateKey pk
Private key from command line option, or NULL.
static int result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
struct GNUNET_PQ_ResultSpec __attribute__
bool GNUNET_CRYPTO_ecdhe_elligator_encoding(uint8_t random_tweak, struct GNUNET_CRYPTO_ElligatorRepresentative *r, const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
Encodes a point on Curve25519 to a an element of the underlying finite field.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdhe_elligator_key_get_public(const struct GNUNET_CRYPTO_ElligatorEcdhePrivateKey *sk, struct GNUNET_CRYPTO_EcdhePublicKey *pk, struct GNUNET_CRYPTO_ElligatorRepresentative *repr)
Generates a valid public key for elligator's inverse map by adding a lower order point to a prime ord...
void GNUNET_CRYPTO_ecdhe_elligator_key_create(struct GNUNET_CRYPTO_ElligatorEcdhePrivateKey *sk)
Generates a private key for Curve25519.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
void GNUNET_CRYPTO_ecdhe_elligator_decoding(struct GNUNET_CRYPTO_EcdhePublicKey *point, bool *high_y, const struct GNUNET_CRYPTO_ElligatorRepresentative *representative)
Clears the most significant bit and second most significant bit of the serialized representaive befor...
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdhe_elligator_key_get_public_norand(uint8_t random_tweak, const struct GNUNET_CRYPTO_ElligatorEcdhePrivateKey *sk, struct GNUNET_CRYPTO_EcdhePublicKey *pk, struct GNUNET_CRYPTO_ElligatorRepresentative *repr)
Generates a valid public key for elligator's inverse map by adding a lower order point to a prime ord...
@ GNUNET_CRYPTO_QUALITY_NONCE
Randomness for IVs etc.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_OK
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static int initialized
Have we been initialized?
Definition plugin.c:57
uint32_t number
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
unsigned char q_y[256/8]
Q consists of an x- and a y-value, each mod p (256 bits), given here in affine coordinates and Ed2551...
unsigned char q_y[256/8]
Point Q consists of a y-value mod p (256 bits); the x-value is always positive.
Special private ECC key generated by GNUNET_CRYPTO_ecdhe_elligator_key_create.
Elligator representative (always for Curve25519)
uint8_t r[256/8]
Represents an element of Curve25519 finite field.