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