-fixes
[oweals/gnunet.git] / src / util / crypto_ecc.c
1 /*
2      This file is part of GNUnet.
3      (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
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_util_lib.h"
29
30 #define EXTRA_CHECKS ALLOW_EXTRA_CHECKS
31
32 /**
33  * Name of the curve we are using.  Note that we have hard-coded
34  * structs that use 256 bits, so using a bigger curve will require
35  * changes that break stuff badly.  The name of the curve given here
36  * must be agreed by all peers and be supported by libgcrypt.
37  *
38  * NOTE: this will change to Curve25519 before GNUnet 0.10.0.
39  */
40 #define CURVE "NIST P-256"
41
42 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
43
44 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
45
46 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", 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, gcry_sexp_t sexp, const char *topname,
67                const char *elems)
68 {
69   gcry_sexp_t list;
70   gcry_sexp_t l2;
71   const char *s;
72   unsigned int i;
73   unsigned int idx;
74
75   list = gcry_sexp_find_token (sexp, topname, 0);
76   if (! list)
77     return 1;
78   l2 = gcry_sexp_cadr (list);
79   gcry_sexp_release (list);
80   list = l2;
81   if (! list)
82     return 2;
83
84   idx = 0;
85   for (s = elems; *s; s++, idx++)
86   {
87     l2 = gcry_sexp_find_token (list, s, 1);
88     if (! l2)
89     {
90       for (i = 0; i < idx; i++)
91       {
92         gcry_free (array[i]);
93         array[i] = NULL;
94       }
95       gcry_sexp_release (list);
96       return 3;                 /* required parameter not found */
97     }
98     array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
99     gcry_sexp_release (l2);
100     if (! array[idx])
101     {
102       for (i = 0; i < idx; i++)
103       {
104         gcry_free (array[i]);
105         array[i] = NULL;
106       }
107       gcry_sexp_release (list);
108       return 4;                 /* required parameter is invalid */
109     }
110   }
111   gcry_sexp_release (list);
112   return 0;
113 }
114
115
116 /**
117  * If target != size, move @a target bytes to the end of the size-sized
118  * buffer and zero out the first @a target - @a size bytes.
119  *
120  * @param buf original buffer
121  * @param size number of bytes in @a buf
122  * @param target target size of the buffer
123  */
124 static void
125 adjust (unsigned char *buf,
126         size_t size,
127         size_t target)
128 {
129   if (size < target)
130   {
131     memmove (&buf[target - size], buf, size);
132     memset (buf, 0, target - size);
133   }
134 }
135
136
137 /**
138  * Output the given MPI value to the given buffer.
139  *
140  * @param buf where to output to
141  * @param size number of bytes in @a buf
142  * @param val value to write to @a buf
143  */
144 static void
145 mpi_print (unsigned char *buf,
146            size_t size,
147            gcry_mpi_t val)
148 {
149   size_t rsize;
150
151   rsize = size;
152   GNUNET_assert (0 ==
153                  gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize,
154                                  val));
155   adjust (buf, rsize, size);
156 }
157
158
159 /**
160  * Convert data buffer into MPI value.
161  *
162  * @param result where to store MPI value (allocated)
163  * @param data raw data (GCRYMPI_FMT_USG)
164  * @param size number of bytes in data
165  */
166 static void
167 mpi_scan (gcry_mpi_t *result,
168           const unsigned char *data,
169           size_t size)
170 {
171   int rc;
172
173   if (0 != (rc = gcry_mpi_scan (result,
174                                 GCRYMPI_FMT_USG,
175                                 data, size, &size)))
176   {
177     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
178     GNUNET_assert (0);
179   }
180 }
181
182
183 /**
184  * Convert the given private key from the network format to the
185  * S-expression that can be used by libgcrypt.
186  *
187  * @param priv private key to decode
188  * @return NULL on error
189  */
190 static gcry_sexp_t
191 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
192 {
193   gcry_sexp_t result;
194   gcry_mpi_t d;
195   int rc;
196
197   mpi_scan (&d,
198             priv->d,
199             sizeof (priv->d));
200   rc = gcry_sexp_build (&result, NULL,
201                         "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))",
202                         d);
203   gcry_mpi_release (d);
204   if (0 != rc)
205   {
206     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
207     GNUNET_assert (0);
208   }
209 #if EXTRA_CHECKS
210   if (0 != (rc = gcry_pk_testkey (result)))
211   {
212     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
213     GNUNET_assert (0);
214   }
215 #endif
216   return result;
217 }
218
219
220 /**
221  * Convert the given private key from the network format to the
222  * S-expression that can be used by libgcrypt.
223  *
224  * @param priv private key to decode
225  * @return NULL on error
226  */
227 static gcry_sexp_t
228 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
229 {
230   gcry_sexp_t result;
231   gcry_mpi_t d;
232   int rc;
233
234   mpi_scan (&d,
235             priv->d,
236             sizeof (priv->d));
237   rc = gcry_sexp_build (&result, NULL,
238                         "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))", // FIXME: eddsa soon!
239                         d);
240   gcry_mpi_release (d);
241   if (0 != rc)
242   {
243     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
244     GNUNET_assert (0);
245   }
246 #if EXTRA_CHECKS
247   if (0 != (rc = gcry_pk_testkey (result)))
248   {
249     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
250     GNUNET_assert (0);
251   }
252 #endif
253   return result;
254 }
255
256
257 /**
258  * Convert the given private key from the network format to the
259  * S-expression that can be used by libgcrypt.
260  *
261  * @param priv private key to decode
262  * @return NULL on error
263  */
264 static gcry_sexp_t
265 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
266 {
267   gcry_sexp_t result;
268   gcry_mpi_t d;
269   int rc;
270
271   mpi_scan (&d,
272             priv->d,
273             sizeof (priv->d));
274   rc = gcry_sexp_build (&result, NULL,
275                         "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))", // FIXME: ecdh here?
276                         d);
277   gcry_mpi_release (d);
278   if (0 != rc)
279   {
280     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
281     GNUNET_assert (0);
282   }
283 #if EXTRA_CHECKS
284   if (0 != (rc = gcry_pk_testkey (result)))
285   {
286     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
287     GNUNET_assert (0);
288   }
289 #endif
290   return result;
291 }
292
293
294 /**
295  * Initialize public key struct from the respective point
296  * on the curve.
297  *
298  * @param q point on curve
299  * @param pub public key struct to initialize
300  * @param ctx context to use for ECC operations
301  */
302 static void
303 point_to_public_ecdsa_key (gcry_mpi_point_t q,
304                            gcry_ctx_t ctx,
305                            struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
306 {
307   gcry_mpi_t q_x;
308   gcry_mpi_t q_y;
309
310   q_x = gcry_mpi_new (256);
311   q_y = gcry_mpi_new (256);
312   if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
313   {
314     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
315     return;
316   }
317
318   mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
319   mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
320   gcry_mpi_release (q_x);
321   gcry_mpi_release (q_y);
322 }
323
324
325 /**
326  * Initialize public key struct from the respective point
327  * on the curve.
328  *
329  * @param q point on curve
330  * @param pub public key struct to initialize
331  * @param ctx context to use for ECC operations
332  */
333 static void
334 point_to_public_eddsa_key (gcry_mpi_point_t q,
335                            gcry_ctx_t ctx,
336                            struct GNUNET_CRYPTO_EddsaPublicKey *pub)
337 {
338   gcry_mpi_t q_x;
339   gcry_mpi_t q_y;
340
341   q_x = gcry_mpi_new (256);
342   q_y = gcry_mpi_new (256);
343   if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
344   {
345     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
346     return;
347   }
348
349   mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
350   mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
351   gcry_mpi_release (q_x);
352   gcry_mpi_release (q_y);
353 }
354
355
356 /**
357  * Initialize public key struct from the respective point
358  * on the curve.
359  *
360  * @param q point on curve
361  * @param pub public key struct to initialize
362  * @param ctx context to use for ECC operations
363  */
364 static void
365 point_to_public_ecdhe_key (gcry_mpi_point_t q,
366                            gcry_ctx_t ctx,
367                            struct GNUNET_CRYPTO_EcdhePublicKey *pub)
368 {
369   gcry_mpi_t q_x;
370   gcry_mpi_t q_y;
371
372   q_x = gcry_mpi_new (256);
373   q_y = gcry_mpi_new (256);
374   if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
375   {
376     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
377     return;
378   }
379
380   mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
381   mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
382   gcry_mpi_release (q_x);
383   gcry_mpi_release (q_y);
384 }
385
386
387 /**
388  * Extract the public key for the given private key.
389  *
390  * @param priv the private key
391  * @param pub where to write the public key
392  */
393 void
394 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
395                                     struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
396 {
397   gcry_sexp_t sexp;
398   gcry_ctx_t ctx;
399   gcry_mpi_point_t q;
400
401   sexp = decode_private_ecdsa_key (priv);
402   GNUNET_assert (NULL != sexp);
403   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
404   gcry_sexp_release (sexp);
405   q = gcry_mpi_ec_get_point ("q", ctx, 0);
406   point_to_public_ecdsa_key (q, ctx, pub);
407   gcry_ctx_release (ctx);
408   gcry_mpi_point_release (q);
409 }
410
411
412 /**
413  * Extract the public key for the given private key.
414  *
415  * @param priv the private key
416  * @param pub where to write the public key
417  */
418 void
419 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
420                                     struct GNUNET_CRYPTO_EddsaPublicKey *pub)
421 {
422   gcry_sexp_t sexp;
423   gcry_ctx_t ctx;
424   gcry_mpi_point_t q;
425
426   sexp = decode_private_eddsa_key (priv);
427   GNUNET_assert (NULL != sexp);
428   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
429   gcry_sexp_release (sexp);
430   q = gcry_mpi_ec_get_point ("q", ctx, 0);
431   point_to_public_eddsa_key (q, ctx, pub);
432   gcry_ctx_release (ctx);
433   gcry_mpi_point_release (q);
434 }
435
436
437 /**
438  * Extract the public key for the given private key.
439  *
440  * @param priv the private key
441  * @param pub where to write the public key
442  */
443 void
444 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
445                                     struct GNUNET_CRYPTO_EcdhePublicKey *pub)
446 {
447   gcry_sexp_t sexp;
448   gcry_ctx_t ctx;
449   gcry_mpi_point_t q;
450
451   sexp = decode_private_ecdhe_key (priv);
452   GNUNET_assert (NULL != sexp);
453   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
454   gcry_sexp_release (sexp);
455   q = gcry_mpi_ec_get_point ("q", ctx, 0);
456   point_to_public_ecdhe_key (q, ctx, pub);
457   gcry_ctx_release (ctx);
458   gcry_mpi_point_release (q);
459 }
460
461
462 /**
463  * Convert a public key to a string.
464  *
465  * @param pub key to convert
466  * @return string representing @a pub
467  */
468 char *
469 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
470 {
471   char *pubkeybuf;
472   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
473   char *end;
474
475   if (keylen % 5 > 0)
476     keylen += 5 - keylen % 5;
477   keylen /= 5;
478   pubkeybuf = GNUNET_malloc (keylen + 1);
479   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
480                                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
481                                        pubkeybuf,
482                                        keylen);
483   if (NULL == end)
484   {
485     GNUNET_free (pubkeybuf);
486     return NULL;
487   }
488   *end = '\0';
489   return pubkeybuf;
490 }
491
492
493 /**
494  * Convert a public key to a string.
495  *
496  * @param pub key to convert
497  * @return string representing @a pub
498  */
499 char *
500 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
501 {
502   char *pubkeybuf;
503   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
504   char *end;
505
506   if (keylen % 5 > 0)
507     keylen += 5 - keylen % 5;
508   keylen /= 5;
509   pubkeybuf = GNUNET_malloc (keylen + 1);
510   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
511                                        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
512                                        pubkeybuf,
513                                        keylen);
514   if (NULL == end)
515   {
516     GNUNET_free (pubkeybuf);
517     return NULL;
518   }
519   *end = '\0';
520   return pubkeybuf;
521 }
522
523
524 /**
525  * Convert a string representing a public key to a public key.
526  *
527  * @param enc encoded public key
528  * @param enclen number of bytes in @a enc (without 0-terminator)
529  * @param pub where to store the public key
530  * @return #GNUNET_OK on success
531  */
532 int
533 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
534                                             size_t enclen,
535                                             struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
536 {
537   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
538
539   if (keylen % 5 > 0)
540     keylen += 5 - keylen % 5;
541   keylen /= 5;
542   if (enclen != keylen)
543     return GNUNET_SYSERR;
544
545   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
546                                                   pub,
547                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
548     return GNUNET_SYSERR;
549   return GNUNET_OK;
550 }
551
552
553 /**
554  * Convert a string representing a public key to a public key.
555  *
556  * @param enc encoded public key
557  * @param enclen number of bytes in @a enc (without 0-terminator)
558  * @param pub where to store the public key
559  * @return #GNUNET_OK on success
560  */
561 int
562 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
563                                             size_t enclen,
564                                             struct GNUNET_CRYPTO_EddsaPublicKey *pub)
565 {
566   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
567
568   if (keylen % 5 > 0)
569     keylen += 5 - keylen % 5;
570   keylen /= 5;
571   if (enclen != keylen)
572     return GNUNET_SYSERR;
573
574   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
575                                                   pub,
576                                                   sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
577     return GNUNET_SYSERR;
578   return GNUNET_OK;
579 }
580
581
582 /**
583  * Convert the given public key from the network format to the
584  * S-expression that can be used by libgcrypt.
585  *
586  * @param pub public key to decode
587  * @return NULL on error
588  */
589 static gcry_sexp_t
590 decode_public_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
591 {
592   gcry_sexp_t pub_sexp;
593   gcry_mpi_t q_x;
594   gcry_mpi_t q_y;
595   gcry_mpi_point_t q;
596   gcry_ctx_t ctx;
597
598   mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
599   mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
600   q = gcry_mpi_point_new (256);
601   gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
602   gcry_mpi_release (q_x);
603   gcry_mpi_release (q_y);
604
605   /* initialize 'ctx' with 'q' */
606   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); // FIXME: need to say ECDSA?
607   gcry_mpi_ec_set_point ("q", q, ctx);
608   gcry_mpi_point_release (q);
609
610   /* convert 'ctx' to 'sexp' */
611   GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
612   gcry_ctx_release (ctx);
613   return pub_sexp;
614 }
615
616
617 /**
618  * Convert the given public key from the network format to the
619  * S-expression that can be used by libgcrypt.
620  *
621  * @param pub public key to decode
622  * @return NULL on error
623  */
624 static gcry_sexp_t
625 decode_public_eddsa_key (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
626 {
627   gcry_sexp_t pub_sexp;
628   gcry_mpi_t q_x;
629   gcry_mpi_t q_y;
630   gcry_mpi_point_t q;
631   gcry_ctx_t ctx;
632
633   mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
634   mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
635   q = gcry_mpi_point_new (256);
636   gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
637   gcry_mpi_release (q_x);
638   gcry_mpi_release (q_y);
639
640   /* initialize 'ctx' with 'q' */
641   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); // FIXME: need to say EdDSA?
642   gcry_mpi_ec_set_point ("q", q, ctx);
643   gcry_mpi_point_release (q);
644
645   /* convert 'ctx' to 'sexp' */
646   GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
647   gcry_ctx_release (ctx);
648   return pub_sexp;
649 }
650
651
652 /**
653  * @ingroup crypto
654  * Clear memory that was used to store a private key.
655  *
656  * @param pk location of the key
657  */
658 void
659 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
660 {
661   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
662 }
663
664
665 /**
666  * @ingroup crypto
667  * Clear memory that was used to store a private key.
668  *
669  * @param pk location of the key
670  */
671 void
672 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
673 {
674   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
675 }
676
677
678 /**
679  * @ingroup crypto
680  * Clear memory that was used to store a private key.
681  *
682  * @param pk location of the key
683  */
684 void
685 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
686 {
687   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
688 }
689
690
691 /**
692  * Create a new private key. Caller must free return value.
693  *
694  * @return fresh private key
695  */
696 struct GNUNET_CRYPTO_EcdhePrivateKey *
697 GNUNET_CRYPTO_ecdhe_key_create ()
698 {
699   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
700   gcry_sexp_t priv_sexp;
701   gcry_sexp_t s_keyparam;
702   gcry_mpi_t d;
703   int rc;
704
705   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
706                                   "(genkey(ecdsa(curve \"" CURVE "\")))"))) // FIXME: ECDHE?
707   {
708     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
709     return NULL;
710   }
711   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
712   {
713     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
714     gcry_sexp_release (s_keyparam);
715     return NULL;
716   }
717   gcry_sexp_release (s_keyparam);
718 #if EXTRA_CHECKS
719   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
720   {
721     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
722     gcry_sexp_release (priv_sexp);
723     return NULL;
724   }
725 #endif
726   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
727   {
728     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
729     gcry_sexp_release (priv_sexp);
730     return NULL;
731   }
732   gcry_sexp_release (priv_sexp);
733   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
734   mpi_print (priv->d, sizeof (priv->d), d);
735   gcry_mpi_release (d);
736   return priv;
737 }
738
739
740 /**
741  * Create a new private key. Caller must free return value.
742  *
743  * @return fresh private key
744  */
745 struct GNUNET_CRYPTO_EcdsaPrivateKey *
746 GNUNET_CRYPTO_ecdsa_key_create ()
747 {
748   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
749   gcry_sexp_t priv_sexp;
750   gcry_sexp_t s_keyparam;
751   gcry_mpi_t d;
752   int rc;
753
754   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
755                                   "(genkey(ecdsa(curve \"" CURVE "\")))")))
756   {
757     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
758     return NULL;
759   }
760   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
761   {
762     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
763     gcry_sexp_release (s_keyparam);
764     return NULL;
765   }
766   gcry_sexp_release (s_keyparam);
767 #if EXTRA_CHECKS
768   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
769   {
770     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
771     gcry_sexp_release (priv_sexp);
772     return NULL;
773   }
774 #endif
775   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
776   {
777     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
778     gcry_sexp_release (priv_sexp);
779     return NULL;
780   }
781   gcry_sexp_release (priv_sexp);
782   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
783   mpi_print (priv->d, sizeof (priv->d), d);
784   gcry_mpi_release (d);
785   return priv;
786 }
787
788 /**
789  * Create a new private key. Caller must free return value.
790  *
791  * @return fresh private key
792  */
793 struct GNUNET_CRYPTO_EddsaPrivateKey *
794 GNUNET_CRYPTO_eddsa_key_create ()
795 {
796   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
797   gcry_sexp_t priv_sexp;
798   gcry_sexp_t s_keyparam;
799   gcry_mpi_t d;
800   int rc;
801
802   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
803                                   "(genkey(ecdsa(curve \"" CURVE "\")))"))) // FIXME: EdDSA?
804   {
805     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
806     return NULL;
807   }
808   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
809   {
810     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
811     gcry_sexp_release (s_keyparam);
812     return NULL;
813   }
814   gcry_sexp_release (s_keyparam);
815 #if EXTRA_CHECKS
816   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
817   {
818     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
819     gcry_sexp_release (priv_sexp);
820     return NULL;
821   }
822 #endif
823   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
824   {
825     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
826     gcry_sexp_release (priv_sexp);
827     return NULL;
828   }
829   gcry_sexp_release (priv_sexp);
830   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
831   mpi_print (priv->d, sizeof (priv->d), d);
832   gcry_mpi_release (d);
833   return priv;
834 }
835
836
837 /**
838  * Get the shared private key we use for anonymous users.
839  *
840  * @return "anonymous" private key
841  */
842 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
843 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
844 {
845   /**
846    * 'anonymous' pseudonym (global static, d=1, public key = G
847    * (generator).
848    */
849   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
850   static int once;
851
852   if (once)
853     return &anonymous;
854   mpi_print (anonymous.d,
855              sizeof (anonymous.d),
856              GCRYMPI_CONST_ONE);
857   once = 1;
858   return &anonymous;
859 }
860
861
862 /**
863  * Wait for a short time (we're trying to lock a file or want
864  * to give another process a shot at finishing a disk write, etc.).
865  * Sleeps for 100ms (as that should be long enough for virtually all
866  * modern systems to context switch and allow another process to do
867  * some 'real' work).
868  */
869 static void
870 short_wait ()
871 {
872   struct GNUNET_TIME_Relative timeout;
873
874   timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
875   (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
876 }
877
878
879 /**
880  * Create a new private key by reading it from a file.  If the
881  * files does not exist, create a new key and write it to the
882  * file.  Caller must free return value.  Note that this function
883  * can not guarantee that another process might not be trying
884  * the same operation on the same file at the same time.
885  * If the contents of the file
886  * are invalid the old file is deleted and a fresh key is
887  * created.
888  *
889  * @param filename name of file to use to store the key
890  * @return new private key, NULL on error (for example,
891  *   permission denied)
892  */
893 struct GNUNET_CRYPTO_EddsaPrivateKey *
894 GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
895 {
896   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
897   struct GNUNET_DISK_FileHandle *fd;
898   unsigned int cnt;
899   int ec;
900   uint64_t fs;
901
902   if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
903     return NULL;
904   while (GNUNET_YES != GNUNET_DISK_file_test (filename))
905   {
906     fd = GNUNET_DISK_file_open (filename,
907                                 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
908                                 | GNUNET_DISK_OPEN_FAILIFEXISTS,
909                                 GNUNET_DISK_PERM_USER_READ |
910                                 GNUNET_DISK_PERM_USER_WRITE);
911     if (NULL == fd)
912     {
913       if (EEXIST == errno)
914       {
915         if (GNUNET_YES != GNUNET_DISK_file_test (filename))
916         {
917           /* must exist but not be accessible, fail for good! */
918           if (0 != ACCESS (filename, R_OK))
919             LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
920           else
921             GNUNET_break (0);   /* what is going on!? */
922           return NULL;
923         }
924         continue;
925       }
926       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
927       return NULL;
928     }
929     cnt = 0;
930     while (GNUNET_YES !=
931            GNUNET_DISK_file_lock (fd, 0,
932                                   sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
933                                   GNUNET_YES))
934     {
935       short_wait ();
936       if (0 == ++cnt % 10)
937       {
938         ec = errno;
939         LOG (GNUNET_ERROR_TYPE_ERROR,
940              _("Could not acquire lock on file `%s': %s...\n"), filename,
941              STRERROR (ec));
942       }
943     }
944     LOG (GNUNET_ERROR_TYPE_INFO,
945          _("Creating a new private key.  This may take a while.\n"));
946     priv = GNUNET_CRYPTO_eddsa_key_create ();
947     GNUNET_assert (NULL != priv);
948     GNUNET_assert (sizeof (*priv) ==
949                    GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
950     GNUNET_DISK_file_sync (fd);
951     if (GNUNET_YES !=
952         GNUNET_DISK_file_unlock (fd, 0,
953                                  sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
954       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
955     GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
956     return priv;
957   }
958   /* key file exists already, read it! */
959   fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
960                               GNUNET_DISK_PERM_NONE);
961   if (NULL == fd)
962   {
963     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
964     return NULL;
965   }
966   cnt = 0;
967   while (1)
968   {
969     if (GNUNET_YES !=
970         GNUNET_DISK_file_lock (fd, 0,
971                                sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
972                                GNUNET_NO))
973     {
974       if (0 == ++cnt % 60)
975       {
976         ec = errno;
977         LOG (GNUNET_ERROR_TYPE_ERROR,
978              _("Could not acquire lock on file `%s': %s...\n"), filename,
979              STRERROR (ec));
980         LOG (GNUNET_ERROR_TYPE_ERROR,
981              _
982              ("This may be ok if someone is currently generating a private key.\n"));
983       }
984       short_wait ();
985       continue;
986     }
987     if (GNUNET_YES != GNUNET_DISK_file_test (filename))
988     {
989       /* eh, what!? File we opened is now gone!? */
990       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
991       if (GNUNET_YES !=
992           GNUNET_DISK_file_unlock (fd, 0,
993                                    sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
994         LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
995       GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
996
997       return NULL;
998     }
999     if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1000       fs = 0;
1001     if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
1002     {
1003       /* maybe we got the read lock before the key generating
1004        * process had a chance to get the write lock; give it up! */
1005       if (GNUNET_YES !=
1006           GNUNET_DISK_file_unlock (fd, 0,
1007                                    sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
1008         LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1009       if (0 == ++cnt % 10)
1010       {
1011         LOG (GNUNET_ERROR_TYPE_ERROR,
1012              _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
1013              filename, (unsigned int) fs,
1014              (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
1015         LOG (GNUNET_ERROR_TYPE_ERROR,
1016              _("This may be ok if someone is currently generating a key.\n"));
1017       }
1018       short_wait ();                /* wait a bit longer! */
1019       continue;
1020     }
1021     break;
1022   }
1023   fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
1024   priv = GNUNET_malloc (fs);
1025   GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
1026   if (GNUNET_YES !=
1027       GNUNET_DISK_file_unlock (fd, 0,
1028                                sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
1029     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1030   GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1031   return priv;
1032 }
1033
1034
1035 /**
1036  * Create a new private key by reading it from a file.  If the
1037  * files does not exist, create a new key and write it to the
1038  * file.  Caller must free return value.  Note that this function
1039  * can not guarantee that another process might not be trying
1040  * the same operation on the same file at the same time.
1041  * If the contents of the file
1042  * are invalid the old file is deleted and a fresh key is
1043  * created.
1044  *
1045  * @param filename name of file to use to store the key
1046  * @return new private key, NULL on error (for example,
1047  *   permission denied)
1048  */
1049 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1050 GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
1051 {
1052   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
1053   struct GNUNET_DISK_FileHandle *fd;
1054   unsigned int cnt;
1055   int ec;
1056   uint64_t fs;
1057
1058   if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
1059     return NULL;
1060   while (GNUNET_YES != GNUNET_DISK_file_test (filename))
1061   {
1062     fd = GNUNET_DISK_file_open (filename,
1063                                 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
1064                                 | GNUNET_DISK_OPEN_FAILIFEXISTS,
1065                                 GNUNET_DISK_PERM_USER_READ |
1066                                 GNUNET_DISK_PERM_USER_WRITE);
1067     if (NULL == fd)
1068     {
1069       if (EEXIST == errno)
1070       {
1071         if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1072         {
1073           /* must exist but not be accessible, fail for good! */
1074           if (0 != ACCESS (filename, R_OK))
1075             LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
1076           else
1077             GNUNET_break (0);   /* what is going on!? */
1078           return NULL;
1079         }
1080         continue;
1081       }
1082       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
1083       return NULL;
1084     }
1085     cnt = 0;
1086     while (GNUNET_YES !=
1087            GNUNET_DISK_file_lock (fd, 0,
1088                                   sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1089                                   GNUNET_YES))
1090     {
1091       short_wait ();
1092       if (0 == ++cnt % 10)
1093       {
1094         ec = errno;
1095         LOG (GNUNET_ERROR_TYPE_ERROR,
1096              _("Could not acquire lock on file `%s': %s...\n"), filename,
1097              STRERROR (ec));
1098       }
1099     }
1100     LOG (GNUNET_ERROR_TYPE_INFO,
1101          _("Creating a new private key.  This may take a while.\n"));
1102     priv = GNUNET_CRYPTO_ecdsa_key_create ();
1103     GNUNET_assert (NULL != priv);
1104     GNUNET_assert (sizeof (*priv) ==
1105                    GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
1106     GNUNET_DISK_file_sync (fd);
1107     if (GNUNET_YES !=
1108         GNUNET_DISK_file_unlock (fd, 0,
1109                                  sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1110       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1111     GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1112     return priv;
1113   }
1114   /* key file exists already, read it! */
1115   fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
1116                               GNUNET_DISK_PERM_NONE);
1117   if (NULL == fd)
1118   {
1119     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
1120     return NULL;
1121   }
1122   cnt = 0;
1123   while (1)
1124   {
1125     if (GNUNET_YES !=
1126         GNUNET_DISK_file_lock (fd, 0,
1127                                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1128                                GNUNET_NO))
1129     {
1130       if (0 == ++cnt % 60)
1131       {
1132         ec = errno;
1133         LOG (GNUNET_ERROR_TYPE_ERROR,
1134              _("Could not acquire lock on file `%s': %s...\n"), filename,
1135              STRERROR (ec));
1136         LOG (GNUNET_ERROR_TYPE_ERROR,
1137              _
1138              ("This may be ok if someone is currently generating a private key.\n"));
1139       }
1140       short_wait ();
1141       continue;
1142     }
1143     if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1144     {
1145       /* eh, what!? File we opened is now gone!? */
1146       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
1147       if (GNUNET_YES !=
1148           GNUNET_DISK_file_unlock (fd, 0,
1149                                    sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1150         LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1151       GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
1152
1153       return NULL;
1154     }
1155     if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1156       fs = 0;
1157     if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
1158     {
1159       /* maybe we got the read lock before the key generating
1160        * process had a chance to get the write lock; give it up! */
1161       if (GNUNET_YES !=
1162           GNUNET_DISK_file_unlock (fd, 0,
1163                                    sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1164         LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1165       if (0 == ++cnt % 10)
1166       {
1167         LOG (GNUNET_ERROR_TYPE_ERROR,
1168              _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
1169              filename, (unsigned int) fs,
1170              (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
1171         LOG (GNUNET_ERROR_TYPE_ERROR,
1172              _("This may be ok if someone is currently generating a key.\n"));
1173       }
1174       short_wait ();                /* wait a bit longer! */
1175       continue;
1176     }
1177     break;
1178   }
1179   fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1180   priv = GNUNET_malloc (fs);
1181   GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
1182   if (GNUNET_YES !=
1183       GNUNET_DISK_file_unlock (fd, 0,
1184                                sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1185     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1186   GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1187   return priv;
1188 }
1189
1190
1191 /**
1192  * Create a new private key by reading our peer's key from
1193  * the file specified in the configuration.
1194  *
1195  * @param cfg the configuration to use
1196  * @return new private key, NULL on error (for example,
1197  *   permission denied)
1198  */
1199 struct GNUNET_CRYPTO_EddsaPrivateKey *
1200 GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
1201 {
1202   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1203   char *fn;
1204
1205   if (GNUNET_OK !=
1206       GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1207     return NULL;
1208   priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
1209   GNUNET_free (fn);
1210   return priv;
1211 }
1212
1213
1214 /**
1215  * Setup a key file for a peer given the name of the
1216  * configuration file (!).  This function is used so that
1217  * at a later point code can be certain that reading a
1218  * key is fast (for example in time-dependent testcases).
1219  *
1220  * @param cfg_name name of the configuration file to use
1221  */
1222 void
1223 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1224 {
1225   struct GNUNET_CONFIGURATION_Handle *cfg;
1226   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1227
1228   cfg = GNUNET_CONFIGURATION_create ();
1229   (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1230   priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1231   if (NULL != priv)
1232     GNUNET_free (priv);
1233   GNUNET_CONFIGURATION_destroy (cfg);
1234 }
1235
1236
1237 /**
1238  * Retrieve the identity of the host's peer.
1239  *
1240  * @param cfg configuration to use
1241  * @param dst pointer to where to write the peer identity
1242  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1243  *         could not be retrieved
1244  */
1245 int
1246 GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1247                                  struct GNUNET_PeerIdentity *dst)
1248 {
1249   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1250
1251   if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1252   {
1253     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1254                 _("Could not load peer's private key\n"));
1255     return GNUNET_SYSERR;
1256   }
1257   GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1258   GNUNET_free (priv);
1259   return GNUNET_OK;
1260 }
1261
1262
1263 /**
1264  * Convert the data specified in the given purpose argument to an
1265  * S-expression suitable for signature operations.
1266  *
1267  * @param purpose data to convert
1268  * @return converted s-expression
1269  */
1270 static gcry_sexp_t
1271 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1272 {
1273   struct GNUNET_HashCode hc;
1274   gcry_sexp_t data;
1275   int rc;
1276
1277   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1278   if (0 != (rc = gcry_sexp_build (&data, NULL,
1279                                   "(data(flags rfc6979)(hash %s %b))", // FIXME: use EdDSA encoding!
1280                                   "sha512",
1281                                   sizeof (hc),
1282                                   &hc)))
1283   {
1284     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1285     return NULL;
1286   }
1287   return data;
1288 }
1289
1290
1291 /**
1292  * Convert the data specified in the given purpose argument to an
1293  * S-expression suitable for signature operations.
1294  *
1295  * @param purpose data to convert
1296  * @return converted s-expression
1297  */
1298 static gcry_sexp_t
1299 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1300 {
1301   struct GNUNET_HashCode hc;
1302   gcry_sexp_t data;
1303   int rc;
1304
1305   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1306   if (0 != (rc = gcry_sexp_build (&data, NULL,
1307                                   "(data(flags rfc6979)(hash %s %b))",
1308                                   "sha512",
1309                                   sizeof (hc),
1310                                   &hc)))
1311   {
1312     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1313     return NULL;
1314   }
1315   return data;
1316 }
1317
1318
1319 /**
1320  * Sign a given block.
1321  *
1322  * @param priv private key to use for the signing
1323  * @param purpose what to sign (size, purpose)
1324  * @param sig where to write the signature
1325  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1326  */
1327 int
1328 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1329                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1330                           struct GNUNET_CRYPTO_EcdsaSignature *sig)
1331 {
1332   gcry_sexp_t priv_sexp;
1333   gcry_sexp_t sig_sexp;
1334   gcry_sexp_t data;
1335   int rc;
1336   gcry_mpi_t rs[2];
1337
1338   priv_sexp = decode_private_ecdsa_key (priv);
1339   data = data_to_ecdsa_value (purpose);
1340   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1341   {
1342     LOG (GNUNET_ERROR_TYPE_WARNING,
1343          _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1344          __LINE__, gcry_strerror (rc));
1345     gcry_sexp_release (data);
1346     gcry_sexp_release (priv_sexp);
1347     return GNUNET_SYSERR;
1348   }
1349   gcry_sexp_release (priv_sexp);
1350   gcry_sexp_release (data);
1351
1352   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1353      'signature' */
1354   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1355   {
1356     GNUNET_break (0);
1357     gcry_sexp_release (sig_sexp);
1358     return GNUNET_SYSERR;
1359   }
1360   gcry_sexp_release (sig_sexp);
1361   mpi_print (sig->r, sizeof (sig->r), rs[0]);
1362   mpi_print (sig->s, sizeof (sig->s), rs[1]);
1363   gcry_mpi_release (rs[0]);
1364   gcry_mpi_release (rs[1]);
1365   return GNUNET_OK;
1366 }
1367
1368
1369 /**
1370  * Sign a given block.
1371  *
1372  * @param priv private key to use for the signing
1373  * @param purpose what to sign (size, purpose)
1374  * @param sig where to write the signature
1375  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1376  */
1377 int
1378 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1379                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1380                           struct GNUNET_CRYPTO_EddsaSignature *sig)
1381 {
1382   gcry_sexp_t priv_sexp;
1383   gcry_sexp_t sig_sexp;
1384   gcry_sexp_t data;
1385   int rc;
1386   gcry_mpi_t rs[2];
1387
1388   priv_sexp = decode_private_eddsa_key (priv);
1389   data = data_to_eddsa_value (purpose);
1390   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1391   {
1392     LOG (GNUNET_ERROR_TYPE_WARNING,
1393          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
1394          __LINE__, gcry_strerror (rc));
1395     gcry_sexp_release (data);
1396     gcry_sexp_release (priv_sexp);
1397     return GNUNET_SYSERR;
1398   }
1399   gcry_sexp_release (priv_sexp);
1400   gcry_sexp_release (data);
1401
1402   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1403      'signature' */
1404   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1405   {
1406     GNUNET_break (0);
1407     gcry_sexp_release (sig_sexp);
1408     return GNUNET_SYSERR;
1409   }
1410   gcry_sexp_release (sig_sexp);
1411   mpi_print (sig->r, sizeof (sig->r), rs[0]);
1412   mpi_print (sig->s, sizeof (sig->s), rs[1]);
1413   gcry_mpi_release (rs[0]);
1414   gcry_mpi_release (rs[1]);
1415   return GNUNET_OK;
1416 }
1417
1418
1419 /**
1420  * Verify signature.
1421  *
1422  * @param purpose what is the purpose that the signature should have?
1423  * @param validate block to validate (size, purpose, data)
1424  * @param sig signature that is being validated
1425  * @param pub public key of the signer
1426  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1427  */
1428 int
1429 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1430                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1431                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1432                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1433 {
1434   gcry_sexp_t data;
1435   gcry_sexp_t sig_sexpr;
1436   gcry_sexp_t pub_sexpr;
1437   int rc;
1438   gcry_mpi_t r;
1439   gcry_mpi_t s;
1440
1441   if (purpose != ntohl (validate->purpose))
1442     return GNUNET_SYSERR;       /* purpose mismatch */
1443
1444   /* build s-expression for signature */
1445   mpi_scan (&r, sig->r, sizeof (sig->r));
1446   mpi_scan (&s, sig->s, sizeof (sig->s));
1447   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1448                                   "(sig-val(ecdsa(r %m)(s %m)))",
1449                                   r, s)))
1450   {
1451     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1452     gcry_mpi_release (r);
1453     gcry_mpi_release (s);
1454     return GNUNET_SYSERR;
1455   }
1456   gcry_mpi_release (r);
1457   gcry_mpi_release (s);
1458   data = data_to_ecdsa_value (validate);
1459   if (! (pub_sexpr = decode_public_ecdsa_key (pub)))
1460   {
1461     gcry_sexp_release (data);
1462     gcry_sexp_release (sig_sexpr);
1463     return GNUNET_SYSERR;
1464   }
1465   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1466   gcry_sexp_release (pub_sexpr);
1467   gcry_sexp_release (data);
1468   gcry_sexp_release (sig_sexpr);
1469   if (0 != rc)
1470   {
1471     LOG (GNUNET_ERROR_TYPE_INFO,
1472          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1473          __LINE__, gcry_strerror (rc));
1474     return GNUNET_SYSERR;
1475   }
1476   return GNUNET_OK;
1477 }
1478
1479
1480
1481 /**
1482  * Verify signature.
1483  *
1484  * @param purpose what is the purpose that the signature should have?
1485  * @param validate block to validate (size, purpose, data)
1486  * @param sig signature that is being validated
1487  * @param pub public key of the signer
1488  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1489  */
1490 int
1491 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1492                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1493                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
1494                             const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1495 {
1496   gcry_sexp_t data;
1497   gcry_sexp_t sig_sexpr;
1498   gcry_sexp_t pub_sexpr;
1499   int rc;
1500   gcry_mpi_t r;
1501   gcry_mpi_t s;
1502
1503   if (purpose != ntohl (validate->purpose))
1504     return GNUNET_SYSERR;       /* purpose mismatch */
1505
1506   /* build s-expression for signature */
1507   mpi_scan (&r, sig->r, sizeof (sig->r));
1508   mpi_scan (&s, sig->s, sizeof (sig->s));
1509   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1510                                   "(sig-val(ecdsa(r %m)(s %m)))", // FIXME: eddsa soon...
1511                                   r, s)))
1512   {
1513     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1514     gcry_mpi_release (r);
1515     gcry_mpi_release (s);
1516     return GNUNET_SYSERR;
1517   }
1518   gcry_mpi_release (r);
1519   gcry_mpi_release (s);
1520   data = data_to_eddsa_value (validate);
1521   if (! (pub_sexpr = decode_public_eddsa_key (pub)))
1522   {
1523     gcry_sexp_release (data);
1524     gcry_sexp_release (sig_sexpr);
1525     return GNUNET_SYSERR;
1526   }
1527   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1528   gcry_sexp_release (pub_sexpr);
1529   gcry_sexp_release (data);
1530   gcry_sexp_release (sig_sexpr);
1531   if (0 != rc)
1532   {
1533     LOG (GNUNET_ERROR_TYPE_INFO,
1534          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1535          __LINE__, gcry_strerror (rc));
1536     return GNUNET_SYSERR;
1537   }
1538   return GNUNET_OK;
1539 }
1540
1541
1542 /**
1543  * Convert the given public key from the network format to the
1544  * S-expression that can be used by libgcrypt.
1545  *
1546  * @param pub public key to decode
1547  * @return NULL on error
1548  */
1549 static gcry_sexp_t
1550 decode_public_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
1551 {
1552   gcry_sexp_t pub_sexp;
1553   gcry_mpi_t q_x;
1554   gcry_mpi_t q_y;
1555   gcry_mpi_point_t q;
1556   gcry_ctx_t ctx;
1557
1558   mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
1559   mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
1560   q = gcry_mpi_point_new (256);
1561   gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1562   gcry_mpi_release (q_x);
1563   gcry_mpi_release (q_y);
1564
1565   /* initialize 'ctx' with 'q' */
1566   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1567   gcry_mpi_ec_set_point ("q", q, ctx);
1568   gcry_mpi_point_release (q);
1569
1570   /* convert 'ctx' to 'sexp' */
1571   GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
1572   gcry_ctx_release (ctx);
1573   return pub_sexp;
1574 }
1575
1576
1577 /**
1578  * Derive key material from a public and a private ECDHE key.
1579  *
1580  * @param priv private key to use for the ECDH (x)
1581  * @param pub public key to use for the ECDH (yG)
1582  * @param key_material where to write the key material (xyG)
1583  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1584  */
1585 int
1586 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1587                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1588                         struct GNUNET_HashCode *key_material)
1589 {
1590   gcry_mpi_point_t result;
1591   gcry_mpi_point_t q;
1592   gcry_mpi_t d;
1593   gcry_ctx_t ctx;
1594   gcry_sexp_t pub_sexpr;
1595   gcry_mpi_t result_x;
1596   gcry_mpi_t result_y;
1597   unsigned char xbuf[256 / 8];
1598
1599   /* first, extract the q = dP value from the public key */
1600   if (! (pub_sexpr = decode_public_ecdhe_key (pub)))
1601     return GNUNET_SYSERR;
1602   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1603   gcry_sexp_release (pub_sexpr);
1604   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1605
1606   /* second, extract the d value from our private key */
1607   mpi_scan (&d, priv->d, sizeof (priv->d));
1608
1609   /* then call the 'multiply' function, to compute the product */
1610   result = gcry_mpi_point_new (0);
1611   gcry_mpi_ec_mul (result, d, q, ctx);
1612   gcry_mpi_point_release (q);
1613   gcry_mpi_release (d);
1614
1615   /* finally, convert point to string for hashing */
1616   result_x = gcry_mpi_new (256);
1617   result_y = gcry_mpi_new (256);
1618   if (gcry_mpi_ec_get_affine (result_x, result_y, result, ctx))
1619   {
1620     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1621     gcry_mpi_point_release (result);
1622     gcry_ctx_release (ctx);
1623     return GNUNET_SYSERR;
1624   }
1625   gcry_mpi_point_release (result);
1626   gcry_ctx_release (ctx);
1627
1628   mpi_print (xbuf, sizeof (xbuf), result_x);
1629   GNUNET_CRYPTO_hash (xbuf, sizeof (xbuf), key_material);
1630   gcry_mpi_release (result_x);
1631   gcry_mpi_release (result_y);
1632   return GNUNET_OK;
1633 }
1634
1635
1636 /**
1637  * Derive the 'h' value for key derivation, where
1638  * 'h = H(l,P)'.
1639  *
1640  * @param pub public key for deriviation
1641  * @param label label for deriviation
1642  * @param context additional context to use for HKDF of 'h';
1643  *        typically the name of the subsystem/application
1644  * @return h value
1645  */
1646 static gcry_mpi_t
1647 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1648           const char *label,
1649           const char *context)
1650 {
1651   gcry_mpi_t h;
1652   struct GNUNET_HashCode hc;
1653
1654   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1655                      "key-derivation", strlen ("key-derivation"),
1656                      pub, sizeof (*pub),
1657                      label, strlen (label),
1658                      context, strlen (context),
1659                      NULL, 0);
1660   mpi_scan (&h, (unsigned char *) &hc, sizeof (hc));
1661   return h;
1662 }
1663
1664
1665 /**
1666  * Derive a private key from a given private key and a label.
1667  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1668  * where n is the size of the ECC group and P is the public
1669  * key associated with the private key 'd'.
1670  *
1671  * @param priv original private key
1672  * @param label label to use for key deriviation
1673  * @param context additional context to use for HKDF of 'h';
1674  *        typically the name of the subsystem/application
1675  * @return derived private key
1676  */
1677 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1678 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1679                                         const char *label,
1680                                         const char *context)
1681 {
1682   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1683   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1684   gcry_mpi_t h;
1685   gcry_mpi_t x;
1686   gcry_mpi_t d;
1687   gcry_mpi_t n;
1688   gcry_ctx_t ctx;
1689
1690   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1691   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1692   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1693   h = derive_h (&pub, label, context);
1694   mpi_scan (&x, priv->d, sizeof (priv->d));
1695   d = gcry_mpi_new (256);
1696   gcry_mpi_mulm (d, h, x, n);
1697   gcry_mpi_release (h);
1698   gcry_mpi_release (x);
1699   gcry_mpi_release (n);
1700   gcry_ctx_release (ctx);
1701   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1702   mpi_print (ret->d, sizeof (ret->d), d);
1703   gcry_mpi_release (d);
1704   return ret;
1705 }
1706
1707
1708 /**
1709  * Derive a public key from a given public key and a label.
1710  * Essentially calculates a public key 'V = H(l,P) * P'.
1711  *
1712  * @param pub original public key
1713  * @param label label to use for key deriviation
1714  * @param context additional context to use for HKDF of 'h';
1715  *        typically the name of the subsystem/application
1716  * @param result where to write the derived public key
1717  */
1718 void
1719 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1720                                        const char *label,
1721                                        const char *context,
1722                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1723 {
1724   gcry_ctx_t ctx;
1725   gcry_mpi_t h;
1726   gcry_mpi_t n;
1727   gcry_mpi_t h_mod_n;
1728   gcry_mpi_t q_x;
1729   gcry_mpi_t q_y;
1730   gcry_mpi_point_t q;
1731   gcry_mpi_point_t v;
1732
1733   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1734
1735   /* obtain point 'q' from original public key */
1736   mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
1737   mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
1738
1739   q = gcry_mpi_point_new (0);
1740   gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1741   gcry_mpi_release (q_x);
1742   gcry_mpi_release (q_y);
1743
1744   /* calulcate h_mod_n = h % n */
1745   h = derive_h (pub, label, context);
1746   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1747   h_mod_n = gcry_mpi_new (256);
1748   gcry_mpi_mod (h_mod_n, h, n);
1749   /* calculate v = h_mod_n * q */
1750   v = gcry_mpi_point_new (0);
1751   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1752   gcry_mpi_release (h_mod_n);
1753   gcry_mpi_release (h);
1754   gcry_mpi_release (n);
1755   gcry_mpi_point_release (q);
1756   /* convert point 'v' to public key that we return */
1757   point_to_public_ecdsa_key (v, ctx, result);
1758   gcry_mpi_point_release (v);
1759   gcry_ctx_release (ctx);
1760 }
1761
1762
1763 /* end of crypto_ecc.c */