Merge branch 'master' of ssh://gnunet.org/gnunet
[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 string representing a public key to a public key.
358  *
359  * @param enc encoded public key
360  * @param enclen number of bytes in @a enc (without 0-terminator)
361  * @param pub where to store the public key
362  * @return #GNUNET_OK on success
363  */
364 int
365 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
366                                             size_t enclen,
367                                             struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
368 {
369   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
370
371   if (keylen % 5 > 0)
372     keylen += 5 - keylen % 5;
373   keylen /= 5;
374   if (enclen != keylen)
375     return GNUNET_SYSERR;
376
377   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
378                                                   pub,
379                                                   sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
380     return GNUNET_SYSERR;
381   return GNUNET_OK;
382 }
383
384
385 /**
386  * Convert a string representing a public key to a public key.
387  *
388  * @param enc encoded public key
389  * @param enclen number of bytes in @a enc (without 0-terminator)
390  * @param pub where to store the public key
391  * @return #GNUNET_OK on success
392  */
393 int
394 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
395                                             size_t enclen,
396                                             struct GNUNET_CRYPTO_EddsaPublicKey *pub)
397 {
398   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
399
400   if (keylen % 5 > 0)
401     keylen += 5 - keylen % 5;
402   keylen /= 5;
403   if (enclen != keylen)
404     return GNUNET_SYSERR;
405
406   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
407                                                   pub,
408                                                   sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
409     return GNUNET_SYSERR;
410   return GNUNET_OK;
411 }
412
413
414 /**
415  * Convert a string representing a private key to a private key.
416  *
417  * @param enc encoded public key
418  * @param enclen number of bytes in @a enc (without 0-terminator)
419  * @param priv where to store the private key
420  * @return #GNUNET_OK on success
421  */
422 int
423 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
424                                              size_t enclen,
425                                              struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
426 {
427   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
428
429   if (keylen % 5 > 0)
430     keylen += 5 - keylen % 5;
431   keylen /= 5;
432   if (enclen != keylen)
433     return GNUNET_SYSERR;
434
435   if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
436                                                   pub,
437                                                   sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
438     return GNUNET_SYSERR;
439   return GNUNET_OK;
440 }
441
442
443 /**
444  * @ingroup crypto
445  * Clear memory that was used to store a private key.
446  *
447  * @param pk location of the key
448  */
449 void
450 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
451 {
452   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
453 }
454
455
456 /**
457  * @ingroup crypto
458  * Clear memory that was used to store a private key.
459  *
460  * @param pk location of the key
461  */
462 void
463 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
464 {
465   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
466 }
467
468
469 /**
470  * @ingroup crypto
471  * Clear memory that was used to store a private key.
472  *
473  * @param pk location of the key
474  */
475 void
476 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
477 {
478   memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
479 }
480
481
482 /**
483  * Create a new private key. Caller must free return value.
484  *
485  * @return fresh private key
486  */
487 struct GNUNET_CRYPTO_EcdhePrivateKey *
488 GNUNET_CRYPTO_ecdhe_key_create ()
489 {
490   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
491
492   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
493   if (GNUNET_OK !=
494       GNUNET_CRYPTO_ecdhe_key_create2 (priv))
495   {
496     GNUNET_free (priv);
497     return NULL;
498   }
499   return priv;
500 }
501
502
503 /**
504  * @ingroup crypto
505  * Create a new private key.  Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
506  *
507  * @param[out] pk set to fresh private key;
508  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
509  */
510 int
511 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
512 {
513   gcry_sexp_t priv_sexp;
514   gcry_sexp_t s_keyparam;
515   gcry_mpi_t d;
516   int rc;
517
518   /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
519      but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
520      disables an expensive key testing routine. We do not want to run
521      the expensive check for ECDHE, as we generate TONS of keys to
522      use for a very short time. */
523   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
524                                   "(genkey(ecc(curve \"" CURVE "\")"
525                                   "(flags eddsa no-keytest)))")))
526   {
527     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
528     return GNUNET_SYSERR;
529   }
530   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
531   {
532     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
533     gcry_sexp_release (s_keyparam);
534     return GNUNET_SYSERR;
535   }
536   gcry_sexp_release (s_keyparam);
537 #if EXTRA_CHECKS
538   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
539   {
540     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
541     gcry_sexp_release (priv_sexp);
542     return GNUNET_SYSERR;
543   }
544 #endif
545   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
546   {
547     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
548     gcry_sexp_release (priv_sexp);
549     return GNUNET_SYSERR;
550   }
551   gcry_sexp_release (priv_sexp);
552   GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
553   gcry_mpi_release (d);
554   return GNUNET_OK;
555 }
556
557
558 /**
559  * Create a new private key. Caller must free return value.
560  *
561  * @return fresh private key
562  */
563 struct GNUNET_CRYPTO_EcdsaPrivateKey *
564 GNUNET_CRYPTO_ecdsa_key_create ()
565 {
566   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
567   gcry_sexp_t priv_sexp;
568   gcry_sexp_t s_keyparam;
569   gcry_mpi_t d;
570   int rc;
571
572   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
573                                   "(genkey(ecc(curve \"" CURVE "\")"
574                                   "(flags)))")))
575   {
576     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
577     return NULL;
578   }
579   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
580   {
581     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
582     gcry_sexp_release (s_keyparam);
583     return NULL;
584   }
585   gcry_sexp_release (s_keyparam);
586 #if EXTRA_CHECKS
587   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
588   {
589     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
590     gcry_sexp_release (priv_sexp);
591     return NULL;
592   }
593 #endif
594   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
595   {
596     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
597     gcry_sexp_release (priv_sexp);
598     return NULL;
599   }
600   gcry_sexp_release (priv_sexp);
601   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
602   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
603   gcry_mpi_release (d);
604   return priv;
605 }
606
607 /**
608  * Create a new private key. Caller must free return value.
609  *
610  * @return fresh private key
611  */
612 struct GNUNET_CRYPTO_EddsaPrivateKey *
613 GNUNET_CRYPTO_eddsa_key_create ()
614 {
615   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
616   gcry_sexp_t priv_sexp;
617   gcry_sexp_t s_keyparam;
618   gcry_mpi_t d;
619   int rc;
620
621   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
622                                   "(genkey(ecc(curve \"" CURVE "\")"
623                                   "(flags eddsa)))")))
624   {
625     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
626     return NULL;
627   }
628   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
629   {
630     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
631     gcry_sexp_release (s_keyparam);
632     return NULL;
633   }
634   gcry_sexp_release (s_keyparam);
635 #if EXTRA_CHECKS
636   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
637   {
638     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
639     gcry_sexp_release (priv_sexp);
640     return NULL;
641   }
642 #endif
643   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
644   {
645     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
646     gcry_sexp_release (priv_sexp);
647     return NULL;
648   }
649   gcry_sexp_release (priv_sexp);
650   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
651   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
652   gcry_mpi_release (d);
653   return priv;
654 }
655
656
657 /**
658  * Get the shared private key we use for anonymous users.
659  *
660  * @return "anonymous" private key
661  */
662 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
663 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
664 {
665   /**
666    * 'anonymous' pseudonym (global static, d=1, public key = G
667    * (generator).
668    */
669   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
670   static int once;
671
672   if (once)
673     return &anonymous;
674   GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
675              sizeof (anonymous.d),
676              GCRYMPI_CONST_ONE);
677   once = 1;
678   return &anonymous;
679 }
680
681
682 /**
683  * Compare two Peer Identities.
684  *
685  * @param first first peer identity
686  * @param second second peer identity
687  * @return bigger than 0 if first > second,
688  *         0 if they are the same
689  *         smaller than 0 if second > first
690  */
691 int
692 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
693                                  const struct GNUNET_PeerIdentity *second)
694 {
695   return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
696 }
697
698
699 /**
700  * Convert the data specified in the given purpose argument to an
701  * S-expression suitable for signature operations.
702  *
703  * @param purpose data to convert
704  * @return converted s-expression
705  */
706 static gcry_sexp_t
707 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
708 {
709   struct GNUNET_HashCode hc;
710   gcry_sexp_t data;
711   int rc;
712
713   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
714   if (0 != (rc = gcry_sexp_build (&data, NULL,
715                                   "(data(flags eddsa)(hash-algo %s)(value %b))",
716                                   "sha512",
717                                   (int)sizeof (hc), &hc)))
718   {
719     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
720     return NULL;
721   }
722   return data;
723 }
724
725
726 /**
727  * Convert the data specified in the given purpose argument to an
728  * S-expression suitable for signature operations.
729  *
730  * @param purpose data to convert
731  * @return converted s-expression
732  */
733 static gcry_sexp_t
734 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
735 {
736   struct GNUNET_HashCode hc;
737   gcry_sexp_t data;
738   int rc;
739
740   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
741   if (0 != (rc = gcry_sexp_build (&data, NULL,
742                                   "(data(flags rfc6979)(hash %s %b))",
743                                   "sha512",
744                                   (int)sizeof (hc), &hc)))
745   {
746     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
747     return NULL;
748   }
749   return data;
750 }
751
752
753 /**
754  * Sign a given block.
755  *
756  * @param priv private key to use for the signing
757  * @param purpose what to sign (size, purpose)
758  * @param sig where to write the signature
759  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
760  */
761 int
762 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
763                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
764                           struct GNUNET_CRYPTO_EcdsaSignature *sig)
765 {
766   gcry_sexp_t priv_sexp;
767   gcry_sexp_t sig_sexp;
768   gcry_sexp_t data;
769   int rc;
770   gcry_mpi_t rs[2];
771
772   priv_sexp = decode_private_ecdsa_key (priv);
773   data = data_to_ecdsa_value (purpose);
774   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
775   {
776     LOG (GNUNET_ERROR_TYPE_WARNING,
777          _("ECC signing failed at %s:%d: %s\n"), __FILE__,
778          __LINE__, gcry_strerror (rc));
779     gcry_sexp_release (data);
780     gcry_sexp_release (priv_sexp);
781     return GNUNET_SYSERR;
782   }
783   gcry_sexp_release (priv_sexp);
784   gcry_sexp_release (data);
785
786   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
787      'signature' */
788   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
789   {
790     GNUNET_break (0);
791     gcry_sexp_release (sig_sexp);
792     return GNUNET_SYSERR;
793   }
794   gcry_sexp_release (sig_sexp);
795   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
796   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
797   gcry_mpi_release (rs[0]);
798   gcry_mpi_release (rs[1]);
799   return GNUNET_OK;
800 }
801
802
803 /**
804  * Sign a given block.
805  *
806  * @param priv private key to use for the signing
807  * @param purpose what to sign (size, purpose)
808  * @param sig where to write the signature
809  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
810  */
811 int
812 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
813                           const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
814                           struct GNUNET_CRYPTO_EddsaSignature *sig)
815 {
816   gcry_sexp_t priv_sexp;
817   gcry_sexp_t sig_sexp;
818   gcry_sexp_t data;
819   int rc;
820   gcry_mpi_t rs[2];
821
822   priv_sexp = decode_private_eddsa_key (priv);
823   data = data_to_eddsa_value (purpose);
824   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
825   {
826     LOG (GNUNET_ERROR_TYPE_WARNING,
827          _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
828          __LINE__, gcry_strerror (rc));
829     gcry_sexp_release (data);
830     gcry_sexp_release (priv_sexp);
831     return GNUNET_SYSERR;
832   }
833   gcry_sexp_release (priv_sexp);
834   gcry_sexp_release (data);
835
836   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
837      'signature' */
838   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
839   {
840     GNUNET_break (0);
841     gcry_sexp_release (sig_sexp);
842     return GNUNET_SYSERR;
843   }
844   gcry_sexp_release (sig_sexp);
845   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
846   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
847   gcry_mpi_release (rs[0]);
848   gcry_mpi_release (rs[1]);
849   return GNUNET_OK;
850 }
851
852
853 /**
854  * Verify signature.
855  *
856  * @param purpose what is the purpose that the signature should have?
857  * @param validate block to validate (size, purpose, data)
858  * @param sig signature that is being validated
859  * @param pub public key of the signer
860  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
861  */
862 int
863 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
864                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
865                             const struct GNUNET_CRYPTO_EcdsaSignature *sig,
866                             const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
867 {
868   gcry_sexp_t data;
869   gcry_sexp_t sig_sexpr;
870   gcry_sexp_t pub_sexpr;
871   int rc;
872
873   if (purpose != ntohl (validate->purpose))
874     return GNUNET_SYSERR;       /* purpose mismatch */
875
876   /* build s-expression for signature */
877   if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
878                                   "(sig-val(ecdsa(r %b)(s %b)))",
879                                   (int) sizeof (sig->r), sig->r,
880                                   (int) sizeof (sig->s), sig->s)))
881   {
882     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
883     return GNUNET_SYSERR;
884   }
885   data = data_to_ecdsa_value (validate);
886   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
887                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
888                                   (int) sizeof (pub->q_y), pub->q_y)))
889   {
890     gcry_sexp_release (data);
891     gcry_sexp_release (sig_sexpr);
892     return GNUNET_SYSERR;
893   }
894   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
895   gcry_sexp_release (pub_sexpr);
896   gcry_sexp_release (data);
897   gcry_sexp_release (sig_sexpr);
898   if (0 != rc)
899   {
900     LOG (GNUNET_ERROR_TYPE_INFO,
901          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
902          __LINE__, gcry_strerror (rc));
903     return GNUNET_SYSERR;
904   }
905   return GNUNET_OK;
906 }
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_eddsa_verify (uint32_t purpose,
921                             const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
922                             const struct GNUNET_CRYPTO_EddsaSignature *sig,
923                             const struct GNUNET_CRYPTO_EddsaPublicKey *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(eddsa(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_eddsa_value (validate);
943   if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
944                                   "(public-key(ecc(curve " CURVE ")(flags eddsa)(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          _("EdDSA 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  * Derive key material from a public and a private ECDHE key.
968  *
969  * @param priv private key to use for the ECDH (x)
970  * @param pub public key to use for the ECDH (yG)
971  * @param key_material where to write the key material (xyG)
972  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
973  */
974 int
975 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
976                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
977                         struct GNUNET_HashCode *key_material)
978 {
979   gcry_mpi_point_t result;
980   gcry_mpi_point_t q;
981   gcry_mpi_t d;
982   gcry_ctx_t ctx;
983   gcry_sexp_t pub_sexpr;
984   gcry_mpi_t result_x;
985   unsigned char xbuf[256 / 8];
986   size_t rsize;
987
988   /* first, extract the q = dP value from the public key */
989   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
990                             "(public-key(ecc(curve " CURVE ")(q %b)))",
991                             (int)sizeof (pub->q_y), pub->q_y))
992     return GNUNET_SYSERR;
993   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
994   gcry_sexp_release (pub_sexpr);
995   q = gcry_mpi_ec_get_point ("q", ctx, 0);
996
997   /* second, extract the d value from our private key */
998   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
999
1000   /* then call the 'multiply' function, to compute the product */
1001   result = gcry_mpi_point_new (0);
1002   gcry_mpi_ec_mul (result, d, q, ctx);
1003   gcry_mpi_point_release (q);
1004   gcry_mpi_release (d);
1005
1006   /* finally, convert point to string for hashing */
1007   result_x = gcry_mpi_new (256);
1008   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1009   {
1010     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1011     gcry_mpi_point_release (result);
1012     gcry_ctx_release (ctx);
1013     return GNUNET_SYSERR;
1014   }
1015   gcry_mpi_point_release (result);
1016   gcry_ctx_release (ctx);
1017
1018   rsize = sizeof (xbuf);
1019   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1020   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1021      as that does not include the sign bit; x should be a 255-bit
1022      value, so with the sign it should fit snugly into the 256-bit
1023      xbuf */
1024   GNUNET_assert (0 ==
1025                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1026                                  result_x));
1027   GNUNET_CRYPTO_hash (xbuf,
1028                       rsize,
1029                       key_material);
1030   gcry_mpi_release (result_x);
1031   return GNUNET_OK;
1032 }
1033
1034
1035 /**
1036  * Derive the 'h' value for key derivation, where
1037  * 'h = H(l,P)'.
1038  *
1039  * @param pub public key for deriviation
1040  * @param label label for deriviation
1041  * @param context additional context to use for HKDF of 'h';
1042  *        typically the name of the subsystem/application
1043  * @return h value
1044  */
1045 static gcry_mpi_t
1046 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1047           const char *label,
1048           const char *context)
1049 {
1050   gcry_mpi_t h;
1051   struct GNUNET_HashCode hc;
1052   static const char *const salt = "key-derivation";
1053
1054   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1055                      salt, strlen (salt),
1056                      pub, sizeof (*pub),
1057                      label, strlen (label),
1058                      context, strlen (context),
1059                      NULL, 0);
1060   GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1061                                    (unsigned char *) &hc,
1062                                    sizeof (hc));
1063   return h;
1064 }
1065
1066
1067 /**
1068  * Derive a private key from a given private key and a label.
1069  * Essentially calculates a private key 'd = H(l,P) * x mod n'
1070  * where n is the size of the ECC group and P is the public
1071  * key associated with the private key 'd'.
1072  *
1073  * @param priv original private key
1074  * @param label label to use for key deriviation
1075  * @param context additional context to use for HKDF of 'h';
1076  *        typically the name of the subsystem/application
1077  * @return derived private key
1078  */
1079 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1080 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1081                                         const char *label,
1082                                         const char *context)
1083 {
1084   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1085   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1086   gcry_mpi_t h;
1087   gcry_mpi_t x;
1088   gcry_mpi_t d;
1089   gcry_mpi_t n;
1090   gcry_ctx_t ctx;
1091
1092   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1093
1094   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1095   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1096
1097   h = derive_h (&pub, label, context);
1098   GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1099                                    priv->d,
1100                                    sizeof (priv->d));
1101   d = gcry_mpi_new (256);
1102   gcry_mpi_mulm (d, h, x, n);
1103   gcry_mpi_release (h);
1104   gcry_mpi_release (x);
1105   gcry_mpi_release (n);
1106   gcry_ctx_release (ctx);
1107   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1108   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1109   gcry_mpi_release (d);
1110   return ret;
1111 }
1112
1113
1114 /**
1115  * Derive a public key from a given public key and a label.
1116  * Essentially calculates a public key 'V = H(l,P) * P'.
1117  *
1118  * @param pub original public key
1119  * @param label label to use for key derivation
1120  * @param context additional context to use for HKDF of 'h';
1121  *        typically the name of the subsystem/application
1122  * @param result where to write the derived public key
1123  */
1124 void
1125 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1126                                        const char *label,
1127                                        const char *context,
1128                                        struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1129 {
1130   gcry_ctx_t ctx;
1131   gcry_mpi_t q_y;
1132   gcry_mpi_t h;
1133   gcry_mpi_t n;
1134   gcry_mpi_t h_mod_n;
1135   gcry_mpi_point_t q;
1136   gcry_mpi_point_t v;
1137
1138   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1139
1140   /* obtain point 'q' from original public key.  The provided 'q' is
1141      compressed thus we first store it in the context and then get it
1142      back as a (decompresssed) point.  */
1143   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1144   GNUNET_assert (NULL != q_y);
1145   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1146   gcry_mpi_release (q_y);
1147   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1148   GNUNET_assert (q);
1149
1150   /* calculate h_mod_n = h % n */
1151   h = derive_h (pub, label, context);
1152   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1153   h_mod_n = gcry_mpi_new (256);
1154   gcry_mpi_mod (h_mod_n, h, n);
1155   /* calculate v = h_mod_n * q */
1156   v = gcry_mpi_point_new (0);
1157   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1158   gcry_mpi_release (h_mod_n);
1159   gcry_mpi_release (h);
1160   gcry_mpi_release (n);
1161   gcry_mpi_point_release (q);
1162
1163   /* convert point 'v' to public key that we return */
1164   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1165   gcry_mpi_point_release (v);
1166   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1167   GNUNET_assert (q_y);
1168   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1169                                     sizeof (result->q_y),
1170                                     q_y);
1171   gcry_mpi_release (q_y);
1172   gcry_ctx_release (ctx);
1173 }
1174
1175
1176 /**
1177  * Reverse the sequence of the bytes in @a buffer
1178  *
1179  * @param[in|out] buffer buffer to invert
1180  * @param length number of bytes in @a buffer
1181  */
1182 static void
1183 reverse_buffer (unsigned char *buffer,
1184                 size_t length)
1185 {
1186   unsigned char tmp;
1187   size_t i;
1188
1189   for (i=0; i < length/2; i++)
1190   {
1191     tmp = buffer[i];
1192     buffer[i] = buffer[length-1-i];
1193     buffer[length-1-i] = tmp;
1194   }
1195 }
1196
1197
1198 /**
1199  * Convert the secret @a d of an EdDSA key to the
1200  * value that is actually used in the EdDSA computation.
1201  *
1202  * @param d secret input
1203  * @return value used for the calculation in EdDSA
1204  */
1205 static gcry_mpi_t
1206 eddsa_d_to_a (gcry_mpi_t d)
1207 {
1208   unsigned char rawmpi[32]; /* 256-bit value */
1209   size_t rawmpilen;
1210   unsigned char digest[64]; /* 512-bit hash value */
1211   gcry_buffer_t hvec[2];
1212   int b;
1213   gcry_mpi_t a;
1214
1215   b = 256 / 8; /* number of bytes in `d` */
1216
1217   /* Note that we clear DIGEST so we can use it as input to left pad
1218      the key with zeroes for hashing.  */
1219   memset (hvec, 0, sizeof hvec);
1220   rawmpilen = sizeof (rawmpi);
1221   GNUNET_assert (0 ==
1222                  gcry_mpi_print (GCRYMPI_FMT_USG,
1223                                  rawmpi, rawmpilen, &rawmpilen,
1224                                  d));
1225   hvec[0].data = digest;
1226   hvec[0].off = 0;
1227   hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
1228   hvec[1].data = rawmpi;
1229   hvec[1].off = 0;
1230   hvec[1].len = rawmpilen;
1231   GNUNET_assert (0 ==
1232                  gcry_md_hash_buffers (GCRY_MD_SHA512,
1233                                        0 /* flags */,
1234                                        digest,
1235                                        hvec, 2));
1236   /* Compute the A value.  */
1237   reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
1238   digest[0]   = (digest[0] & 0x7f) | 0x40;
1239   digest[31] &= 0xf8;
1240
1241   GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1242                                    digest,
1243                                    32);
1244   return a;
1245 }
1246
1247
1248 /**
1249  * @ingroup crypto
1250  * Derive key material from a ECDH public key and a private EdDSA key.
1251  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1252  *
1253  * @param priv private key from EdDSA to use for the ECDH (x)
1254  * @param pub public key to use for the ECDH (yG)
1255  * @param key_material where to write the key material H(h(x)yG)
1256  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1257  */
1258 int
1259 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1260                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1261                           struct GNUNET_HashCode *key_material)
1262 {
1263   gcry_mpi_point_t result;
1264   gcry_mpi_point_t q;
1265   gcry_mpi_t d;
1266   gcry_mpi_t a;
1267   gcry_ctx_t ctx;
1268   gcry_sexp_t pub_sexpr;
1269   gcry_mpi_t result_x;
1270   unsigned char xbuf[256 / 8];
1271   size_t rsize;
1272
1273   /* first, extract the q = dP value from the public key */
1274   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1275                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1276                             (int)sizeof (pub->q_y), pub->q_y))
1277     return GNUNET_SYSERR;
1278   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1279   gcry_sexp_release (pub_sexpr);
1280   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1281
1282   /* second, extract the d value from our private key */
1283   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1284
1285   /* NOW, because this is EdDSA, HASH 'd' first! */
1286   a = eddsa_d_to_a (d);
1287   gcry_mpi_release (d);
1288
1289   /* then call the 'multiply' function, to compute the product */
1290   result = gcry_mpi_point_new (0);
1291   gcry_mpi_ec_mul (result, a, q, ctx);
1292   gcry_mpi_point_release (q);
1293   gcry_mpi_release (a);
1294
1295   /* finally, convert point to string for hashing */
1296   result_x = gcry_mpi_new (256);
1297   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1298   {
1299     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1300     gcry_mpi_point_release (result);
1301     gcry_ctx_release (ctx);
1302     return GNUNET_SYSERR;
1303   }
1304   gcry_mpi_point_release (result);
1305   gcry_ctx_release (ctx);
1306
1307   rsize = sizeof (xbuf);
1308   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1309   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1310      as that does not include the sign bit; x should be a 255-bit
1311      value, so with the sign it should fit snugly into the 256-bit
1312      xbuf */
1313   GNUNET_assert (0 ==
1314                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1315                                  result_x));
1316   GNUNET_CRYPTO_hash (xbuf,
1317                       rsize,
1318                       key_material);
1319   gcry_mpi_release (result_x);
1320   return GNUNET_OK;
1321 }
1322
1323 /**
1324  * @ingroup crypto
1325  * Derive key material from a ECDH public key and a private ECDSA key.
1326  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1327  *
1328  * @param priv private key from ECDSA to use for the ECDH (x)
1329  * @param pub public key to use for the ECDH (yG)
1330  * @param key_material where to write the key material H(h(x)yG)
1331  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1332  */
1333 int
1334 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1335                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1336                           struct GNUNET_HashCode *key_material)
1337 {
1338   gcry_mpi_point_t result;
1339   gcry_mpi_point_t q;
1340   gcry_mpi_t d;
1341   gcry_ctx_t ctx;
1342   gcry_sexp_t pub_sexpr;
1343   gcry_mpi_t result_x;
1344   unsigned char xbuf[256 / 8];
1345   size_t rsize;
1346
1347   /* first, extract the q = dP value from the public key */
1348   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1349                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1350                             (int)sizeof (pub->q_y), pub->q_y))
1351     return GNUNET_SYSERR;
1352   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1353   gcry_sexp_release (pub_sexpr);
1354   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1355
1356   /* second, extract the d value from our private key */
1357   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1358
1359   /* then call the 'multiply' function, to compute the product */
1360   result = gcry_mpi_point_new (0);
1361   gcry_mpi_ec_mul (result, d, q, ctx);
1362   gcry_mpi_point_release (q);
1363   gcry_mpi_release (d);
1364
1365   /* finally, convert point to string for hashing */
1366   result_x = gcry_mpi_new (256);
1367   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1368   {
1369     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1370     gcry_mpi_point_release (result);
1371     gcry_ctx_release (ctx);
1372     return GNUNET_SYSERR;
1373   }
1374   gcry_mpi_point_release (result);
1375   gcry_ctx_release (ctx);
1376
1377   rsize = sizeof (xbuf);
1378   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1379   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1380      as that does not include the sign bit; x should be a 255-bit
1381      value, so with the sign it should fit snugly into the 256-bit
1382      xbuf */
1383   GNUNET_assert (0 ==
1384                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1385                                  result_x));
1386   GNUNET_CRYPTO_hash (xbuf,
1387                       rsize,
1388                       key_material);
1389   gcry_mpi_release (result_x);
1390   return GNUNET_OK;
1391 }
1392
1393
1394
1395 /**
1396  * @ingroup crypto
1397  * Derive key material from a EdDSA public key and a private ECDH key.
1398  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1399  *
1400  * @param priv private key to use for the ECDH (y)
1401  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1402  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1403  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1404  */
1405 int
1406 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1407                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1408                           struct GNUNET_HashCode *key_material)
1409 {
1410   gcry_mpi_point_t result;
1411   gcry_mpi_point_t q;
1412   gcry_mpi_t d;
1413   gcry_ctx_t ctx;
1414   gcry_sexp_t pub_sexpr;
1415   gcry_mpi_t result_x;
1416   unsigned char xbuf[256 / 8];
1417   size_t rsize;
1418
1419   /* first, extract the q = dP value from the public key */
1420   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1421                             "(public-key(ecc(curve " CURVE ")(q %b)))",
1422                             (int)sizeof (pub->q_y), pub->q_y))
1423     return GNUNET_SYSERR;
1424   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1425   gcry_sexp_release (pub_sexpr);
1426   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1427
1428   /* second, extract the d value from our private key */
1429   GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1430
1431   /* then call the 'multiply' function, to compute the product */
1432   result = gcry_mpi_point_new (0);
1433   gcry_mpi_ec_mul (result, d, q, ctx);
1434   gcry_mpi_point_release (q);
1435   gcry_mpi_release (d);
1436
1437   /* finally, convert point to string for hashing */
1438   result_x = gcry_mpi_new (256);
1439   if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1440   {
1441     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1442     gcry_mpi_point_release (result);
1443     gcry_ctx_release (ctx);
1444     return GNUNET_SYSERR;
1445   }
1446   gcry_mpi_point_release (result);
1447   gcry_ctx_release (ctx);
1448
1449   rsize = sizeof (xbuf);
1450   GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1451   /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1452      as that does not include the sign bit; x should be a 255-bit
1453      value, so with the sign it should fit snugly into the 256-bit
1454      xbuf */
1455   GNUNET_assert (0 ==
1456                  gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1457                                  result_x));
1458   GNUNET_CRYPTO_hash (xbuf,
1459                       rsize,
1460                       key_material);
1461   gcry_mpi_release (result_x);
1462   return GNUNET_OK;
1463 }
1464
1465 /**
1466  * @ingroup crypto
1467  * Derive key material from a ECDSA public key and a private ECDH key.
1468  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1469  *
1470  * @param priv private key to use for the ECDH (y)
1471  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1472  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1473  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1474  */
1475 int
1476 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1477                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1478                           struct GNUNET_HashCode *key_material)
1479 {
1480   return GNUNET_CRYPTO_ecdh_eddsa (priv,
1481                                    (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1482                                    key_material);
1483 }
1484
1485 /* end of crypto_ecc.c */