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