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