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