geq redefinition breaks texi2pdf, instead just avoid @geq
[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 #if 1
796   struct GNUNET_HashCode hc;
797   
798   GNUNET_CRYPTO_hash (purpose,
799                       ntohl (purpose->size),
800                       &hc);
801   if (0 != (rc = gcry_sexp_build (&data, NULL,
802                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
803                                   "sha512",
804                                   (int)sizeof (hc),
805                                   &hc)))
806   {
807     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
808               "gcry_sexp_build",
809               rc);
810     return NULL;
811   }
812 #else
813   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
814   if (0 != (rc = gcry_sexp_build (&data, NULL,
815                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
816                                   "sha512",
817                                   ntohl (purpose->size),
818                                   purpose)))
819   {
820     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
821               "gcry_sexp_build",
822               rc);
823     return NULL;
824   }
825 #endif    
826   return data;
827 }
828
829
830 /**
831  * Convert the data specified in the given purpose argument to an
832  * S-expression suitable for signature operations.
833  *
834  * @param purpose data to convert
835  * @return converted s-expression
836  */
837 static gcry_sexp_t
838 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
839 {
840   gcry_sexp_t data;
841   int rc;
842
843 #if 1
844   struct GNUNET_HashCode hc;
845
846   GNUNET_CRYPTO_hash (purpose,
847                       ntohl (purpose->size),
848                       &hc);
849   if (0 != (rc = gcry_sexp_build (&data, NULL,
850                                   "(data(flags rfc6979)(hash %s %b))",
851                                   "sha512",
852                                   (int)sizeof (hc), &hc)))
853   {
854     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
855               "gcry_sexp_build",
856               rc);
857     return NULL;
858   }
859 #else
860   if (0 != (rc = gcry_sexp_build (&data, NULL,
861                                   "(data(flags rfc6979)(hash %s %b))",
862                                   "sha512",
863                                   ntohl (purpose->size),
864                                   purpose)))
865   {
866     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
867               "gcry_sexp_build",
868               rc);
869     return NULL;
870   }
871 #endif
872   return data;
873 }
874
875
876 /**
877  * Sign a given block.
878  *
879  * @param priv private key to use for the signing
880  * @param purpose what to sign (size, purpose)
881  * @param sig where to write the signature
882  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
883  */
884 int
885 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
886                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
887                           struct GNUNET_CRYPTO_EcdsaSignature *sig)
888 {
889   gcry_sexp_t priv_sexp;
890   gcry_sexp_t sig_sexp;
891   gcry_sexp_t data;
892   int rc;
893   gcry_mpi_t rs[2];
894
895   BENCHMARK_START (ecdsa_sign);
896
897   priv_sexp = decode_private_ecdsa_key (priv);
898   data = data_to_ecdsa_value (purpose);
899   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
900   {
901     LOG (GNUNET_ERROR_TYPE_WARNING,
902          _("ECC signing failed at %s:%d: %s\n"), __FILE__,
903          __LINE__, gcry_strerror (rc));
904     gcry_sexp_release (data);
905     gcry_sexp_release (priv_sexp);
906     return GNUNET_SYSERR;
907   }
908   gcry_sexp_release (priv_sexp);
909   gcry_sexp_release (data);
910
911   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
912      'signature' */
913   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
914   {
915     GNUNET_break (0);
916     gcry_sexp_release (sig_sexp);
917     return GNUNET_SYSERR;
918   }
919   gcry_sexp_release (sig_sexp);
920   GNUNET_CRYPTO_mpi_print_unsigned (sig->r,
921                                     sizeof (sig->r),
922                                     rs[0]);
923   GNUNET_CRYPTO_mpi_print_unsigned (sig->s,
924                                     sizeof (sig->s),
925                                     rs[1]);
926   gcry_mpi_release (rs[0]);
927   gcry_mpi_release (rs[1]);
928
929   BENCHMARK_END (ecdsa_sign);
930
931   return GNUNET_OK;
932 }
933
934
935 /**
936  * Sign a given block.
937  *
938  * @param priv private key to use for the signing
939  * @param purpose what to sign (size, purpose)
940  * @param sig where to write the signature
941  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
942  */
943 int
944 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
945                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
946                           struct GNUNET_CRYPTO_EddsaSignature *sig)
947 {
948   gcry_sexp_t priv_sexp;
949   gcry_sexp_t sig_sexp;
950   gcry_sexp_t data;
951   int rc;
952   gcry_mpi_t rs[2];
953
954   BENCHMARK_START (eddsa_sign);
955
956   priv_sexp = decode_private_eddsa_key (priv);
957   data = data_to_eddsa_value (purpose);
958   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
959   {
960     LOG (GNUNET_ERROR_TYPE_WARNING,
961          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
962          __LINE__, gcry_strerror (rc));
963     gcry_sexp_release (data);
964     gcry_sexp_release (priv_sexp);
965     return GNUNET_SYSERR;
966   }
967   gcry_sexp_release (priv_sexp);
968   gcry_sexp_release (data);
969
970   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
971      'signature' */
972   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
973   {
974     GNUNET_break (0);
975     gcry_sexp_release (sig_sexp);
976     return GNUNET_SYSERR;
977   }
978   gcry_sexp_release (sig_sexp);
979   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
980   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
981   gcry_mpi_release (rs[0]);
982   gcry_mpi_release (rs[1]);
983
984   BENCHMARK_END (eddsa_sign);
985
986   return GNUNET_OK;
987 }
988
989
990 /**
991  * Verify signature.
992  *
993  * @param purpose what is the purpose that the signature should have?
994  * @param validate block to validate (size, purpose, data)
995  * @param sig signature that is being validated
996  * @param pub public key of the signer
997  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
998  */
999 int
1000 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1001                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1002                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1003                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1004 {
1005   gcry_sexp_t data;
1006   gcry_sexp_t sig_sexpr;
1007   gcry_sexp_t pub_sexpr;
1008   int rc;
1009
1010   BENCHMARK_START (ecdsa_verify);
1011
1012   if (purpose != ntohl (validate->purpose))
1013     return GNUNET_SYSERR;       /* purpose mismatch */
1014
1015   /* build s-expression for signature */
1016   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1017                                   "(sig-val(ecdsa(r %b)(s %b)))",
1018                                   (int) sizeof (sig->r), sig->r,
1019                                   (int) sizeof (sig->s), sig->s)))
1020   {
1021     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1022     return GNUNET_SYSERR;
1023   }
1024   data = data_to_ecdsa_value (validate);
1025   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1026                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
1027                                   (int) sizeof (pub->q_y), pub->q_y)))
1028   {
1029     gcry_sexp_release (data);
1030     gcry_sexp_release (sig_sexpr);
1031     return GNUNET_SYSERR;
1032   }
1033   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1034   gcry_sexp_release (pub_sexpr);
1035   gcry_sexp_release (data);
1036   gcry_sexp_release (sig_sexpr);
1037   if (0 != rc)
1038   {
1039     LOG (GNUNET_ERROR_TYPE_INFO,
1040          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1041          __LINE__, gcry_strerror (rc));
1042     BENCHMARK_END (ecdsa_verify);
1043     return GNUNET_SYSERR;
1044   }
1045   BENCHMARK_END (ecdsa_verify);
1046   return GNUNET_OK;
1047 }
1048
1049
1050
1051 /**
1052  * Verify signature.
1053  *
1054  * @param purpose what is the purpose that the signature should have?
1055  * @param validate block to validate (size, purpose, data)
1056  * @param sig signature that is being validated
1057  * @param pub public key of the signer
1058  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1059  */
1060 int
1061 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1062                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1063                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
1064                             const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1065 {
1066   gcry_sexp_t data;
1067   gcry_sexp_t sig_sexpr;
1068   gcry_sexp_t pub_sexpr;
1069   int rc;
1070
1071   BENCHMARK_START (eddsa_verify);
1072
1073   if (purpose != ntohl (validate->purpose))
1074     return GNUNET_SYSERR;       /* purpose mismatch */
1075
1076   /* build s-expression for signature */
1077   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1078                                   "(sig-val(eddsa(r %b)(s %b)))",
1079                                   (int)sizeof (sig->r), sig->r,
1080                                   (int)sizeof (sig->s), sig->s)))
1081   {
1082     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1083     return GNUNET_SYSERR;
1084   }
1085   data = data_to_eddsa_value (validate);
1086   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1087                                   "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1088                                   (int)sizeof (pub->q_y), pub->q_y)))
1089   {
1090     gcry_sexp_release (data);
1091     gcry_sexp_release (sig_sexpr);
1092     return GNUNET_SYSERR;
1093   }
1094   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1095   gcry_sexp_release (pub_sexpr);
1096   gcry_sexp_release (data);
1097   gcry_sexp_release (sig_sexpr);
1098   if (0 != rc)
1099   {
1100     LOG (GNUNET_ERROR_TYPE_INFO,
1101          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1102          __LINE__, gcry_strerror (rc));
1103     BENCHMARK_END (eddsa_verify);
1104     return GNUNET_SYSERR;
1105   }
1106   BENCHMARK_END (eddsa_verify);
1107   return GNUNET_OK;
1108 }
1109
1110
1111 /**
1112  * Derive key material from a public and a private ECDHE key.
1113  *
1114  * @param priv private key to use for the ECDH (x)
1115  * @param pub public key to use for the ECDH (yG)
1116  * @param key_material where to write the key material (xyG)
1117  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1118  */
1119 int
1120 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1121                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1122                         struct GNUNET_HashCode *key_material)
1123 {
1124   gcry_mpi_point_t result;
1125   gcry_mpi_point_t q;
1126   gcry_mpi_t d;
1127   gcry_ctx_t ctx;
1128   gcry_sexp_t pub_sexpr;
1129   gcry_mpi_t result_x;
1130   unsigned char xbuf[256 / 8];
1131   size_t rsize;
1132
1133   BENCHMARK_START (ecc_ecdh);
1134
1135   /* first, extract the q = dP value from the public key */
1136   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1137                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1138                             (int)sizeof (pub->q_y), pub->q_y))
1139     return GNUNET_SYSERR;
1140   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1141   gcry_sexp_release (pub_sexpr);
1142   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1143
1144   /* second, extract the d value from our private key */
1145   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1146
1147   /* then call the 'multiply' function, to compute the product */
1148   result = gcry_mpi_point_new (0);
1149   gcry_mpi_ec_mul (result, d, q, ctx);
1150   gcry_mpi_point_release (q);
1151   gcry_mpi_release (d);
1152
1153   /* finally, convert point to string for hashing */
1154   result_x = gcry_mpi_new (256);
1155   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1156   {
1157     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1158     gcry_mpi_point_release (result);
1159     gcry_ctx_release (ctx);
1160     return GNUNET_SYSERR;
1161   }
1162   gcry_mpi_point_release (result);
1163   gcry_ctx_release (ctx);
1164
1165   rsize = sizeof (xbuf);
1166   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1167   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1168      as that does not include the sign bit; x should be a 255-bit
1169      value, so with the sign it should fit snugly into the 256-bit
1170      xbuf */
1171   GNUNET_assert (0 ==
1172                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1173                                  result_x));
1174   GNUNET_CRYPTO_hash (xbuf,
1175                       rsize,
1176                       key_material);
1177   gcry_mpi_release (result_x);
1178   BENCHMARK_END (ecc_ecdh);
1179   return GNUNET_OK;
1180 }
1181
1182
1183 /**
1184  * Derive the 'h' value for key derivation, where
1185  * 'h = H(l,P)'.
1186  *
1187  * @param pub public key for deriviation
1188  * @param label label for deriviation
1189  * @param context additional context to use for HKDF of 'h';
1190  *        typically the name of the subsystem/application
1191  * @return h value
1192  */
1193 static gcry_mpi_t
1194 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1195           const char *label,
1196           const char *context)
1197 {
1198   gcry_mpi_t h;
1199   struct GNUNET_HashCode hc;
1200   static const char *const salt = "key-derivation";
1201
1202   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1203                      salt, strlen (salt),
1204                      pub, sizeof (*pub),
1205                      label, strlen (label),
1206                      context, strlen (context),
1207                      NULL, 0);
1208   GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1209                                    (unsigned char *) &hc,
1210                                    sizeof (hc));
1211   return h;
1212 }
1213
1214
1215 /**
1216  * Derive a private key from a given private key and a label.
1217  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1218  * where n is the size of the ECC group and P is the public
1219  * key associated with the private key 'd'.
1220  *
1221  * @param priv original private key
1222  * @param label label to use for key deriviation
1223  * @param context additional context to use for HKDF of 'h';
1224  *        typically the name of the subsystem/application
1225  * @return derived private key
1226  */
1227 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1228 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1229                                         const char *label,
1230                                         const char *context)
1231 {
1232   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1233   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1234   gcry_mpi_t h;
1235   gcry_mpi_t x;
1236   gcry_mpi_t d;
1237   gcry_mpi_t n;
1238   gcry_ctx_t ctx;
1239
1240   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1241
1242   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1243   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1244
1245   h = derive_h (&pub, label, context);
1246   GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1247                                    priv->d,
1248                                    sizeof (priv->d));
1249   d = gcry_mpi_new (256);
1250   gcry_mpi_mulm (d, h, x, n);
1251   gcry_mpi_release (h);
1252   gcry_mpi_release (x);
1253   gcry_mpi_release (n);
1254   gcry_ctx_release (ctx);
1255   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1256   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1257   gcry_mpi_release (d);
1258   return ret;
1259 }
1260
1261
1262 /**
1263  * Derive a public key from a given public key and a label.
1264  * Essentially calculates a public key 'V = H(l,P) * P'.
1265  *
1266  * @param pub original public key
1267  * @param label label to use for key derivation
1268  * @param context additional context to use for HKDF of 'h';
1269  *        typically the name of the subsystem/application
1270  * @param result where to write the derived public key
1271  */
1272 void
1273 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1274                                        const char *label,
1275                                        const char *context,
1276                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1277 {
1278   gcry_ctx_t ctx;
1279   gcry_mpi_t q_y;
1280   gcry_mpi_t h;
1281   gcry_mpi_t n;
1282   gcry_mpi_t h_mod_n;
1283   gcry_mpi_point_t q;
1284   gcry_mpi_point_t v;
1285
1286   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1287
1288   /* obtain point 'q' from original public key.  The provided 'q' is
1289      compressed thus we first store it in the context and then get it
1290      back as a (decompresssed) point.  */
1291   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1292   GNUNET_assert (NULL != q_y);
1293   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1294   gcry_mpi_release (q_y);
1295   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1296   GNUNET_assert (q);
1297
1298   /* calculate h_mod_n = h % n */
1299   h = derive_h (pub, label, context);
1300   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1301   h_mod_n = gcry_mpi_new (256);
1302   gcry_mpi_mod (h_mod_n, h, n);
1303   /* calculate v = h_mod_n * q */
1304   v = gcry_mpi_point_new (0);
1305   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1306   gcry_mpi_release (h_mod_n);
1307   gcry_mpi_release (h);
1308   gcry_mpi_release (n);
1309   gcry_mpi_point_release (q);
1310
1311   /* convert point 'v' to public key that we return */
1312   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1313   gcry_mpi_point_release (v);
1314   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1315   GNUNET_assert (q_y);
1316   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1317                                     sizeof (result->q_y),
1318                                     q_y);
1319   gcry_mpi_release (q_y);
1320   gcry_ctx_release (ctx);
1321 }
1322
1323
1324 /**
1325  * Reverse the sequence of the bytes in @a buffer
1326  *
1327  * @param[in|out] buffer buffer to invert
1328  * @param length number of bytes in @a buffer
1329  */
1330 static void
1331 reverse_buffer (unsigned char *buffer,
1332                 size_t length)
1333 {
1334   unsigned char tmp;
1335   size_t i;
1336
1337   for (i=0; i < length/2; i++)
1338   {
1339     tmp = buffer[i];
1340     buffer[i] = buffer[length-1-i];
1341     buffer[length-1-i] = tmp;
1342   }
1343 }
1344
1345
1346 /**
1347  * Convert the secret @a d of an EdDSA key to the
1348  * value that is actually used in the EdDSA computation.
1349  *
1350  * @param d secret input
1351  * @return value used for the calculation in EdDSA
1352  */
1353 static gcry_mpi_t
1354 eddsa_d_to_a (gcry_mpi_t d)
1355 {
1356   unsigned char rawmpi[32]; /* 256-bit value */
1357   size_t rawmpilen;
1358   unsigned char digest[64]; /* 512-bit hash value */
1359   gcry_buffer_t hvec[2];
1360   unsigned int b;
1361   gcry_mpi_t a;
1362
1363   b = 256 / 8; /* number of bytes in `d` */
1364
1365   /* Note that we clear DIGEST so we can use it as input to left pad
1366      the key with zeroes for hashing.  */
1367   memset (digest, 0, sizeof digest);
1368   memset (hvec, 0, sizeof hvec);
1369   rawmpilen = sizeof (rawmpi);
1370   GNUNET_assert (0 ==
1371                  gcry_mpi_print (GCRYMPI_FMT_USG,
1372                                  rawmpi, rawmpilen, &rawmpilen,
1373                                  d));
1374   hvec[0].data = digest;
1375   hvec[0].off = 0;
1376   hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1377   hvec[1].data = rawmpi;
1378   hvec[1].off = 0;
1379   hvec[1].len = rawmpilen;
1380   GNUNET_assert (0 ==
1381                  gcry_md_hash_buffers (GCRY_MD_SHA512,
1382                                        0 /* flags */,
1383                                        digest,
1384                                        hvec, 2));
1385   /* Compute the A value.  */
1386   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
1387   digest[0]   = (digest[0] & 0x7f) | 0x40;
1388   digest[31] &= 0xf8;
1389
1390   GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1391                                    digest,
1392                                    32);
1393   return a;
1394 }
1395
1396
1397 /**
1398  * Take point from ECDH and convert it to key material.
1399  *
1400  * @param result point from ECDH
1401  * @param ctx ECC context
1402  * @param key_material[out] set to derived key material
1403  * @return #GNUNET_OK on success
1404  */
1405 static int
1406 point_to_hash (gcry_mpi_point_t result,
1407                gcry_ctx_t ctx,
1408                struct GNUNET_HashCode *key_material)
1409 {
1410   gcry_mpi_t result_x;
1411   unsigned char xbuf[256 / 8];
1412   size_t rsize;
1413
1414   /* finally, convert point to string for hashing */
1415   result_x = gcry_mpi_new (256);
1416   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1417   {
1418     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1419     return GNUNET_SYSERR;
1420   }
1421
1422   rsize = sizeof (xbuf);
1423   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1424   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1425      as that does not include the sign bit; x should be a 255-bit
1426      value, so with the sign it should fit snugly into the 256-bit
1427      xbuf */
1428   GNUNET_assert (0 ==
1429                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1430                                  result_x));
1431   GNUNET_CRYPTO_hash (xbuf,
1432                       rsize,
1433                       key_material);
1434   gcry_mpi_release (result_x);
1435   return GNUNET_OK;
1436 }
1437
1438
1439 /**
1440  * @ingroup crypto
1441  * Derive key material from a ECDH public key and a private EdDSA key.
1442  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1443  *
1444  * @param priv private key from EdDSA to use for the ECDH (x)
1445  * @param pub public key to use for the ECDH (yG)
1446  * @param key_material where to write the key material H(h(x)yG)
1447  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1448  */
1449 int
1450 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1451                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1452                           struct GNUNET_HashCode *key_material)
1453 {
1454   gcry_mpi_point_t result;
1455   gcry_mpi_point_t q;
1456   gcry_mpi_t d;
1457   gcry_mpi_t a;
1458   gcry_ctx_t ctx;
1459   gcry_sexp_t pub_sexpr;
1460   int ret;
1461
1462   BENCHMARK_START (eddsa_ecdh);
1463
1464   /* first, extract the q = dP value from the public key */
1465   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1466                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1467                             (int)sizeof (pub->q_y), pub->q_y))
1468     return GNUNET_SYSERR;
1469   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1470   gcry_sexp_release (pub_sexpr);
1471   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1472
1473   /* second, extract the d value from our private key */
1474   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1475
1476   /* NOW, because this is EdDSA, HASH 'd' first! */
1477   a = eddsa_d_to_a (d);
1478   gcry_mpi_release (d);
1479
1480   /* then call the 'multiply' function, to compute the product */
1481   result = gcry_mpi_point_new (0);
1482   gcry_mpi_ec_mul (result, a, q, ctx);
1483   gcry_mpi_point_release (q);
1484   gcry_mpi_release (a);
1485
1486   ret = point_to_hash (result,
1487                        ctx,
1488                        key_material);
1489   gcry_mpi_point_release (result);
1490   gcry_ctx_release (ctx);
1491   BENCHMARK_END (eddsa_ecdh);
1492   return ret;
1493 }
1494
1495
1496 /**
1497  * @ingroup crypto
1498  * Derive key material from a ECDH public key and a private ECDSA key.
1499  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1500  *
1501  * @param priv private key from ECDSA to use for the ECDH (x)
1502  * @param pub public key to use for the ECDH (yG)
1503  * @param key_material where to write the key material H(h(x)yG)
1504  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1505  */
1506 int
1507 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1508                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1509                           struct GNUNET_HashCode *key_material)
1510 {
1511   gcry_mpi_point_t result;
1512   gcry_mpi_point_t q;
1513   gcry_mpi_t d;
1514   gcry_ctx_t ctx;
1515   gcry_sexp_t pub_sexpr;
1516   int ret;
1517
1518   BENCHMARK_START (ecdsa_ecdh);
1519
1520   /* first, extract the q = dP value from the public key */
1521   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1522                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1523                             (int)sizeof (pub->q_y), 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   /* then call the 'multiply' function, to compute the product */
1533   result = gcry_mpi_point_new (0);
1534   gcry_mpi_ec_mul (result, d, q, ctx);
1535   gcry_mpi_point_release (q);
1536   gcry_mpi_release (d);
1537
1538   /* finally, convert point to string for hashing */
1539   ret = point_to_hash (result,
1540                        ctx,
1541                        key_material);
1542   gcry_mpi_point_release (result);
1543   gcry_ctx_release (ctx);
1544   BENCHMARK_END (ecdsa_ecdh);
1545   return ret;
1546 }
1547
1548
1549
1550 /**
1551  * @ingroup crypto
1552  * Derive key material from a EdDSA public key and a private ECDH key.
1553  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1554  *
1555  * @param priv private key to use for the ECDH (y)
1556  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1557  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1558  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1559  */
1560 int
1561 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1562                           const struct GNUNET_CRYPTO_EddsaPublicKey *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 (ecdh_eddsa);
1573
1574   /* first, extract the q = dP value from the public key */
1575   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1576                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1577                             (int)sizeof (pub->q_y), pub->q_y))
1578     return GNUNET_SYSERR;
1579   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1580   gcry_sexp_release (pub_sexpr);
1581   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1582
1583   /* second, extract the d value from our private key */
1584   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1585
1586   /* then call the 'multiply' function, to compute the product */
1587   result = gcry_mpi_point_new (0);
1588   gcry_mpi_ec_mul (result, d, q, ctx);
1589   gcry_mpi_point_release (q);
1590   gcry_mpi_release (d);
1591
1592   /* finally, convert point to string for hashing */
1593   ret = point_to_hash (result,
1594                        ctx,
1595                        key_material);
1596   gcry_mpi_point_release (result);
1597   gcry_ctx_release (ctx);
1598   BENCHMARK_END (ecdh_eddsa);
1599   return ret;
1600 }
1601
1602 /**
1603  * @ingroup crypto
1604  * Derive key material from a ECDSA public key and a private ECDH key.
1605  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1606  *
1607  * @param priv private key to use for the ECDH (y)
1608  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1609  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1610  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1611  */
1612 int
1613 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1614                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1615                           struct GNUNET_HashCode *key_material)
1616 {
1617   return GNUNET_CRYPTO_ecdh_eddsa (priv,
1618                                    (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1619                                    key_material);
1620 }
1621
1622 /* end of crypto_ecc.c */