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