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