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