96d546185f5b1b2e425090fbe327326aa9e58856
[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 <sodium.h>
30 #include "gnunet_crypto_lib.h"
31 #include "gnunet_strings_lib.h"
32 #include "benchmark.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   uint8_t d[32];
143
144   for (size_t i=0; i<32; i++)
145     d[i] = priv->d[31 - i];
146
147   rc = gcry_sexp_build (&result,
148                         NULL,
149                         "(private-key(ecc(curve \"" CURVE "\")"
150                         "(d %b)))",
151                         32,
152                         d);
153   if (0 != rc)
154   {
155     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
156     GNUNET_assert (0);
157   }
158 #if EXTRA_CHECKS
159   if (0 != (rc = gcry_pk_testkey (result)))
160   {
161     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
162     GNUNET_assert (0);
163   }
164 #endif
165   return result;
166 }
167
168
169 /**
170  * Extract the public key for the given private key.
171  *
172  * @param priv the private key
173  * @param pub where to write the public key
174  */
175 void
176 GNUNET_CRYPTO_ecdsa_key_get_public (
177   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
178   struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
179 {
180   BENCHMARK_START (ecdsa_key_get_public);
181   crypto_scalarmult_ed25519_base_noclamp (pub->q_y, priv->d);
182   BENCHMARK_END (ecdsa_key_get_public);
183 }
184
185
186 /**
187  * Extract the public key for the given private key.
188  *
189  * @param priv the private key
190  * @param pub where to write the public key
191  */
192 void
193 GNUNET_CRYPTO_eddsa_key_get_public (
194   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
195   struct GNUNET_CRYPTO_EddsaPublicKey *pub)
196 {
197   unsigned char pk[crypto_sign_PUBLICKEYBYTES];
198   unsigned char sk[crypto_sign_SECRETKEYBYTES]; 
199
200   BENCHMARK_START (eddsa_key_get_public);
201   GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
202   GNUNET_memcpy (pub->q_y, pk, crypto_sign_PUBLICKEYBYTES);
203   sodium_memzero (sk, crypto_sign_SECRETKEYBYTES);
204   BENCHMARK_END (eddsa_key_get_public);
205 }
206
207
208 /**
209  * Extract the public key for the given private key.
210  *
211  * @param priv the private key
212  * @param pub where to write the public key
213  */
214 void
215 GNUNET_CRYPTO_ecdhe_key_get_public (
216   const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
217   struct GNUNET_CRYPTO_EcdhePublicKey *pub)
218 {
219   BENCHMARK_START (ecdhe_key_get_public);
220   GNUNET_assert (0 == crypto_scalarmult_base (pub->q_y, priv->d));
221   BENCHMARK_END (ecdhe_key_get_public);
222 }
223
224
225 /**
226  * Convert a public key to a string.
227  *
228  * @param pub key to convert
229  * @return string representing @a pub
230  */
231 char *
232 GNUNET_CRYPTO_ecdsa_public_key_to_string (
233   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
234 {
235   char *pubkeybuf;
236   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
237   char *end;
238
239   if (keylen % 5 > 0)
240     keylen += 5 - keylen % 5;
241   keylen /= 5;
242   pubkeybuf = GNUNET_malloc (keylen + 1);
243   end =
244     GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
245                                    sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
246                                    pubkeybuf,
247                                    keylen);
248   if (NULL == end)
249   {
250     GNUNET_free (pubkeybuf);
251     return NULL;
252   }
253   *end = '\0';
254   return pubkeybuf;
255 }
256
257
258 /**
259  * Convert a public key to a string.
260  *
261  * @param pub key to convert
262  * @return string representing @a pub
263  */
264 char *
265 GNUNET_CRYPTO_eddsa_public_key_to_string (
266   const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
267 {
268   char *pubkeybuf;
269   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
270   char *end;
271
272   if (keylen % 5 > 0)
273     keylen += 5 - keylen % 5;
274   keylen /= 5;
275   pubkeybuf = GNUNET_malloc (keylen + 1);
276   end =
277     GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
278                                    sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
279                                    pubkeybuf,
280                                    keylen);
281   if (NULL == end)
282   {
283     GNUNET_free (pubkeybuf);
284     return NULL;
285   }
286   *end = '\0';
287   return pubkeybuf;
288 }
289
290
291 /**
292  * Convert a private key to a string.
293  *
294  * @param priv key to convert
295  * @return string representing @a pub
296  */
297 char *
298 GNUNET_CRYPTO_eddsa_private_key_to_string (
299   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
300 {
301   char *privkeybuf;
302   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
303   char *end;
304
305   if (keylen % 5 > 0)
306     keylen += 5 - keylen % 5;
307   keylen /= 5;
308   privkeybuf = GNUNET_malloc (keylen + 1);
309   end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
310                                        sizeof(
311                                          struct GNUNET_CRYPTO_EddsaPrivateKey),
312                                        privkeybuf,
313                                        keylen);
314   if (NULL == end)
315   {
316     GNUNET_free (privkeybuf);
317     return NULL;
318   }
319   *end = '\0';
320   return privkeybuf;
321 }
322
323
324 /**
325  * Convert a private key to a string.
326  *
327  * @param priv key to convert
328  * @return string representing @a priv
329  */
330 char *
331 GNUNET_CRYPTO_ecdsa_private_key_to_string (
332   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
333 {
334   char *privkeybuf;
335   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
336   char *end;
337
338   if (keylen % 5 > 0)
339     keylen += 5 - keylen % 5;
340   keylen /= 5;
341   privkeybuf = GNUNET_malloc (keylen + 1);
342   end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
343                                        sizeof(
344                                          struct GNUNET_CRYPTO_EcdsaPrivateKey),
345                                        privkeybuf,
346                                        keylen);
347   if (NULL == end)
348   {
349     GNUNET_free (privkeybuf);
350     return NULL;
351   }
352   *end = '\0';
353   return privkeybuf;
354 }
355
356
357 /**
358  * Convert a string representing a public key to a public key.
359  *
360  * @param enc encoded public key
361  * @param enclen number of bytes in @a enc (without 0-terminator)
362  * @param pub where to store the public key
363  * @return #GNUNET_OK on success
364  */
365 int
366 GNUNET_CRYPTO_ecdsa_public_key_from_string (
367   const char *enc,
368   size_t enclen,
369   struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
370 {
371   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
372
373   if (keylen % 5 > 0)
374     keylen += 5 - keylen % 5;
375   keylen /= 5;
376   if (enclen != keylen)
377     return GNUNET_SYSERR;
378
379   if (GNUNET_OK !=
380       GNUNET_STRINGS_string_to_data (enc,
381                                      enclen,
382                                      pub,
383                                      sizeof(
384                                        struct GNUNET_CRYPTO_EcdsaPublicKey)))
385     return GNUNET_SYSERR;
386   return GNUNET_OK;
387 }
388
389
390 /**
391  * Convert a string representing a public key to a public key.
392  *
393  * @param enc encoded public key
394  * @param enclen number of bytes in @a enc (without 0-terminator)
395  * @param pub where to store the public key
396  * @return #GNUNET_OK on success
397  */
398 int
399 GNUNET_CRYPTO_eddsa_public_key_from_string (
400   const char *enc,
401   size_t enclen,
402   struct GNUNET_CRYPTO_EddsaPublicKey *pub)
403 {
404   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
405
406   if (keylen % 5 > 0)
407     keylen += 5 - keylen % 5;
408   keylen /= 5;
409   if (enclen != keylen)
410     return GNUNET_SYSERR;
411
412   if (GNUNET_OK !=
413       GNUNET_STRINGS_string_to_data (enc,
414                                      enclen,
415                                      pub,
416                                      sizeof(
417                                        struct GNUNET_CRYPTO_EddsaPublicKey)))
418     return GNUNET_SYSERR;
419   return GNUNET_OK;
420 }
421
422
423 /**
424  * Convert a string representing a private key to a private key.
425  *
426  * @param enc encoded public key
427  * @param enclen number of bytes in @a enc (without 0-terminator)
428  * @param priv where to store the private key
429  * @return #GNUNET_OK on success
430  */
431 int
432 GNUNET_CRYPTO_eddsa_private_key_from_string (
433   const char *enc,
434   size_t enclen,
435   struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
436 {
437   size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
438
439   if (keylen % 5 > 0)
440     keylen += 5 - keylen % 5;
441   keylen /= 5;
442   if (enclen != keylen)
443     return GNUNET_SYSERR;
444
445   if (GNUNET_OK !=
446       GNUNET_STRINGS_string_to_data (enc,
447                                      enclen,
448                                      priv,
449                                      sizeof(
450                                        struct GNUNET_CRYPTO_EddsaPrivateKey)))
451     return GNUNET_SYSERR;
452 #if CRYPTO_BUG
453   if (GNUNET_OK != check_eddsa_key (priv))
454   {
455     GNUNET_break (0);
456     return GNUNET_OK;
457   }
458 #endif
459   return GNUNET_OK;
460 }
461
462
463 /**
464  * @ingroup crypto
465  * Clear memory that was used to store a private key.
466  *
467  * @param pk location of the key
468  */
469 void
470 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
471 {
472   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
473 }
474
475
476 /**
477  * @ingroup crypto
478  * Clear memory that was used to store a private key.
479  *
480  * @param pk location of the key
481  */
482 void
483 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
484 {
485   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
486 }
487
488
489 /**
490  * @ingroup crypto
491  * Clear memory that was used to store a private key.
492  *
493  * @param pk location of the key
494  */
495 void
496 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
497 {
498   memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
499 }
500
501
502 /**
503  * Create a new private key.
504  *
505  * @param[out] pk fresh private key
506  */
507 void
508 GNUNET_CRYPTO_ecdhe_key_create (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
509 {
510   BENCHMARK_START (ecdhe_key_create);
511   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
512                               pk,
513                               sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
514   BENCHMARK_END (ecdhe_key_create);
515 }
516
517
518 /**
519  * Create a new private key.
520  *
521  * @param[out] pk private key to initialize
522  */
523 void
524 GNUNET_CRYPTO_ecdsa_key_create (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
525 {
526   BENCHMARK_START (ecdsa_key_create);
527   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
528                               pk,
529                               sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
530   pk->d[0] &= 248;
531   pk->d[31] &= 127;
532   pk->d[31] |= 64;
533
534   BENCHMARK_END (ecdsa_key_create);
535 }
536
537
538 /**
539  * Create a new private key.
540  *
541  * @param[out] pk set to fresh private key
542  */
543 void
544 GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
545 {
546   BENCHMARK_START (eddsa_key_create);
547   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
548                               pk,
549                               sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
550   // FIXME: should we not do the clamping here? Or is this done elsewhere?
551   BENCHMARK_END (eddsa_key_create);
552 }
553
554
555 /**
556  * Get the shared private key we use for anonymous users.
557  *
558  * @return "anonymous" private key
559  */
560 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
561 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
562 {
563   /**
564    * 'anonymous' pseudonym (global static, d=1, public key = G
565    * (generator).
566    */
567   static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
568   static int once;
569
570   if (once)
571     return &anonymous;
572   GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
573                                     sizeof(anonymous.d),
574                                     GCRYMPI_CONST_ONE);
575   once = 1;
576   return &anonymous;
577 }
578
579
580 /**
581  * Convert the data specified in the given purpose argument to an
582  * S-expression suitable for signature operations.
583  *
584  * @param purpose data to convert
585  * @return converted s-expression
586  */
587 static gcry_sexp_t
588 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
589 {
590   gcry_sexp_t data;
591   int rc;
592
593 /* See #5398 */
594 #if 1
595   struct GNUNET_HashCode hc;
596
597   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
598   if (0 != (rc = gcry_sexp_build (&data,
599                                   NULL,
600                                   "(data(flags rfc6979)(hash %s %b))",
601                                   "sha512",
602                                   (int) sizeof(hc),
603                                   &hc)))
604   {
605     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
606     return NULL;
607   }
608 #else
609   if (0 != (rc = gcry_sexp_build (&data,
610                                   NULL,
611                                   "(data(flags rfc6979)(hash %s %b))",
612                                   "sha512",
613                                   ntohl (purpose->size),
614                                   purpose)))
615   {
616     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
617     return NULL;
618   }
619 #endif
620   return data;
621 }
622
623
624 /**
625  * Sign a given block.  The @a purpose data is the
626  * beginning of the data of which the signature is to be
627  * created. The `size` field in @a purpose must correctly
628  * indicate the number of bytes of the data structure, including
629  * its header.
630  *
631  * @param priv private key to use for the signing
632  * @param purpose what to sign (size, purpose)
633  * @param sig where to write the signature
634  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
635  */
636 int
637 GNUNET_CRYPTO_ecdsa_sign_ (
638   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
639   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
640   struct GNUNET_CRYPTO_EcdsaSignature *sig)
641 {
642   gcry_sexp_t priv_sexp;
643   gcry_sexp_t sig_sexp;
644   gcry_sexp_t data;
645   int rc;
646   gcry_mpi_t rs[2];
647
648   BENCHMARK_START (ecdsa_sign);
649
650   priv_sexp = decode_private_ecdsa_key (priv);
651   data = data_to_ecdsa_value (purpose);
652   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
653   {
654     LOG (GNUNET_ERROR_TYPE_WARNING,
655          _ ("ECC signing failed at %s:%d: %s\n"),
656          __FILE__,
657          __LINE__,
658          gcry_strerror (rc));
659     gcry_sexp_release (data);
660     gcry_sexp_release (priv_sexp);
661     return GNUNET_SYSERR;
662   }
663   gcry_sexp_release (priv_sexp);
664   gcry_sexp_release (data);
665
666   /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
667      'signature' */
668   if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
669   {
670     GNUNET_break (0);
671     gcry_sexp_release (sig_sexp);
672     return GNUNET_SYSERR;
673   }
674   gcry_sexp_release (sig_sexp);
675   GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
676   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
677   gcry_mpi_release (rs[0]);
678   gcry_mpi_release (rs[1]);
679
680   BENCHMARK_END (ecdsa_sign);
681
682   return GNUNET_OK;
683 }
684
685
686 /**
687  * Sign a given block. The @a purpose data is the
688  * beginning of the data of which the signature is to be
689  * created. The `size` field in @a purpose must correctly
690  * indicate the number of bytes of the data structure, including
691  * its header.
692  *
693  * @param priv private key to use for the signing
694  * @param purpose what to sign (size, purpose)
695  * @param sig where to write the signature
696  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
697  */
698 int
699 GNUNET_CRYPTO_eddsa_sign_ (
700   const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
701   const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
702   struct GNUNET_CRYPTO_EddsaSignature *sig)
703 {
704
705   size_t mlen = ntohl (purpose->size);
706   unsigned char sk[crypto_sign_SECRETKEYBYTES];
707   unsigned char pk[crypto_sign_PUBLICKEYBYTES];
708   int res;
709
710   BENCHMARK_START (eddsa_sign);
711   GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
712   res = crypto_sign_detached ((uint8_t *) sig,
713                               NULL,
714                               (uint8_t *) purpose,
715                               mlen,
716                               sk);
717   BENCHMARK_END (eddsa_sign);
718   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
719 }
720
721
722 /**
723  * Verify signature.   The @a validate data is the
724  * beginning of the data of which the signature is to be
725  * verified. The `size` field in @a validate must correctly
726  * indicate the number of bytes of the data structure, including
727  * its header.  If @a purpose does not match the purpose given
728  * in @a validate (the latter
729  *
730  * @param purpose what is the purpose that the signature should have?
731  * @param validate block to validate (size, purpose, data)
732  * @param sig signature that is being validated
733  * @param pub public key of the signer
734  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
735  */
736 int
737 GNUNET_CRYPTO_ecdsa_verify_ (
738   uint32_t purpose,
739   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
740   const struct GNUNET_CRYPTO_EcdsaSignature *sig,
741   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
742 {
743   gcry_sexp_t data;
744   gcry_sexp_t sig_sexpr;
745   gcry_sexp_t pub_sexpr;
746   int rc;
747
748   BENCHMARK_START (ecdsa_verify);
749
750   if (purpose != ntohl (validate->purpose))
751     return GNUNET_SYSERR; /* purpose mismatch */
752
753   /* build s-expression for signature */
754   if (0 != (rc = gcry_sexp_build (&sig_sexpr,
755                                   NULL,
756                                   "(sig-val(ecdsa(r %b)(s %b)))",
757                                   (int) sizeof(sig->r),
758                                   sig->r,
759                                   (int) sizeof(sig->s),
760                                   sig->s)))
761   {
762     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
763     return GNUNET_SYSERR;
764   }
765   data = data_to_ecdsa_value (validate);
766   if (0 != (rc = gcry_sexp_build (&pub_sexpr,
767                                   NULL,
768                                   "(public-key(ecc(curve " CURVE ")(q %b)))",
769                                   (int) sizeof(pub->q_y),
770                                   pub->q_y)))
771   {
772     gcry_sexp_release (data);
773     gcry_sexp_release (sig_sexpr);
774     return GNUNET_SYSERR;
775   }
776   rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
777   gcry_sexp_release (pub_sexpr);
778   gcry_sexp_release (data);
779   gcry_sexp_release (sig_sexpr);
780   if (0 != rc)
781   {
782     LOG (GNUNET_ERROR_TYPE_INFO,
783          _ ("ECDSA signature verification failed at %s:%d: %s\n"),
784          __FILE__,
785          __LINE__,
786          gcry_strerror (rc));
787     BENCHMARK_END (ecdsa_verify);
788     return GNUNET_SYSERR;
789   }
790   BENCHMARK_END (ecdsa_verify);
791   return GNUNET_OK;
792 }
793
794
795 /**
796  * Verify signature. The @a validate data is the
797  * beginning of the data of which the signature is to be
798  * verified. The `size` field in @a validate must correctly
799  * indicate the number of bytes of the data structure, including
800  * its header.  If @a purpose does not match the purpose given
801  * in @a validate (the latter must be in big endian), signature
802  * verification fails.
803  *
804  * @param purpose what is the purpose that the signature should have?
805  * @param validate block to validate (size, purpose, data)
806  * @param sig signature that is being validated
807  * @param pub public key of the signer
808  * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
809  */
810 int
811 GNUNET_CRYPTO_eddsa_verify_ (
812   uint32_t purpose,
813   const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
814   const struct GNUNET_CRYPTO_EddsaSignature *sig,
815   const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
816 {
817   const unsigned char *m = (const void *) validate;
818   size_t mlen = ntohl (validate->size);
819   const unsigned char *s = (const void *) sig;
820
821   int res;
822
823   if (purpose != ntohl (validate->purpose))
824     return GNUNET_SYSERR; /* purpose mismatch */
825
826   BENCHMARK_START (eddsa_verify);
827   res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
828   BENCHMARK_END (eddsa_verify);
829   return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
830 }
831
832
833 /**
834  * Derive key material from a public and a private ECDHE key.
835  *
836  * @param priv private key to use for the ECDH (x)
837  * @param pub public key to use for the ECDH (yG)
838  * @param key_material where to write the key material (xyG)
839  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
840  */
841 int
842 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
843                         const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
844                         struct GNUNET_HashCode *key_material)
845 {
846   uint8_t p[crypto_scalarmult_BYTES];
847   if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
848     return GNUNET_SYSERR;
849   GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
850   return GNUNET_OK;
851 }
852
853
854 /**
855  * Derive the 'h' value for key derivation, where
856  * 'h = H(l,P)'.
857  *
858  * @param pub public key for deriviation
859  * @param label label for deriviation
860  * @param context additional context to use for HKDF of 'h';
861  *        typically the name of the subsystem/application
862  * @return h value
863  */
864 static gcry_mpi_t
865 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
866           const char *label,
867           const char *context)
868 {
869   gcry_mpi_t h;
870   struct GNUNET_HashCode hc;
871   static const char *const salt = "key-derivation";
872
873   GNUNET_CRYPTO_kdf (&hc,
874                      sizeof(hc),
875                      salt,
876                      strlen (salt),
877                      pub,
878                      sizeof(*pub),
879                      label,
880                      strlen (label),
881                      context,
882                      strlen (context),
883                      NULL,
884                      0);
885   GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
886   return h;
887 }
888
889
890 /**
891  * Derive a private key from a given private key and a label.
892  * Essentially calculates a private key 'd = H(l,P) * x mod n'
893  * where n is the size of the ECC group and P is the public
894  * key associated with the private key 'd'.
895  *
896  * @param priv original private key
897  * @param label label to use for key deriviation
898  * @param context additional context to use for HKDF of 'h';
899  *        typically the name of the subsystem/application
900  * @return derived private key
901  */
902 struct GNUNET_CRYPTO_EcdsaPrivateKey *
903 GNUNET_CRYPTO_ecdsa_private_key_derive (
904   const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
905   const char *label,
906   const char *context)
907 {
908   struct GNUNET_CRYPTO_EcdsaPublicKey pub;
909   struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
910   uint8_t dc[32];
911   gcry_mpi_t h;
912   gcry_mpi_t x;
913   gcry_mpi_t d;
914   gcry_mpi_t n;
915   gcry_ctx_t ctx;
916
917   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
918
919   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
920   GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
921
922   h = derive_h (&pub, label, context);
923   /* Convert to big endian for libgcrypt */
924   for (size_t i=0; i < 32; i++)
925     dc[i] = priv->d[31 - i];
926   GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
927   d = gcry_mpi_new (256);
928   gcry_mpi_mulm (d, h, x, n);
929   gcry_mpi_release (h);
930   gcry_mpi_release (x);
931   gcry_mpi_release (n);
932   gcry_ctx_release (ctx);
933   ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
934   GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
935   /* Convert to big endian for libgcrypt */
936   for (size_t i=0; i < 32; i++)
937     ret->d[i] = dc[31 - i];
938   sodium_memzero(dc, sizeof(dc));
939   gcry_mpi_release (d);
940   return ret;
941 }
942
943
944 /**
945  * Derive a public key from a given public key and a label.
946  * Essentially calculates a public key 'V = H(l,P) * P'.
947  *
948  * @param pub original public key
949  * @param label label to use for key derivation
950  * @param context additional context to use for HKDF of 'h';
951  *        typically the name of the subsystem/application
952  * @param result where to write the derived public key
953  */
954 void
955 GNUNET_CRYPTO_ecdsa_public_key_derive (
956   const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
957   const char *label,
958   const char *context,
959   struct GNUNET_CRYPTO_EcdsaPublicKey *result)
960 {
961   gcry_ctx_t ctx;
962   gcry_mpi_t q_y;
963   gcry_mpi_t h;
964   gcry_mpi_t n;
965   gcry_mpi_t h_mod_n;
966   gcry_mpi_point_t q;
967   gcry_mpi_point_t v;
968
969   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
970
971   /* obtain point 'q' from original public key.  The provided 'q' is
972      compressed thus we first store it in the context and then get it
973      back as a (decompresssed) point.  */
974   q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
975   GNUNET_assert (NULL != q_y);
976   GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
977   gcry_mpi_release (q_y);
978   q = gcry_mpi_ec_get_point ("q", ctx, 0);
979   GNUNET_assert (q);
980
981   /* calculate h_mod_n = h % n */
982   h = derive_h (pub, label, context);
983   n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
984   h_mod_n = gcry_mpi_new (256);
985   gcry_mpi_mod (h_mod_n, h, n);
986   /* calculate v = h_mod_n * q */
987   v = gcry_mpi_point_new (0);
988   gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
989   gcry_mpi_release (h_mod_n);
990   gcry_mpi_release (h);
991   gcry_mpi_release (n);
992   gcry_mpi_point_release (q);
993
994   /* convert point 'v' to public key that we return */
995   GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
996   gcry_mpi_point_release (v);
997   q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
998   GNUNET_assert (q_y);
999   GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
1000   gcry_mpi_release (q_y);
1001   gcry_ctx_release (ctx);
1002 }
1003
1004
1005 /**
1006  * @ingroup crypto
1007  * Derive key material from a ECDH public key and a private EdDSA key.
1008  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1009  *
1010  * @param priv private key from EdDSA to use for the ECDH (x)
1011  * @param pub public key to use for the ECDH (yG)
1012  * @param key_material where to write the key material H(h(x)yG)
1013  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1014  */
1015 int
1016 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1017                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1018                           struct GNUNET_HashCode *key_material)
1019 {
1020   struct GNUNET_HashCode hc;
1021   uint8_t a[crypto_scalarmult_SCALARBYTES];
1022   uint8_t p[crypto_scalarmult_BYTES];
1023
1024   GNUNET_CRYPTO_hash (priv,
1025                       sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1026                       &hc);
1027   memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1028   if (0 != crypto_scalarmult (p, a, pub->q_y))
1029     return GNUNET_SYSERR;
1030   GNUNET_CRYPTO_hash (p,
1031                       crypto_scalarmult_BYTES,
1032                       key_material);
1033   return GNUNET_OK;
1034 }
1035
1036
1037 /**
1038  * @ingroup crypto
1039  * Derive key material from a ECDH public key and a private ECDSA key.
1040  * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1041  *
1042  * @param priv private key from ECDSA to use for the ECDH (x)
1043  * @param pub public key to use for the ECDH (yG)
1044  * @param key_material where to write the key material H(h(x)yG)
1045  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1046  */
1047 int
1048 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1049                           const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1050                           struct GNUNET_HashCode *key_material)
1051 {
1052   uint8_t p[crypto_scalarmult_BYTES];
1053
1054   BENCHMARK_START (ecdsa_ecdh);
1055   if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
1056     return GNUNET_SYSERR;
1057   GNUNET_CRYPTO_hash (p,
1058                       crypto_scalarmult_BYTES,
1059                       key_material);
1060   BENCHMARK_END (ecdsa_ecdh);
1061   return GNUNET_OK;
1062 }
1063
1064
1065 /**
1066  * @ingroup crypto
1067  * Derive key material from a EdDSA public key and a private ECDH key.
1068  * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1069  *
1070  * @param priv private key to use for the ECDH (y)
1071  * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1072  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1073  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1074  */
1075 int
1076 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1077                           const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1078                           struct GNUNET_HashCode *key_material)
1079 {
1080   uint8_t p[crypto_scalarmult_BYTES];
1081   uint8_t curve25510_pk[crypto_scalarmult_BYTES];
1082
1083   if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
1084     return GNUNET_SYSERR;
1085   if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
1086     return GNUNET_SYSERR;
1087   GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
1088   return GNUNET_OK;
1089 }
1090
1091
1092 /**
1093  * @ingroup crypto
1094  * Derive key material from a ECDSA public key and a private ECDH key.
1095  * Dual to #GNUNET_CRYPTO_ecdsa_ecdh.
1096  *
1097  * @param priv private key to use for the ECDH (y)
1098  * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1099  * @param key_material where to write the key material H(yX)=H(h(x)yG)
1100  * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1101  */
1102 int
1103 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1104                           const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1105                           struct GNUNET_HashCode *key_material)
1106 {
1107   uint8_t p[crypto_scalarmult_BYTES];
1108   uint8_t curve25510_pk[crypto_scalarmult_BYTES];
1109
1110   if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
1111     return GNUNET_SYSERR;
1112   if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
1113     return GNUNET_SYSERR;
1114   GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
1115   return GNUNET_OK;
1116 }
1117
1118
1119 /* end of crypto_ecc.c */