tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / crypto_ecc.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2015 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 /**
22  * @file util/crypto_ecc.c
23  * @brief public key cryptography (ECC) with libgcrypt
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include <gcrypt.h>
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_strings_lib.h"
30 #include "benchmark.h"
31
32 #define EXTRA_CHECKS 0
33
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 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
43
44 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
45
46 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
47
48 /**
49  * Log an error message at log-level 'level' that indicates
50  * a failure of the command 'cmd' with the message given
51  * by gcry_strerror(rc).
52  */
53 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
54
55
56 /**
57  * Extract values from an S-expression.
58  *
59  * @param array where to store the result(s)
60  * @param sexp S-expression to parse
61  * @param topname top-level name in the S-expression that is of interest
62  * @param elems names of the elements to extract
63  * @return 0 on success
64  */
65 static int
66 key_from_sexp (gcry_mpi_t * array,
67                gcry_sexp_t sexp,
68                const char *topname,
69                const char *elems)
70 {
71   gcry_sexp_t list;
72   gcry_sexp_t l2;
73   const char *s;
74   unsigned int i;
75   unsigned int idx;
76
77   list = gcry_sexp_find_token (sexp, topname, 0);
78   if (! list)
79     return 1;
80   l2 = gcry_sexp_cadr (list);
81   gcry_sexp_release (list);
82   list = l2;
83   if (! list)
84     return 2;
85
86   idx = 0;
87   for (s = elems; *s; s++, idx++)
88   {
89     l2 = gcry_sexp_find_token (list, s, 1);
90     if (! l2)
91     {
92       for (i = 0; i < idx; i++)
93       {
94         gcry_free (array[i]);
95         array[i] = NULL;
96       }
97       gcry_sexp_release (list);
98       return 3;                 /* required parameter not found */
99     }
100     array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
101     gcry_sexp_release (l2);
102     if (! array[idx])
103     {
104       for (i = 0; i < idx; i++)
105       {
106         gcry_free (array[i]);
107         array[i] = NULL;
108       }
109       gcry_sexp_release (list);
110       return 4;                 /* required parameter is invalid */
111     }
112   }
113   gcry_sexp_release (list);
114   return 0;
115 }
116
117
118 /**
119  * Convert the given private key from the network format to the
120  * S-expression that can be used by libgcrypt.
121  *
122  * @param priv private key to decode
123  * @return NULL on error
124  */
125 static gcry_sexp_t
126 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
127 {
128   gcry_sexp_t result;
129   int rc;
130
131   rc = gcry_sexp_build (&result, NULL,
132                         "(private-key(ecc(curve \"" CURVE "\")"
133                         "(d %b)))",
134                         (int) sizeof (priv->d), priv->d);
135   if (0 != rc)
136   {
137     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
138     GNUNET_assert (0);
139   }
140 #if EXTRA_CHECKS
141   if (0 != (rc = gcry_pk_testkey (result)))
142   {
143     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
144     GNUNET_assert (0);
145   }
146 #endif
147   return result;
148 }
149
150
151 /**
152  * Convert the given private key from the network format to the
153  * S-expression that can be used by libgcrypt.
154  *
155  * @param priv private key to decode
156  * @return NULL on error
157  */
158 static gcry_sexp_t
159 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
160 {
161   gcry_sexp_t result;
162   int rc;
163
164   rc = gcry_sexp_build (&result, NULL,
165                         "(private-key(ecc(curve \"" CURVE "\")"
166                         "(flags eddsa)(d %b)))",
167                         (int)sizeof (priv->d), priv->d);
168   if (0 != rc)
169   {
170     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
171     GNUNET_assert (0);
172   }
173 #if EXTRA_CHECKS
174   if (0 != (rc = gcry_pk_testkey (result)))
175   {
176     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
177     GNUNET_assert (0);
178   }
179 #endif
180   return result;
181 }
182
183
184 /**
185  * Convert the given private key from the network format to the
186  * S-expression that can be used by libgcrypt.
187  *
188  * @param priv private key to decode
189  * @return NULL on error
190  */
191 static gcry_sexp_t
192 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
193 {
194   gcry_sexp_t result;
195   int rc;
196
197   rc = gcry_sexp_build (&result, NULL,
198                         "(private-key(ecc(curve \"" CURVE "\")"
199                         "(d %b)))",
200                         (int)sizeof (priv->d), priv->d);
201   if (0 != rc)
202   {
203     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
204     GNUNET_assert (0);
205   }
206 #if EXTRA_CHECKS
207   if (0 != (rc = gcry_pk_testkey (result)))
208   {
209     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
210     GNUNET_assert (0);
211   }
212 #endif
213   return result;
214 }
215
216
217 /**
218  * Extract the public key for the given private key.
219  *
220  * @param priv the private key
221  * @param pub where to write the public key
222  */
223 void
224 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
225                                     struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
226 {
227   gcry_sexp_t sexp;
228   gcry_ctx_t ctx;
229   gcry_mpi_t q;
230
231   BENCHMARK_START (ecdsa_key_get_public);
232
233   sexp = decode_private_ecdsa_key (priv);
234   GNUNET_assert (NULL != sexp);
235   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
236   gcry_sexp_release (sexp);
237   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
238   GNUNET_assert (NULL != q);
239   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
240   gcry_mpi_release (q);
241   gcry_ctx_release (ctx);
242
243   BENCHMARK_END (ecdsa_key_get_public);
244 }
245
246
247 /**
248  * Extract the public key for the given private key.
249  *
250  * @param priv the private key
251  * @param pub where to write the public key
252  */
253 void
254 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
255                                     struct GNUNET_CRYPTO_EddsaPublicKey *pub)
256 {
257   gcry_sexp_t sexp;
258   gcry_ctx_t ctx;
259   gcry_mpi_t q;
260
261   BENCHMARK_START (eddsa_key_get_public);
262
263   sexp = decode_private_eddsa_key (priv);
264   GNUNET_assert (NULL != sexp);
265   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
266   gcry_sexp_release (sexp);
267   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
268   GNUNET_assert (q);
269   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
270   gcry_mpi_release (q);
271   gcry_ctx_release (ctx);
272
273   BENCHMARK_END (eddsa_key_get_public);
274 }
275
276
277 /**
278  * Extract the public key for the given private key.
279  *
280  * @param priv the private key
281  * @param pub where to write the public key
282  */
283 void
284 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
285                                     struct GNUNET_CRYPTO_EcdhePublicKey *pub)
286 {
287   gcry_sexp_t sexp;
288   gcry_ctx_t ctx;
289   gcry_mpi_t q;
290
291   BENCHMARK_START (ecdhe_key_get_public);
292
293   sexp = decode_private_ecdhe_key (priv);
294   GNUNET_assert (NULL != sexp);
295   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
296   gcry_sexp_release (sexp);
297   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
298   GNUNET_assert (q);
299   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
300   gcry_mpi_release (q);
301   gcry_ctx_release (ctx);
302
303   BENCHMARK_END (ecdhe_key_get_public);
304 }
305
306
307 /**
308  * Convert a public key to a string.
309  *
310  * @param pub key to convert
311  * @return string representing @a pub
312  */
313 char *
314 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
315 {
316   char *pubkeybuf;
317   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
318   char *end;
319
320   if (keylen % 5 > 0)
321     keylen += 5 - keylen % 5;
322   keylen /= 5;
323   pubkeybuf = GNUNET_malloc (keylen + 1);
324   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
325                                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
326                                        pubkeybuf,
327                                        keylen);
328   if (NULL == end)
329   {
330     GNUNET_free (pubkeybuf);
331     return NULL;
332   }
333   *end = '\0';
334   return pubkeybuf;
335 }
336
337
338 /**
339  * Convert a public key to a string.
340  *
341  * @param pub key to convert
342  * @return string representing @a pub
343  */
344 char *
345 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
346 {
347   char *pubkeybuf;
348   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
349   char *end;
350
351   if (keylen % 5 > 0)
352     keylen += 5 - keylen % 5;
353   keylen /= 5;
354   pubkeybuf = GNUNET_malloc (keylen + 1);
355   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
356                                        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
357                                        pubkeybuf,
358                                        keylen);
359   if (NULL == end)
360   {
361     GNUNET_free (pubkeybuf);
362     return NULL;
363   }
364   *end = '\0';
365   return pubkeybuf;
366 }
367
368
369 /**
370  * Convert a private key to a string.
371  *
372  * @param priv key to convert
373  * @return string representing @a pub
374  */
375 char *
376 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
377 {
378   char *privkeybuf;
379   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
380   char *end;
381
382   if (keylen % 5 > 0)
383     keylen += 5 - keylen % 5;
384   keylen /= 5;
385   privkeybuf = GNUNET_malloc (keylen + 1);
386   end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
387                                        sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
388                                        privkeybuf,
389                                        keylen);
390   if (NULL == end)
391   {
392     GNUNET_free (privkeybuf);
393     return NULL;
394   }
395   *end = '\0';
396   return privkeybuf;
397 }
398
399
400 /**
401  * Convert a string representing a public key to a public key.
402  *
403  * @param enc encoded public key
404  * @param enclen number of bytes in @a enc (without 0-terminator)
405  * @param pub where to store the public key
406  * @return #GNUNET_OK on success
407  */
408 int
409 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
410                                             size_t enclen,
411                                             struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
412 {
413   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
414
415   if (keylen % 5 > 0)
416     keylen += 5 - keylen % 5;
417   keylen /= 5;
418   if (enclen != keylen)
419     return GNUNET_SYSERR;
420
421   if (GNUNET_OK !=
422       GNUNET_STRINGS_string_to_data (enc, enclen,
423                                      pub,
424                                      sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
425     return GNUNET_SYSERR;
426   return GNUNET_OK;
427 }
428
429
430 /**
431  * Convert a string representing a public key to a public key.
432  *
433  * @param enc encoded public key
434  * @param enclen number of bytes in @a enc (without 0-terminator)
435  * @param pub where to store the public key
436  * @return #GNUNET_OK on success
437  */
438 int
439 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
440                                             size_t enclen,
441                                             struct GNUNET_CRYPTO_EddsaPublicKey *pub)
442 {
443   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
444
445   if (keylen % 5 > 0)
446     keylen += 5 - keylen % 5;
447   keylen /= 5;
448   if (enclen != keylen)
449     return GNUNET_SYSERR;
450
451   if (GNUNET_OK !=
452       GNUNET_STRINGS_string_to_data (enc, enclen,
453                                      pub,
454                                      sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
455     return GNUNET_SYSERR;
456   return GNUNET_OK;
457 }
458
459
460 /**
461  * Convert a string representing a private key to a private key.
462  *
463  * @param enc encoded public key
464  * @param enclen number of bytes in @a enc (without 0-terminator)
465  * @param priv where to store the private key
466  * @return #GNUNET_OK on success
467  */
468 int
469 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
470                                              size_t enclen,
471                                              struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
472 {
473   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
474
475   if (keylen % 5 > 0)
476     keylen += 5 - keylen % 5;
477   keylen /= 5;
478   if (enclen != keylen)
479     return GNUNET_SYSERR;
480
481   if (GNUNET_OK !=
482       GNUNET_STRINGS_string_to_data (enc, enclen,
483                                      priv,
484                                      sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
485     return GNUNET_SYSERR;
486 #if CRYPTO_BUG
487   if (GNUNET_OK !=
488       check_eddsa_key (priv))
489   {
490     GNUNET_break (0);
491     return GNUNET_OK;
492   }
493 #endif
494   return GNUNET_OK;
495 }
496
497
498 /**
499  * @ingroup crypto
500  * Clear memory that was used to store a private key.
501  *
502  * @param pk location of the key
503  */
504 void
505 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
506 {
507   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
508 }
509
510
511 /**
512  * @ingroup crypto
513  * Clear memory that was used to store a private key.
514  *
515  * @param pk location of the key
516  */
517 void
518 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
519 {
520   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
521 }
522
523
524 /**
525  * @ingroup crypto
526  * Clear memory that was used to store a private key.
527  *
528  * @param pk location of the key
529  */
530 void
531 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
532 {
533   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
534 }
535
536
537 /**
538  * Create a new private key. Caller must free return value.
539  *
540  * @return fresh private key
541  */
542 struct GNUNET_CRYPTO_EcdhePrivateKey *
543 GNUNET_CRYPTO_ecdhe_key_create ()
544 {
545   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
546
547   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
548   if (GNUNET_OK !=
549       GNUNET_CRYPTO_ecdhe_key_create2 (priv))
550   {
551     GNUNET_free (priv);
552     return NULL;
553   }
554   return priv;
555 }
556
557
558 /**
559  * @ingroup crypto
560  * Create a new private key.  Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
561  *
562  * @param[out] pk set to fresh private key;
563  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
564  */
565 int
566 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
567 {
568   gcry_sexp_t priv_sexp;
569   gcry_sexp_t s_keyparam;
570   gcry_mpi_t d;
571   int rc;
572
573   BENCHMARK_START (ecdhe_key_create);
574
575   /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
576      but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
577      disables an expensive key testing routine. We do not want to run
578      the expensive check for ECDHE, as we generate TONS of keys to
579      use for a very short time. */
580   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
581                                   "(genkey(ecc(curve \"" CURVE "\")"
582                                   "(flags eddsa no-keytest)))")))
583   {
584     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
585     return GNUNET_SYSERR;
586   }
587   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
588   {
589     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
590     gcry_sexp_release (s_keyparam);
591     return GNUNET_SYSERR;
592   }
593   gcry_sexp_release (s_keyparam);
594 #if EXTRA_CHECKS
595   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
596   {
597     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
598     gcry_sexp_release (priv_sexp);
599     return GNUNET_SYSERR;
600   }
601 #endif
602   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
603   {
604     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
605     gcry_sexp_release (priv_sexp);
606     return GNUNET_SYSERR;
607   }
608   gcry_sexp_release (priv_sexp);
609   GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
610   gcry_mpi_release (d);
611
612   BENCHMARK_END (ecdhe_key_create);
613
614   return GNUNET_OK;
615 }
616
617
618 /**
619  * Create a new private key. Caller must free return value.
620  *
621  * @return fresh private key
622  */
623 struct GNUNET_CRYPTO_EcdsaPrivateKey *
624 GNUNET_CRYPTO_ecdsa_key_create ()
625 {
626   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
627   gcry_sexp_t priv_sexp;
628   gcry_sexp_t s_keyparam;
629   gcry_mpi_t d;
630   int rc;
631
632   BENCHMARK_START (ecdsa_key_create);
633
634   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
635                                   "(genkey(ecc(curve \"" CURVE "\")"
636                                   "(flags)))")))
637   {
638     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
639     return NULL;
640   }
641   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
642   {
643     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
644     gcry_sexp_release (s_keyparam);
645     return NULL;
646   }
647   gcry_sexp_release (s_keyparam);
648 #if EXTRA_CHECKS
649   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
650   {
651     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
652     gcry_sexp_release (priv_sexp);
653     return NULL;
654   }
655 #endif
656   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
657   {
658     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
659     gcry_sexp_release (priv_sexp);
660     return NULL;
661   }
662   gcry_sexp_release (priv_sexp);
663   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
664   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
665   gcry_mpi_release (d);
666
667   BENCHMARK_END (ecdsa_key_create);
668
669   return priv;
670 }
671
672 /**
673  * Create a new private key. Caller must free return value.
674  *
675  * @return fresh private key
676  */
677 struct GNUNET_CRYPTO_EddsaPrivateKey *
678 GNUNET_CRYPTO_eddsa_key_create ()
679 {
680   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
681   gcry_sexp_t priv_sexp;
682   gcry_sexp_t s_keyparam;
683   gcry_mpi_t d;
684   int rc;
685
686   BENCHMARK_START (eddsa_key_create);
687
688 #if CRYPTO_BUG
689  again:
690 #endif
691   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
692                                   "(genkey(ecc(curve \"" CURVE "\")"
693                                   "(flags eddsa)))")))
694   {
695     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
696     return NULL;
697   }
698   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
699   {
700     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
701     gcry_sexp_release (s_keyparam);
702     return NULL;
703   }
704   gcry_sexp_release (s_keyparam);
705 #if EXTRA_CHECKS
706   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
707   {
708     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
709     gcry_sexp_release (priv_sexp);
710     return NULL;
711   }
712 #endif
713   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
714   {
715     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
716     gcry_sexp_release (priv_sexp);
717     return NULL;
718   }
719   gcry_sexp_release (priv_sexp);
720   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
721   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
722   gcry_mpi_release (d);
723
724 #if CRYPTO_BUG
725   if (GNUNET_OK !=
726       check_eddsa_key (priv))
727   {
728     GNUNET_break (0);
729     GNUNET_free (priv);
730     goto again;
731   }
732 #endif
733
734   BENCHMARK_END (eddsa_key_create);
735
736   return priv;
737 }
738
739
740 /**
741  * Get the shared private key we use for anonymous users.
742  *
743  * @return "anonymous" private key
744  */
745 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
746 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
747 {
748   /**
749    * 'anonymous' pseudonym (global static, d=1, public key = G
750    * (generator).
751    */
752   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
753   static int once;
754
755   if (once)
756     return &anonymous;
757   GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
758              sizeof (anonymous.d),
759              GCRYMPI_CONST_ONE);
760   once = 1;
761   return &anonymous;
762 }
763
764
765 /**
766  * Convert the data specified in the given purpose argument to an
767  * S-expression suitable for signature operations.
768  *
769  * @param purpose data to convert
770  * @return converted s-expression
771  */
772 static gcry_sexp_t
773 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
774 {
775   gcry_sexp_t data;
776   int rc;
777
778 /* SEE #5398 */
779 #if 1
780   struct GNUNET_HashCode hc;
781
782   GNUNET_CRYPTO_hash (purpose,
783                       ntohl (purpose->size),
784                       &hc);
785   if (0 != (rc = gcry_sexp_build (&data, NULL,
786                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
787                                   "sha512",
788                                   (int)sizeof (hc),
789                                   &hc)))
790   {
791     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
792               "gcry_sexp_build",
793               rc);
794     return NULL;
795   }
796 #else
797   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
798   if (0 != (rc = gcry_sexp_build (&data, NULL,
799                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
800                                   "sha512",
801                                   ntohl (purpose->size),
802                                   purpose)))
803   {
804     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
805               "gcry_sexp_build",
806               rc);
807     return NULL;
808   }
809 #endif
810   return data;
811 }
812
813
814 /**
815  * Convert the data specified in the given purpose argument to an
816  * S-expression suitable for signature operations.
817  *
818  * @param purpose data to convert
819  * @return converted s-expression
820  */
821 static gcry_sexp_t
822 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
823 {
824   gcry_sexp_t data;
825   int rc;
826
827 /* See #5398 */
828 #if 1
829   struct GNUNET_HashCode hc;
830
831   GNUNET_CRYPTO_hash (purpose,
832                       ntohl (purpose->size),
833                       &hc);
834   if (0 != (rc = gcry_sexp_build (&data, NULL,
835                                   "(data(flags rfc6979)(hash %s %b))",
836                                   "sha512",
837                                   (int)sizeof (hc), &hc)))
838   {
839     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
840               "gcry_sexp_build",
841               rc);
842     return NULL;
843   }
844 #else
845   if (0 != (rc = gcry_sexp_build (&data, NULL,
846                                   "(data(flags rfc6979)(hash %s %b))",
847                                   "sha512",
848                                   ntohl (purpose->size),
849                                   purpose)))
850   {
851     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
852               "gcry_sexp_build",
853               rc);
854     return NULL;
855   }
856 #endif
857   return data;
858 }
859
860
861 /**
862  * Sign a given block.
863  *
864  * @param priv private key to use for the signing
865  * @param purpose what to sign (size, purpose)
866  * @param sig where to write the signature
867  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
868  */
869 int
870 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
871                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
872                           struct GNUNET_CRYPTO_EcdsaSignature *sig)
873 {
874   gcry_sexp_t priv_sexp;
875   gcry_sexp_t sig_sexp;
876   gcry_sexp_t data;
877   int rc;
878   gcry_mpi_t rs[2];
879
880   BENCHMARK_START (ecdsa_sign);
881
882   priv_sexp = decode_private_ecdsa_key (priv);
883   data = data_to_ecdsa_value (purpose);
884   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
885   {
886     LOG (GNUNET_ERROR_TYPE_WARNING,
887          _("ECC signing failed at %s:%d: %s\n"), __FILE__,
888          __LINE__, gcry_strerror (rc));
889     gcry_sexp_release (data);
890     gcry_sexp_release (priv_sexp);
891     return GNUNET_SYSERR;
892   }
893   gcry_sexp_release (priv_sexp);
894   gcry_sexp_release (data);
895
896   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
897      'signature' */
898   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
899   {
900     GNUNET_break (0);
901     gcry_sexp_release (sig_sexp);
902     return GNUNET_SYSERR;
903   }
904   gcry_sexp_release (sig_sexp);
905   GNUNET_CRYPTO_mpi_print_unsigned (sig->r,
906                                     sizeof (sig->r),
907                                     rs[0]);
908   GNUNET_CRYPTO_mpi_print_unsigned (sig->s,
909                                     sizeof (sig->s),
910                                     rs[1]);
911   gcry_mpi_release (rs[0]);
912   gcry_mpi_release (rs[1]);
913
914   BENCHMARK_END (ecdsa_sign);
915
916   return GNUNET_OK;
917 }
918
919
920 /**
921  * Sign a given block.
922  *
923  * @param priv private key to use for the signing
924  * @param purpose what to sign (size, purpose)
925  * @param sig where to write the signature
926  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
927  */
928 int
929 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
930                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
931                           struct GNUNET_CRYPTO_EddsaSignature *sig)
932 {
933   gcry_sexp_t priv_sexp;
934   gcry_sexp_t sig_sexp;
935   gcry_sexp_t data;
936   int rc;
937   gcry_mpi_t rs[2];
938
939   BENCHMARK_START (eddsa_sign);
940
941   priv_sexp = decode_private_eddsa_key (priv);
942   data = data_to_eddsa_value (purpose);
943   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
944   {
945     LOG (GNUNET_ERROR_TYPE_WARNING,
946          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
947          __LINE__, gcry_strerror (rc));
948     gcry_sexp_release (data);
949     gcry_sexp_release (priv_sexp);
950     return GNUNET_SYSERR;
951   }
952   gcry_sexp_release (priv_sexp);
953   gcry_sexp_release (data);
954
955   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
956      'signature' */
957   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
958   {
959     GNUNET_break (0);
960     gcry_sexp_release (sig_sexp);
961     return GNUNET_SYSERR;
962   }
963   gcry_sexp_release (sig_sexp);
964   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
965   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
966   gcry_mpi_release (rs[0]);
967   gcry_mpi_release (rs[1]);
968
969   BENCHMARK_END (eddsa_sign);
970
971   return GNUNET_OK;
972 }
973
974
975 /**
976  * Verify signature.
977  *
978  * @param purpose what is the purpose that the signature should have?
979  * @param validate block to validate (size, purpose, data)
980  * @param sig signature that is being validated
981  * @param pub public key of the signer
982  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
983  */
984 int
985 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
986                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
987                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
988                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
989 {
990   gcry_sexp_t data;
991   gcry_sexp_t sig_sexpr;
992   gcry_sexp_t pub_sexpr;
993   int rc;
994
995   BENCHMARK_START (ecdsa_verify);
996
997   if (purpose != ntohl (validate->purpose))
998     return GNUNET_SYSERR;       /* purpose mismatch */
999
1000   /* build s-expression for signature */
1001   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1002                                   "(sig-val(ecdsa(r %b)(s %b)))",
1003                                   (int) sizeof (sig->r), sig->r,
1004                                   (int) sizeof (sig->s), sig->s)))
1005   {
1006     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1007     return GNUNET_SYSERR;
1008   }
1009   data = data_to_ecdsa_value (validate);
1010   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1011                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
1012                                   (int) sizeof (pub->q_y), pub->q_y)))
1013   {
1014     gcry_sexp_release (data);
1015     gcry_sexp_release (sig_sexpr);
1016     return GNUNET_SYSERR;
1017   }
1018   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1019   gcry_sexp_release (pub_sexpr);
1020   gcry_sexp_release (data);
1021   gcry_sexp_release (sig_sexpr);
1022   if (0 != rc)
1023   {
1024     LOG (GNUNET_ERROR_TYPE_INFO,
1025          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1026          __LINE__, gcry_strerror (rc));
1027     BENCHMARK_END (ecdsa_verify);
1028     return GNUNET_SYSERR;
1029   }
1030   BENCHMARK_END (ecdsa_verify);
1031   return GNUNET_OK;
1032 }
1033
1034
1035
1036 /**
1037  * Verify signature.
1038  *
1039  * @param purpose what is the purpose that the signature should have?
1040  * @param validate block to validate (size, purpose, data)
1041  * @param sig signature that is being validated
1042  * @param pub public key of the signer
1043  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1044  */
1045 int
1046 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1047                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1048                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
1049                             const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1050 {
1051   gcry_sexp_t data;
1052   gcry_sexp_t sig_sexpr;
1053   gcry_sexp_t pub_sexpr;
1054   int rc;
1055
1056   BENCHMARK_START (eddsa_verify);
1057
1058   if (purpose != ntohl (validate->purpose))
1059     return GNUNET_SYSERR;       /* purpose mismatch */
1060
1061   /* build s-expression for signature */
1062   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1063                                   "(sig-val(eddsa(r %b)(s %b)))",
1064                                   (int)sizeof (sig->r), sig->r,
1065                                   (int)sizeof (sig->s), sig->s)))
1066   {
1067     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1068     return GNUNET_SYSERR;
1069   }
1070   data = data_to_eddsa_value (validate);
1071   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1072                                   "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1073                                   (int)sizeof (pub->q_y), pub->q_y)))
1074   {
1075     gcry_sexp_release (data);
1076     gcry_sexp_release (sig_sexpr);
1077     return GNUNET_SYSERR;
1078   }
1079   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1080   gcry_sexp_release (pub_sexpr);
1081   gcry_sexp_release (data);
1082   gcry_sexp_release (sig_sexpr);
1083   if (0 != rc)
1084   {
1085     LOG (GNUNET_ERROR_TYPE_INFO,
1086          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1087          __LINE__, gcry_strerror (rc));
1088     BENCHMARK_END (eddsa_verify);
1089     return GNUNET_SYSERR;
1090   }
1091   BENCHMARK_END (eddsa_verify);
1092   return GNUNET_OK;
1093 }
1094
1095
1096 /**
1097  * Derive key material from a public and a private ECDHE key.
1098  *
1099  * @param priv private key to use for the ECDH (x)
1100  * @param pub public key to use for the ECDH (yG)
1101  * @param key_material where to write the key material (xyG)
1102  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1103  */
1104 int
1105 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1106                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1107                         struct GNUNET_HashCode *key_material)
1108 {
1109   gcry_mpi_point_t result;
1110   gcry_mpi_point_t q;
1111   gcry_mpi_t d;
1112   gcry_ctx_t ctx;
1113   gcry_sexp_t pub_sexpr;
1114   gcry_mpi_t result_x;
1115   unsigned char xbuf[256 / 8];
1116   size_t rsize;
1117
1118   BENCHMARK_START (ecc_ecdh);
1119
1120   /* first, extract the q = dP value from the public key */
1121   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1122                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1123                             (int)sizeof (pub->q_y), pub->q_y))
1124     return GNUNET_SYSERR;
1125   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1126   gcry_sexp_release (pub_sexpr);
1127   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1128
1129   /* second, extract the d value from our private key */
1130   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1131
1132   /* then call the 'multiply' function, to compute the product */
1133   result = gcry_mpi_point_new (0);
1134   gcry_mpi_ec_mul (result, d, q, ctx);
1135   gcry_mpi_point_release (q);
1136   gcry_mpi_release (d);
1137
1138   /* finally, convert point to string for hashing */
1139   result_x = gcry_mpi_new (256);
1140   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1141   {
1142     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1143     gcry_mpi_point_release (result);
1144     gcry_ctx_release (ctx);
1145     return GNUNET_SYSERR;
1146   }
1147   gcry_mpi_point_release (result);
1148   gcry_ctx_release (ctx);
1149
1150   rsize = sizeof (xbuf);
1151   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1152   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1153      as that does not include the sign bit; x should be a 255-bit
1154      value, so with the sign it should fit snugly into the 256-bit
1155      xbuf */
1156   GNUNET_assert (0 ==
1157                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1158                                  result_x));
1159   GNUNET_CRYPTO_hash (xbuf,
1160                       rsize,
1161                       key_material);
1162   gcry_mpi_release (result_x);
1163   BENCHMARK_END (ecc_ecdh);
1164   return GNUNET_OK;
1165 }
1166
1167
1168 /**
1169  * Derive the 'h' value for key derivation, where
1170  * 'h = H(l,P)'.
1171  *
1172  * @param pub public key for deriviation
1173  * @param label label for deriviation
1174  * @param context additional context to use for HKDF of 'h';
1175  *        typically the name of the subsystem/application
1176  * @return h value
1177  */
1178 static gcry_mpi_t
1179 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1180           const char *label,
1181           const char *context)
1182 {
1183   gcry_mpi_t h;
1184   struct GNUNET_HashCode hc;
1185   static const char *const salt = "key-derivation";
1186
1187   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1188                      salt, strlen (salt),
1189                      pub, sizeof (*pub),
1190                      label, strlen (label),
1191                      context, strlen (context),
1192                      NULL, 0);
1193   GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1194                                    (unsigned char *) &hc,
1195                                    sizeof (hc));
1196   return h;
1197 }
1198
1199
1200 /**
1201  * Derive a private key from a given private key and a label.
1202  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1203  * where n is the size of the ECC group and P is the public
1204  * key associated with the private key 'd'.
1205  *
1206  * @param priv original private key
1207  * @param label label to use for key deriviation
1208  * @param context additional context to use for HKDF of 'h';
1209  *        typically the name of the subsystem/application
1210  * @return derived private key
1211  */
1212 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1213 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1214                                         const char *label,
1215                                         const char *context)
1216 {
1217   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1218   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1219   gcry_mpi_t h;
1220   gcry_mpi_t x;
1221   gcry_mpi_t d;
1222   gcry_mpi_t n;
1223   gcry_ctx_t ctx;
1224
1225   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1226
1227   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1228   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1229
1230   h = derive_h (&pub, label, context);
1231   GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1232                                    priv->d,
1233                                    sizeof (priv->d));
1234   d = gcry_mpi_new (256);
1235   gcry_mpi_mulm (d, h, x, n);
1236   gcry_mpi_release (h);
1237   gcry_mpi_release (x);
1238   gcry_mpi_release (n);
1239   gcry_ctx_release (ctx);
1240   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1241   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1242   gcry_mpi_release (d);
1243   return ret;
1244 }
1245
1246
1247 /**
1248  * Derive a public key from a given public key and a label.
1249  * Essentially calculates a public key 'V = H(l,P) * P'.
1250  *
1251  * @param pub original public key
1252  * @param label label to use for key derivation
1253  * @param context additional context to use for HKDF of 'h';
1254  *        typically the name of the subsystem/application
1255  * @param result where to write the derived public key
1256  */
1257 void
1258 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1259                                        const char *label,
1260                                        const char *context,
1261                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1262 {
1263   gcry_ctx_t ctx;
1264   gcry_mpi_t q_y;
1265   gcry_mpi_t h;
1266   gcry_mpi_t n;
1267   gcry_mpi_t h_mod_n;
1268   gcry_mpi_point_t q;
1269   gcry_mpi_point_t v;
1270
1271   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1272
1273   /* obtain point 'q' from original public key.  The provided 'q' is
1274      compressed thus we first store it in the context and then get it
1275      back as a (decompresssed) point.  */
1276   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1277   GNUNET_assert (NULL != q_y);
1278   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1279   gcry_mpi_release (q_y);
1280   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1281   GNUNET_assert (q);
1282
1283   /* calculate h_mod_n = h % n */
1284   h = derive_h (pub, label, context);
1285   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1286   h_mod_n = gcry_mpi_new (256);
1287   gcry_mpi_mod (h_mod_n, h, n);
1288   /* calculate v = h_mod_n * q */
1289   v = gcry_mpi_point_new (0);
1290   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1291   gcry_mpi_release (h_mod_n);
1292   gcry_mpi_release (h);
1293   gcry_mpi_release (n);
1294   gcry_mpi_point_release (q);
1295
1296   /* convert point 'v' to public key that we return */
1297   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1298   gcry_mpi_point_release (v);
1299   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1300   GNUNET_assert (q_y);
1301   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1302                                     sizeof (result->q_y),
1303                                     q_y);
1304   gcry_mpi_release (q_y);
1305   gcry_ctx_release (ctx);
1306 }
1307
1308
1309 /**
1310  * Reverse the sequence of the bytes in @a buffer
1311  *
1312  * @param[in|out] buffer buffer to invert
1313  * @param length number of bytes in @a buffer
1314  */
1315 static void
1316 reverse_buffer (unsigned char *buffer,
1317                 size_t length)
1318 {
1319   unsigned char tmp;
1320   size_t i;
1321
1322   for (i=0; i < length/2; i++)
1323   {
1324     tmp = buffer[i];
1325     buffer[i] = buffer[length-1-i];
1326     buffer[length-1-i] = tmp;
1327   }
1328 }
1329
1330
1331 /**
1332  * Convert the secret @a d of an EdDSA key to the
1333  * value that is actually used in the EdDSA computation.
1334  *
1335  * @param d secret input
1336  * @return value used for the calculation in EdDSA
1337  */
1338 static gcry_mpi_t
1339 eddsa_d_to_a (gcry_mpi_t d)
1340 {
1341   unsigned char rawmpi[32]; /* 256-bit value */
1342   size_t rawmpilen;
1343   unsigned char digest[64]; /* 512-bit hash value */
1344   gcry_buffer_t hvec[2];
1345   unsigned int b;
1346   gcry_mpi_t a;
1347
1348   b = 256 / 8; /* number of bytes in `d` */
1349
1350   /* Note that we clear DIGEST so we can use it as input to left pad
1351      the key with zeroes for hashing.  */
1352   memset (digest, 0, sizeof digest);
1353   memset (hvec, 0, sizeof hvec);
1354   rawmpilen = sizeof (rawmpi);
1355   GNUNET_assert (0 ==
1356                  gcry_mpi_print (GCRYMPI_FMT_USG,
1357                                  rawmpi, rawmpilen, &rawmpilen,
1358                                  d));
1359   hvec[0].data = digest;
1360   hvec[0].off = 0;
1361   hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1362   hvec[1].data = rawmpi;
1363   hvec[1].off = 0;
1364   hvec[1].len = rawmpilen;
1365   GNUNET_assert (0 ==
1366                  gcry_md_hash_buffers (GCRY_MD_SHA512,
1367                                        0 /* flags */,
1368                                        digest,
1369                                        hvec, 2));
1370   /* Compute the A value.  */
1371   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
1372   digest[0]   = (digest[0] & 0x7f) | 0x40;
1373   digest[31] &= 0xf8;
1374
1375   GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1376                                    digest,
1377                                    32);
1378   return a;
1379 }
1380
1381
1382 /**
1383  * Take point from ECDH and convert it to key material.
1384  *
1385  * @param result point from ECDH
1386  * @param ctx ECC context
1387  * @param key_material[out] set to derived key material
1388  * @return #GNUNET_OK on success
1389  */
1390 static int
1391 point_to_hash (gcry_mpi_point_t result,
1392                gcry_ctx_t ctx,
1393                struct GNUNET_HashCode *key_material)
1394 {
1395   gcry_mpi_t result_x;
1396   unsigned char xbuf[256 / 8];
1397   size_t rsize;
1398
1399   /* finally, convert point to string for hashing */
1400   result_x = gcry_mpi_new (256);
1401   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1402   {
1403     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1404     return GNUNET_SYSERR;
1405   }
1406
1407   rsize = sizeof (xbuf);
1408   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1409   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1410      as that does not include the sign bit; x should be a 255-bit
1411      value, so with the sign it should fit snugly into the 256-bit
1412      xbuf */
1413   GNUNET_assert (0 ==
1414                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1415                                  result_x));
1416   GNUNET_CRYPTO_hash (xbuf,
1417                       rsize,
1418                       key_material);
1419   gcry_mpi_release (result_x);
1420   return GNUNET_OK;
1421 }
1422
1423
1424 /**
1425  * @ingroup crypto
1426  * Derive key material from a ECDH public key and a private EdDSA key.
1427  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1428  *
1429  * @param priv private key from EdDSA to use for the ECDH (x)
1430  * @param pub public key to use for the ECDH (yG)
1431  * @param key_material where to write the key material H(h(x)yG)
1432  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1433  */
1434 int
1435 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1436                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1437                           struct GNUNET_HashCode *key_material)
1438 {
1439   gcry_mpi_point_t result;
1440   gcry_mpi_point_t q;
1441   gcry_mpi_t d;
1442   gcry_mpi_t a;
1443   gcry_ctx_t ctx;
1444   gcry_sexp_t pub_sexpr;
1445   int ret;
1446
1447   BENCHMARK_START (eddsa_ecdh);
1448
1449   /* first, extract the q = dP value from the public key */
1450   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1451                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1452                             (int)sizeof (pub->q_y), pub->q_y))
1453     return GNUNET_SYSERR;
1454   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1455   gcry_sexp_release (pub_sexpr);
1456   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1457
1458   /* second, extract the d value from our private key */
1459   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1460
1461   /* NOW, because this is EdDSA, HASH 'd' first! */
1462   a = eddsa_d_to_a (d);
1463   gcry_mpi_release (d);
1464
1465   /* then call the 'multiply' function, to compute the product */
1466   result = gcry_mpi_point_new (0);
1467   gcry_mpi_ec_mul (result, a, q, ctx);
1468   gcry_mpi_point_release (q);
1469   gcry_mpi_release (a);
1470
1471   ret = point_to_hash (result,
1472                        ctx,
1473                        key_material);
1474   gcry_mpi_point_release (result);
1475   gcry_ctx_release (ctx);
1476   BENCHMARK_END (eddsa_ecdh);
1477   return ret;
1478 }
1479
1480
1481 /**
1482  * @ingroup crypto
1483  * Derive key material from a ECDH public key and a private ECDSA key.
1484  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1485  *
1486  * @param priv private key from ECDSA to use for the ECDH (x)
1487  * @param pub public key to use for the ECDH (yG)
1488  * @param key_material where to write the key material H(h(x)yG)
1489  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1490  */
1491 int
1492 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1493                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1494                           struct GNUNET_HashCode *key_material)
1495 {
1496   gcry_mpi_point_t result;
1497   gcry_mpi_point_t q;
1498   gcry_mpi_t d;
1499   gcry_ctx_t ctx;
1500   gcry_sexp_t pub_sexpr;
1501   int ret;
1502
1503   BENCHMARK_START (ecdsa_ecdh);
1504
1505   /* first, extract the q = dP value from the public key */
1506   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1507                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1508                             (int)sizeof (pub->q_y), pub->q_y))
1509     return GNUNET_SYSERR;
1510   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1511   gcry_sexp_release (pub_sexpr);
1512   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1513
1514   /* second, extract the d value from our private key */
1515   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1516
1517   /* then call the 'multiply' function, to compute the product */
1518   result = gcry_mpi_point_new (0);
1519   gcry_mpi_ec_mul (result, d, q, ctx);
1520   gcry_mpi_point_release (q);
1521   gcry_mpi_release (d);
1522
1523   /* finally, convert point to string for hashing */
1524   ret = point_to_hash (result,
1525                        ctx,
1526                        key_material);
1527   gcry_mpi_point_release (result);
1528   gcry_ctx_release (ctx);
1529   BENCHMARK_END (ecdsa_ecdh);
1530   return ret;
1531 }
1532
1533
1534
1535 /**
1536  * @ingroup crypto
1537  * Derive key material from a EdDSA public key and a private ECDH key.
1538  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1539  *
1540  * @param priv private key to use for the ECDH (y)
1541  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1542  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1543  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1544  */
1545 int
1546 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1547                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1548                           struct GNUNET_HashCode *key_material)
1549 {
1550   gcry_mpi_point_t result;
1551   gcry_mpi_point_t q;
1552   gcry_mpi_t d;
1553   gcry_ctx_t ctx;
1554   gcry_sexp_t pub_sexpr;
1555   int ret;
1556
1557   BENCHMARK_START (ecdh_eddsa);
1558
1559   /* first, extract the q = dP value from the public key */
1560   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1561                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1562                             (int)sizeof (pub->q_y), pub->q_y))
1563     return GNUNET_SYSERR;
1564   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1565   gcry_sexp_release (pub_sexpr);
1566   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1567
1568   /* second, extract the d value from our private key */
1569   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1570
1571   /* then call the 'multiply' function, to compute the product */
1572   result = gcry_mpi_point_new (0);
1573   gcry_mpi_ec_mul (result, d, q, ctx);
1574   gcry_mpi_point_release (q);
1575   gcry_mpi_release (d);
1576
1577   /* finally, convert point to string for hashing */
1578   ret = point_to_hash (result,
1579                        ctx,
1580                        key_material);
1581   gcry_mpi_point_release (result);
1582   gcry_ctx_release (ctx);
1583   BENCHMARK_END (ecdh_eddsa);
1584   return ret;
1585 }
1586
1587 /**
1588  * @ingroup crypto
1589  * Derive key material from a ECDSA public key and a private ECDH key.
1590  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1591  *
1592  * @param priv private key to use for the ECDH (y)
1593  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1594  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1595  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1596  */
1597 int
1598 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1599                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1600                           struct GNUNET_HashCode *key_material)
1601 {
1602   return GNUNET_CRYPTO_ecdh_eddsa (priv,
1603                                    (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1604                                    key_material);
1605 }
1606
1607 /* end of crypto_ecc.c */