basic benchmarking
[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   printf("crypto eddsa sign\n");
881 #endif
882
883   priv_sexp = decode_private_eddsa_key (priv);
884   data = data_to_eddsa_value (purpose);
885   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
886   {
887     LOG (GNUNET_ERROR_TYPE_WARNING,
888          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
889          __LINE__, gcry_strerror (rc));
890     gcry_sexp_release (data);
891     gcry_sexp_release (priv_sexp);
892     return GNUNET_SYSERR;
893   }
894   gcry_sexp_release (priv_sexp);
895   gcry_sexp_release (data);
896
897   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
898      'signature' */
899   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
900   {
901     GNUNET_break (0);
902     gcry_sexp_release (sig_sexp);
903     return GNUNET_SYSERR;
904   }
905   gcry_sexp_release (sig_sexp);
906   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
907   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
908   gcry_mpi_release (rs[0]);
909   gcry_mpi_release (rs[1]);
910   return GNUNET_OK;
911 }
912
913
914 /**
915  * Verify signature.
916  *
917  * @param purpose what is the purpose that the signature should have?
918  * @param validate block to validate (size, purpose, data)
919  * @param sig signature that is being validated
920  * @param pub public key of the signer
921  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
922  */
923 int
924 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
925                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
926                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
927                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
928 {
929   gcry_sexp_t data;
930   gcry_sexp_t sig_sexpr;
931   gcry_sexp_t pub_sexpr;
932   int rc;
933
934   if (purpose != ntohl (validate->purpose))
935     return GNUNET_SYSERR;       /* purpose mismatch */
936
937   /* build s-expression for signature */
938   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
939                                   "(sig-val(ecdsa(r %b)(s %b)))",
940                                   (int) sizeof (sig->r), sig->r,
941                                   (int) sizeof (sig->s), sig->s)))
942   {
943     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
944     return GNUNET_SYSERR;
945   }
946   data = data_to_ecdsa_value (validate);
947   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
948                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
949                                   (int) sizeof (pub->q_y), pub->q_y)))
950   {
951     gcry_sexp_release (data);
952     gcry_sexp_release (sig_sexpr);
953     return GNUNET_SYSERR;
954   }
955   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
956   gcry_sexp_release (pub_sexpr);
957   gcry_sexp_release (data);
958   gcry_sexp_release (sig_sexpr);
959   if (0 != rc)
960   {
961     LOG (GNUNET_ERROR_TYPE_INFO,
962          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
963          __LINE__, gcry_strerror (rc));
964     return GNUNET_SYSERR;
965   }
966   return GNUNET_OK;
967 }
968
969
970
971 /**
972  * Verify signature.
973  *
974  * @param purpose what is the purpose that the signature should have?
975  * @param validate block to validate (size, purpose, data)
976  * @param sig signature that is being validated
977  * @param pub public key of the signer
978  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
979  */
980 int
981 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
982                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
983                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
984                             const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
985 {
986   gcry_sexp_t data;
987   gcry_sexp_t sig_sexpr;
988   gcry_sexp_t pub_sexpr;
989   int rc;
990
991   if (purpose != ntohl (validate->purpose))
992     return GNUNET_SYSERR;       /* purpose mismatch */
993
994   /* build s-expression for signature */
995   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
996                                   "(sig-val(eddsa(r %b)(s %b)))",
997                                   (int)sizeof (sig->r), sig->r,
998                                   (int)sizeof (sig->s), sig->s)))
999   {
1000     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1001     return GNUNET_SYSERR;
1002   }
1003   data = data_to_eddsa_value (validate);
1004   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1005                                   "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1006                                   (int)sizeof (pub->q_y), pub->q_y)))
1007   {
1008     gcry_sexp_release (data);
1009     gcry_sexp_release (sig_sexpr);
1010     return GNUNET_SYSERR;
1011   }
1012   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1013   gcry_sexp_release (pub_sexpr);
1014   gcry_sexp_release (data);
1015   gcry_sexp_release (sig_sexpr);
1016   if (0 != rc)
1017   {
1018     LOG (GNUNET_ERROR_TYPE_INFO,
1019          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1020          __LINE__, gcry_strerror (rc));
1021     return GNUNET_SYSERR;
1022   }
1023   return GNUNET_OK;
1024 }
1025
1026
1027 /**
1028  * Derive key material from a public and a private ECDHE key.
1029  *
1030  * @param priv private key to use for the ECDH (x)
1031  * @param pub public key to use for the ECDH (yG)
1032  * @param key_material where to write the key material (xyG)
1033  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1034  */
1035 int
1036 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1037                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1038                         struct GNUNET_HashCode *key_material)
1039 {
1040   gcry_mpi_point_t result;
1041   gcry_mpi_point_t q;
1042   gcry_mpi_t d;
1043   gcry_ctx_t ctx;
1044   gcry_sexp_t pub_sexpr;
1045   gcry_mpi_t result_x;
1046   unsigned char xbuf[256 / 8];
1047   size_t rsize;
1048
1049   /* first, extract the q = dP value from the public key */
1050   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1051                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1052                             (int)sizeof (pub->q_y), pub->q_y))
1053     return GNUNET_SYSERR;
1054   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1055   gcry_sexp_release (pub_sexpr);
1056   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1057
1058   /* second, extract the d value from our private key */
1059   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1060
1061   /* then call the 'multiply' function, to compute the product */
1062   result = gcry_mpi_point_new (0);
1063   gcry_mpi_ec_mul (result, d, q, ctx);
1064   gcry_mpi_point_release (q);
1065   gcry_mpi_release (d);
1066
1067   /* finally, convert point to string for hashing */
1068   result_x = gcry_mpi_new (256);
1069   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1070   {
1071     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1072     gcry_mpi_point_release (result);
1073     gcry_ctx_release (ctx);
1074     return GNUNET_SYSERR;
1075   }
1076   gcry_mpi_point_release (result);
1077   gcry_ctx_release (ctx);
1078
1079   rsize = sizeof (xbuf);
1080   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1081   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1082      as that does not include the sign bit; x should be a 255-bit
1083      value, so with the sign it should fit snugly into the 256-bit
1084      xbuf */
1085   GNUNET_assert (0 ==
1086                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1087                                  result_x));
1088   GNUNET_CRYPTO_hash (xbuf,
1089                       rsize,
1090                       key_material);
1091   gcry_mpi_release (result_x);
1092   return GNUNET_OK;
1093 }
1094
1095
1096 /**
1097  * Derive the 'h' value for key derivation, where
1098  * 'h = H(l,P)'.
1099  *
1100  * @param pub public key for deriviation
1101  * @param label label for deriviation
1102  * @param context additional context to use for HKDF of 'h';
1103  *        typically the name of the subsystem/application
1104  * @return h value
1105  */
1106 static gcry_mpi_t
1107 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1108           const char *label,
1109           const char *context)
1110 {
1111   gcry_mpi_t h;
1112   struct GNUNET_HashCode hc;
1113   static const char *const salt = "key-derivation";
1114
1115   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1116                      salt, strlen (salt),
1117                      pub, sizeof (*pub),
1118                      label, strlen (label),
1119                      context, strlen (context),
1120                      NULL, 0);
1121   GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1122                                    (unsigned char *) &hc,
1123                                    sizeof (hc));
1124   return h;
1125 }
1126
1127
1128 /**
1129  * Derive a private key from a given private key and a label.
1130  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1131  * where n is the size of the ECC group and P is the public
1132  * key associated with the private key 'd'.
1133  *
1134  * @param priv original private key
1135  * @param label label to use for key deriviation
1136  * @param context additional context to use for HKDF of 'h';
1137  *        typically the name of the subsystem/application
1138  * @return derived private key
1139  */
1140 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1141 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1142                                         const char *label,
1143                                         const char *context)
1144 {
1145   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1146   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1147   gcry_mpi_t h;
1148   gcry_mpi_t x;
1149   gcry_mpi_t d;
1150   gcry_mpi_t n;
1151   gcry_ctx_t ctx;
1152
1153   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1154
1155   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1156   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1157
1158   h = derive_h (&pub, label, context);
1159   GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1160                                    priv->d,
1161                                    sizeof (priv->d));
1162   d = gcry_mpi_new (256);
1163   gcry_mpi_mulm (d, h, x, n);
1164   gcry_mpi_release (h);
1165   gcry_mpi_release (x);
1166   gcry_mpi_release (n);
1167   gcry_ctx_release (ctx);
1168   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1169   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1170   gcry_mpi_release (d);
1171   return ret;
1172 }
1173
1174
1175 /**
1176  * Derive a public key from a given public key and a label.
1177  * Essentially calculates a public key 'V = H(l,P) * P'.
1178  *
1179  * @param pub original public key
1180  * @param label label to use for key derivation
1181  * @param context additional context to use for HKDF of 'h';
1182  *        typically the name of the subsystem/application
1183  * @param result where to write the derived public key
1184  */
1185 void
1186 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1187                                        const char *label,
1188                                        const char *context,
1189                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1190 {
1191   gcry_ctx_t ctx;
1192   gcry_mpi_t q_y;
1193   gcry_mpi_t h;
1194   gcry_mpi_t n;
1195   gcry_mpi_t h_mod_n;
1196   gcry_mpi_point_t q;
1197   gcry_mpi_point_t v;
1198
1199   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1200
1201   /* obtain point 'q' from original public key.  The provided 'q' is
1202      compressed thus we first store it in the context and then get it
1203      back as a (decompresssed) point.  */
1204   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1205   GNUNET_assert (NULL != q_y);
1206   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1207   gcry_mpi_release (q_y);
1208   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1209   GNUNET_assert (q);
1210
1211   /* calculate h_mod_n = h % n */
1212   h = derive_h (pub, label, context);
1213   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1214   h_mod_n = gcry_mpi_new (256);
1215   gcry_mpi_mod (h_mod_n, h, n);
1216   /* calculate v = h_mod_n * q */
1217   v = gcry_mpi_point_new (0);
1218   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1219   gcry_mpi_release (h_mod_n);
1220   gcry_mpi_release (h);
1221   gcry_mpi_release (n);
1222   gcry_mpi_point_release (q);
1223
1224   /* convert point 'v' to public key that we return */
1225   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1226   gcry_mpi_point_release (v);
1227   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1228   GNUNET_assert (q_y);
1229   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1230                                     sizeof (result->q_y),
1231                                     q_y);
1232   gcry_mpi_release (q_y);
1233   gcry_ctx_release (ctx);
1234 }
1235
1236
1237 /**
1238  * Reverse the sequence of the bytes in @a buffer
1239  *
1240  * @param[in|out] buffer buffer to invert
1241  * @param length number of bytes in @a buffer
1242  */
1243 static void
1244 reverse_buffer (unsigned char *buffer,
1245                 size_t length)
1246 {
1247   unsigned char tmp;
1248   size_t i;
1249
1250   for (i=0; i < length/2; i++)
1251   {
1252     tmp = buffer[i];
1253     buffer[i] = buffer[length-1-i];
1254     buffer[length-1-i] = tmp;
1255   }
1256 }
1257
1258
1259 /**
1260  * Convert the secret @a d of an EdDSA key to the
1261  * value that is actually used in the EdDSA computation.
1262  *
1263  * @param d secret input
1264  * @return value used for the calculation in EdDSA
1265  */
1266 static gcry_mpi_t
1267 eddsa_d_to_a (gcry_mpi_t d)
1268 {
1269   unsigned char rawmpi[32]; /* 256-bit value */
1270   size_t rawmpilen;
1271   unsigned char digest[64]; /* 512-bit hash value */
1272   gcry_buffer_t hvec[2];
1273   unsigned int b;
1274   gcry_mpi_t a;
1275
1276   b = 256 / 8; /* number of bytes in `d` */
1277
1278   /* Note that we clear DIGEST so we can use it as input to left pad
1279      the key with zeroes for hashing.  */
1280   memset (digest, 0, sizeof digest);
1281   memset (hvec, 0, sizeof hvec);
1282   rawmpilen = sizeof (rawmpi);
1283   GNUNET_assert (0 ==
1284                  gcry_mpi_print (GCRYMPI_FMT_USG,
1285                                  rawmpi, rawmpilen, &rawmpilen,
1286                                  d));
1287   hvec[0].data = digest;
1288   hvec[0].off = 0;
1289   hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1290   hvec[1].data = rawmpi;
1291   hvec[1].off = 0;
1292   hvec[1].len = rawmpilen;
1293   GNUNET_assert (0 ==
1294                  gcry_md_hash_buffers (GCRY_MD_SHA512,
1295                                        0 /* flags */,
1296                                        digest,
1297                                        hvec, 2));
1298   /* Compute the A value.  */
1299   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
1300   digest[0]   = (digest[0] & 0x7f) | 0x40;
1301   digest[31] &= 0xf8;
1302
1303   GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1304                                    digest,
1305                                    32);
1306   return a;
1307 }
1308
1309
1310 /**
1311  * Take point from ECDH and convert it to key material.
1312  *
1313  * @param result point from ECDH
1314  * @param ctx ECC context
1315  * @param key_material[out] set to derived key material
1316  * @return #GNUNET_OK on success
1317  */
1318 static int
1319 point_to_hash (gcry_mpi_point_t result,
1320                gcry_ctx_t ctx,
1321                struct GNUNET_HashCode *key_material)
1322 {
1323   gcry_mpi_t result_x;
1324   unsigned char xbuf[256 / 8];
1325   size_t rsize;
1326
1327   /* finally, convert point to string for hashing */
1328   result_x = gcry_mpi_new (256);
1329   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1330   {
1331     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1332     return GNUNET_SYSERR;
1333   }
1334
1335   rsize = sizeof (xbuf);
1336   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1337   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1338      as that does not include the sign bit; x should be a 255-bit
1339      value, so with the sign it should fit snugly into the 256-bit
1340      xbuf */
1341   GNUNET_assert (0 ==
1342                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1343                                  result_x));
1344   GNUNET_CRYPTO_hash (xbuf,
1345                       rsize,
1346                       key_material);
1347   gcry_mpi_release (result_x);
1348   return GNUNET_OK;
1349 }
1350
1351
1352 /**
1353  * @ingroup crypto
1354  * Derive key material from a ECDH public key and a private EdDSA key.
1355  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1356  *
1357  * @param priv private key from EdDSA to use for the ECDH (x)
1358  * @param pub public key to use for the ECDH (yG)
1359  * @param key_material where to write the key material H(h(x)yG)
1360  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1361  */
1362 int
1363 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1364                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1365                           struct GNUNET_HashCode *key_material)
1366 {
1367   gcry_mpi_point_t result;
1368   gcry_mpi_point_t q;
1369   gcry_mpi_t d;
1370   gcry_mpi_t a;
1371   gcry_ctx_t ctx;
1372   gcry_sexp_t pub_sexpr;
1373   int ret;
1374
1375   /* first, extract the q = dP value from the public key */
1376   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1377                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1378                             (int)sizeof (pub->q_y), pub->q_y))
1379     return GNUNET_SYSERR;
1380   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1381   gcry_sexp_release (pub_sexpr);
1382   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1383
1384   /* second, extract the d value from our private key */
1385   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1386
1387   /* NOW, because this is EdDSA, HASH 'd' first! */
1388   a = eddsa_d_to_a (d);
1389   gcry_mpi_release (d);
1390
1391   /* then call the 'multiply' function, to compute the product */
1392   result = gcry_mpi_point_new (0);
1393   gcry_mpi_ec_mul (result, a, q, ctx);
1394   gcry_mpi_point_release (q);
1395   gcry_mpi_release (a);
1396
1397   ret = point_to_hash (result,
1398                        ctx,
1399                        key_material);
1400   gcry_mpi_point_release (result);
1401   gcry_ctx_release (ctx);
1402   return ret;
1403 }
1404
1405
1406 /**
1407  * @ingroup crypto
1408  * Derive key material from a ECDH public key and a private ECDSA key.
1409  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1410  *
1411  * @param priv private key from ECDSA to use for the ECDH (x)
1412  * @param pub public key to use for the ECDH (yG)
1413  * @param key_material where to write the key material H(h(x)yG)
1414  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1415  */
1416 int
1417 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1418                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1419                           struct GNUNET_HashCode *key_material)
1420 {
1421   gcry_mpi_point_t result;
1422   gcry_mpi_point_t q;
1423   gcry_mpi_t d;
1424   gcry_ctx_t ctx;
1425   gcry_sexp_t pub_sexpr;
1426   int ret;
1427
1428   /* first, extract the q = dP value from the public key */
1429   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1430                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1431                             (int)sizeof (pub->q_y), pub->q_y))
1432     return GNUNET_SYSERR;
1433   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1434   gcry_sexp_release (pub_sexpr);
1435   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1436
1437   /* second, extract the d value from our private key */
1438   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1439
1440   /* then call the 'multiply' function, to compute the product */
1441   result = gcry_mpi_point_new (0);
1442   gcry_mpi_ec_mul (result, d, q, ctx);
1443   gcry_mpi_point_release (q);
1444   gcry_mpi_release (d);
1445
1446   /* finally, convert point to string for hashing */
1447   ret = point_to_hash (result,
1448                        ctx,
1449                        key_material);
1450   gcry_mpi_point_release (result);
1451   gcry_ctx_release (ctx);
1452   return ret;
1453 }
1454
1455
1456
1457 /**
1458  * @ingroup crypto
1459  * Derive key material from a EdDSA public key and a private ECDH key.
1460  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1461  *
1462  * @param priv private key to use for the ECDH (y)
1463  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1464  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1465  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1466  */
1467 int
1468 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1469                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1470                           struct GNUNET_HashCode *key_material)
1471 {
1472   gcry_mpi_point_t result;
1473   gcry_mpi_point_t q;
1474   gcry_mpi_t d;
1475   gcry_ctx_t ctx;
1476   gcry_sexp_t pub_sexpr;
1477   int ret;
1478
1479   /* first, extract the q = dP value from the public key */
1480   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1481                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1482                             (int)sizeof (pub->q_y), pub->q_y))
1483     return GNUNET_SYSERR;
1484   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1485   gcry_sexp_release (pub_sexpr);
1486   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1487
1488   /* second, extract the d value from our private key */
1489   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1490
1491   /* then call the 'multiply' function, to compute the product */
1492   result = gcry_mpi_point_new (0);
1493   gcry_mpi_ec_mul (result, d, q, ctx);
1494   gcry_mpi_point_release (q);
1495   gcry_mpi_release (d);
1496
1497   /* finally, convert point to string for hashing */
1498   ret = point_to_hash (result,
1499                        ctx,
1500                        key_material);
1501   gcry_mpi_point_release (result);
1502   gcry_ctx_release (ctx);
1503   return ret;
1504 }
1505
1506 /**
1507  * @ingroup crypto
1508  * Derive key material from a ECDSA public key and a private ECDH key.
1509  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1510  *
1511  * @param priv private key to use for the ECDH (y)
1512  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1513  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1514  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1515  */
1516 int
1517 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1518                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1519                           struct GNUNET_HashCode *key_material)
1520 {
1521   return GNUNET_CRYPTO_ecdh_eddsa (priv,
1522                                    (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1523                                    key_material);
1524 }
1525
1526 /* end of crypto_ecc.c */