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