87c78718586cb0c4e64164d9f28ae6aacbf794b5
[oweals/gnunet.git] / src / util / crypto_ecc.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2015 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,
65                gcry_sexp_t sexp,
66                const char *topname,
67                const char *elems)
68 {
69   gcry_sexp_t list;
70   gcry_sexp_t l2;
71   const char *s;
72   unsigned int i;
73   unsigned int idx;
74
75   list = gcry_sexp_find_token (sexp, topname, 0);
76   if (! list)
77     return 1;
78   l2 = gcry_sexp_cadr (list);
79   gcry_sexp_release (list);
80   list = l2;
81   if (! list)
82     return 2;
83
84   idx = 0;
85   for (s = elems; *s; s++, idx++)
86   {
87     l2 = gcry_sexp_find_token (list, s, 1);
88     if (! l2)
89     {
90       for (i = 0; i < idx; i++)
91       {
92         gcry_free (array[i]);
93         array[i] = NULL;
94       }
95       gcry_sexp_release (list);
96       return 3;                 /* required parameter not found */
97     }
98     array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
99     gcry_sexp_release (l2);
100     if (! array[idx])
101     {
102       for (i = 0; i < idx; i++)
103       {
104         gcry_free (array[i]);
105         array[i] = NULL;
106       }
107       gcry_sexp_release (list);
108       return 4;                 /* required parameter is invalid */
109     }
110   }
111   gcry_sexp_release (list);
112   return 0;
113 }
114
115
116 /**
117  * Convert the given private key from the network format to the
118  * S-expression that can be used by libgcrypt.
119  *
120  * @param priv private key to decode
121  * @return NULL on error
122  */
123 static gcry_sexp_t
124 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
125 {
126   gcry_sexp_t result;
127   int rc;
128
129   rc = gcry_sexp_build (&result, NULL,
130                         "(private-key(ecc(curve \"" CURVE "\")"
131                         "(d %b)))",
132                         (int)sizeof (priv->d), priv->d);
133   if (0 != rc)
134   {
135     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
136     GNUNET_assert (0);
137   }
138 #if EXTRA_CHECKS
139   if (0 != (rc = gcry_pk_testkey (result)))
140   {
141     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
142     GNUNET_assert (0);
143   }
144 #endif
145   return result;
146 }
147
148
149 /**
150  * Convert the given private key from the network format to the
151  * S-expression that can be used by libgcrypt.
152  *
153  * @param priv private key to decode
154  * @return NULL on error
155  */
156 static gcry_sexp_t
157 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
158 {
159   gcry_sexp_t result;
160   int rc;
161
162   rc = gcry_sexp_build (&result, NULL,
163                         "(private-key(ecc(curve \"" CURVE "\")"
164                         "(flags eddsa)(d %b)))",
165                         (int)sizeof (priv->d), priv->d);
166   if (0 != rc)
167   {
168     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
169     GNUNET_assert (0);
170   }
171 #if EXTRA_CHECKS
172   if (0 != (rc = gcry_pk_testkey (result)))
173   {
174     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
175     GNUNET_assert (0);
176   }
177 #endif
178   return result;
179 }
180
181
182 /**
183  * Convert the given private key from the network format to the
184  * S-expression that can be used by libgcrypt.
185  *
186  * @param priv private key to decode
187  * @return NULL on error
188  */
189 static gcry_sexp_t
190 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
191 {
192   gcry_sexp_t result;
193   int rc;
194
195   rc = gcry_sexp_build (&result, NULL,
196                         "(private-key(ecc(curve \"" CURVE "\")"
197                         "(d %b)))",
198                         (int)sizeof (priv->d), priv->d);
199   if (0 != rc)
200   {
201     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
202     GNUNET_assert (0);
203   }
204 #if EXTRA_CHECKS
205   if (0 != (rc = gcry_pk_testkey (result)))
206   {
207     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
208     GNUNET_assert (0);
209   }
210 #endif
211   return result;
212 }
213
214
215 /**
216  * Extract the public key for the given private key.
217  *
218  * @param priv the private key
219  * @param pub where to write the public key
220  */
221 void
222 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
223                                     struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
224 {
225   gcry_sexp_t sexp;
226   gcry_ctx_t ctx;
227   gcry_mpi_t q;
228
229   sexp = decode_private_ecdsa_key (priv);
230   GNUNET_assert (NULL != sexp);
231   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
232   gcry_sexp_release (sexp);
233   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
234   GNUNET_assert (NULL != q);
235   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
236   gcry_mpi_release (q);
237   gcry_ctx_release (ctx);
238 }
239
240
241 /**
242  * Extract the public key for the given private key.
243  *
244  * @param priv the private key
245  * @param pub where to write the public key
246  */
247 void
248 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
249                                     struct GNUNET_CRYPTO_EddsaPublicKey *pub)
250 {
251   gcry_sexp_t sexp;
252   gcry_ctx_t ctx;
253   gcry_mpi_t q;
254
255   sexp = decode_private_eddsa_key (priv);
256   GNUNET_assert (NULL != sexp);
257   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
258   gcry_sexp_release (sexp);
259   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
260   GNUNET_assert (q);
261   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
262   gcry_mpi_release (q);
263   gcry_ctx_release (ctx);
264 }
265
266
267 /**
268  * Extract the public key for the given private key.
269  *
270  * @param priv the private key
271  * @param pub where to write the public key
272  */
273 void
274 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
275                                     struct GNUNET_CRYPTO_EcdhePublicKey *pub)
276 {
277   gcry_sexp_t sexp;
278   gcry_ctx_t ctx;
279   gcry_mpi_t q;
280
281   sexp = decode_private_ecdhe_key (priv);
282   GNUNET_assert (NULL != sexp);
283   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
284   gcry_sexp_release (sexp);
285   q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
286   GNUNET_assert (q);
287   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
288   gcry_mpi_release (q);
289   gcry_ctx_release (ctx);
290 }
291
292
293 /**
294  * Convert a public key to a string.
295  *
296  * @param pub key to convert
297  * @return string representing @a pub
298  */
299 char *
300 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
301 {
302   char *pubkeybuf;
303   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
304   char *end;
305
306   if (keylen % 5 > 0)
307     keylen += 5 - keylen % 5;
308   keylen /= 5;
309   pubkeybuf = GNUNET_malloc (keylen + 1);
310   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
311                                        sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
312                                        pubkeybuf,
313                                        keylen);
314   if (NULL == end)
315   {
316     GNUNET_free (pubkeybuf);
317     return NULL;
318   }
319   *end = '\0';
320   return pubkeybuf;
321 }
322
323
324 /**
325  * Convert a public key to a string.
326  *
327  * @param pub key to convert
328  * @return string representing @a pub
329  */
330 char *
331 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
332 {
333   char *pubkeybuf;
334   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
335   char *end;
336
337   if (keylen % 5 > 0)
338     keylen += 5 - keylen % 5;
339   keylen /= 5;
340   pubkeybuf = GNUNET_malloc (keylen + 1);
341   end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
342                                        sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
343                                        pubkeybuf,
344                                        keylen);
345   if (NULL == end)
346   {
347     GNUNET_free (pubkeybuf);
348     return NULL;
349   }
350   *end = '\0';
351   return pubkeybuf;
352 }
353
354
355 /**
356  * Convert a string representing a public key to a public key.
357  *
358  * @param enc encoded public key
359  * @param enclen number of bytes in @a enc (without 0-terminator)
360  * @param pub where to store the public key
361  * @return #GNUNET_OK on success
362  */
363 int
364 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
365                                             size_t enclen,
366                                             struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
367 {
368   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
369
370   if (keylen % 5 > 0)
371     keylen += 5 - keylen % 5;
372   keylen /= 5;
373   if (enclen != keylen)
374     return GNUNET_SYSERR;
375
376   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
377                                                   pub,
378                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
379     return GNUNET_SYSERR;
380   return GNUNET_OK;
381 }
382
383
384 /**
385  * Convert a string representing a public key to a public key.
386  *
387  * @param enc encoded public key
388  * @param enclen number of bytes in @a enc (without 0-terminator)
389  * @param pub where to store the public key
390  * @return #GNUNET_OK on success
391  */
392 int
393 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
394                                             size_t enclen,
395                                             struct GNUNET_CRYPTO_EddsaPublicKey *pub)
396 {
397   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
398
399   if (keylen % 5 > 0)
400     keylen += 5 - keylen % 5;
401   keylen /= 5;
402   if (enclen != keylen)
403     return GNUNET_SYSERR;
404
405   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
406                                                   pub,
407                                                   sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
408     return GNUNET_SYSERR;
409   return GNUNET_OK;
410 }
411
412
413 /**
414  * Convert a string representing a private key to a private key.
415  *
416  * @param enc encoded public key
417  * @param enclen number of bytes in @a enc (without 0-terminator)
418  * @param priv where to store the private key
419  * @return #GNUNET_OK on success
420  */
421 int
422 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
423                                              size_t enclen,
424                                              struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
425 {
426   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
427
428   if (keylen % 5 > 0)
429     keylen += 5 - keylen % 5;
430   keylen /= 5;
431   if (enclen != keylen)
432     return GNUNET_SYSERR;
433
434   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
435                                                   pub,
436                                                   sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
437     return GNUNET_SYSERR;
438   return GNUNET_OK;
439 }
440
441
442 /**
443  * @ingroup crypto
444  * Clear memory that was used to store a private key.
445  *
446  * @param pk location of the key
447  */
448 void
449 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
450 {
451   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
452 }
453
454
455 /**
456  * @ingroup crypto
457  * Clear memory that was used to store a private key.
458  *
459  * @param pk location of the key
460  */
461 void
462 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
463 {
464   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
465 }
466
467
468 /**
469  * @ingroup crypto
470  * Clear memory that was used to store a private key.
471  *
472  * @param pk location of the key
473  */
474 void
475 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
476 {
477   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
478 }
479
480
481 /**
482  * Create a new private key. Caller must free return value.
483  *
484  * @return fresh private key
485  */
486 struct GNUNET_CRYPTO_EcdhePrivateKey *
487 GNUNET_CRYPTO_ecdhe_key_create ()
488 {
489   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
490   gcry_sexp_t priv_sexp;
491   gcry_sexp_t s_keyparam;
492   gcry_mpi_t d;
493   int rc;
494
495   /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
496      but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
497      disables an expensive key testing routine. We do not want to run
498      the expensive check for ECDHE, as we generate TONS of keys to
499      use for a very short time. */
500   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
501                                   "(genkey(ecc(curve \"" CURVE "\")"
502                                   "(flags eddsa no-keytest)))")))
503   {
504     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
505     return NULL;
506   }
507   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
508   {
509     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
510     gcry_sexp_release (s_keyparam);
511     return NULL;
512   }
513   gcry_sexp_release (s_keyparam);
514 #if EXTRA_CHECKS
515   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
516   {
517     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
518     gcry_sexp_release (priv_sexp);
519     return NULL;
520   }
521 #endif
522   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
523   {
524     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
525     gcry_sexp_release (priv_sexp);
526     return NULL;
527   }
528   gcry_sexp_release (priv_sexp);
529   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
530   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
531   gcry_mpi_release (d);
532   return priv;
533 }
534
535
536 /**
537  * Create a new private key. Caller must free return value.
538  *
539  * @return fresh private key
540  */
541 struct GNUNET_CRYPTO_EcdsaPrivateKey *
542 GNUNET_CRYPTO_ecdsa_key_create ()
543 {
544   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
545   gcry_sexp_t priv_sexp;
546   gcry_sexp_t s_keyparam;
547   gcry_mpi_t d;
548   int rc;
549
550   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
551                                   "(genkey(ecc(curve \"" CURVE "\")"
552                                   "(flags)))")))
553   {
554     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
555     return NULL;
556   }
557   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
558   {
559     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
560     gcry_sexp_release (s_keyparam);
561     return NULL;
562   }
563   gcry_sexp_release (s_keyparam);
564 #if EXTRA_CHECKS
565   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
566   {
567     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
568     gcry_sexp_release (priv_sexp);
569     return NULL;
570   }
571 #endif
572   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
573   {
574     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
575     gcry_sexp_release (priv_sexp);
576     return NULL;
577   }
578   gcry_sexp_release (priv_sexp);
579   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
580   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
581   gcry_mpi_release (d);
582   return priv;
583 }
584
585 /**
586  * Create a new private key. Caller must free return value.
587  *
588  * @return fresh private key
589  */
590 struct GNUNET_CRYPTO_EddsaPrivateKey *
591 GNUNET_CRYPTO_eddsa_key_create ()
592 {
593   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
594   gcry_sexp_t priv_sexp;
595   gcry_sexp_t s_keyparam;
596   gcry_mpi_t d;
597   int rc;
598
599   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
600                                   "(genkey(ecc(curve \"" CURVE "\")"
601                                   "(flags eddsa)))")))
602   {
603     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
604     return NULL;
605   }
606   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
607   {
608     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
609     gcry_sexp_release (s_keyparam);
610     return NULL;
611   }
612   gcry_sexp_release (s_keyparam);
613 #if EXTRA_CHECKS
614   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
615   {
616     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
617     gcry_sexp_release (priv_sexp);
618     return NULL;
619   }
620 #endif
621   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
622   {
623     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
624     gcry_sexp_release (priv_sexp);
625     return NULL;
626   }
627   gcry_sexp_release (priv_sexp);
628   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
629   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
630   gcry_mpi_release (d);
631   return priv;
632 }
633
634
635 /**
636  * Get the shared private key we use for anonymous users.
637  *
638  * @return "anonymous" private key
639  */
640 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
641 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
642 {
643   /**
644    * 'anonymous' pseudonym (global static, d=1, public key = G
645    * (generator).
646    */
647   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
648   static int once;
649
650   if (once)
651     return &anonymous;
652   GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
653              sizeof (anonymous.d),
654              GCRYMPI_CONST_ONE);
655   once = 1;
656   return &anonymous;
657 }
658
659
660 /**
661  * Compare two Peer Identities.
662  *
663  * @param first first peer identity
664  * @param second second peer identity
665  * @return bigger than 0 if first > second,
666  *         0 if they are the same
667  *         smaller than 0 if second > first
668  */
669 int
670 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
671                                  const struct GNUNET_PeerIdentity *second)
672 {
673   return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
674 }
675
676
677 /**
678  * Convert the data specified in the given purpose argument to an
679  * S-expression suitable for signature operations.
680  *
681  * @param purpose data to convert
682  * @return converted s-expression
683  */
684 static gcry_sexp_t
685 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
686 {
687   struct GNUNET_HashCode hc;
688   gcry_sexp_t data;
689   int rc;
690
691   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
692   if (0 != (rc = gcry_sexp_build (&data, NULL,
693                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
694                                   "sha512",
695                                   (int)sizeof (hc), &hc)))
696   {
697     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
698     return NULL;
699   }
700   return data;
701 }
702
703
704 /**
705  * Convert the data specified in the given purpose argument to an
706  * S-expression suitable for signature operations.
707  *
708  * @param purpose data to convert
709  * @return converted s-expression
710  */
711 static gcry_sexp_t
712 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
713 {
714   struct GNUNET_HashCode hc;
715   gcry_sexp_t data;
716   int rc;
717
718   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
719   if (0 != (rc = gcry_sexp_build (&data, NULL,
720                                   "(data(flags rfc6979)(hash %s %b))",
721                                   "sha512",
722                                   (int)sizeof (hc), &hc)))
723   {
724     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
725     return NULL;
726   }
727   return data;
728 }
729
730
731 /**
732  * Sign a given block.
733  *
734  * @param priv private key to use for the signing
735  * @param purpose what to sign (size, purpose)
736  * @param sig where to write the signature
737  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
738  */
739 int
740 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
741                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
742                           struct GNUNET_CRYPTO_EcdsaSignature *sig)
743 {
744   gcry_sexp_t priv_sexp;
745   gcry_sexp_t sig_sexp;
746   gcry_sexp_t data;
747   int rc;
748   gcry_mpi_t rs[2];
749
750   priv_sexp = decode_private_ecdsa_key (priv);
751   data = data_to_ecdsa_value (purpose);
752   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
753   {
754     LOG (GNUNET_ERROR_TYPE_WARNING,
755          _("ECC signing failed at %s:%d: %s\n"), __FILE__,
756          __LINE__, gcry_strerror (rc));
757     gcry_sexp_release (data);
758     gcry_sexp_release (priv_sexp);
759     return GNUNET_SYSERR;
760   }
761   gcry_sexp_release (priv_sexp);
762   gcry_sexp_release (data);
763
764   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
765      'signature' */
766   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
767   {
768     GNUNET_break (0);
769     gcry_sexp_release (sig_sexp);
770     return GNUNET_SYSERR;
771   }
772   gcry_sexp_release (sig_sexp);
773   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
774   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
775   gcry_mpi_release (rs[0]);
776   gcry_mpi_release (rs[1]);
777   return GNUNET_OK;
778 }
779
780
781 /**
782  * Sign a given block.
783  *
784  * @param priv private key to use for the signing
785  * @param purpose what to sign (size, purpose)
786  * @param sig where to write the signature
787  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
788  */
789 int
790 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
791                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
792                           struct GNUNET_CRYPTO_EddsaSignature *sig)
793 {
794   gcry_sexp_t priv_sexp;
795   gcry_sexp_t sig_sexp;
796   gcry_sexp_t data;
797   int rc;
798   gcry_mpi_t rs[2];
799
800   priv_sexp = decode_private_eddsa_key (priv);
801   data = data_to_eddsa_value (purpose);
802   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
803   {
804     LOG (GNUNET_ERROR_TYPE_WARNING,
805          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
806          __LINE__, gcry_strerror (rc));
807     gcry_sexp_release (data);
808     gcry_sexp_release (priv_sexp);
809     return GNUNET_SYSERR;
810   }
811   gcry_sexp_release (priv_sexp);
812   gcry_sexp_release (data);
813
814   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
815      'signature' */
816   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
817   {
818     GNUNET_break (0);
819     gcry_sexp_release (sig_sexp);
820     return GNUNET_SYSERR;
821   }
822   gcry_sexp_release (sig_sexp);
823   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
824   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
825   gcry_mpi_release (rs[0]);
826   gcry_mpi_release (rs[1]);
827   return GNUNET_OK;
828 }
829
830
831 /**
832  * Verify signature.
833  *
834  * @param purpose what is the purpose that the signature should have?
835  * @param validate block to validate (size, purpose, data)
836  * @param sig signature that is being validated
837  * @param pub public key of the signer
838  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
839  */
840 int
841 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
842                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
843                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
844                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
845 {
846   gcry_sexp_t data;
847   gcry_sexp_t sig_sexpr;
848   gcry_sexp_t pub_sexpr;
849   int rc;
850
851   if (purpose != ntohl (validate->purpose))
852     return GNUNET_SYSERR;       /* purpose mismatch */
853
854   /* build s-expression for signature */
855   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
856                                   "(sig-val(ecdsa(r %b)(s %b)))",
857                                   (int)sizeof (sig->r), sig->r,
858                                   (int)sizeof (sig->s), sig->s)))
859   {
860     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
861     return GNUNET_SYSERR;
862   }
863   data = data_to_ecdsa_value (validate);
864   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
865                             "(public-key(ecc(curve " CURVE ")(q %b)))",
866                                   (int)sizeof (pub->q_y), pub->q_y)))
867   {
868     gcry_sexp_release (data);
869     gcry_sexp_release (sig_sexpr);
870     return GNUNET_SYSERR;
871   }
872   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
873   gcry_sexp_release (pub_sexpr);
874   gcry_sexp_release (data);
875   gcry_sexp_release (sig_sexpr);
876   if (0 != rc)
877   {
878     LOG (GNUNET_ERROR_TYPE_INFO,
879          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
880          __LINE__, gcry_strerror (rc));
881     return GNUNET_SYSERR;
882   }
883   return GNUNET_OK;
884 }
885
886
887
888 /**
889  * Verify signature.
890  *
891  * @param purpose what is the purpose that the signature should have?
892  * @param validate block to validate (size, purpose, data)
893  * @param sig signature that is being validated
894  * @param pub public key of the signer
895  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
896  */
897 int
898 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
899                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
900                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
901                             const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
902 {
903   gcry_sexp_t data;
904   gcry_sexp_t sig_sexpr;
905   gcry_sexp_t pub_sexpr;
906   int rc;
907
908   if (purpose != ntohl (validate->purpose))
909     return GNUNET_SYSERR;       /* purpose mismatch */
910
911   /* build s-expression for signature */
912   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
913                                   "(sig-val(eddsa(r %b)(s %b)))",
914                                   (int)sizeof (sig->r), sig->r,
915                                   (int)sizeof (sig->s), sig->s)))
916   {
917     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
918     return GNUNET_SYSERR;
919   }
920   data = data_to_eddsa_value (validate);
921   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
922                                   "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
923                                   (int)sizeof (pub->q_y), pub->q_y)))
924   {
925     gcry_sexp_release (data);
926     gcry_sexp_release (sig_sexpr);
927     return GNUNET_SYSERR;
928   }
929   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
930   gcry_sexp_release (pub_sexpr);
931   gcry_sexp_release (data);
932   gcry_sexp_release (sig_sexpr);
933   if (0 != rc)
934   {
935     LOG (GNUNET_ERROR_TYPE_INFO,
936          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
937          __LINE__, gcry_strerror (rc));
938     return GNUNET_SYSERR;
939   }
940   return GNUNET_OK;
941 }
942
943
944 /**
945  * Derive key material from a public and a private ECDHE key.
946  *
947  * @param priv private key to use for the ECDH (x)
948  * @param pub public key to use for the ECDH (yG)
949  * @param key_material where to write the key material (xyG)
950  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
951  */
952 int
953 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
954                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
955                         struct GNUNET_HashCode *key_material)
956 {
957   gcry_mpi_point_t result;
958   gcry_mpi_point_t q;
959   gcry_mpi_t d;
960   gcry_ctx_t ctx;
961   gcry_sexp_t pub_sexpr;
962   gcry_mpi_t result_x;
963   unsigned char xbuf[256 / 8];
964   size_t rsize;
965
966   /* first, extract the q = dP value from the public key */
967   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
968                             "(public-key(ecc(curve " CURVE ")(q %b)))",
969                             (int)sizeof (pub->q_y), pub->q_y))
970     return GNUNET_SYSERR;
971   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
972   gcry_sexp_release (pub_sexpr);
973   q = gcry_mpi_ec_get_point ("q", ctx, 0);
974
975   /* second, extract the d value from our private key */
976   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
977
978   /* then call the 'multiply' function, to compute the product */
979   result = gcry_mpi_point_new (0);
980   gcry_mpi_ec_mul (result, d, q, ctx);
981   gcry_mpi_point_release (q);
982   gcry_mpi_release (d);
983
984   /* finally, convert point to string for hashing */
985   result_x = gcry_mpi_new (256);
986   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
987   {
988     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
989     gcry_mpi_point_release (result);
990     gcry_ctx_release (ctx);
991     return GNUNET_SYSERR;
992   }
993   gcry_mpi_point_release (result);
994   gcry_ctx_release (ctx);
995
996   rsize = sizeof (xbuf);
997   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
998   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
999      as that does not include the sign bit; x should be a 255-bit
1000      value, so with the sign it should fit snugly into the 256-bit
1001      xbuf */
1002   GNUNET_assert (0 ==
1003                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1004                                  result_x));
1005   GNUNET_CRYPTO_hash (xbuf,
1006                       rsize,
1007                       key_material);
1008   gcry_mpi_release (result_x);
1009   return GNUNET_OK;
1010 }
1011
1012
1013 /**
1014  * Derive the 'h' value for key derivation, where
1015  * 'h = H(l,P)'.
1016  *
1017  * @param pub public key for deriviation
1018  * @param label label for deriviation
1019  * @param context additional context to use for HKDF of 'h';
1020  *        typically the name of the subsystem/application
1021  * @return h value
1022  */
1023 static gcry_mpi_t
1024 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1025           const char *label,
1026           const char *context)
1027 {
1028   gcry_mpi_t h;
1029   struct GNUNET_HashCode hc;
1030
1031   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1032                      "key-derivation", strlen ("key-derivation"),
1033                      pub, sizeof (*pub),
1034                      label, strlen (label),
1035                      context, strlen (context),
1036                      NULL, 0);
1037   GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1038                                    (unsigned char *) &hc,
1039                                    sizeof (hc));
1040   return h;
1041 }
1042
1043
1044 /**
1045  * Derive a private key from a given private key and a label.
1046  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1047  * where n is the size of the ECC group and P is the public
1048  * key associated with the private key 'd'.
1049  *
1050  * @param priv original private key
1051  * @param label label to use for key deriviation
1052  * @param context additional context to use for HKDF of 'h';
1053  *        typically the name of the subsystem/application
1054  * @return derived private key
1055  */
1056 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1057 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1058                                         const char *label,
1059                                         const char *context)
1060 {
1061   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1062   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1063   gcry_mpi_t h;
1064   gcry_mpi_t x;
1065   gcry_mpi_t d;
1066   gcry_mpi_t n;
1067   gcry_ctx_t ctx;
1068
1069   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1070
1071   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1072   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1073
1074   h = derive_h (&pub, label, context);
1075   GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1076                                    priv->d,
1077                                    sizeof (priv->d));
1078   d = gcry_mpi_new (256);
1079   gcry_mpi_mulm (d, h, x, n);
1080   gcry_mpi_release (h);
1081   gcry_mpi_release (x);
1082   gcry_mpi_release (n);
1083   gcry_ctx_release (ctx);
1084   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1085   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1086   gcry_mpi_release (d);
1087   return ret;
1088 }
1089
1090
1091 /**
1092  * Derive a public key from a given public key and a label.
1093  * Essentially calculates a public key 'V = H(l,P) * P'.
1094  *
1095  * @param pub original public key
1096  * @param label label to use for key derivation
1097  * @param context additional context to use for HKDF of 'h';
1098  *        typically the name of the subsystem/application
1099  * @param result where to write the derived public key
1100  */
1101 void
1102 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1103                                        const char *label,
1104                                        const char *context,
1105                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1106 {
1107   gcry_ctx_t ctx;
1108   gcry_mpi_t q_y;
1109   gcry_mpi_t h;
1110   gcry_mpi_t n;
1111   gcry_mpi_t h_mod_n;
1112   gcry_mpi_point_t q;
1113   gcry_mpi_point_t v;
1114
1115   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1116
1117   /* obtain point 'q' from original public key.  The provided 'q' is
1118      compressed thus we first store it in the context and then get it
1119      back as a (decompresssed) point.  */
1120   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1121   GNUNET_assert (NULL != q_y);
1122   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1123   gcry_mpi_release (q_y);
1124   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1125   GNUNET_assert (q);
1126
1127   /* calculate h_mod_n = h % n */
1128   h = derive_h (pub, label, context);
1129   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1130   h_mod_n = gcry_mpi_new (256);
1131   gcry_mpi_mod (h_mod_n, h, n);
1132   /* calculate v = h_mod_n * q */
1133   v = gcry_mpi_point_new (0);
1134   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1135   gcry_mpi_release (h_mod_n);
1136   gcry_mpi_release (h);
1137   gcry_mpi_release (n);
1138   gcry_mpi_point_release (q);
1139
1140   /* convert point 'v' to public key that we return */
1141   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1142   gcry_mpi_point_release (v);
1143   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1144   GNUNET_assert (q_y);
1145   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1146                                     sizeof (result->q_y),
1147                                     q_y);
1148   gcry_mpi_release (q_y);
1149   gcry_ctx_release (ctx);
1150 }
1151
1152
1153 /**
1154  * Reverse the sequence of the bytes in @a buffer
1155  *
1156  * @param[in|out] buffer buffer to invert
1157  * @param length number of bytes in @a buffer
1158  */
1159 static void
1160 reverse_buffer (unsigned char *buffer,
1161                 size_t length)
1162 {
1163   unsigned char tmp;
1164   size_t i;
1165
1166   for (i=0; i < length/2; i++)
1167   {
1168     tmp = buffer[i];
1169     buffer[i] = buffer[length-1-i];
1170     buffer[length-1-i] = tmp;
1171   }
1172 }
1173
1174
1175 /**
1176  * Convert the secret @a d of an EdDSA key to the
1177  * value that is actually used in the EdDSA computation.
1178  *
1179  * @param d secret input
1180  * @return value used for the calculation in EdDSA
1181  */
1182 static gcry_mpi_t
1183 eddsa_d_to_a (gcry_mpi_t d)
1184 {
1185   unsigned char rawmpi[32]; /* 256-bit value */
1186   size_t rawmpilen;
1187   unsigned char digest[64]; /* 512-bit hash value */
1188   gcry_buffer_t hvec[2];
1189   int b;
1190   gcry_mpi_t a;
1191
1192   b = 256 / 8; /* number of bytes in `d` */
1193
1194   /* Note that we clear DIGEST so we can use it as input to left pad
1195      the key with zeroes for hashing.  */
1196   memset (hvec, 0, sizeof hvec);
1197   rawmpilen = sizeof (rawmpi);
1198   GNUNET_assert (0 ==
1199                  gcry_mpi_print (GCRYMPI_FMT_USG,
1200                                  rawmpi, rawmpilen, &rawmpilen,
1201                                  d));
1202   hvec[0].data = digest;
1203   hvec[0].off = 0;
1204   hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
1205   hvec[1].data = rawmpi;
1206   hvec[1].off = 0;
1207   hvec[1].len = rawmpilen;
1208   GNUNET_assert (0 ==
1209                  gcry_md_hash_buffers (GCRY_MD_SHA512,
1210                                        0 /* flags */,
1211                                        digest,
1212                                        hvec, 2));
1213   /* Compute the A value.  */
1214   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
1215   digest[0]   = (digest[0] & 0x7f) | 0x40;
1216   digest[31] &= 0xf8;
1217
1218   GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1219                                    digest,
1220                                    32);
1221   return a;
1222 }
1223
1224
1225 /**
1226  * @ingroup crypto
1227  * Derive key material from a ECDH public key and a private EdDSA key.
1228  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1229  *
1230  * @param priv private key from EdDSA to use for the ECDH (x)
1231  * @param pub public key to use for the ECDH (yG)
1232  * @param key_material where to write the key material H(h(x)yG)
1233  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1234  */
1235 int
1236 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1237                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1238                           struct GNUNET_HashCode *key_material)
1239 {
1240   gcry_mpi_point_t result;
1241   gcry_mpi_point_t q;
1242   gcry_mpi_t d;
1243   gcry_mpi_t a;
1244   gcry_ctx_t ctx;
1245   gcry_sexp_t pub_sexpr;
1246   gcry_mpi_t result_x;
1247   unsigned char xbuf[256 / 8];
1248   size_t rsize;
1249
1250   /* first, extract the q = dP value from the public key */
1251   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1252                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1253                             (int)sizeof (pub->q_y), pub->q_y))
1254     return GNUNET_SYSERR;
1255   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1256   gcry_sexp_release (pub_sexpr);
1257   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1258
1259   /* second, extract the d value from our private key */
1260   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1261
1262   /* NOW, because this is EdDSA, HASH 'd' first! */
1263   a = eddsa_d_to_a (d);
1264   gcry_mpi_release (d);
1265
1266   /* then call the 'multiply' function, to compute the product */
1267   result = gcry_mpi_point_new (0);
1268   gcry_mpi_ec_mul (result, a, q, ctx);
1269   gcry_mpi_point_release (q);
1270   gcry_mpi_release (a);
1271
1272   /* finally, convert point to string for hashing */
1273   result_x = gcry_mpi_new (256);
1274   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1275   {
1276     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1277     gcry_mpi_point_release (result);
1278     gcry_ctx_release (ctx);
1279     return GNUNET_SYSERR;
1280   }
1281   gcry_mpi_point_release (result);
1282   gcry_ctx_release (ctx);
1283
1284   rsize = sizeof (xbuf);
1285   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1286   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1287      as that does not include the sign bit; x should be a 255-bit
1288      value, so with the sign it should fit snugly into the 256-bit
1289      xbuf */
1290   GNUNET_assert (0 ==
1291                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1292                                  result_x));
1293   GNUNET_CRYPTO_hash (xbuf,
1294                       rsize,
1295                       key_material);
1296   gcry_mpi_release (result_x);
1297   return GNUNET_OK;
1298 }
1299
1300
1301 /**
1302  * @ingroup crypto
1303  * Derive key material from a EdDSA public key and a private ECDH key.
1304  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1305  *
1306  * @param priv private key to use for the ECDH (y)
1307  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1308  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1309  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1310  */
1311 int
1312 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1313                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1314                           struct GNUNET_HashCode *key_material)
1315 {
1316   gcry_mpi_point_t result;
1317   gcry_mpi_point_t q;
1318   gcry_mpi_t d;
1319   gcry_ctx_t ctx;
1320   gcry_sexp_t pub_sexpr;
1321   gcry_mpi_t result_x;
1322   unsigned char xbuf[256 / 8];
1323   size_t rsize;
1324
1325   /* first, extract the q = dP value from the public key */
1326   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1327                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1328                             (int)sizeof (pub->q_y), pub->q_y))
1329     return GNUNET_SYSERR;
1330   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1331   gcry_sexp_release (pub_sexpr);
1332   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1333
1334   /* second, extract the d value from our private key */
1335   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1336
1337   /* then call the 'multiply' function, to compute the product */
1338   result = gcry_mpi_point_new (0);
1339   gcry_mpi_ec_mul (result, d, q, ctx);
1340   gcry_mpi_point_release (q);
1341   gcry_mpi_release (d);
1342
1343   /* finally, convert point to string for hashing */
1344   result_x = gcry_mpi_new (256);
1345   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1346   {
1347     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1348     gcry_mpi_point_release (result);
1349     gcry_ctx_release (ctx);
1350     return GNUNET_SYSERR;
1351   }
1352   gcry_mpi_point_release (result);
1353   gcry_ctx_release (ctx);
1354
1355   rsize = sizeof (xbuf);
1356   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1357   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1358      as that does not include the sign bit; x should be a 255-bit
1359      value, so with the sign it should fit snugly into the 256-bit
1360      xbuf */
1361   GNUNET_assert (0 ==
1362                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1363                                  result_x));
1364   GNUNET_CRYPTO_hash (xbuf,
1365                       rsize,
1366                       key_material);
1367   gcry_mpi_release (result_x);
1368   return GNUNET_OK;
1369 }
1370
1371
1372
1373 /* end of crypto_ecc.c */