use NULL value in load_path_suffix to NOT load any files
[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.
680  *
681  * @param priv private key to use for the signing
682  * @param purpose what to sign (size, purpose)
683  * @param sig where to write the signature
684  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
685  */
686 int
687 GNUNET_CRYPTO_ecdsa_sign (
688   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
689   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
690   struct GNUNET_CRYPTO_EcdsaSignature *sig)
691 {
692   gcry_sexp_t priv_sexp;
693   gcry_sexp_t sig_sexp;
694   gcry_sexp_t data;
695   int rc;
696   gcry_mpi_t rs[2];
697
698   BENCHMARK_START (ecdsa_sign);
699
700   priv_sexp = decode_private_ecdsa_key (priv);
701   data = data_to_ecdsa_value (purpose);
702   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
703   {
704     LOG (GNUNET_ERROR_TYPE_WARNING,
705          _ ("ECC signing failed at %s:%d: %s\n"),
706          __FILE__,
707          __LINE__,
708          gcry_strerror (rc));
709     gcry_sexp_release (data);
710     gcry_sexp_release (priv_sexp);
711     return GNUNET_SYSERR;
712   }
713   gcry_sexp_release (priv_sexp);
714   gcry_sexp_release (data);
715
716   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
717      'signature' */
718   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
719   {
720     GNUNET_break (0);
721     gcry_sexp_release (sig_sexp);
722     return GNUNET_SYSERR;
723   }
724   gcry_sexp_release (sig_sexp);
725   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
726   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
727   gcry_mpi_release (rs[0]);
728   gcry_mpi_release (rs[1]);
729
730   BENCHMARK_END (ecdsa_sign);
731
732   return GNUNET_OK;
733 }
734
735
736 /**
737  * Sign a given block.
738  *
739  * @param priv private key to use for the signing
740  * @param purpose what to sign (size, purpose)
741  * @param sig where to write the signature
742  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
743  */
744 int
745 GNUNET_CRYPTO_eddsa_sign (
746   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
747   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
748   struct GNUNET_CRYPTO_EddsaSignature *sig)
749 {
750
751   size_t mlen = ntohl (purpose->size);
752   unsigned char sk[GNUNET_TWEETNACL_SIGN_SECRETKEYBYTES];
753   int res;
754
755   BENCHMARK_START (eddsa_sign);
756   GNUNET_TWEETNACL_sign_sk_from_seed (sk, priv->d);
757   res = GNUNET_TWEETNACL_sign_detached ((uint8_t *) sig,
758                                         (uint8_t *) purpose,
759                                         mlen,
760                                         sk);
761   BENCHMARK_END (eddsa_sign);
762   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
763 }
764
765
766 /**
767  * Verify signature.
768  *
769  * @param purpose what is the purpose that the signature should have?
770  * @param validate block to validate (size, purpose, data)
771  * @param sig signature that is being validated
772  * @param pub public key of the signer
773  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
774  */
775 int
776 GNUNET_CRYPTO_ecdsa_verify (
777   uint32_t purpose,
778   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
779   const struct GNUNET_CRYPTO_EcdsaSignature *sig,
780   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
781 {
782   gcry_sexp_t data;
783   gcry_sexp_t sig_sexpr;
784   gcry_sexp_t pub_sexpr;
785   int rc;
786
787   BENCHMARK_START (ecdsa_verify);
788
789   if (purpose != ntohl (validate->purpose))
790     return GNUNET_SYSERR; /* purpose mismatch */
791
792   /* build s-expression for signature */
793   if (0 != (rc = gcry_sexp_build (&sig_sexpr,
794                                   NULL,
795                                   "(sig-val(ecdsa(r %b)(s %b)))",
796                                   (int) sizeof(sig->r),
797                                   sig->r,
798                                   (int) sizeof(sig->s),
799                                   sig->s)))
800   {
801     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
802     return GNUNET_SYSERR;
803   }
804   data = data_to_ecdsa_value (validate);
805   if (0 != (rc = gcry_sexp_build (&pub_sexpr,
806                                   NULL,
807                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
808                                   (int) sizeof(pub->q_y),
809                                   pub->q_y)))
810   {
811     gcry_sexp_release (data);
812     gcry_sexp_release (sig_sexpr);
813     return GNUNET_SYSERR;
814   }
815   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
816   gcry_sexp_release (pub_sexpr);
817   gcry_sexp_release (data);
818   gcry_sexp_release (sig_sexpr);
819   if (0 != rc)
820   {
821     LOG (GNUNET_ERROR_TYPE_INFO,
822          _ ("ECDSA signature verification failed at %s:%d: %s\n"),
823          __FILE__,
824          __LINE__,
825          gcry_strerror (rc));
826     BENCHMARK_END (ecdsa_verify);
827     return GNUNET_SYSERR;
828   }
829   BENCHMARK_END (ecdsa_verify);
830   return GNUNET_OK;
831 }
832
833
834 /**
835  * Verify signature.
836  *
837  * @param purpose what is the purpose that the signature should have?
838  * @param validate block to validate (size, purpose, data)
839  * @param sig signature that is being validated
840  * @param pub public key of the signer
841  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
842  */
843 int
844 GNUNET_CRYPTO_eddsa_verify (
845   uint32_t purpose,
846   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
847   const struct GNUNET_CRYPTO_EddsaSignature *sig,
848   const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
849 {
850   unsigned char *m = (void *) validate;
851   size_t mlen = ntohl (validate->size);
852   unsigned char *s = (void *) sig;
853
854   int res;
855
856   if (purpose != ntohl (validate->purpose))
857     return GNUNET_SYSERR; /* purpose mismatch */
858
859   BENCHMARK_START (eddsa_verify);
860   res = GNUNET_TWEETNACL_sign_detached_verify (s, m, mlen, pub->q_y);
861   BENCHMARK_END (eddsa_verify);
862   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
863 }
864
865
866 /**
867  * Derive key material from a public and a private ECDHE key.
868  *
869  * @param priv private key to use for the ECDH (x)
870  * @param pub public key to use for the ECDH (yG)
871  * @param key_material where to write the key material (xyG)
872  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
873  */
874 int
875 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
876                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
877                         struct GNUNET_HashCode *key_material)
878 {
879   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
880   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, pub->q_y);
881   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
882   return GNUNET_OK;
883 }
884
885
886 /**
887  * Derive the 'h' value for key derivation, where
888  * 'h = H(l,P)'.
889  *
890  * @param pub public key for deriviation
891  * @param label label for deriviation
892  * @param context additional context to use for HKDF of 'h';
893  *        typically the name of the subsystem/application
894  * @return h value
895  */
896 static gcry_mpi_t
897 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
898           const char *label,
899           const char *context)
900 {
901   gcry_mpi_t h;
902   struct GNUNET_HashCode hc;
903   static const char *const salt = "key-derivation";
904
905   GNUNET_CRYPTO_kdf (&hc,
906                      sizeof(hc),
907                      salt,
908                      strlen (salt),
909                      pub,
910                      sizeof(*pub),
911                      label,
912                      strlen (label),
913                      context,
914                      strlen (context),
915                      NULL,
916                      0);
917   GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
918   return h;
919 }
920
921
922 /**
923  * Derive a private key from a given private key and a label.
924  * Essentially calculates a private key 'd = H(l,P) * x mod n'
925  * where n is the size of the ECC group and P is the public
926  * key associated with the private key 'd'.
927  *
928  * @param priv original private key
929  * @param label label to use for key deriviation
930  * @param context additional context to use for HKDF of 'h';
931  *        typically the name of the subsystem/application
932  * @return derived private key
933  */
934 struct GNUNET_CRYPTO_EcdsaPrivateKey *
935 GNUNET_CRYPTO_ecdsa_private_key_derive (
936   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
937   const char *label,
938   const char *context)
939 {
940   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
941   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
942   gcry_mpi_t h;
943   gcry_mpi_t x;
944   gcry_mpi_t d;
945   gcry_mpi_t n;
946   gcry_ctx_t ctx;
947
948   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
949
950   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
951   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
952
953   h = derive_h (&pub, label, context);
954   GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof(priv->d));
955   d = gcry_mpi_new (256);
956   gcry_mpi_mulm (d, h, x, n);
957   gcry_mpi_release (h);
958   gcry_mpi_release (x);
959   gcry_mpi_release (n);
960   gcry_ctx_release (ctx);
961   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
962   GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof(ret->d), d);
963   gcry_mpi_release (d);
964   return ret;
965 }
966
967
968 /**
969  * Derive a public key from a given public key and a label.
970  * Essentially calculates a public key 'V = H(l,P) * P'.
971  *
972  * @param pub original public key
973  * @param label label to use for key derivation
974  * @param context additional context to use for HKDF of 'h';
975  *        typically the name of the subsystem/application
976  * @param result where to write the derived public key
977  */
978 void
979 GNUNET_CRYPTO_ecdsa_public_key_derive (
980   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
981   const char *label,
982   const char *context,
983   struct GNUNET_CRYPTO_EcdsaPublicKey *result)
984 {
985   gcry_ctx_t ctx;
986   gcry_mpi_t q_y;
987   gcry_mpi_t h;
988   gcry_mpi_t n;
989   gcry_mpi_t h_mod_n;
990   gcry_mpi_point_t q;
991   gcry_mpi_point_t v;
992
993   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
994
995   /* obtain point 'q' from original public key.  The provided 'q' is
996      compressed thus we first store it in the context and then get it
997      back as a (decompresssed) point.  */
998   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
999   GNUNET_assert (NULL != q_y);
1000   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1001   gcry_mpi_release (q_y);
1002   q = gcry_mpi_ec_get_point ("q", ctx, 0);
1003   GNUNET_assert (q);
1004
1005   /* calculate h_mod_n = h % n */
1006   h = derive_h (pub, label, context);
1007   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1008   h_mod_n = gcry_mpi_new (256);
1009   gcry_mpi_mod (h_mod_n, h, n);
1010   /* calculate v = h_mod_n * q */
1011   v = gcry_mpi_point_new (0);
1012   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1013   gcry_mpi_release (h_mod_n);
1014   gcry_mpi_release (h);
1015   gcry_mpi_release (n);
1016   gcry_mpi_point_release (q);
1017
1018   /* convert point 'v' to public key that we return */
1019   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1020   gcry_mpi_point_release (v);
1021   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1022   GNUNET_assert (q_y);
1023   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
1024   gcry_mpi_release (q_y);
1025   gcry_ctx_release (ctx);
1026 }
1027
1028
1029 /**
1030  * @ingroup crypto
1031  * Derive key material from a ECDH public key and a private EdDSA key.
1032  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1033  *
1034  * @param priv private key from EdDSA to use for the ECDH (x)
1035  * @param pub public key to use for the ECDH (yG)
1036  * @param key_material where to write the key material H(h(x)yG)
1037  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1038  */
1039 int
1040 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1041                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1042                           struct GNUNET_HashCode *key_material)
1043 {
1044   struct GNUNET_HashCode hc;
1045   uint8_t a[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1046   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1047
1048   GNUNET_CRYPTO_hash (priv,
1049                       sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1050                       &hc);
1051   memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1052   GNUNET_TWEETNACL_scalarmult_curve25519 (p, a, pub->q_y);
1053   GNUNET_CRYPTO_hash (p,
1054                       GNUNET_TWEETNACL_SCALARMULT_BYTES,
1055                       key_material);
1056   return GNUNET_OK;
1057 }
1058
1059
1060 /**
1061  * @ingroup crypto
1062  * Derive key material from a ECDH public key and a private ECDSA key.
1063  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1064  *
1065  * @param priv private key from ECDSA to use for the ECDH (x)
1066  * @param pub public key to use for the ECDH (yG)
1067  * @param key_material where to write the key material H(h(x)yG)
1068  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1069  */
1070 int
1071 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1072                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1073                           struct GNUNET_HashCode *key_material)
1074 {
1075   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1076   uint8_t d_rev[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1077
1078   BENCHMARK_START (ecdsa_ecdh);
1079   for (size_t i = 0; i < 32; i++)
1080     d_rev[i] = priv->d[31 - i];
1081   GNUNET_TWEETNACL_scalarmult_curve25519 (p, d_rev, pub->q_y);
1082   GNUNET_CRYPTO_hash (p,
1083                       GNUNET_TWEETNACL_SCALARMULT_BYTES,
1084                       key_material);
1085   BENCHMARK_END (ecdsa_ecdh);
1086   return GNUNET_OK;
1087 }
1088
1089
1090 /**
1091  * @ingroup crypto
1092  * Derive key material from a EdDSA public key and a private ECDH key.
1093  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1094  *
1095  * @param priv private key to use for the ECDH (y)
1096  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1097  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1098  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1099  */
1100 int
1101 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1102                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1103                           struct GNUNET_HashCode *key_material)
1104 {
1105   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1106   uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
1107
1108   GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
1109   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
1110   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
1111   return GNUNET_OK;
1112 }
1113
1114
1115 /**
1116  * @ingroup crypto
1117  * Derive key material from a ECDSA public key and a private ECDH key.
1118  * Dual to #GNUNET_CRYPTO_ecdsa_ecdh.
1119  *
1120  * @param priv private key to use for the ECDH (y)
1121  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1122  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1123  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1124  */
1125 int
1126 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1127                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1128                           struct GNUNET_HashCode *key_material)
1129 {
1130   uint8_t p[GNUNET_TWEETNACL_SCALARMULT_BYTES];
1131   uint8_t curve25510_pk[GNUNET_TWEETNACL_SIGN_PUBLICBYTES];
1132
1133   GNUNET_TWEETNACL_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
1134   GNUNET_TWEETNACL_scalarmult_curve25519 (p, priv->d, curve25510_pk);
1135   GNUNET_CRYPTO_hash (p, GNUNET_TWEETNACL_SCALARMULT_BYTES, key_material);
1136   return GNUNET_OK;
1137 }
1138
1139
1140 /* end of crypto_ecc.c */