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