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