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