2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/crypto_ecc.c
23 * @brief public key cryptography (ECC) with libgcrypt
24 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
30 #define EXTRA_CHECKS 0
33 * Name of the curve we are using. Note that we have hard-coded
34 * structs that use 256 bits, so using a bigger curve will require
35 * changes that break stuff badly. The name of the curve given here
36 * must be agreed by all peers and be supported by libgcrypt.
38 #define CURVE "Ed25519"
40 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
42 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
44 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
47 * Log an error message at log-level 'level' that indicates
48 * a failure of the command 'cmd' with the message given
49 * by gcry_strerror(rc).
51 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
55 * Extract values from an S-expression.
57 * @param array where to store the result(s)
58 * @param sexp S-expression to parse
59 * @param topname top-level name in the S-expression that is of interest
60 * @param elems names of the elements to extract
61 * @return 0 on success
64 key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
73 list = gcry_sexp_find_token (sexp, topname, 0);
76 l2 = gcry_sexp_cadr (list);
77 gcry_sexp_release (list);
83 for (s = elems; *s; s++, idx++)
85 l2 = gcry_sexp_find_token (list, s, 1);
88 for (i = 0; i < idx; i++)
93 gcry_sexp_release (list);
94 return 3; /* required parameter not found */
96 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
97 gcry_sexp_release (l2);
100 for (i = 0; i < idx; i++)
102 gcry_free (array[i]);
105 gcry_sexp_release (list);
106 return 4; /* required parameter is invalid */
109 gcry_sexp_release (list);
115 * If target != size, move @a target bytes to the end of the size-sized
116 * buffer and zero out the first @a target - @a size bytes.
118 * @param buf original buffer
119 * @param size number of bytes in @a buf
120 * @param target target size of the buffer
123 adjust (unsigned char *buf,
129 memmove (&buf[target - size], buf, size);
130 memset (buf, 0, target - size);
136 * Convert the given private key from the network format to the
137 * S-expression that can be used by libgcrypt.
139 * @param priv private key to decode
140 * @return NULL on error
143 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
148 rc = gcry_sexp_build (&result, NULL,
149 "(private-key(ecc(curve \"" CURVE "\")"
151 (int)sizeof (priv->d), priv->d);
154 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
158 if (0 != (rc = gcry_pk_testkey (result)))
160 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
169 * Convert the given private key from the network format to the
170 * S-expression that can be used by libgcrypt.
172 * @param priv private key to decode
173 * @return NULL on error
176 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
181 rc = gcry_sexp_build (&result, NULL,
182 "(private-key(ecc(curve \"" CURVE "\")"
183 "(flags eddsa)(d %b)))",
184 (int)sizeof (priv->d), priv->d);
187 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
191 if (0 != (rc = gcry_pk_testkey (result)))
193 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
202 * Convert the given private key from the network format to the
203 * S-expression that can be used by libgcrypt.
205 * @param priv private key to decode
206 * @return NULL on error
209 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
214 rc = gcry_sexp_build (&result, NULL,
215 "(private-key(ecc(curve \"" CURVE "\")"
217 (int)sizeof (priv->d), priv->d);
220 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
224 if (0 != (rc = gcry_pk_testkey (result)))
226 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
235 * Extract the public key for the given private key.
237 * @param priv the private key
238 * @param pub where to write the public key
241 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
242 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
248 sexp = decode_private_ecdsa_key (priv);
249 GNUNET_assert (NULL != sexp);
250 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
251 gcry_sexp_release (sexp);
252 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
254 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
255 gcry_mpi_release (q);
256 gcry_ctx_release (ctx);
261 * Extract the public key for the given private key.
263 * @param priv the private key
264 * @param pub where to write the public key
267 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
268 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
274 sexp = decode_private_eddsa_key (priv);
275 GNUNET_assert (NULL != sexp);
276 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
277 gcry_sexp_release (sexp);
278 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
280 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
281 gcry_mpi_release (q);
282 gcry_ctx_release (ctx);
287 * Extract the public key for the given private key.
289 * @param priv the private key
290 * @param pub where to write the public key
293 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
294 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
300 sexp = decode_private_ecdhe_key (priv);
301 GNUNET_assert (NULL != sexp);
302 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
303 gcry_sexp_release (sexp);
304 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
306 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
307 gcry_mpi_release (q);
308 gcry_ctx_release (ctx);
313 * Convert a public key to a string.
315 * @param pub key to convert
316 * @return string representing @a pub
319 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
322 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
326 keylen += 5 - keylen % 5;
328 pubkeybuf = GNUNET_malloc (keylen + 1);
329 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
330 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
335 GNUNET_free (pubkeybuf);
344 * Convert a public key to a string.
346 * @param pub key to convert
347 * @return string representing @a pub
350 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
353 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
357 keylen += 5 - keylen % 5;
359 pubkeybuf = GNUNET_malloc (keylen + 1);
360 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
361 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
366 GNUNET_free (pubkeybuf);
375 * Convert a string representing a public key to a public key.
377 * @param enc encoded public key
378 * @param enclen number of bytes in @a enc (without 0-terminator)
379 * @param pub where to store the public key
380 * @return #GNUNET_OK on success
383 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
385 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
387 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
390 keylen += 5 - keylen % 5;
392 if (enclen != keylen)
393 return GNUNET_SYSERR;
395 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
397 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
398 return GNUNET_SYSERR;
404 * Convert a string representing a public key to a public key.
406 * @param enc encoded public key
407 * @param enclen number of bytes in @a enc (without 0-terminator)
408 * @param pub where to store the public key
409 * @return #GNUNET_OK on success
412 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
414 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
416 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
419 keylen += 5 - keylen % 5;
421 if (enclen != keylen)
422 return GNUNET_SYSERR;
424 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
426 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
427 return GNUNET_SYSERR;
434 * Clear memory that was used to store a private key.
436 * @param pk location of the key
439 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
441 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
447 * Clear memory that was used to store a private key.
449 * @param pk location of the key
452 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
454 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
460 * Clear memory that was used to store a private key.
462 * @param pk location of the key
465 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
467 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
472 * Create a new private key. Caller must free return value.
474 * @return fresh private key
476 struct GNUNET_CRYPTO_EcdhePrivateKey *
477 GNUNET_CRYPTO_ecdhe_key_create ()
479 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
480 gcry_sexp_t priv_sexp;
481 gcry_sexp_t s_keyparam;
485 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
486 "(genkey(ecc(curve \"" CURVE "\")"
489 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
492 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
494 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
495 gcry_sexp_release (s_keyparam);
498 gcry_sexp_release (s_keyparam);
500 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
502 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
503 gcry_sexp_release (priv_sexp);
507 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
509 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
510 gcry_sexp_release (priv_sexp);
513 gcry_sexp_release (priv_sexp);
514 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
515 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
516 gcry_mpi_release (d);
522 * Create a new private key. Caller must free return value.
524 * @return fresh private key
526 struct GNUNET_CRYPTO_EcdsaPrivateKey *
527 GNUNET_CRYPTO_ecdsa_key_create ()
529 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
530 gcry_sexp_t priv_sexp;
531 gcry_sexp_t s_keyparam;
535 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
536 "(genkey(ecc(curve \"" CURVE "\")"
539 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
542 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
544 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
545 gcry_sexp_release (s_keyparam);
548 gcry_sexp_release (s_keyparam);
550 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
552 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
553 gcry_sexp_release (priv_sexp);
557 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
559 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
560 gcry_sexp_release (priv_sexp);
563 gcry_sexp_release (priv_sexp);
564 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
565 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
566 gcry_mpi_release (d);
571 * Create a new private key. Caller must free return value.
573 * @return fresh private key
575 struct GNUNET_CRYPTO_EddsaPrivateKey *
576 GNUNET_CRYPTO_eddsa_key_create ()
578 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
579 gcry_sexp_t priv_sexp;
580 gcry_sexp_t s_keyparam;
584 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
585 "(genkey(ecc(curve \"" CURVE "\")"
588 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
591 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
593 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
594 gcry_sexp_release (s_keyparam);
597 gcry_sexp_release (s_keyparam);
599 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
601 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
602 gcry_sexp_release (priv_sexp);
606 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
608 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
609 gcry_sexp_release (priv_sexp);
612 gcry_sexp_release (priv_sexp);
613 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
614 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
615 gcry_mpi_release (d);
621 * Get the shared private key we use for anonymous users.
623 * @return "anonymous" private key
625 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
626 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
629 * 'anonymous' pseudonym (global static, d=1, public key = G
632 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
637 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
638 sizeof (anonymous.d),
646 * Wait for a short time (we're trying to lock a file or want
647 * to give another process a shot at finishing a disk write, etc.).
648 * Sleeps for 100ms (as that should be long enough for virtually all
649 * modern systems to context switch and allow another process to do
655 struct GNUNET_TIME_Relative timeout;
657 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
658 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
663 * Create a new private key by reading it from a file. If the
664 * files does not exist, create a new key and write it to the
665 * file. Caller must free return value. Note that this function
666 * can not guarantee that another process might not be trying
667 * the same operation on the same file at the same time.
668 * If the contents of the file
669 * are invalid the old file is deleted and a fresh key is
672 * @param filename name of file to use to store the key
673 * @return new private key, NULL on error (for example,
676 struct GNUNET_CRYPTO_EddsaPrivateKey *
677 GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
679 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
680 struct GNUNET_DISK_FileHandle *fd;
685 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
687 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
689 fd = GNUNET_DISK_file_open (filename,
690 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
691 | GNUNET_DISK_OPEN_FAILIFEXISTS,
692 GNUNET_DISK_PERM_USER_READ |
693 GNUNET_DISK_PERM_USER_WRITE);
698 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
700 /* must exist but not be accessible, fail for good! */
701 if (0 != ACCESS (filename, R_OK))
702 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
704 GNUNET_break (0); /* what is going on!? */
709 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
714 GNUNET_DISK_file_lock (fd, 0,
715 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
722 LOG (GNUNET_ERROR_TYPE_ERROR,
723 _("Could not acquire lock on file `%s': %s...\n"), filename,
727 LOG (GNUNET_ERROR_TYPE_INFO,
728 _("Creating a new private key. This may take a while.\n"));
729 priv = GNUNET_CRYPTO_eddsa_key_create ();
730 GNUNET_assert (NULL != priv);
731 GNUNET_assert (sizeof (*priv) ==
732 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
733 GNUNET_DISK_file_sync (fd);
735 GNUNET_DISK_file_unlock (fd, 0,
736 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
737 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
738 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
741 /* key file exists already, read it! */
742 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
743 GNUNET_DISK_PERM_NONE);
746 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
753 GNUNET_DISK_file_lock (fd, 0,
754 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
760 LOG (GNUNET_ERROR_TYPE_ERROR,
761 _("Could not acquire lock on file `%s': %s...\n"), filename,
763 LOG (GNUNET_ERROR_TYPE_ERROR,
765 ("This may be ok if someone is currently generating a private key.\n"));
770 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
772 /* eh, what!? File we opened is now gone!? */
773 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
775 GNUNET_DISK_file_unlock (fd, 0,
776 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
777 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
778 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
782 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
784 if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
786 /* maybe we got the read lock before the key generating
787 * process had a chance to get the write lock; give it up! */
789 GNUNET_DISK_file_unlock (fd, 0,
790 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
791 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
794 LOG (GNUNET_ERROR_TYPE_ERROR,
795 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
796 filename, (unsigned int) fs,
797 (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
798 LOG (GNUNET_ERROR_TYPE_ERROR,
799 _("This may be ok if someone is currently generating a key.\n"));
801 short_wait (); /* wait a bit longer! */
806 fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
807 priv = GNUNET_malloc (fs);
808 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
810 GNUNET_DISK_file_unlock (fd, 0,
811 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
812 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
813 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
819 * Create a new private key by reading it from a file. If the
820 * files does not exist, create a new key and write it to the
821 * file. Caller must free return value. Note that this function
822 * can not guarantee that another process might not be trying
823 * the same operation on the same file at the same time.
824 * If the contents of the file
825 * are invalid the old file is deleted and a fresh key is
828 * @param filename name of file to use to store the key
829 * @return new private key, NULL on error (for example,
832 struct GNUNET_CRYPTO_EcdsaPrivateKey *
833 GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
835 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
836 struct GNUNET_DISK_FileHandle *fd;
841 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
843 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
845 fd = GNUNET_DISK_file_open (filename,
846 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
847 | GNUNET_DISK_OPEN_FAILIFEXISTS,
848 GNUNET_DISK_PERM_USER_READ |
849 GNUNET_DISK_PERM_USER_WRITE);
854 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
856 /* must exist but not be accessible, fail for good! */
857 if (0 != ACCESS (filename, R_OK))
858 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
860 GNUNET_break (0); /* what is going on!? */
865 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
870 GNUNET_DISK_file_lock (fd, 0,
871 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
878 LOG (GNUNET_ERROR_TYPE_ERROR,
879 _("Could not acquire lock on file `%s': %s...\n"), filename,
883 LOG (GNUNET_ERROR_TYPE_INFO,
884 _("Creating a new private key. This may take a while.\n"));
885 priv = GNUNET_CRYPTO_ecdsa_key_create ();
886 GNUNET_assert (NULL != priv);
887 GNUNET_assert (sizeof (*priv) ==
888 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
889 GNUNET_DISK_file_sync (fd);
891 GNUNET_DISK_file_unlock (fd, 0,
892 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
893 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
894 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
897 /* key file exists already, read it! */
898 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
899 GNUNET_DISK_PERM_NONE);
902 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
909 GNUNET_DISK_file_lock (fd, 0,
910 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
916 LOG (GNUNET_ERROR_TYPE_ERROR,
917 _("Could not acquire lock on file `%s': %s...\n"), filename,
919 LOG (GNUNET_ERROR_TYPE_ERROR,
921 ("This may be ok if someone is currently generating a private key.\n"));
926 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
928 /* eh, what!? File we opened is now gone!? */
929 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
931 GNUNET_DISK_file_unlock (fd, 0,
932 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
933 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
934 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
938 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
940 if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
942 /* maybe we got the read lock before the key generating
943 * process had a chance to get the write lock; give it up! */
945 GNUNET_DISK_file_unlock (fd, 0,
946 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
947 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
950 LOG (GNUNET_ERROR_TYPE_ERROR,
951 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
952 filename, (unsigned int) fs,
953 (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
954 LOG (GNUNET_ERROR_TYPE_ERROR,
955 _("This may be ok if someone is currently generating a key.\n"));
957 short_wait (); /* wait a bit longer! */
962 fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
963 priv = GNUNET_malloc (fs);
964 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
966 GNUNET_DISK_file_unlock (fd, 0,
967 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
968 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
969 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
975 * Create a new private key by reading our peer's key from
976 * the file specified in the configuration.
978 * @param cfg the configuration to use
979 * @return new private key, NULL on error (for example,
982 struct GNUNET_CRYPTO_EddsaPrivateKey *
983 GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
985 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
989 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
991 priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
998 * Setup a key file for a peer given the name of the
999 * configuration file (!). This function is used so that
1000 * at a later point code can be certain that reading a
1001 * key is fast (for example in time-dependent testcases).
1003 * @param cfg_name name of the configuration file to use
1006 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1008 struct GNUNET_CONFIGURATION_Handle *cfg;
1009 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1011 cfg = GNUNET_CONFIGURATION_create ();
1012 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1013 priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1016 GNUNET_CONFIGURATION_destroy (cfg);
1021 * Retrieve the identity of the host's peer.
1023 * @param cfg configuration to use
1024 * @param dst pointer to where to write the peer identity
1025 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1026 * could not be retrieved
1029 GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1030 struct GNUNET_PeerIdentity *dst)
1032 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1034 if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1036 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1037 _("Could not load peer's private key\n"));
1038 return GNUNET_SYSERR;
1040 GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1047 * Compare two Peer Identities.
1049 * @param first first peer identity
1050 * @param second second peer identity
1051 * @return bigger than 0 if first > second,
1052 * 0 if they are the same
1053 * smaller than 0 if second > first
1056 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
1057 const struct GNUNET_PeerIdentity *second)
1059 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
1064 * Convert the data specified in the given purpose argument to an
1065 * S-expression suitable for signature operations.
1067 * @param purpose data to convert
1068 * @return converted s-expression
1071 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1073 struct GNUNET_HashCode hc;
1077 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1078 if (0 != (rc = gcry_sexp_build (&data, NULL,
1079 "(data(flags eddsa)(hash-algo %s)(value %b))",
1081 (int)sizeof (hc), &hc)))
1083 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1091 * Convert the data specified in the given purpose argument to an
1092 * S-expression suitable for signature operations.
1094 * @param purpose data to convert
1095 * @return converted s-expression
1098 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1100 struct GNUNET_HashCode hc;
1104 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1105 if (0 != (rc = gcry_sexp_build (&data, NULL,
1106 "(data(flags rfc6979)(hash %s %b))",
1108 (int)sizeof (hc), &hc)))
1110 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1118 * Sign a given block.
1120 * @param priv private key to use for the signing
1121 * @param purpose what to sign (size, purpose)
1122 * @param sig where to write the signature
1123 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1126 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1127 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1128 struct GNUNET_CRYPTO_EcdsaSignature *sig)
1130 gcry_sexp_t priv_sexp;
1131 gcry_sexp_t sig_sexp;
1136 priv_sexp = decode_private_ecdsa_key (priv);
1137 data = data_to_ecdsa_value (purpose);
1138 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1140 LOG (GNUNET_ERROR_TYPE_WARNING,
1141 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1142 __LINE__, gcry_strerror (rc));
1143 gcry_sexp_release (data);
1144 gcry_sexp_release (priv_sexp);
1145 return GNUNET_SYSERR;
1147 gcry_sexp_release (priv_sexp);
1148 gcry_sexp_release (data);
1150 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1152 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1155 gcry_sexp_release (sig_sexp);
1156 return GNUNET_SYSERR;
1158 gcry_sexp_release (sig_sexp);
1159 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1160 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1161 gcry_mpi_release (rs[0]);
1162 gcry_mpi_release (rs[1]);
1168 * Sign a given block.
1170 * @param priv private key to use for the signing
1171 * @param purpose what to sign (size, purpose)
1172 * @param sig where to write the signature
1173 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1176 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1177 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1178 struct GNUNET_CRYPTO_EddsaSignature *sig)
1180 gcry_sexp_t priv_sexp;
1181 gcry_sexp_t sig_sexp;
1186 priv_sexp = decode_private_eddsa_key (priv);
1187 data = data_to_eddsa_value (purpose);
1188 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1190 LOG (GNUNET_ERROR_TYPE_WARNING,
1191 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
1192 __LINE__, gcry_strerror (rc));
1193 gcry_sexp_release (data);
1194 gcry_sexp_release (priv_sexp);
1195 return GNUNET_SYSERR;
1197 gcry_sexp_release (priv_sexp);
1198 gcry_sexp_release (data);
1200 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1202 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1205 gcry_sexp_release (sig_sexp);
1206 return GNUNET_SYSERR;
1208 gcry_sexp_release (sig_sexp);
1209 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1210 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1211 gcry_mpi_release (rs[0]);
1212 gcry_mpi_release (rs[1]);
1220 * @param purpose what is the purpose that the signature should have?
1221 * @param validate block to validate (size, purpose, data)
1222 * @param sig signature that is being validated
1223 * @param pub public key of the signer
1224 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1227 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1228 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1229 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1230 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1233 gcry_sexp_t sig_sexpr;
1234 gcry_sexp_t pub_sexpr;
1237 if (purpose != ntohl (validate->purpose))
1238 return GNUNET_SYSERR; /* purpose mismatch */
1240 /* build s-expression for signature */
1241 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1242 "(sig-val(ecdsa(r %b)(s %b)))",
1243 (int)sizeof (sig->r), sig->r,
1244 (int)sizeof (sig->s), sig->s)))
1246 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1247 return GNUNET_SYSERR;
1249 data = data_to_ecdsa_value (validate);
1250 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1251 "(public-key(ecc(curve " CURVE ")(q %b)))",
1252 (int)sizeof (pub->q_y), pub->q_y)))
1254 gcry_sexp_release (data);
1255 gcry_sexp_release (sig_sexpr);
1256 return GNUNET_SYSERR;
1258 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1259 gcry_sexp_release (pub_sexpr);
1260 gcry_sexp_release (data);
1261 gcry_sexp_release (sig_sexpr);
1264 LOG (GNUNET_ERROR_TYPE_INFO,
1265 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1266 __LINE__, gcry_strerror (rc));
1267 return GNUNET_SYSERR;
1277 * @param purpose what is the purpose that the signature should have?
1278 * @param validate block to validate (size, purpose, data)
1279 * @param sig signature that is being validated
1280 * @param pub public key of the signer
1281 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1284 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1285 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1286 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1287 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1290 gcry_sexp_t sig_sexpr;
1291 gcry_sexp_t pub_sexpr;
1294 if (purpose != ntohl (validate->purpose))
1295 return GNUNET_SYSERR; /* purpose mismatch */
1297 /* build s-expression for signature */
1298 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1299 "(sig-val(eddsa(r %b)(s %b)))",
1300 (int)sizeof (sig->r), sig->r,
1301 (int)sizeof (sig->s), sig->s)))
1303 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1304 return GNUNET_SYSERR;
1306 data = data_to_eddsa_value (validate);
1307 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1308 "(public-key(ecc(curve " CURVE ")(q %b)))",
1309 (int)sizeof (pub->q_y), pub->q_y)))
1311 gcry_sexp_release (data);
1312 gcry_sexp_release (sig_sexpr);
1313 return GNUNET_SYSERR;
1315 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1316 gcry_sexp_release (pub_sexpr);
1317 gcry_sexp_release (data);
1318 gcry_sexp_release (sig_sexpr);
1321 LOG (GNUNET_ERROR_TYPE_INFO,
1322 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1323 __LINE__, gcry_strerror (rc));
1324 return GNUNET_SYSERR;
1331 * Derive key material from a public and a private ECDHE key.
1333 * @param priv private key to use for the ECDH (x)
1334 * @param pub public key to use for the ECDH (yG)
1335 * @param key_material where to write the key material (xyG)
1336 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1339 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1340 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1341 struct GNUNET_HashCode *key_material)
1343 gcry_mpi_point_t result;
1347 gcry_sexp_t pub_sexpr;
1348 gcry_mpi_t result_x;
1349 unsigned char xbuf[256 / 8];
1352 /* first, extract the q = dP value from the public key */
1353 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1354 "(public-key(ecc(curve " CURVE ")(q %b)))",
1355 (int)sizeof (pub->q_y), pub->q_y))
1356 return GNUNET_SYSERR;
1357 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1358 gcry_sexp_release (pub_sexpr);
1359 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1361 /* second, extract the d value from our private key */
1362 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1364 /* then call the 'multiply' function, to compute the product */
1365 result = gcry_mpi_point_new (0);
1366 gcry_mpi_ec_mul (result, d, q, ctx);
1367 gcry_mpi_point_release (q);
1368 gcry_mpi_release (d);
1370 /* finally, convert point to string for hashing */
1371 result_x = gcry_mpi_new (256);
1372 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1374 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1375 gcry_mpi_point_release (result);
1376 gcry_ctx_release (ctx);
1377 return GNUNET_SYSERR;
1379 gcry_mpi_point_release (result);
1380 gcry_ctx_release (ctx);
1382 rsize = sizeof (xbuf);
1383 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1384 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1385 as that does not include the sign bit; x should be a 255-bit
1386 value, so with the sign it should fit snugly into the 256-bit
1389 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1391 GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
1392 gcry_mpi_release (result_x);
1398 * Derive the 'h' value for key derivation, where
1401 * @param pub public key for deriviation
1402 * @param label label for deriviation
1403 * @param context additional context to use for HKDF of 'h';
1404 * typically the name of the subsystem/application
1408 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1410 const char *context)
1413 struct GNUNET_HashCode hc;
1415 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1416 "key-derivation", strlen ("key-derivation"),
1418 label, strlen (label),
1419 context, strlen (context),
1421 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof (hc));
1427 * Derive a private key from a given private key and a label.
1428 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1429 * where n is the size of the ECC group and P is the public
1430 * key associated with the private key 'd'.
1432 * @param priv original private key
1433 * @param label label to use for key deriviation
1434 * @param context additional context to use for HKDF of 'h';
1435 * typically the name of the subsystem/application
1436 * @return derived private key
1438 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1439 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1441 const char *context)
1443 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1444 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1451 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1453 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1454 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1456 h = derive_h (&pub, label, context);
1457 GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof (priv->d));
1458 d = gcry_mpi_new (256);
1459 gcry_mpi_mulm (d, h, x, n);
1460 gcry_mpi_release (h);
1461 gcry_mpi_release (x);
1462 gcry_mpi_release (n);
1463 gcry_ctx_release (ctx);
1464 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1465 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1466 gcry_mpi_release (d);
1472 * Derive a public key from a given public key and a label.
1473 * Essentially calculates a public key 'V = H(l,P) * P'.
1475 * @param pub original public key
1476 * @param label label to use for key deriviation
1477 * @param context additional context to use for HKDF of 'h';
1478 * typically the name of the subsystem/application
1479 * @param result where to write the derived public key
1482 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1484 const char *context,
1485 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1495 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1497 /* obtain point 'q' from original public key. The provided 'q' is
1498 compressed thus we first store it in the context and then get it
1499 back as a (decompresssed) point. */
1500 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1501 GNUNET_assert (q_y);
1502 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1503 gcry_mpi_release (q_y);
1504 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1507 /* calulcate h_mod_n = h % n */
1508 h = derive_h (pub, label, context);
1509 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1510 h_mod_n = gcry_mpi_new (256);
1511 gcry_mpi_mod (h_mod_n, h, n);
1512 /* calculate v = h_mod_n * q */
1513 v = gcry_mpi_point_new (0);
1514 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1515 gcry_mpi_release (h_mod_n);
1516 gcry_mpi_release (h);
1517 gcry_mpi_release (n);
1518 gcry_mpi_point_release (q);
1520 /* convert point 'v' to public key that we return */
1521 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1522 gcry_mpi_point_release (v);
1523 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1524 GNUNET_assert (q_y);
1525 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof result->q_y, q_y);
1526 gcry_mpi_release (q_y);
1527 gcry_ctx_release (ctx);
1531 /* end of crypto_ecc.c */