aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc_dlog.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_ecc_dlog.c')
-rw-r--r--src/util/crypto_ecc_dlog.c525
1 files changed, 178 insertions, 347 deletions
diff --git a/src/util/crypto_ecc_dlog.c b/src/util/crypto_ecc_dlog.c
index 408d64e58..916acd9dd 100644
--- a/src/util/crypto_ecc_dlog.c
+++ b/src/util/crypto_ecc_dlog.c
@@ -32,35 +32,6 @@
32 32
33 33
34/** 34/**
35 * Name of the curve we are using. Note that we have hard-coded
36 * structs that use 256 bits, so using a bigger curve will require
37 * changes that break stuff badly. The name of the curve given here
38 * must be agreed by all peers and be supported by libgcrypt.
39 */
40#define CURVE "Ed25519"
41
42
43/**
44 *
45 */
46static void
47extract_pk (gcry_mpi_point_t pt,
48 gcry_ctx_t ctx,
49 struct GNUNET_PeerIdentity *pid)
50{
51 gcry_mpi_t q_y;
52
53 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", pt, ctx));
54 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
55 GNUNET_assert (q_y);
56 GNUNET_CRYPTO_mpi_print_unsigned (pid->public_key.q_y,
57 sizeof(pid->public_key.q_y),
58 q_y);
59 gcry_mpi_release (q_y);
60}
61
62
63/**
64 * Internal structure used to cache pre-calculated values for DLOG calculation. 35 * Internal structure used to cache pre-calculated values for DLOG calculation.
65 */ 36 */
66struct GNUNET_CRYPTO_EccDlogContext 37struct GNUNET_CRYPTO_EccDlogContext
@@ -90,160 +61,105 @@ struct GNUNET_CRYPTO_EccDlogContext
90}; 61};
91 62
92 63
93/**
94 * Convert point value to binary representation.
95 *
96 * @param edc calculation context for ECC operations
97 * @param point computational point representation
98 * @param[out] bin binary point representation
99 */
100void
101GNUNET_CRYPTO_ecc_point_to_bin (struct GNUNET_CRYPTO_EccDlogContext *edc,
102 gcry_mpi_point_t point,
103 struct GNUNET_CRYPTO_EccPoint *bin)
104{
105 gcry_mpi_t q_y;
106
107 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", point, edc->ctx));
108 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", edc->ctx, 0);
109 GNUNET_assert (q_y);
110 GNUNET_CRYPTO_mpi_print_unsigned (bin->q_y,
111 sizeof(bin->q_y),
112 q_y);
113 gcry_mpi_release (q_y);
114}
115
116
117/**
118 * Convert binary representation of a point to computational representation.
119 *
120 * @param edc calculation context for ECC operations
121 * @param bin binary point representation
122 * @return computational representation
123 */
124gcry_mpi_point_t
125GNUNET_CRYPTO_ecc_bin_to_point (struct GNUNET_CRYPTO_EccDlogContext *edc,
126 const struct GNUNET_CRYPTO_EccPoint *bin)
127{
128 gcry_sexp_t pub_sexpr;
129 gcry_ctx_t ctx;
130 gcry_mpi_point_t q;
131
132 (void) edc;
133 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
134 "(public-key(ecc(curve " CURVE ")(q %b)))",
135 (int) sizeof(bin->q_y),
136 bin->q_y))
137 {
138 GNUNET_break (0);
139 return NULL;
140 }
141 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
142 gcry_sexp_release (pub_sexpr);
143 q = gcry_mpi_ec_get_point ("q", ctx, 0);
144 gcry_ctx_release (ctx);
145 return q;
146}
147
148
149/**
150 * Do pre-calculation for ECC discrete logarithm for small factors.
151 *
152 * @param max maximum value the factor can be
153 * @param mem memory to use (should be smaller than @a max), must not be zero.
154 * @return NULL on error
155 */
156struct GNUNET_CRYPTO_EccDlogContext * 64struct GNUNET_CRYPTO_EccDlogContext *
157GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max, 65GNUNET_CRYPTO_ecc_dlog_prepare (unsigned int max,
158 unsigned int mem) 66 unsigned int mem)
159{ 67{
160 struct GNUNET_CRYPTO_EccDlogContext *edc; 68 struct GNUNET_CRYPTO_EccDlogContext *edc;
161 unsigned int K = ((max + (mem - 1)) / mem); 69 int K = ((max + (mem - 1)) / mem);
162 gcry_mpi_point_t g;
163 struct GNUNET_PeerIdentity key;
164 gcry_mpi_point_t gKi;
165 gcry_mpi_t fact;
166 gcry_mpi_t n;
167 unsigned int i;
168 70
169 GNUNET_assert (max < INT32_MAX); 71 GNUNET_assert (max < INT32_MAX);
170 edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext); 72 edc = GNUNET_new (struct GNUNET_CRYPTO_EccDlogContext);
171 edc->max = max; 73 edc->max = max;
172 edc->mem = mem; 74 edc->mem = mem;
173
174 edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2, 75 edc->map = GNUNET_CONTAINER_multipeermap_create (mem * 2,
175 GNUNET_NO); 76 GNUNET_NO);
176 77 for (int i = -(int) mem; i <= (int) mem; i++)
177 GNUNET_assert (0 == gcry_mpi_ec_new (&edc->ctx,
178 NULL,
179 CURVE));
180 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0);
181 GNUNET_assert (NULL != g);
182 fact = gcry_mpi_new (0);
183 gKi = gcry_mpi_point_new (0);
184 for (i = 0; i <= mem; i++)
185 { 78 {
186 gcry_mpi_set_ui (fact, i * K); 79 struct GNUNET_CRYPTO_EccScalar Ki;
187 gcry_mpi_ec_mul (gKi, fact, g, edc->ctx); 80 struct GNUNET_PeerIdentity key;
188 extract_pk (gKi, edc->ctx, &key); 81
82 GNUNET_CRYPTO_ecc_scalar_from_int (K * i,
83 &Ki);
84 if (0 == i) /* libsodium does not like to multiply with zero */
85 GNUNET_assert (
86 0 ==
87 crypto_core_ed25519_sub ((unsigned char *) &key,
88 (unsigned char *) &key,
89 (unsigned char *) &key));
90 else
91 GNUNET_assert (
92 0 ==
93 crypto_scalarmult_ed25519_base_noclamp ((unsigned char*) &key,
94 Ki.v));
95 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
96 "K*i: %d (mem=%u, i=%d) => %s\n",
97 K * i,
98 mem,
99 i,
100 GNUNET_i2s (&key));
189 GNUNET_assert (GNUNET_OK == 101 GNUNET_assert (GNUNET_OK ==
190 GNUNET_CONTAINER_multipeermap_put (edc->map, 102 GNUNET_CONTAINER_multipeermap_put (edc->map,
191 &key, 103 &key,
192 (void *) (long) i + max, 104 (void *) (long) i + max,
193 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); 105 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
194 } 106 }
195 /* negative values */
196 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
197 for (i = 1; i < mem; i++)
198 {
199 gcry_mpi_set_ui (fact, i * K);
200 gcry_mpi_sub (fact, n, fact);
201 gcry_mpi_ec_mul (gKi, fact, g, edc->ctx);
202 extract_pk (gKi, edc->ctx, &key);
203 GNUNET_assert (GNUNET_OK ==
204 GNUNET_CONTAINER_multipeermap_put (edc->map,
205 &key,
206 (void *) (long) max - i,
207 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
208 }
209 gcry_mpi_release (fact);
210 gcry_mpi_release (n);
211 gcry_mpi_point_release (gKi);
212 gcry_mpi_point_release (g);
213 return edc; 107 return edc;
214} 108}
215 109
216 110
217/**
218 * Calculate ECC discrete logarithm for small factors.
219 *
220 * @param edc precalculated values, determine range of factors
221 * @param input point on the curve to factor
222 * @return INT_MAX if dlog failed, otherwise the factor
223 */
224int 111int
225GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc, 112GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
226 gcry_mpi_point_t input) 113 const struct GNUNET_CRYPTO_EccPoint *input)
227{ 114{
228 unsigned int K = ((edc->max + (edc->mem - 1)) / edc->mem); 115 unsigned int K = ((edc->max + (edc->mem - 1)) / edc->mem);
229 gcry_mpi_point_t g;
230 struct GNUNET_PeerIdentity key;
231 gcry_mpi_point_t q;
232 unsigned int i;
233 int res; 116 int res;
234 void *retp; 117 struct GNUNET_CRYPTO_EccPoint g;
235 118 struct GNUNET_CRYPTO_EccPoint q;
236 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); 119 struct GNUNET_CRYPTO_EccPoint nq;
237 GNUNET_assert (NULL != g);
238 q = gcry_mpi_point_new (0);
239 120
121 {
122 struct GNUNET_CRYPTO_EccScalar fact;
123
124 memset (&fact,
125 0,
126 sizeof (fact));
127 sodium_increment (fact.v,
128 sizeof (fact.v));
129 GNUNET_assert (0 ==
130 crypto_scalarmult_ed25519_base_noclamp (g.v,
131 fact.v));
132 }
133 /* make compiler happy: initialize q and nq, technically not needed! */
134 memset (&q,
135 0,
136 sizeof (q));
137 memset (&nq,
138 0,
139 sizeof (nq));
240 res = INT_MAX; 140 res = INT_MAX;
241 for (i = 0; i <= edc->max / edc->mem; i++) 141 for (unsigned int i = 0; i <= edc->max / edc->mem; i++)
242 { 142 {
143 struct GNUNET_PeerIdentity key;
144 void *retp;
145
146 GNUNET_assert (sizeof (key) == crypto_scalarmult_BYTES);
243 if (0 == i) 147 if (0 == i)
244 extract_pk (input, edc->ctx, &key); 148 {
149 memcpy (&key,
150 input,
151 sizeof (key));
152 }
245 else 153 else
246 extract_pk (q, edc->ctx, &key); 154 {
155 memcpy (&key,
156 &q,
157 sizeof (key));
158 }
159 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
160 "Trying offset i=%u): %s\n",
161 i,
162 GNUNET_i2s (&key));
247 retp = GNUNET_CONTAINER_multipeermap_get (edc->map, 163 retp = GNUNET_CONTAINER_multipeermap_get (edc->map,
248 &key); 164 &key);
249 if (NULL != retp) 165 if (NULL != retp)
@@ -257,248 +173,163 @@ GNUNET_CRYPTO_ecc_dlog (struct GNUNET_CRYPTO_EccDlogContext *edc,
257 break; 173 break;
258 /* q = q + g */ 174 /* q = q + g */
259 if (0 == i) 175 if (0 == i)
260 gcry_mpi_ec_add (q, input, g, edc->ctx); 176 {
177 GNUNET_assert (0 ==
178 crypto_core_ed25519_add (q.v,
179 input->v,
180 g.v));
181 }
261 else 182 else
262 gcry_mpi_ec_add (q, q, g, edc->ctx); 183 {
184 GNUNET_assert (0 ==
185 crypto_core_ed25519_add (q.v,
186 q.v,
187 g.v));
188 }
263 } 189 }
264 gcry_mpi_point_release (g);
265 gcry_mpi_point_release (q);
266
267 return res; 190 return res;
268} 191}
269 192
270 193
271/** 194void
272 * Generate a random value mod n. 195GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccScalar *r)
273 *
274 * @param edc ECC context
275 * @return random value mod n.
276 */
277gcry_mpi_t
278GNUNET_CRYPTO_ecc_random_mod_n (struct GNUNET_CRYPTO_EccDlogContext *edc)
279{ 196{
280 gcry_mpi_t n; 197 crypto_core_ed25519_scalar_random (r->v);
281 unsigned int highbit;
282 gcry_mpi_t r;
283
284 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
285
286 /* check public key for number of bits, bail out if key is all zeros */
287 highbit = 256; /* Curve25519 */
288 while ((! gcry_mpi_test_bit (n, highbit)) &&
289 (0 != highbit))
290 highbit--;
291 GNUNET_assert (0 != highbit);
292 /* generate fact < n (without bias) */
293 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
294 do
295 {
296 gcry_mpi_randomize (r,
297 highbit + 1,
298 GCRY_STRONG_RANDOM);
299 }
300 while (gcry_mpi_cmp (r, n) >= 0);
301 gcry_mpi_release (n);
302 return r;
303} 198}
304 199
305 200
306/**
307 * Release precalculated values.
308 *
309 * @param edc dlog context
310 */
311void 201void
312GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc) 202GNUNET_CRYPTO_ecc_dlog_release (struct GNUNET_CRYPTO_EccDlogContext *edc)
313{ 203{
314 gcry_ctx_release (edc->ctx);
315 GNUNET_CONTAINER_multipeermap_destroy (edc->map); 204 GNUNET_CONTAINER_multipeermap_destroy (edc->map);
316 GNUNET_free (edc); 205 GNUNET_free (edc);
317} 206}
318 207
319 208
320/** 209void
321 * Multiply the generator g of the elliptic curve by @a val 210GNUNET_CRYPTO_ecc_dexp (int val,
322 * to obtain the point on the curve representing @a val. 211 struct GNUNET_CRYPTO_EccPoint *r)
323 * Afterwards, point addition will correspond to integer
324 * addition. #GNUNET_CRYPTO_ecc_dlog() can be used to
325 * convert a point back to an integer (as long as the
326 * integer is smaller than the MAX of the @a edc context).
327 *
328 * @param edc calculation context for ECC operations
329 * @param val value to encode into a point
330 * @return representation of the value as an ECC point,
331 * must be freed using #GNUNET_CRYPTO_ecc_free()
332 */
333gcry_mpi_point_t
334GNUNET_CRYPTO_ecc_dexp (struct GNUNET_CRYPTO_EccDlogContext *edc,
335 int val)
336{ 212{
337 gcry_mpi_t fact; 213 struct GNUNET_CRYPTO_EccScalar fact;
338 gcry_mpi_t n; 214
339 gcry_mpi_point_t g; 215 GNUNET_CRYPTO_ecc_scalar_from_int (val,
340 gcry_mpi_point_t r; 216 &fact);
341 217 crypto_scalarmult_ed25519_base_noclamp (r->v,
342 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); 218 fact.v);
343 GNUNET_assert (NULL != g);
344 fact = gcry_mpi_new (0);
345 if (val < 0)
346 {
347 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
348 gcry_mpi_set_ui (fact, -val);
349 gcry_mpi_sub (fact, n, fact);
350 gcry_mpi_release (n);
351 }
352 else
353 {
354 gcry_mpi_set_ui (fact, val);
355 }
356 r = gcry_mpi_point_new (0);
357 gcry_mpi_ec_mul (r, fact, g, edc->ctx);
358 gcry_mpi_release (fact);
359 gcry_mpi_point_release (g);
360 return r;
361} 219}
362 220
363 221
364/** 222enum GNUNET_GenericReturnValue
365 * Multiply the generator g of the elliptic curve by @a val 223GNUNET_CRYPTO_ecc_dexp_mpi (const struct GNUNET_CRYPTO_EccScalar *val,
366 * to obtain the point on the curve representing @a val. 224 struct GNUNET_CRYPTO_EccPoint *r)
367 *
368 * @param edc calculation context for ECC operations
369 * @param val (positive) value to encode into a point
370 * @return representation of the value as an ECC point,
371 * must be freed using #GNUNET_CRYPTO_ecc_free()
372 */
373gcry_mpi_point_t
374GNUNET_CRYPTO_ecc_dexp_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
375 gcry_mpi_t val)
376{ 225{
377 gcry_mpi_point_t g; 226 if (0 ==
378 gcry_mpi_point_t r; 227 crypto_scalarmult_ed25519_base_noclamp (r->v,
379 228 val->v))
380 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); 229 return GNUNET_OK;
381 GNUNET_assert (NULL != g); 230 return GNUNET_SYSERR;
382 r = gcry_mpi_point_new (0);
383 gcry_mpi_ec_mul (r, val, g, edc->ctx);
384 gcry_mpi_point_release (g);
385 return r;
386} 231}
387 232
388 233
389/** 234enum GNUNET_GenericReturnValue
390 * Add two points on the elliptic curve. 235GNUNET_CRYPTO_ecc_add (const struct GNUNET_CRYPTO_EccPoint *a,
391 * 236 const struct GNUNET_CRYPTO_EccPoint *b,
392 * @param edc calculation context for ECC operations 237 struct GNUNET_CRYPTO_EccPoint *r)
393 * @param a some value
394 * @param b some value
395 * @return @a a + @a b, must be freed using #GNUNET_CRYPTO_ecc_free()
396 */
397gcry_mpi_point_t
398GNUNET_CRYPTO_ecc_add (struct GNUNET_CRYPTO_EccDlogContext *edc,
399 gcry_mpi_point_t a,
400 gcry_mpi_point_t b)
401{ 238{
402 gcry_mpi_point_t r; 239 if (0 ==
403 240 crypto_core_ed25519_add (r->v,
404 r = gcry_mpi_point_new (0); 241 a->v,
405 gcry_mpi_ec_add (r, a, b, edc->ctx); 242 b->v))
406 return r; 243 return GNUNET_OK;
244 return GNUNET_SYSERR;
407} 245}
408 246
409 247
410/** 248enum GNUNET_GenericReturnValue
411 * Multiply the point @a p on the elliptic curve by @a val. 249GNUNET_CRYPTO_ecc_pmul_mpi (const struct GNUNET_CRYPTO_EccPoint *p,
412 * 250 const struct GNUNET_CRYPTO_EccScalar *val,
413 * @param edc calculation context for ECC operations 251 struct GNUNET_CRYPTO_EccPoint *r)
414 * @param p point to multiply
415 * @param val (positive) value to encode into a point
416 * @return representation of the value as an ECC point,
417 * must be freed using #GNUNET_CRYPTO_ecc_free()
418 */
419gcry_mpi_point_t
420GNUNET_CRYPTO_ecc_pmul_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc,
421 gcry_mpi_point_t p,
422 gcry_mpi_t val)
423{ 252{
424 gcry_mpi_point_t r; 253 if (0 ==
425 254 crypto_scalarmult_ed25519_noclamp (r->v,
426 r = gcry_mpi_point_new (0); 255 val->v,
427 gcry_mpi_ec_mul (r, val, p, edc->ctx); 256 p->v))
428 return r; 257 return GNUNET_OK;
258 return GNUNET_SYSERR;
429} 259}
430 260
431 261
432/** 262enum GNUNET_GenericReturnValue
433 * Obtain a random point on the curve and its 263GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccPoint *r,
434 * additive inverse. Both returned values 264 struct GNUNET_CRYPTO_EccPoint *r_inv)
435 * must be freed using #GNUNET_CRYPTO_ecc_free().
436 *
437 * @param edc calculation context for ECC operations
438 * @param[out] r set to a random point on the curve
439 * @param[out] r_inv set to the additive inverse of @a r
440 */
441void
442GNUNET_CRYPTO_ecc_rnd (struct GNUNET_CRYPTO_EccDlogContext *edc,
443 gcry_mpi_point_t *r,
444 gcry_mpi_point_t *r_inv)
445{ 265{
446 gcry_mpi_t fact; 266 struct GNUNET_CRYPTO_EccScalar s;
447 gcry_mpi_t n; 267 unsigned char inv_s[crypto_scalarmult_ed25519_SCALARBYTES];
448 gcry_mpi_point_t g; 268
449 269 GNUNET_CRYPTO_ecc_random_mod_n (&s);
450 fact = GNUNET_CRYPTO_ecc_random_mod_n (edc); 270 if (0 !=
451 271 crypto_scalarmult_ed25519_base_noclamp (r->v,
452 /* calculate 'r' */ 272 s.v))
453 g = gcry_mpi_ec_get_point ("g", edc->ctx, 0); 273 return GNUNET_SYSERR;
454 GNUNET_assert (NULL != g); 274 crypto_core_ed25519_scalar_negate (inv_s,
455 *r = gcry_mpi_point_new (0); 275 s.v);
456 gcry_mpi_ec_mul (*r, fact, g, edc->ctx); 276 if (0 !=
457 277 crypto_scalarmult_ed25519_base_noclamp (r_inv->v,
458 /* calculate 'r_inv' */ 278 inv_s))
459 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1); 279 return GNUNET_SYSERR;
460 gcry_mpi_sub (fact, n, fact); /* fact = n - fact = - fact */ 280 return GNUNET_OK;
461 *r_inv = gcry_mpi_point_new (0);
462 gcry_mpi_ec_mul (*r_inv, fact, g, edc->ctx);
463
464 gcry_mpi_release (n);
465 gcry_mpi_release (fact);
466 gcry_mpi_point_release (g);
467} 281}
468 282
469 283
470/**
471 * Obtain a random scalar for point multiplication on the curve and
472 * its multiplicative inverse.
473 *
474 * @param edc calculation context for ECC operations
475 * @param[out] r set to a random scalar on the curve
476 * @param[out] r_inv set to the multiplicative inverse of @a r
477 */
478void 284void
479GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccDlogContext *edc, 285GNUNET_CRYPTO_ecc_rnd_mpi (struct GNUNET_CRYPTO_EccScalar *r,
480 gcry_mpi_t *r, 286 struct GNUNET_CRYPTO_EccScalar *r_neg)
481 gcry_mpi_t *r_inv)
482{ 287{
483 gcry_mpi_t n; 288 GNUNET_CRYPTO_ecc_random_mod_n (r);
484 289 crypto_core_ed25519_scalar_negate (r_neg->v,
485 *r = GNUNET_CRYPTO_ecc_random_mod_n (edc); 290 r->v);
486 /* r_inv = n - r = - r */
487 *r_inv = gcry_mpi_new (0);
488 n = gcry_mpi_ec_get_mpi ("n", edc->ctx, 1);
489 gcry_mpi_sub (*r_inv, n, *r);
490} 291}
491 292
492 293
493/**
494 * Free a point value returned by the API.
495 *
496 * @param p point to free
497 */
498void 294void
499GNUNET_CRYPTO_ecc_free (gcry_mpi_point_t p) 295GNUNET_CRYPTO_ecc_scalar_from_int (int64_t val,
296 struct GNUNET_CRYPTO_EccScalar *r)
500{ 297{
501 gcry_mpi_point_release (p); 298 unsigned char fact[crypto_scalarmult_ed25519_SCALARBYTES];
299 uint64_t valBe;
300
301 GNUNET_assert (sizeof (*r) == sizeof (fact));
302 if (val < 0)
303 {
304 if (INT64_MIN == val)
305 valBe = GNUNET_htonll ((uint64_t) INT64_MAX);
306 else
307 valBe = GNUNET_htonll ((uint64_t) (-val));
308 }
309 else
310 {
311 valBe = GNUNET_htonll ((uint64_t) val);
312 }
313 memset (fact,
314 0,
315 sizeof (fact));
316 for (unsigned int i = 0; i < sizeof (val); i++)
317 fact[i] = ((unsigned char*) &valBe)[sizeof (val) - 1 - i];
318 if (val < 0)
319 {
320 if (INT64_MIN == val)
321 /* See above: fact is one too small, increment now that we can */
322 sodium_increment (fact,
323 sizeof (fact));
324 crypto_core_ed25519_scalar_negate (r->v,
325 fact);
326 }
327 else
328 {
329 memcpy (r,
330 fact,
331 sizeof (fact));
332 }
502} 333}
503 334
504 335