fix sign api for to address #6164
[oweals/gnunet.git] / src / util / crypto_ecc.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012, 2013, 2015 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file util/crypto_ecc.c
23  * @brief public key cryptography (ECC) with libgcrypt
24  * @author Christian Grothoff
25  * @author Florian Dold
26  */
27 #include "platform.h"
28 #include <gcrypt.h>
29 #include "gnunet_crypto_lib.h"
30 #include "gnunet_strings_lib.h"
31 #include "benchmark.h"
32 #include "tweetnacl-gnunet.h"
33
34 #define EXTRA_CHECKS 0
35
36
37 /**
38  * Name of the curve we are using.  Note that we have hard-coded
39  * structs that use 256 bits, so using a bigger curve will require
40  * changes that break stuff badly.  The name of the curve given here
41  * must be agreed by all peers and be supported by libgcrypt.
42  */
43 #define CURVE "Ed25519"
44
45 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
46
47 #define LOG_STRERROR(kind, syscall) \
48   GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
49
50 #define LOG_STRERROR_FILE(kind, syscall, filename) \
51   GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
52
53 /**
54  * Log an error message at log-level 'level' that indicates
55  * a failure of the command 'cmd' with the message given
56  * by gcry_strerror(rc).
57  */
58 #define LOG_GCRY(level, cmd, rc)                      \
59   do                                                  \
60   {                                                   \
61     LOG (level,                                       \
62          _ ("`%s' failed at %s:%d with error: %s\n"), \
63          cmd,                                         \
64          __FILE__,                                    \
65          __LINE__,                                    \
66          gcry_strerror (rc));                         \
67   } while (0)
68
69
70 /**
71  * Extract values from an S-expression.
72  *
73  * @param array where to store the result(s)
74  * @param sexp S-expression to parse
75  * @param topname top-level name in the S-expression that is of interest
76  * @param elems names of the elements to extract
77  * @return 0 on success
78  */
79 static int
80 key_from_sexp (gcry_mpi_t *array,
81                gcry_sexp_t sexp,
82                const char *topname,
83                const char *elems)
84 {
85   gcry_sexp_t list;
86   gcry_sexp_t l2;
87   unsigned int idx;
88
89   list = gcry_sexp_find_token (sexp, topname, 0);
90   if (! list)
91     return 1;
92   l2 = gcry_sexp_cadr (list);
93   gcry_sexp_release (list);
94   list = l2;
95   if (! list)
96     return 2;
97
98   idx = 0;
99   for (const char *s = elems; *s; s++, idx++)
100   {
101     l2 = gcry_sexp_find_token (list, s, 1);
102     if (! l2)
103     {
104       for (unsigned int i = 0; i < idx; i++)
105       {
106         gcry_free (array[i]);
107         array[i] = NULL;
108       }
109       gcry_sexp_release (list);
110       return 3;     /* required parameter not found */
111     }
112     array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
113     gcry_sexp_release (l2);
114     if (! array[idx])
115     {
116       for (unsigned int i = 0; i < idx; i++)
117       {
118         gcry_free (array[i]);
119         array[i] = NULL;
120       }
121       gcry_sexp_release (list);
122       return 4;     /* required parameter is invalid */
123     }
124   }
125   gcry_sexp_release (list);
126   return 0;
127 }
128
129
130 /**
131  * Convert the given private key from the network format to the
132  * S-expression that can be used by libgcrypt.
133  *
134  * @param priv private key to decode
135  * @return NULL on error
136  */
137 static gcry_sexp_t
138 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
139 {
140   gcry_sexp_t result;
141   int rc;
142
143   rc = gcry_sexp_build (&result,
144                         NULL,
145                         "(private-key(ecc(curve \"" CURVE "\")"
146                         "(d %b)))",
147                         (int) sizeof(priv->d),
148                         priv->d);
149   if (0 != rc)
150   {
151     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
152     GNUNET_assert (0);
153   }
154 #if EXTRA_CHECKS
155   if (0 != (rc = gcry_pk_testkey (result)))
156   {
157     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
158     GNUNET_assert (0);
159   }
160 #endif
161   return result;
162 }
163
164
165 /**
166  * Extract the public key for the given private key.
167  *
168  * @param priv the private key
169  * @param pub where to write the public key
170  */
171 void
172 GNUNET_CRYPTO_ecdsa_key_get_public (
173   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
174   struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
175 {
176   BENCHMARK_START (ecdsa_key_get_public);
177   GNUNET_TWEETNACL_scalarmult_gnunet_ecdsa (pub->q_y, priv->d);
178   BENCHMARK_END (ecdsa_key_get_public);
179 }
180
181
182 /**
183  * Extract the public key for the given private key.
184  *
185  * @param priv the private key
186  * @param pub where to write the public key
187  */
188 void
189 GNUNET_CRYPTO_eddsa_key_get_public (
190   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
191   struct GNUNET_CRYPTO_EddsaPublicKey *pub)
192 {
193   BENCHMARK_START (eddsa_key_get_public);
194   GNUNET_TWEETNACL_sign_pk_from_seed (pub->q_y, priv->d);
195   BENCHMARK_END (eddsa_key_get_public);
196 }
197
198
199 /**
200  * Extract the public key for the given private key.
201  *
202  * @param priv the private key
203  * @param pub where to write the public key
204  */
205 void
206 GNUNET_CRYPTO_ecdhe_key_get_public (
207   const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
208   struct GNUNET_CRYPTO_EcdhePublicKey *pub)
209 {
210   BENCHMARK_START (ecdhe_key_get_public);
211   GNUNET_TWEETNACL_scalarmult_curve25519_base (pub->q_y, priv->d);
212   BENCHMARK_END (ecdhe_key_get_public);
213 }
214
215
216 /**
217  * Convert a public key to a string.
218  *
219  * @param pub key to convert
220  * @return string representing @a pub
221  */
222 char *
223 GNUNET_CRYPTO_ecdsa_public_key_to_string (
224   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
225 {
226   char *pubkeybuf;
227   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
228   char *end;
229
230   if (keylen % 5 > 0)
231     keylen += 5 - keylen % 5;
232   keylen /= 5;
233   pubkeybuf = GNUNET_malloc (keylen + 1);
234   end =
235     GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
236                                    sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
237                                    pubkeybuf,
238                                    keylen);
239   if (NULL == end)
240   {
241     GNUNET_free (pubkeybuf);
242     return NULL;
243   }
244   *end = '\0';
245   return pubkeybuf;
246 }
247
248
249 /**
250  * Convert a public key to a string.
251  *
252  * @param pub key to convert
253  * @return string representing @a pub
254  */
255 char *
256 GNUNET_CRYPTO_eddsa_public_key_to_string (
257   const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
258 {
259   char *pubkeybuf;
260   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
261   char *end;
262
263   if (keylen % 5 > 0)
264     keylen += 5 - keylen % 5;
265   keylen /= 5;
266   pubkeybuf = GNUNET_malloc (keylen + 1);
267   end =
268     GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
269                                    sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
270                                    pubkeybuf,
271                                    keylen);
272   if (NULL == end)
273   {
274     GNUNET_free (pubkeybuf);
275     return NULL;
276   }
277   *end = '\0';
278   return pubkeybuf;
279 }
280
281
282 /**
283  * Convert a private key to a string.
284  *
285  * @param priv key to convert
286  * @return string representing @a pub
287  */
288 char *
289 GNUNET_CRYPTO_eddsa_private_key_to_string (
290   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
291 {
292   char *privkeybuf;
293   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
294   char *end;
295
296   if (keylen % 5 > 0)
297     keylen += 5 - keylen % 5;
298   keylen /= 5;
299   privkeybuf = GNUNET_malloc (keylen + 1);
300   end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
301                                        sizeof(
302                                          struct GNUNET_CRYPTO_EddsaPrivateKey),
303                                        privkeybuf,
304                                        keylen);
305   if (NULL == end)
306   {
307     GNUNET_free (privkeybuf);
308     return NULL;
309   }
310   *end = '\0';
311   return privkeybuf;
312 }
313
314
315 /**
316  * Convert a private key to a string.
317  *
318  * @param priv key to convert
319  * @return string representing @a priv
320  */
321 char *
322 GNUNET_CRYPTO_ecdsa_private_key_to_string (
323   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
324 {
325   char *privkeybuf;
326   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
327   char *end;
328
329   if (keylen % 5 > 0)
330     keylen += 5 - keylen % 5;
331   keylen /= 5;
332   privkeybuf = GNUNET_malloc (keylen + 1);
333   end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
334                                        sizeof(
335                                          struct GNUNET_CRYPTO_EcdsaPrivateKey),
336                                        privkeybuf,
337                                        keylen);
338   if (NULL == end)
339   {
340     GNUNET_free (privkeybuf);
341     return NULL;
342   }
343   *end = '\0';
344   return privkeybuf;
345 }
346
347
348 /**
349  * Convert a string representing a public key to a public key.
350  *
351  * @param enc encoded public key
352  * @param enclen number of bytes in @a enc (without 0-terminator)
353  * @param pub where to store the public key
354  * @return #GNUNET_OK on success
355  */
356 int
357 GNUNET_CRYPTO_ecdsa_public_key_from_string (
358   const char *enc,
359   size_t enclen,
360   struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
361 {
362   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
363
364   if (keylen % 5 > 0)
365     keylen += 5 - keylen % 5;
366   keylen /= 5;
367   if (enclen != keylen)
368     return GNUNET_SYSERR;
369
370   if (GNUNET_OK !=
371       GNUNET_STRINGS_string_to_data (enc,
372                                      enclen,
373                                      pub,
374                                      sizeof(
375                                        struct GNUNET_CRYPTO_EcdsaPublicKey)))
376     return GNUNET_SYSERR;
377   return GNUNET_OK;
378 }
379
380
381 /**
382  * Convert a string representing a public key to a public key.
383  *
384  * @param enc encoded public key
385  * @param enclen number of bytes in @a enc (without 0-terminator)
386  * @param pub where to store the public key
387  * @return #GNUNET_OK on success
388  */
389 int
390 GNUNET_CRYPTO_eddsa_public_key_from_string (
391   const char *enc,
392   size_t enclen,
393   struct GNUNET_CRYPTO_EddsaPublicKey *pub)
394 {
395   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
396
397   if (keylen % 5 > 0)
398     keylen += 5 - keylen % 5;
399   keylen /= 5;
400   if (enclen != keylen)
401     return GNUNET_SYSERR;
402
403   if (GNUNET_OK !=
404       GNUNET_STRINGS_string_to_data (enc,
405                                      enclen,
406                                      pub,
407                                      sizeof(
408                                        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 (
424   const char *enc,
425   size_t enclen,
426   struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
427 {
428   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
429
430   if (keylen % 5 > 0)
431     keylen += 5 - keylen % 5;
432   keylen /= 5;
433   if (enclen != keylen)
434     return GNUNET_SYSERR;
435
436   if (GNUNET_OK !=
437       GNUNET_STRINGS_string_to_data (enc,
438                                      enclen,
439                                      priv,
440                                      sizeof(
441                                        struct GNUNET_CRYPTO_EddsaPrivateKey)))
442     return GNUNET_SYSERR;
443 #if CRYPTO_BUG
444   if (GNUNET_OK != check_eddsa_key (priv))
445   {
446     GNUNET_break (0);
447     return GNUNET_OK;
448   }
449 #endif
450   return GNUNET_OK;
451 }
452
453
454 /**
455  * @ingroup crypto
456  * Clear memory that was used to store a private key.
457  *
458  * @param pk location of the key
459  */
460 void
461 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
462 {
463   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
464 }
465
466
467 /**
468  * @ingroup crypto
469  * Clear memory that was used to store a private key.
470  *
471  * @param pk location of the key
472  */
473 void
474 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
475 {
476   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
477 }
478
479
480 /**
481  * @ingroup crypto
482  * Clear memory that was used to store a private key.
483  *
484  * @param pk location of the key
485  */
486 void
487 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
488 {
489   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
490 }
491
492
493 /**
494  * Create a new private key. Caller must free return value.
495  *
496  * @return fresh private key
497  */
498 struct GNUNET_CRYPTO_EcdhePrivateKey *
499 GNUNET_CRYPTO_ecdhe_key_create ()
500 {
501   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
502
503   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
504   if (GNUNET_OK != GNUNET_CRYPTO_ecdhe_key_create2 (priv))
505   {
506     GNUNET_free (priv);
507     return NULL;
508   }
509   return priv;
510 }
511
512
513 /**
514  * @ingroup crypto
515  * Create a new private key.  Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
516  *
517  * @param[out] pk set to fresh private key;
518  * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
519  */
520 int
521 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
522 {
523   BENCHMARK_START (ecdhe_key_create);
524   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
525                               pk,
526                               sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
527   BENCHMARK_END (ecdhe_key_create);
528   return GNUNET_OK;
529 }
530
531
532 /**
533  * Create a new private key. Caller must free return value.
534  *
535  * @return fresh private key
536  */
537 struct GNUNET_CRYPTO_EcdsaPrivateKey *
538 GNUNET_CRYPTO_ecdsa_key_create ()
539 {
540   struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
541   gcry_sexp_t priv_sexp;
542   gcry_sexp_t s_keyparam;
543   gcry_mpi_t d;
544   int rc;
545
546   BENCHMARK_START (ecdsa_key_create);
547
548   if (0 != (rc = gcry_sexp_build (&s_keyparam,
549                                   NULL,
550                                   "(genkey(ecc(curve \"" CURVE "\")"
551                                   "(flags)))")))
552   {
553     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
554     return NULL;
555   }
556   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
557   {
558     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
559     gcry_sexp_release (s_keyparam);
560     return NULL;
561   }
562   gcry_sexp_release (s_keyparam);
563 #if EXTRA_CHECKS
564   if (0 != (rc = gcry_pk_testkey (priv_sexp)))
565   {
566     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
567     gcry_sexp_release (priv_sexp);
568     return NULL;
569   }
570 #endif
571   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
572   {
573     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
574     gcry_sexp_release (priv_sexp);
575     return NULL;
576   }
577   gcry_sexp_release (priv_sexp);
578   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
579   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof(priv->d), d);
580   gcry_mpi_release (d);
581
582   BENCHMARK_END (ecdsa_key_create);
583
584   return priv;
585 }
586
587
588 /**
589  * Create a new private key. Caller must free return value.
590  *
591  * @return fresh private key
592  */
593 struct GNUNET_CRYPTO_EddsaPrivateKey *
594 GNUNET_CRYPTO_eddsa_key_create ()
595 {
596   struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
597
598   BENCHMARK_START (eddsa_key_create);
599   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
600   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
601                               priv,
602                               sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
603   BENCHMARK_END (eddsa_key_create);
604
605   return priv;
606 }
607
608
609 /**
610  * Get the shared private key we use for anonymous users.
611  *
612  * @return "anonymous" private key
613  */
614 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
615 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
616 {
617   /**
618    * 'anonymous' pseudonym (global static, d=1, public key = G
619    * (generator).
620    */
621   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
622   static int once;
623
624   if (once)
625     return &anonymous;
626   GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
627                                     sizeof(anonymous.d),
628                                     GCRYMPI_CONST_ONE);
629   once = 1;
630   return &anonymous;
631 }
632
633
634 /**
635  * Convert the data specified in the given purpose argument to an
636  * S-expression suitable for signature operations.
637  *
638  * @param purpose data to convert
639  * @return converted s-expression
640  */
641 static gcry_sexp_t
642 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
643 {
644   gcry_sexp_t data;
645   int rc;
646
647 /* See #5398 */
648 #if 1
649   struct GNUNET_HashCode hc;
650
651   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
652   if (0 != (rc = gcry_sexp_build (&data,
653                                   NULL,
654                                   "(data(flags rfc6979)(hash %s %b))",
655                                   "sha512",
656                                   (int) sizeof(hc),
657                                   &hc)))
658   {
659     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
660     return NULL;
661   }
662 #else
663   if (0 != (rc = gcry_sexp_build (&data,
664                                   NULL,
665                                   "(data(flags rfc6979)(hash %s %b))",
666                                   "sha512",
667                                   ntohl (purpose->size),
668                                   purpose)))
669   {
670     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
671     return NULL;
672   }
673 #endif
674   return data;
675 }
676
677
678 /**
679  * Sign a given block.  The @a purpose data is the
680  * beginning of the data of which the signature is to be
681  * created. The `size` field in @a purpose must correctly
682  * indicate the number of bytes of the data structure, including
683  * its header.
684  *
685  * @param priv private key to use for the signing
686  * @param purpose what to sign (size, purpose)
687  * @param sig where to write the signature
688  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
689  */
690 int
691 GNUNET_CRYPTO_ecdsa_sign_ (
692   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
693   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
694   struct GNUNET_CRYPTO_EcdsaSignature *sig)
695 {
696   gcry_sexp_t priv_sexp;
697   gcry_sexp_t sig_sexp;
698   gcry_sexp_t data;
699   int rc;
700   gcry_mpi_t rs[2];
701
702   BENCHMARK_START (ecdsa_sign);
703
704   priv_sexp = decode_private_ecdsa_key (priv);
705   data = data_to_ecdsa_value (purpose);
706   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
707   {
708     LOG (GNUNET_ERROR_TYPE_WARNING,
709          _ ("ECC signing failed at %s:%d: %s\n"),
710          __FILE__,
711          __LINE__,
712          gcry_strerror (rc));
713     gcry_sexp_release (data);
714     gcry_sexp_release (priv_sexp);
715     return GNUNET_SYSERR;
716   }
717   gcry_sexp_release (priv_sexp);
718   gcry_sexp_release (data);
719
720   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
721      'signature' */
722   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
723   {
724     GNUNET_break (0);
725     gcry_sexp_release (sig_sexp);
726     return GNUNET_SYSERR;
727   }
728   gcry_sexp_release (sig_sexp);
729   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
730   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
731   gcry_mpi_release (rs[0]);
732   gcry_mpi_release (rs[1]);
733
734   BENCHMARK_END (ecdsa_sign);
735
736   return GNUNET_OK;
737 }
738
739
740 /**
741  * Sign a given block. The @a purpose data is the
742  * beginning of the data of which the signature is to be
743  * created. The `size` field in @a purpose must correctly
744  * indicate the number of bytes of the data structure, including
745  * its header.
746  *
747  * @param priv private key to use for the signing
748  * @param purpose what to sign (size, purpose)
749  * @param sig where to write the signature
750  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
751  */
752 int
753 GNUNET_CRYPTO_eddsa_sign_ (
754   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
755   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
756   struct GNUNET_CRYPTO_EddsaSignature *sig)
757 {
758
759   size_t mlen = ntohl (purpose->size);
760   unsigned char sk[GNUNET_TWEETNACL_SIGN_SECRETKEYBYTES];
761   int res;
762
763   BENCHMARK_START (eddsa_sign);
764   GNUNET_TWEETNACL_sign_sk_from_seed (sk, priv->d);
765   res = GNUNET_TWEETNACL_sign_detached ((uint8_t *) sig,
766                                         (uint8_t *) purpose,
767                                         mlen,
768                                         sk);
769   BENCHMARK_END (eddsa_sign);
770   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
771 }
772
773
774 /**
775  * Verify signature.   The @a validate data is the
776  * beginning of the data of which the signature is to be
777  * verified. The `size` field in @a validate must correctly
778  * indicate the number of bytes of the data structure, including
779  * its header.  If @a purpose does not match the purpose given
780  * in @a validate (the latter
781  *
782  * @param purpose what is the purpose that the signature should have?
783  * @param validate block to validate (size, purpose, data)
784  * @param sig signature that is being validated
785  * @param pub public key of the signer
786  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
787  */
788 int
789 GNUNET_CRYPTO_ecdsa_verify_ (
790   uint32_t purpose,
791   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
792   const struct GNUNET_CRYPTO_EcdsaSignature *sig,
793   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
794 {
795   gcry_sexp_t data;
796   gcry_sexp_t sig_sexpr;
797   gcry_sexp_t pub_sexpr;
798   int rc;
799
800   BENCHMARK_START (ecdsa_verify);
801
802   if (purpose != ntohl (validate->purpose))
803     return GNUNET_SYSERR; /* purpose mismatch */
804
805   /* build s-expression for signature */
806   if (0 != (rc = gcry_sexp_build (&sig_sexpr,
807                                   NULL,
808                                   "(sig-val(ecdsa(r %b)(s %b)))",
809                                   (int) sizeof(sig->r),
810                                   sig->r,
811                                   (int) sizeof(sig->s),
812                                   sig->s)))
813   {
814     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
815     return GNUNET_SYSERR;
816   }
817   data = data_to_ecdsa_value (validate);
818   if (0 != (rc = gcry_sexp_build (&pub_sexpr,
819                                   NULL,
820                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
821                                   (int) sizeof(pub->q_y),
822                                   pub->q_y)))
823   {
824     gcry_sexp_release (data);
825     gcry_sexp_release (sig_sexpr);
826     return GNUNET_SYSERR;
827   }
828   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
829   gcry_sexp_release (pub_sexpr);
830   gcry_sexp_release (data);
831   gcry_sexp_release (sig_sexpr);
832   if (0 != rc)
833   {
834     LOG (GNUNET_ERROR_TYPE_INFO,
835          _ ("ECDSA signature verification failed at %s:%d: %s\n"),
836          __FILE__,
837          __LINE__,
838          gcry_strerror (rc));
839     BENCHMARK_END (ecdsa_verify);
840     return GNUNET_SYSERR;
841   }
842   BENCHMARK_END (ecdsa_verify);
843   return GNUNET_OK;
844 }
845
846
847 /**
848  * Verify signature. The @a validate data is the
849  * beginning of the data of which the signature is to be
850  * verified. The `size` field in @a validate must correctly
851  * indicate the number of bytes of the data structure, including
852  * its header.  If @a purpose does not match the purpose given
853  * in @a validate (the latter must be in big endian), signature
854  * verification fails.
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_eddsa_verify_ (
864   uint32_t purpose,
865   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
866   const struct GNUNET_CRYPTO_EddsaSignature *sig,
867   const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
868 {
869   const unsigned char *m = (const void *) validate;
870   size_t mlen = ntohl (validate->size);
871   const unsigned char *s = (const void *) sig;
872
873   int res;
874
875   if (purpose != ntohl (validate->purpose))
876     return GNUNET_SYSERR; /* purpose mismatch */
877
878   BENCHMARK_START (eddsa_verify);
879   res = GNUNET_TWEETNACL_sign_detached_verify (s, m, mlen, pub->q_y);
880   BENCHMARK_END (eddsa_verify);
881   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
882 }
883
884
885 /**
886  * Derive key material from a public and a private ECDHE key.
887  *
888  * @param priv private key to use for the ECDH (x)
889  * @param pub public key to use for the ECDH (yG)
890  * @param key_material where to write the key material (xyG)
891  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
892  */
893 int
894 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
895                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
896                         struct GNUNET_HashCode *key_material)
897 {
898   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
899   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, pub->q_y);
900   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
901   return GNUNET_OK;
902 }
903
904
905 /**
906  * Derive the 'h' value for key derivation, where
907  * 'h = H(l,P)'.
908  *
909  * @param pub public key for deriviation
910  * @param label label for deriviation
911  * @param context additional context to use for HKDF of 'h';
912  *        typically the name of the subsystem/application
913  * @return h value
914  */
915 static gcry_mpi_t
916 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
917           const char *label,
918           const char *context)
919 {
920   gcry_mpi_t h;
921   struct GNUNET_HashCode hc;
922   static const char *const salt = "key-derivation";
923
924   GNUNET_CRYPTO_kdf (&hc,
925                      sizeof(hc),
926                      salt,
927                      strlen (salt),
928                      pub,
929                      sizeof(*pub),
930                      label,
931                      strlen (label),
932                      context,
933                      strlen (context),
934                      NULL,
935                      0);
936   GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
937   return h;
938 }
939
940
941 /**
942  * Derive a private key from a given private key and a label.
943  * Essentially calculates a private key 'd = H(l,P) * x mod n'
944  * where n is the size of the ECC group and P is the public
945  * key associated with the private key 'd'.
946  *
947  * @param priv original private key
948  * @param label label to use for key deriviation
949  * @param context additional context to use for HKDF of 'h';
950  *        typically the name of the subsystem/application
951  * @return derived private key
952  */
953 struct GNUNET_CRYPTO_EcdsaPrivateKey *
954 GNUNET_CRYPTO_ecdsa_private_key_derive (
955   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
956   const char *label,
957   const char *context)
958 {
959   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
960   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
961   gcry_mpi_t h;
962   gcry_mpi_t x;
963   gcry_mpi_t d;
964   gcry_mpi_t n;
965   gcry_ctx_t ctx;
966
967   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
968
969   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
970   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
971
972   h = derive_h (&pub, label, context);
973   GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof(priv->d));
974   d = gcry_mpi_new (256);
975   gcry_mpi_mulm (d, h, x, n);
976   gcry_mpi_release (h);
977   gcry_mpi_release (x);
978   gcry_mpi_release (n);
979   gcry_ctx_release (ctx);
980   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
981   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof(ret->d), d);
982   gcry_mpi_release (d);
983   return ret;
984 }
985
986
987 /**
988  * Derive a public key from a given public key and a label.
989  * Essentially calculates a public key 'V = H(l,P) * P'.
990  *
991  * @param pub original public key
992  * @param label label to use for key derivation
993  * @param context additional context to use for HKDF of 'h';
994  *        typically the name of the subsystem/application
995  * @param result where to write the derived public key
996  */
997 void
998 GNUNET_CRYPTO_ecdsa_public_key_derive (
999   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1000   const char *label,
1001   const char *context,
1002   struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1003 {
1004   gcry_ctx_t ctx;
1005   gcry_mpi_t q_y;
1006   gcry_mpi_t h;
1007   gcry_mpi_t n;
1008   gcry_mpi_t h_mod_n;
1009   gcry_mpi_point_t q;
1010   gcry_mpi_point_t v;
1011
1012   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1013
1014   /* obtain point 'q' from original public key.  The provided 'q' is
1015      compressed thus we first store it in the context and then get it
1016      back as a (decompresssed) point.  */
1017   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
1018   GNUNET_assert (NULL != q_y);
1019   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1020   gcry_mpi_release (q_y);
1021   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1022   GNUNET_assert (q);
1023
1024   /* calculate h_mod_n = h % n */
1025   h = derive_h (pub, label, context);
1026   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1027   h_mod_n = gcry_mpi_new (256);
1028   gcry_mpi_mod (h_mod_n, h, n);
1029   /* calculate v = h_mod_n * q */
1030   v = gcry_mpi_point_new (0);
1031   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1032   gcry_mpi_release (h_mod_n);
1033   gcry_mpi_release (h);
1034   gcry_mpi_release (n);
1035   gcry_mpi_point_release (q);
1036
1037   /* convert point 'v' to public key that we return */
1038   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1039   gcry_mpi_point_release (v);
1040   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1041   GNUNET_assert (q_y);
1042   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
1043   gcry_mpi_release (q_y);
1044   gcry_ctx_release (ctx);
1045 }
1046
1047
1048 /**
1049  * @ingroup crypto
1050  * Derive key material from a ECDH public key and a private EdDSA key.
1051  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1052  *
1053  * @param priv private key from EdDSA to use for the ECDH (x)
1054  * @param pub public key to use for the ECDH (yG)
1055  * @param key_material where to write the key material H(h(x)yG)
1056  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1057  */
1058 int
1059 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1060                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1061                           struct GNUNET_HashCode *key_material)
1062 {
1063   struct GNUNET_HashCode hc;
1064   uint8_t a[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1065   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1066
1067   GNUNET_CRYPTO_hash (priv,
1068                       sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1069                       &hc);
1070   memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1071   GNUNET_TWEETNACL_scalarmult_curve25519 (p, a, pub->q_y);
1072   GNUNET_CRYPTO_hash (p,
1073                       GNUNET_TWEETNACL_SCALARMULT_BYTES,
1074                       key_material);
1075   return GNUNET_OK;
1076 }
1077
1078
1079 /**
1080  * @ingroup crypto
1081  * Derive key material from a ECDH public key and a private ECDSA key.
1082  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1083  *
1084  * @param priv private key from ECDSA to use for the ECDH (x)
1085  * @param pub public key to use for the ECDH (yG)
1086  * @param key_material where to write the key material H(h(x)yG)
1087  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1088  */
1089 int
1090 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1091                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1092                           struct GNUNET_HashCode *key_material)
1093 {
1094   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1095   uint8_t d_rev[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1096
1097   BENCHMARK_START (ecdsa_ecdh);
1098   for (size_t i = 0; i < 32; i++)
1099     d_rev[i] = priv->d[31 - i];
1100   GNUNET_TWEETNACL_scalarmult_curve25519 (p, d_rev, pub->q_y);
1101   GNUNET_CRYPTO_hash (p,
1102                       GNUNET_TWEETNACL_SCALARMULT_BYTES,
1103                       key_material);
1104   BENCHMARK_END (ecdsa_ecdh);
1105   return GNUNET_OK;
1106 }
1107
1108
1109 /**
1110  * @ingroup crypto
1111  * Derive key material from a EdDSA public key and a private ECDH key.
1112  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1113  *
1114  * @param priv private key to use for the ECDH (y)
1115  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1116  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1117  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1118  */
1119 int
1120 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1121                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1122                           struct GNUNET_HashCode *key_material)
1123 {
1124   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1125   uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
1126
1127   GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
1128   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
1129   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
1130   return GNUNET_OK;
1131 }
1132
1133
1134 /**
1135  * @ingroup crypto
1136  * Derive key material from a ECDSA public key and a private ECDH key.
1137  * Dual to #GNUNET_CRYPTO_ecdsa_ecdh.
1138  *
1139  * @param priv private key to use for the ECDH (y)
1140  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1141  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1142  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1143  */
1144 int
1145 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1146                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1147                           struct GNUNET_HashCode *key_material)
1148 {
1149   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1150   uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
1151
1152   GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
1153   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
1154   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
1155   return GNUNET_OK;
1156 }
1157
1158
1159 /* end of crypto_ecc.c */