2 This file is part of GNUnet.
3 Copyright (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,
75 list = gcry_sexp_find_token (sexp, topname, 0);
78 l2 = gcry_sexp_cadr (list);
79 gcry_sexp_release (list);
85 for (s = elems; *s; s++, idx++)
87 l2 = gcry_sexp_find_token (list, s, 1);
90 for (i = 0; i < idx; i++)
95 gcry_sexp_release (list);
96 return 3; /* required parameter not found */
98 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
99 gcry_sexp_release (l2);
102 for (i = 0; i < idx; i++)
104 gcry_free (array[i]);
107 gcry_sexp_release (list);
108 return 4; /* required parameter is invalid */
111 gcry_sexp_release (list);
117 * Convert the given private key from the network format to the
118 * S-expression that can be used by libgcrypt.
120 * @param priv private key to decode
121 * @return NULL on error
124 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
129 rc = gcry_sexp_build (&result, NULL,
130 "(private-key(ecc(curve \"" CURVE "\")"
132 (int)sizeof (priv->d), priv->d);
135 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
139 if (0 != (rc = gcry_pk_testkey (result)))
141 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
150 * Convert the given private key from the network format to the
151 * S-expression that can be used by libgcrypt.
153 * @param priv private key to decode
154 * @return NULL on error
157 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
162 rc = gcry_sexp_build (&result, NULL,
163 "(private-key(ecc(curve \"" CURVE "\")"
164 "(flags eddsa)(d %b)))",
165 (int)sizeof (priv->d), priv->d);
168 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
172 if (0 != (rc = gcry_pk_testkey (result)))
174 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
183 * Convert the given private key from the network format to the
184 * S-expression that can be used by libgcrypt.
186 * @param priv private key to decode
187 * @return NULL on error
190 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
195 rc = gcry_sexp_build (&result, NULL,
196 "(private-key(ecc(curve \"" CURVE "\")"
198 (int)sizeof (priv->d), priv->d);
201 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
205 if (0 != (rc = gcry_pk_testkey (result)))
207 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
216 * Extract the public key for the given private key.
218 * @param priv the private key
219 * @param pub where to write the public key
222 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
223 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
229 sexp = decode_private_ecdsa_key (priv);
230 GNUNET_assert (NULL != sexp);
231 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
232 gcry_sexp_release (sexp);
233 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
234 GNUNET_assert (NULL != q);
235 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
236 gcry_mpi_release (q);
237 gcry_ctx_release (ctx);
242 * Extract the public key for the given private key.
244 * @param priv the private key
245 * @param pub where to write the public key
248 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
249 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
255 sexp = decode_private_eddsa_key (priv);
256 GNUNET_assert (NULL != sexp);
257 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
258 gcry_sexp_release (sexp);
259 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
261 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
262 gcry_mpi_release (q);
263 gcry_ctx_release (ctx);
268 * Extract the public key for the given private key.
270 * @param priv the private key
271 * @param pub where to write the public key
274 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
275 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
281 sexp = decode_private_ecdhe_key (priv);
282 GNUNET_assert (NULL != sexp);
283 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
284 gcry_sexp_release (sexp);
285 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
287 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
288 gcry_mpi_release (q);
289 gcry_ctx_release (ctx);
294 * Convert a public key to a string.
296 * @param pub key to convert
297 * @return string representing @a pub
300 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
303 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
307 keylen += 5 - keylen % 5;
309 pubkeybuf = GNUNET_malloc (keylen + 1);
310 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
311 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
316 GNUNET_free (pubkeybuf);
325 * Convert a public key to a string.
327 * @param pub key to convert
328 * @return string representing @a pub
331 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
334 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
338 keylen += 5 - keylen % 5;
340 pubkeybuf = GNUNET_malloc (keylen + 1);
341 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
342 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
347 GNUNET_free (pubkeybuf);
356 * Convert a string representing a public key to a public key.
358 * @param enc encoded public key
359 * @param enclen number of bytes in @a enc (without 0-terminator)
360 * @param pub where to store the public key
361 * @return #GNUNET_OK on success
364 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
366 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
368 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
371 keylen += 5 - keylen % 5;
373 if (enclen != keylen)
374 return GNUNET_SYSERR;
376 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
378 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
379 return GNUNET_SYSERR;
385 * Convert a string representing a public key to a public key.
387 * @param enc encoded public key
388 * @param enclen number of bytes in @a enc (without 0-terminator)
389 * @param pub where to store the public key
390 * @return #GNUNET_OK on success
393 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
395 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
397 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
400 keylen += 5 - keylen % 5;
402 if (enclen != keylen)
403 return GNUNET_SYSERR;
405 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
407 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
408 return GNUNET_SYSERR;
414 * Convert a string representing a private key to a private key.
416 * @param enc encoded public key
417 * @param enclen number of bytes in @a enc (without 0-terminator)
418 * @param priv where to store the private key
419 * @return #GNUNET_OK on success
422 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
424 struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
426 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
429 keylen += 5 - keylen % 5;
431 if (enclen != keylen)
432 return GNUNET_SYSERR;
434 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
436 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
437 return GNUNET_SYSERR;
444 * Clear memory that was used to store a private key.
446 * @param pk location of the key
449 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
451 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
457 * Clear memory that was used to store a private key.
459 * @param pk location of the key
462 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
464 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
470 * Clear memory that was used to store a private key.
472 * @param pk location of the key
475 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
477 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
482 * Create a new private key. Caller must free return value.
484 * @return fresh private key
486 struct GNUNET_CRYPTO_EcdhePrivateKey *
487 GNUNET_CRYPTO_ecdhe_key_create ()
489 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
490 gcry_sexp_t priv_sexp;
491 gcry_sexp_t s_keyparam;
495 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
496 "(genkey(ecc(curve \"" CURVE "\")"
499 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
502 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
504 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
505 gcry_sexp_release (s_keyparam);
508 gcry_sexp_release (s_keyparam);
510 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
512 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
513 gcry_sexp_release (priv_sexp);
517 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
519 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
520 gcry_sexp_release (priv_sexp);
523 gcry_sexp_release (priv_sexp);
524 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
525 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
526 gcry_mpi_release (d);
532 * Create a new private key. Caller must free return value.
534 * @return fresh private key
536 struct GNUNET_CRYPTO_EcdsaPrivateKey *
537 GNUNET_CRYPTO_ecdsa_key_create ()
539 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
540 gcry_sexp_t priv_sexp;
541 gcry_sexp_t s_keyparam;
545 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
546 "(genkey(ecc(curve \"" CURVE "\")"
549 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
552 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
554 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
555 gcry_sexp_release (s_keyparam);
558 gcry_sexp_release (s_keyparam);
560 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
562 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
563 gcry_sexp_release (priv_sexp);
567 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
569 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
570 gcry_sexp_release (priv_sexp);
573 gcry_sexp_release (priv_sexp);
574 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
575 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
576 gcry_mpi_release (d);
581 * Create a new private key. Caller must free return value.
583 * @return fresh private key
585 struct GNUNET_CRYPTO_EddsaPrivateKey *
586 GNUNET_CRYPTO_eddsa_key_create ()
588 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
589 gcry_sexp_t priv_sexp;
590 gcry_sexp_t s_keyparam;
594 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
595 "(genkey(ecc(curve \"" CURVE "\")"
598 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
601 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
603 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
604 gcry_sexp_release (s_keyparam);
607 gcry_sexp_release (s_keyparam);
609 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
611 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
612 gcry_sexp_release (priv_sexp);
616 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
618 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
619 gcry_sexp_release (priv_sexp);
622 gcry_sexp_release (priv_sexp);
623 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
624 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
625 gcry_mpi_release (d);
631 * Get the shared private key we use for anonymous users.
633 * @return "anonymous" private key
635 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
636 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
639 * 'anonymous' pseudonym (global static, d=1, public key = G
642 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
647 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
648 sizeof (anonymous.d),
656 * Wait for a short time (we're trying to lock a file or want
657 * to give another process a shot at finishing a disk write, etc.).
658 * Sleeps for 100ms (as that should be long enough for virtually all
659 * modern systems to context switch and allow another process to do
665 struct GNUNET_TIME_Relative timeout;
667 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
668 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
673 * Create a new private key by reading it from a file. If the
674 * files does not exist, create a new key and write it to the
675 * file. Caller must free return value. Note that this function
676 * can not guarantee that another process might not be trying
677 * the same operation on the same file at the same time.
678 * If the contents of the file
679 * are invalid the old file is deleted and a fresh key is
682 * @param filename name of file to use to store the key
683 * @return new private key, NULL on error (for example,
686 struct GNUNET_CRYPTO_EddsaPrivateKey *
687 GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
689 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
690 struct GNUNET_DISK_FileHandle *fd;
695 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
697 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
699 fd = GNUNET_DISK_file_open (filename,
700 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
701 | GNUNET_DISK_OPEN_FAILIFEXISTS,
702 GNUNET_DISK_PERM_USER_READ |
703 GNUNET_DISK_PERM_USER_WRITE);
708 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
710 /* must exist but not be accessible, fail for good! */
711 if (0 != ACCESS (filename, R_OK))
712 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
714 GNUNET_break (0); /* what is going on!? */
719 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
724 GNUNET_DISK_file_lock (fd, 0,
725 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
732 LOG (GNUNET_ERROR_TYPE_ERROR,
733 _("Could not acquire lock on file `%s': %s...\n"), filename,
737 LOG (GNUNET_ERROR_TYPE_INFO,
738 _("Creating a new private key. This may take a while.\n"));
739 priv = GNUNET_CRYPTO_eddsa_key_create ();
740 GNUNET_assert (NULL != priv);
741 GNUNET_assert (sizeof (*priv) ==
742 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
743 GNUNET_DISK_file_sync (fd);
745 GNUNET_DISK_file_unlock (fd, 0,
746 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
747 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
748 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
751 /* key file exists already, read it! */
752 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
753 GNUNET_DISK_PERM_NONE);
756 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
763 GNUNET_DISK_file_lock (fd, 0,
764 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
770 LOG (GNUNET_ERROR_TYPE_ERROR,
771 _("Could not acquire lock on file `%s': %s...\n"), filename,
773 LOG (GNUNET_ERROR_TYPE_ERROR,
775 ("This may be ok if someone is currently generating a private key.\n"));
780 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
782 /* eh, what!? File we opened is now gone!? */
783 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
785 GNUNET_DISK_file_unlock (fd, 0,
786 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
787 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
788 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
792 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
794 if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
796 /* maybe we got the read lock before the key generating
797 * process had a chance to get the write lock; give it up! */
799 GNUNET_DISK_file_unlock (fd, 0,
800 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
801 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
804 LOG (GNUNET_ERROR_TYPE_ERROR,
805 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
806 filename, (unsigned int) fs,
807 (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
808 LOG (GNUNET_ERROR_TYPE_ERROR,
809 _("This may be ok if someone is currently generating a key.\n"));
811 short_wait (); /* wait a bit longer! */
816 fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
817 priv = GNUNET_malloc (fs);
818 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
820 GNUNET_DISK_file_unlock (fd, 0,
821 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
822 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
823 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
829 * Create a new private key by reading it from a file. If the
830 * files does not exist, create a new key and write it to the
831 * file. Caller must free return value. Note that this function
832 * can not guarantee that another process might not be trying
833 * the same operation on the same file at the same time.
834 * If the contents of the file
835 * are invalid the old file is deleted and a fresh key is
838 * @param filename name of file to use to store the key
839 * @return new private key, NULL on error (for example,
842 struct GNUNET_CRYPTO_EcdsaPrivateKey *
843 GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
845 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
846 struct GNUNET_DISK_FileHandle *fd;
851 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
853 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
855 fd = GNUNET_DISK_file_open (filename,
856 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
857 | GNUNET_DISK_OPEN_FAILIFEXISTS,
858 GNUNET_DISK_PERM_USER_READ |
859 GNUNET_DISK_PERM_USER_WRITE);
864 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
866 /* must exist but not be accessible, fail for good! */
867 if (0 != ACCESS (filename, R_OK))
868 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
870 GNUNET_break (0); /* what is going on!? */
875 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
880 GNUNET_DISK_file_lock (fd, 0,
881 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
888 LOG (GNUNET_ERROR_TYPE_ERROR,
889 _("Could not acquire lock on file `%s': %s...\n"), filename,
893 LOG (GNUNET_ERROR_TYPE_INFO,
894 _("Creating a new private key. This may take a while.\n"));
895 priv = GNUNET_CRYPTO_ecdsa_key_create ();
896 GNUNET_assert (NULL != priv);
897 GNUNET_assert (sizeof (*priv) ==
898 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
899 GNUNET_DISK_file_sync (fd);
901 GNUNET_DISK_file_unlock (fd, 0,
902 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
903 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
904 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
907 /* key file exists already, read it! */
908 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
909 GNUNET_DISK_PERM_NONE);
912 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
919 GNUNET_DISK_file_lock (fd, 0,
920 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
926 LOG (GNUNET_ERROR_TYPE_ERROR,
927 _("Could not acquire lock on file `%s': %s...\n"), filename,
929 LOG (GNUNET_ERROR_TYPE_ERROR,
931 ("This may be ok if someone is currently generating a private key.\n"));
936 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
938 /* eh, what!? File we opened is now gone!? */
939 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
941 GNUNET_DISK_file_unlock (fd, 0,
942 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
943 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
944 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
948 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
950 if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
952 /* maybe we got the read lock before the key generating
953 * process had a chance to get the write lock; give it up! */
955 GNUNET_DISK_file_unlock (fd, 0,
956 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
957 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
960 LOG (GNUNET_ERROR_TYPE_ERROR,
961 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
962 filename, (unsigned int) fs,
963 (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
964 LOG (GNUNET_ERROR_TYPE_ERROR,
965 _("This may be ok if someone is currently generating a key.\n"));
967 short_wait (); /* wait a bit longer! */
972 fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
973 priv = GNUNET_malloc (fs);
974 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
976 GNUNET_DISK_file_unlock (fd, 0,
977 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
978 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
979 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
985 * Create a new private key by reading our peer's key from
986 * the file specified in the configuration.
988 * @param cfg the configuration to use
989 * @return new private key, NULL on error (for example,
992 struct GNUNET_CRYPTO_EddsaPrivateKey *
993 GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
995 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
999 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1001 priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
1008 * Setup a key file for a peer given the name of the
1009 * configuration file (!). This function is used so that
1010 * at a later point code can be certain that reading a
1011 * key is fast (for example in time-dependent testcases).
1013 * @param cfg_name name of the configuration file to use
1016 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1018 struct GNUNET_CONFIGURATION_Handle *cfg;
1019 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1021 cfg = GNUNET_CONFIGURATION_create ();
1022 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1023 priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1026 GNUNET_CONFIGURATION_destroy (cfg);
1031 * Retrieve the identity of the host's peer.
1033 * @param cfg configuration to use
1034 * @param dst pointer to where to write the peer identity
1035 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1036 * could not be retrieved
1039 GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1040 struct GNUNET_PeerIdentity *dst)
1042 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1044 if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1046 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1047 _("Could not load peer's private key\n"));
1048 return GNUNET_SYSERR;
1050 GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1057 * Compare two Peer Identities.
1059 * @param first first peer identity
1060 * @param second second peer identity
1061 * @return bigger than 0 if first > second,
1062 * 0 if they are the same
1063 * smaller than 0 if second > first
1066 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
1067 const struct GNUNET_PeerIdentity *second)
1069 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
1074 * Convert the data specified in the given purpose argument to an
1075 * S-expression suitable for signature operations.
1077 * @param purpose data to convert
1078 * @return converted s-expression
1081 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1083 struct GNUNET_HashCode hc;
1087 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1088 if (0 != (rc = gcry_sexp_build (&data, NULL,
1089 "(data(flags eddsa)(hash-algo %s)(value %b))",
1091 (int)sizeof (hc), &hc)))
1093 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1101 * Convert the data specified in the given purpose argument to an
1102 * S-expression suitable for signature operations.
1104 * @param purpose data to convert
1105 * @return converted s-expression
1108 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1110 struct GNUNET_HashCode hc;
1114 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1115 if (0 != (rc = gcry_sexp_build (&data, NULL,
1116 "(data(flags rfc6979)(hash %s %b))",
1118 (int)sizeof (hc), &hc)))
1120 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1128 * Sign a given block.
1130 * @param priv private key to use for the signing
1131 * @param purpose what to sign (size, purpose)
1132 * @param sig where to write the signature
1133 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1136 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1137 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1138 struct GNUNET_CRYPTO_EcdsaSignature *sig)
1140 gcry_sexp_t priv_sexp;
1141 gcry_sexp_t sig_sexp;
1146 priv_sexp = decode_private_ecdsa_key (priv);
1147 data = data_to_ecdsa_value (purpose);
1148 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1150 LOG (GNUNET_ERROR_TYPE_WARNING,
1151 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1152 __LINE__, gcry_strerror (rc));
1153 gcry_sexp_release (data);
1154 gcry_sexp_release (priv_sexp);
1155 return GNUNET_SYSERR;
1157 gcry_sexp_release (priv_sexp);
1158 gcry_sexp_release (data);
1160 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1162 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1165 gcry_sexp_release (sig_sexp);
1166 return GNUNET_SYSERR;
1168 gcry_sexp_release (sig_sexp);
1169 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1170 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1171 gcry_mpi_release (rs[0]);
1172 gcry_mpi_release (rs[1]);
1178 * Sign a given block.
1180 * @param priv private key to use for the signing
1181 * @param purpose what to sign (size, purpose)
1182 * @param sig where to write the signature
1183 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1186 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1187 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1188 struct GNUNET_CRYPTO_EddsaSignature *sig)
1190 gcry_sexp_t priv_sexp;
1191 gcry_sexp_t sig_sexp;
1196 priv_sexp = decode_private_eddsa_key (priv);
1197 data = data_to_eddsa_value (purpose);
1198 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1200 LOG (GNUNET_ERROR_TYPE_WARNING,
1201 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
1202 __LINE__, gcry_strerror (rc));
1203 gcry_sexp_release (data);
1204 gcry_sexp_release (priv_sexp);
1205 return GNUNET_SYSERR;
1207 gcry_sexp_release (priv_sexp);
1208 gcry_sexp_release (data);
1210 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1212 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1215 gcry_sexp_release (sig_sexp);
1216 return GNUNET_SYSERR;
1218 gcry_sexp_release (sig_sexp);
1219 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1220 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1221 gcry_mpi_release (rs[0]);
1222 gcry_mpi_release (rs[1]);
1230 * @param purpose what is the purpose that the signature should have?
1231 * @param validate block to validate (size, purpose, data)
1232 * @param sig signature that is being validated
1233 * @param pub public key of the signer
1234 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1237 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1238 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1239 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1240 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1243 gcry_sexp_t sig_sexpr;
1244 gcry_sexp_t pub_sexpr;
1247 if (purpose != ntohl (validate->purpose))
1248 return GNUNET_SYSERR; /* purpose mismatch */
1250 /* build s-expression for signature */
1251 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1252 "(sig-val(ecdsa(r %b)(s %b)))",
1253 (int)sizeof (sig->r), sig->r,
1254 (int)sizeof (sig->s), sig->s)))
1256 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1257 return GNUNET_SYSERR;
1259 data = data_to_ecdsa_value (validate);
1260 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1261 "(public-key(ecc(curve " CURVE ")(q %b)))",
1262 (int)sizeof (pub->q_y), pub->q_y)))
1264 gcry_sexp_release (data);
1265 gcry_sexp_release (sig_sexpr);
1266 return GNUNET_SYSERR;
1268 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1269 gcry_sexp_release (pub_sexpr);
1270 gcry_sexp_release (data);
1271 gcry_sexp_release (sig_sexpr);
1274 LOG (GNUNET_ERROR_TYPE_INFO,
1275 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1276 __LINE__, gcry_strerror (rc));
1277 return GNUNET_SYSERR;
1287 * @param purpose what is the purpose that the signature should have?
1288 * @param validate block to validate (size, purpose, data)
1289 * @param sig signature that is being validated
1290 * @param pub public key of the signer
1291 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1294 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1295 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1296 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1297 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1300 gcry_sexp_t sig_sexpr;
1301 gcry_sexp_t pub_sexpr;
1304 if (purpose != ntohl (validate->purpose))
1305 return GNUNET_SYSERR; /* purpose mismatch */
1307 /* build s-expression for signature */
1308 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1309 "(sig-val(eddsa(r %b)(s %b)))",
1310 (int)sizeof (sig->r), sig->r,
1311 (int)sizeof (sig->s), sig->s)))
1313 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1314 return GNUNET_SYSERR;
1316 data = data_to_eddsa_value (validate);
1317 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1318 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1319 (int)sizeof (pub->q_y), pub->q_y)))
1321 gcry_sexp_release (data);
1322 gcry_sexp_release (sig_sexpr);
1323 return GNUNET_SYSERR;
1325 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1326 gcry_sexp_release (pub_sexpr);
1327 gcry_sexp_release (data);
1328 gcry_sexp_release (sig_sexpr);
1331 LOG (GNUNET_ERROR_TYPE_INFO,
1332 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1333 __LINE__, gcry_strerror (rc));
1334 return GNUNET_SYSERR;
1341 * Derive key material from a public and a private ECDHE key.
1343 * @param priv private key to use for the ECDH (x)
1344 * @param pub public key to use for the ECDH (yG)
1345 * @param key_material where to write the key material (xyG)
1346 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1349 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1350 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1351 struct GNUNET_HashCode *key_material)
1353 gcry_mpi_point_t result;
1357 gcry_sexp_t pub_sexpr;
1358 gcry_mpi_t result_x;
1359 unsigned char xbuf[256 / 8];
1362 /* first, extract the q = dP value from the public key */
1363 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1364 "(public-key(ecc(curve " CURVE ")(q %b)))",
1365 (int)sizeof (pub->q_y), pub->q_y))
1366 return GNUNET_SYSERR;
1367 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1368 gcry_sexp_release (pub_sexpr);
1369 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1371 /* second, extract the d value from our private key */
1372 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1374 /* then call the 'multiply' function, to compute the product */
1375 result = gcry_mpi_point_new (0);
1376 gcry_mpi_ec_mul (result, d, q, ctx);
1377 gcry_mpi_point_release (q);
1378 gcry_mpi_release (d);
1380 /* finally, convert point to string for hashing */
1381 result_x = gcry_mpi_new (256);
1382 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1384 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1385 gcry_mpi_point_release (result);
1386 gcry_ctx_release (ctx);
1387 return GNUNET_SYSERR;
1389 gcry_mpi_point_release (result);
1390 gcry_ctx_release (ctx);
1392 rsize = sizeof (xbuf);
1393 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1394 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1395 as that does not include the sign bit; x should be a 255-bit
1396 value, so with the sign it should fit snugly into the 256-bit
1399 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1401 GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
1402 gcry_mpi_release (result_x);
1408 * Derive the 'h' value for key derivation, where
1411 * @param pub public key for deriviation
1412 * @param label label for deriviation
1413 * @param context additional context to use for HKDF of 'h';
1414 * typically the name of the subsystem/application
1418 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1420 const char *context)
1423 struct GNUNET_HashCode hc;
1425 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1426 "key-derivation", strlen ("key-derivation"),
1428 label, strlen (label),
1429 context, strlen (context),
1431 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof (hc));
1437 * Derive a private key from a given private key and a label.
1438 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1439 * where n is the size of the ECC group and P is the public
1440 * key associated with the private key 'd'.
1442 * @param priv original private key
1443 * @param label label to use for key deriviation
1444 * @param context additional context to use for HKDF of 'h';
1445 * typically the name of the subsystem/application
1446 * @return derived private key
1448 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1449 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1451 const char *context)
1453 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1454 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1461 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1463 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1464 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1466 h = derive_h (&pub, label, context);
1467 GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof (priv->d));
1468 d = gcry_mpi_new (256);
1469 gcry_mpi_mulm (d, h, x, n);
1470 gcry_mpi_release (h);
1471 gcry_mpi_release (x);
1472 gcry_mpi_release (n);
1473 gcry_ctx_release (ctx);
1474 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1475 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1476 gcry_mpi_release (d);
1482 * Derive a public key from a given public key and a label.
1483 * Essentially calculates a public key 'V = H(l,P) * P'.
1485 * @param pub original public key
1486 * @param label label to use for key derivation
1487 * @param context additional context to use for HKDF of 'h';
1488 * typically the name of the subsystem/application
1489 * @param result where to write the derived public key
1492 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1494 const char *context,
1495 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1505 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1507 /* obtain point 'q' from original public key. The provided 'q' is
1508 compressed thus we first store it in the context and then get it
1509 back as a (decompresssed) point. */
1510 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1511 GNUNET_assert (NULL != q_y);
1512 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1513 gcry_mpi_release (q_y);
1514 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1517 /* calculate h_mod_n = h % n */
1518 h = derive_h (pub, label, context);
1519 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1520 h_mod_n = gcry_mpi_new (256);
1521 gcry_mpi_mod (h_mod_n, h, n);
1522 /* calculate v = h_mod_n * q */
1523 v = gcry_mpi_point_new (0);
1524 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1525 gcry_mpi_release (h_mod_n);
1526 gcry_mpi_release (h);
1527 gcry_mpi_release (n);
1528 gcry_mpi_point_release (q);
1530 /* convert point 'v' to public key that we return */
1531 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1532 gcry_mpi_point_release (v);
1533 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1534 GNUNET_assert (q_y);
1535 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1536 sizeof (result->q_y),
1538 gcry_mpi_release (q_y);
1539 gcry_ctx_release (ctx);
1545 * Convert ECDSA public key to ECDHE public key.
1546 * Please be very careful when using this function, as mixing
1547 * cryptographic primitives is not always healthy.
1549 * @param ecdsa ecdsa public key
1550 * @param ecdhe[OUT] ecdhe public key
1553 GNUNET_CRYPTO_ecdsa_public_to_ecdhe (const struct GNUNET_CRYPTO_EcdsaPublicKey *ecdsa,
1554 struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe)
1556 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) ==
1557 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey));
1560 sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
1567 * Convert ECDSA private key to ECDHE private key.
1568 * Please be very careful when using this function, as mixing
1569 * cryptographic primitives is not always healthy.
1571 * @param ecdsa ecdsa private key
1572 * @param ecdhe[OUT] ecdhe private key
1575 GNUNET_CRYPTO_ecdsa_private_to_ecdhe (const struct GNUNET_CRYPTO_EcdsaPrivateKey *ecdsa,
1576 struct GNUNET_CRYPTO_EcdhePrivateKey *ecdhe)
1578 GNUNET_assert (sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey) ==
1579 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
1582 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1587 /* end of crypto_ecc.c */