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