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