GNUnet 0.21.2
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 "gnunet_common.h"
30#include "platform.h"
31#include <gcrypt.h>
32#include <sodium.h>
33#include "gnunet_util_lib.h"
34#include "benchmark.h"
35
36#include <stdint.h>
37#include <stdbool.h>
38#include <string.h>
39#include <gmp.h>
40
41// Ed25519 subgroup of points with a low order
42static const uint8_t lookupTable[8][crypto_scalarmult_SCALARBYTES] = {
43 {
44 0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0,
45 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0,
46 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39,
47 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x05
48 },
49 {
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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
54 },
55 {
56 0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F,
57 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F,
58 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6,
59 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0x7A
60 },
61 {
62 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
64 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
65 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F
66 }, {
67 0xC7, 0x17, 0x6A, 0x70, 0x3D, 0x4D, 0xD8, 0x4F,
68 0xBA, 0x3C, 0x0B, 0x76, 0x0D, 0x10, 0x67, 0x0F,
69 0x2A, 0x20, 0x53, 0xFA, 0x2C, 0x39, 0xCC, 0xC6,
70 0x4E, 0xC7, 0xFD, 0x77, 0x92, 0xAC, 0x03, 0xFA
71 }, {
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, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80
76 }, {
77 0x26, 0xE8, 0x95, 0x8F, 0xC2, 0xB2, 0x27, 0xB0,
78 0x45, 0xC3, 0xF4, 0x89, 0xF2, 0xEF, 0x98, 0xF0,
79 0xD5, 0xDF, 0xAC, 0x05, 0xD3, 0xC6, 0x33, 0x39,
80 0xB1, 0x38, 0x02, 0x88, 0x6D, 0x53, 0xFC, 0x85
81 },{
82 0x01, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
86 }
87};
88
89// main.h from Kleshnis's elligator implementation
90#include <limits.h>
91
92#define P_BITS (256) // 255 significant bits + 1 for carry
93#define P_BYTES ((P_BITS + CHAR_BIT - 1) / CHAR_BIT)
94#define P_LIMBS ((P_BITS + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS)
95
96
97// main.c from Kleshnis's elligator implementation
98static const unsigned char p_bytes[P_BYTES] = {
99 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
100 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
101 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
102 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
103};
104
105static const unsigned char negative_1_bytes[P_BYTES] = {
106 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
110};
111
112static const unsigned char negative_2_bytes[P_BYTES] = {
113 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
114 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
115 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
116 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
117};
118
119static const unsigned char divide_negative_1_2_bytes[P_BYTES] = {
120 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
121 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
122 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
123 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
124};
125
126static const unsigned char divide_plus_p_3_8_bytes[P_BYTES] = {
127 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f
131};
132
133static const unsigned char divide_minus_p_1_2_bytes[P_BYTES] = {
134 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
138};
139
140static const unsigned char square_root_negative_1_bytes[P_BYTES] = {
141 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
142 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
143 0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
144 0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b
145};
146
147static const unsigned char A_bytes[P_BYTES] = {
148 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
152};
153
154static const unsigned char negative_A_bytes[P_BYTES] = {
155 0xe7, 0x92, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
159};
160
161static const unsigned char u_bytes[P_BYTES] = {
162 0x02, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
166};
167
168static const unsigned char inverted_u_bytes[P_BYTES] = {
169 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
170 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
171 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
172 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
173};
174
175static const unsigned char d_bytes[P_BYTES] = {
176 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
177 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
178 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
179 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
180};
181
182static mp_limb_t p[P_LIMBS];
183static mp_limb_t negative_1[P_LIMBS];
184static mp_limb_t negative_2[P_LIMBS];
185static mp_limb_t divide_negative_1_2[P_LIMBS];
186static mp_limb_t divide_plus_p_3_8[P_LIMBS];
187static mp_limb_t divide_minus_p_1_2[P_LIMBS];
189static mp_limb_t A[P_LIMBS];
190static mp_limb_t negative_A[P_LIMBS];
191static mp_limb_t u[P_LIMBS];
192static mp_limb_t inverted_u[P_LIMBS];
193static mp_limb_t d[P_LIMBS];
194
195static mp_size_t scratch_space_length;
196
197// TODO
198static void
199decode_bytes (mp_limb_t *number, const uint8_t *bytes)
200{
201 mp_limb_t scratch_space[1];
202
203 for (size_t i = 0; i < P_BYTES; ++i)
204 {
205 mpn_lshift (number, number, P_LIMBS, 8);
206 mpn_sec_add_1 (number, number, 1, bytes[P_BYTES - i - 1], scratch_space);
207 }
208}
209
210
211// TODO
212static void
213encode_bytes (uint8_t *bytes, mp_limb_t *number)
214{
215 for (size_t i = 0; i < P_BYTES; ++i)
216 {
217 bytes[P_BYTES - i - 1] = mpn_lshift (number, number, P_LIMBS, 8);
218 }
219}
220
221
225void __attribute__ ((constructor))
226GNUNET_CRYPTO_ecdhe_elligator_initialize ()
227{
228 static bool initialized = false;
229
230 if (initialized)
231 {
232 return;
233 }
234
247
248 mp_size_t scratch_space_lengths[] = {
249 // For least_square_root
250
251 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
252 mpn_sec_sqr_itch (P_LIMBS),
253 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
254 mpn_sec_sub_1_itch (P_LIMBS),
255 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
256
257 // For Elligator_2_Curve25519_encode
258
259 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
260 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
261 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
262 mpn_sec_sqr_itch (P_LIMBS),
263 mpn_sec_sub_1_itch (P_LIMBS),
264
265 // For Elligator_2_Curve25519_decode
266
267 mpn_sec_sqr_itch (P_LIMBS),
268 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
269 mpn_sec_div_r_itch (P_LIMBS, P_LIMBS),
270 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
271 mpn_sec_add_1_itch (P_LIMBS),
272 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
273
274 // For Elligator_2_Curve25519_convert_from_Ed25519
275 mpn_sec_sqr_itch (P_LIMBS),
276 mpn_sec_div_r_itch (P_LIMBS + P_LIMBS, P_LIMBS),
277 mpn_sec_mul_itch (P_LIMBS, P_LIMBS),
278 mpn_sec_add_1_itch (P_LIMBS),
279 mpn_sec_powm_itch (P_LIMBS, P_BITS - 1, P_LIMBS),
280 mpn_sec_sub_1_itch (P_LIMBS)
281 };
282
283 for (size_t i = 0; i < sizeof scratch_space_lengths
284 / sizeof *scratch_space_lengths; ++i)
285 {
286 if (scratch_space_lengths[i] > scratch_space_length)
287 {
288 scratch_space_length = scratch_space_lengths[i];
289 }
290 }
291
292 initialized = true;
293}
294
295
304static void
305least_square_root (mp_limb_t *root,
306 const mp_limb_t *number,
307 mp_limb_t *scratch_space)
308{
309 mp_limb_t a[P_LIMBS + P_LIMBS];
310 mp_limb_t b[P_LIMBS];
311
312 // root := number ^ ((p + 3) / 8)
313
314 mpn_add_n (b, number, p, P_LIMBS); // The next function requires a nonzero input
315 mpn_sec_powm (root, b, P_LIMBS, divide_plus_p_3_8, P_BITS - 1, p, P_LIMBS,
316 scratch_space);
317
318 // If root ^ 2 != number, root := root * square_root(-1)
319
320 mpn_sec_sqr (a, root, P_LIMBS, scratch_space);
321 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
322 mpn_sub_n (b, a, number, P_LIMBS);
323
324 mp_limb_t condition = mpn_sec_sub_1 (b, b, P_LIMBS, 1, scratch_space) ^ 1;
325
326 mpn_sec_mul (a, root, P_LIMBS, square_root_negative_1, P_LIMBS,
327 scratch_space);
328 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
329
330 mpn_cnd_swap (condition, root, a, P_LIMBS);
331
332 // If root > (p - 1) / 2, root := -root
333
334 condition = mpn_sub_n (a, divide_minus_p_1_2, root, P_LIMBS);
335
336 mpn_sub_n (a, p, root, P_LIMBS); // If root = 0, a := p
337
338 mpn_cnd_swap (condition, root, a, P_LIMBS);
339}
340
341bool
344 uint8_t seed,
345 const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
346{
347 bool high_y;
348 bool msb_set;
349 bool smsb_set;
350
351 high_y = seed & 1;
352
353 uint8_t *representative = r->r;
354 uint8_t *point = (uint8_t *) pub->q_y;
355
356 mp_limb_t scratch_space[scratch_space_length];
357
358 mp_limb_t a[P_LIMBS + P_LIMBS];
359 mp_limb_t b[P_LIMBS + P_LIMBS];
360 mp_limb_t c[P_LIMBS + P_LIMBS];
361
362 // a := point
363
364 decode_bytes (a, point);
365
366 // b := -a / (a + A), or b := p if a = 0
367
368 mpn_add_n (b, a, A, P_LIMBS);
369 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
370 scratch_space);
371 mpn_sec_mul (b, c, P_LIMBS, a, P_LIMBS, scratch_space);
372 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
373 mpn_sub_n (b, p, b, P_LIMBS);
374
375 // If high_y = true, b := 1 / b or b := 0 if it was = p
376
377 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
378 scratch_space);
379 mpn_cnd_swap (high_y, b, c, P_LIMBS);
380
381 // c := b / u
382
383 mpn_sec_mul (c, b, P_LIMBS, inverted_u, P_LIMBS, scratch_space);
384 mpn_sec_div_r (c, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
385
386 // If c is a square modulo p, b := least_square_root(c)
387
388 least_square_root (b, c, scratch_space);
389
390 // Determine, whether b ^ 2 = c
391
392 mpn_sec_sqr (a, b, P_LIMBS, scratch_space);
393 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
394 mpn_sub_n (a, a, c, P_LIMBS);
395
396 bool result = mpn_sec_sub_1 (a, a, P_LIMBS, 1, scratch_space);
397
398 encode_bytes (representative, b);
399
400 // Setting most significant bit and second most significant bit randomly
401 msb_set = (seed >> 1) & 1;
402 smsb_set = (seed >> 2) & 1;
403 if (msb_set)
404 {
405 r->r[31] |= 128;
406 }
407 if (smsb_set)
408 {
409 r->r[31] |= 64;
410 }
411 return result;
412}
413
414bool
417 const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
418{
419 uint8_t random_tweak;
420
421
423 &random_tweak,
424 sizeof(uint8_t));
425 return GNUNET_CRYPTO_ecdhe_elligator_encoding_norand(r, random_tweak, pub);
426}
427
428
440static bool
441elligator_direct_map (uint8_t *point,
442 bool *high_y,
443 uint8_t *representative)
444{
445 mp_limb_t scratch_space[scratch_space_length];
446
447 mp_limb_t a[P_LIMBS + P_LIMBS];
448 mp_limb_t b[P_LIMBS + P_LIMBS];
449 mp_limb_t c[P_LIMBS];
450 mp_limb_t e[P_LIMBS + P_LIMBS];
451
452 // a := representative
453
454 decode_bytes (a, representative);
455
456 // Determine whether a < (p - 1) / 2
457
458 bool result = mpn_sub_n (b, divide_minus_p_1_2, a, P_LIMBS) ^ 1;
459
460 // b := -A / (1 + u * a ^ 2)
461
462 mpn_sec_sqr (b, a, P_LIMBS, scratch_space);
463 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
464 mpn_sec_mul (a, u, P_LIMBS, b, P_LIMBS, scratch_space);
465 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
466 mpn_sec_add_1 (b, a, P_LIMBS, 1, scratch_space);
467 mpn_sec_powm (a, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
468 scratch_space);
469 mpn_sec_mul (b, a, P_LIMBS, negative_A, P_LIMBS, scratch_space);
470 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
471
472 // a := b ^ 3 + A * b ^ 2 + b (with 1-bit overflow)
473
474 mpn_sec_sqr (a, b, P_LIMBS, scratch_space);
475 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
476 mpn_add_n (c, b, A, P_LIMBS);
477 mpn_sec_mul (e, c, P_LIMBS, a, P_LIMBS, scratch_space);
478 mpn_sec_div_r (e, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
479 mpn_add_n (a, e, b, P_LIMBS);
480
481 // If a is a quadratic residue modulo p, point := b and high_y := 1
482 // Otherwise point := -b - A and high_y := 0
483
484 mpn_sub_n (c, p, b, P_LIMBS);
485 mpn_add_n (c, c, negative_A, P_LIMBS);
486 mpn_sec_div_r (c, P_LIMBS, p, P_LIMBS, scratch_space);
487
488 mpn_sec_powm (e, a, P_LIMBS, divide_minus_p_1_2, P_BITS - 1, p, P_LIMBS,
489 scratch_space);
490 *high_y = mpn_sub_n (e, e, divide_minus_p_1_2, P_LIMBS);
491
492 mpn_cnd_swap (*high_y, b, c, P_LIMBS);
493
494 encode_bytes (point, c);
495
496 return result;
497}
498
499
500void
502 struct GNUNET_CRYPTO_EcdhePublicKey *point,
503 bool *high_y,
504 const struct GNUNET_CRYPTO_ElligatorRepresentative *representative)
505{
506 // if sign of direct map transformation not needed throw it away
507 bool high_y_local;
508 bool *high_y_ptr;
509 if (NULL == high_y)
510 high_y_ptr = &high_y_local;
511 else
512 high_y_ptr = high_y;
513
515 memcpy (&r_tmp.r, &representative->r, sizeof(r_tmp.r));
516 r_tmp.r[31] &= 63;
517 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Print high_y\n");
518 elligator_direct_map ((uint8_t *) point->q_y,
519 high_y_ptr,
520 (uint8_t *) r_tmp.r);
521}
522
523
534static bool
536 const uint8_t *source)
537{
538 mp_limb_t scratch_space[scratch_space_length];
539
540 mp_limb_t y[P_LIMBS];
541 mp_limb_t a[P_LIMBS + P_LIMBS];
542 mp_limb_t b[P_LIMBS + P_LIMBS];
543 mp_limb_t c[P_LIMBS + P_LIMBS];
544
545 uint8_t y_bytes[P_BYTES];
546
547 memcpy (y_bytes, source, 31);
548
549 y_bytes[31] = source[31] & 0x7f;
550
551 decode_bytes (y, y_bytes);
552
553 // Check if y < p
554
555 bool result = mpn_sub_n (a, y, p, P_LIMBS);
556
557 // a := (y ^ 2 - 1) / (1 + d * y ^ 2)
558
559 mpn_sec_sqr (a, y, P_LIMBS, scratch_space);
560 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
561 mpn_sec_mul (b, a, P_LIMBS, d, P_LIMBS, scratch_space);
562 mpn_sec_add_1 (b, b, P_LIMBS, 1, scratch_space);
563 mpn_sec_div_r (b, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
564 mpn_sec_powm (c, b, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
565 scratch_space);
566 mpn_add_n (b, a, negative_1, P_LIMBS);
567 mpn_sec_mul (a, b, P_LIMBS, c, P_LIMBS, scratch_space);
568 mpn_sec_div_r (a, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
569
570 // Check, whether a is a square modulo p (including a = 0)
571
572 mpn_add_n (a, a, p, P_LIMBS);
573 mpn_sec_powm (b, a, P_LIMBS, divide_negative_1_2, P_BITS - 1, p, P_LIMBS,
574 scratch_space);
575
576 result &= mpn_sub_n (c, b, divide_minus_p_1_2, P_LIMBS);
577
578 // If a = p, the parity bit must be 0
579
580 mpn_sub_n (a, a, p, P_LIMBS);
581
582 result ^= mpn_sec_sub_1 (a, a, P_LIMBS, 1, scratch_space) & source[31] >> 7;
583
584 // If y != 1, c := (1 + y) / (1 - y), otherwise c := 0
585
586 mpn_sub_n (a, p, y, P_LIMBS);
587 mpn_sec_add_1 (a, a, P_LIMBS, 1, scratch_space);
588 mpn_sec_powm (b, a, P_LIMBS, negative_2, P_BITS - 1, p, P_LIMBS,
589 scratch_space);
590 mpn_sec_add_1 (a, y, P_LIMBS, 1, scratch_space);
591 mpn_sec_mul (c, a, P_LIMBS, b, P_LIMBS, scratch_space);
592 mpn_sec_div_r (c, P_LIMBS + P_LIMBS, p, P_LIMBS, scratch_space);
593
594 encode_bytes (point, c);
595
596 return result;
597}
598
599
602 const struct GNUNET_CRYPTO_EcdhePrivateKey *pk,
604{
605 // eHigh
606 // crypto_scalarmult_ed25519_base clamps the scalar pk->d and return only 0 if pk->d is zero
607 unsigned char eHigh[crypto_scalarmult_SCALARBYTES] = {0};
608 GNUNET_assert (0 == crypto_scalarmult_ed25519_base (eHigh, pk->d));
609
610 // eLow: choose a random point of low order
611 int sLow = (pk->d)[0] % 8;
612 unsigned char eLow[crypto_scalarmult_SCALARBYTES] = {0};
613 memcpy (eLow, lookupTable[sLow], crypto_scalarmult_SCALARBYTES);
614
615 // eHigh + eLow
616 unsigned char edPub[crypto_scalarmult_SCALARBYTES] = {0};
617 if (crypto_core_ed25519_add (edPub, eLow, eHigh) == -1)
618 {
619 return GNUNET_SYSERR;
620 }
621
622 if (convert_from_ed_to_curve (pub->q_y, edPub) == false)
623 {
624 return GNUNET_SYSERR;
625 }
626 return GNUNET_OK;
627}
628
629
632 const struct GNUNET_CRYPTO_EcdhePrivateKey *sk,
635{
637 // Continue if generate_public_key fails
638 if (GNUNET_SYSERR ==
640 return GNUNET_SYSERR;
641
642 if (NULL == repr)
643 return GNUNET_OK;
645 &pub))
646 return GNUNET_SYSERR;
647 return GNUNET_OK;
648}
649
650
651void
654{
657 // inverse map can fail for some public keys generated by GNUNET_CRYPTO_ecdhe_elligator_generate_public_key
658 while (true)
659 {
661 sk,
662 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
664 &repr))
665 break;
666 }
667
668}
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)
static void encode_bytes(uint8_t *bytes, mp_limb_t *number)
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 const unsigned char negative_2_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
static enum GNUNET_GenericReturnValue elligator_generate_public_key(const struct GNUNET_CRYPTO_EcdhePrivateKey *pk, struct GNUNET_CRYPTO_EcdhePublicKey *pub)
bool GNUNET_CRYPTO_ecdhe_elligator_encoding_norand(struct GNUNET_CRYPTO_ElligatorRepresentative *r, uint8_t seed, const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
static mp_size_t scratch_space_length
static const unsigned char A_bytes[(((256)+CHAR_BIT - 1)/CHAR_BIT)]
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)]
void __attribute__((constructor))
Initialize elligator scratch space.
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_PrivateKey pk
Private key from command line option, or NULL.
static int result
Global testing status.
static struct GNUNET_CRYPTO_EddsaPublicKey pub
Definition: gnunet-scrypt.c:47
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
enum GNUNET_GenericReturnValue GNUNET_CRYPTO_ecdhe_elligator_key_get_public(const struct GNUNET_CRYPTO_EcdhePrivateKey *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_EcdhePrivateKey *sk)
Generates a private key for Curve25519.
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...
bool GNUNET_CRYPTO_ecdhe_elligator_encoding(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.
@ 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:59
uint32_t number
Private ECC key encoded for transmission.
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.
Elligator representative (always for Curve25519)
uint8_t r[256/8]
Represents an element of Curve25519 finite field.