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 * Convert the given private key from the network format to the
116 * S-expression that can be used by libgcrypt.
118 * @param priv private key to decode
119 * @return NULL on error
122 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
127 rc = gcry_sexp_build (&result, NULL,
128 "(private-key(ecc(curve \"" CURVE "\")"
130 (int)sizeof (priv->d), priv->d);
133 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
137 if (0 != (rc = gcry_pk_testkey (result)))
139 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
148 * Convert the given private key from the network format to the
149 * S-expression that can be used by libgcrypt.
151 * @param priv private key to decode
152 * @return NULL on error
155 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
160 rc = gcry_sexp_build (&result, NULL,
161 "(private-key(ecc(curve \"" CURVE "\")"
162 "(flags eddsa)(d %b)))",
163 (int)sizeof (priv->d), priv->d);
166 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
170 if (0 != (rc = gcry_pk_testkey (result)))
172 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
181 * Convert the given private key from the network format to the
182 * S-expression that can be used by libgcrypt.
184 * @param priv private key to decode
185 * @return NULL on error
188 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
193 rc = gcry_sexp_build (&result, NULL,
194 "(private-key(ecc(curve \"" CURVE "\")"
196 (int)sizeof (priv->d), priv->d);
199 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
203 if (0 != (rc = gcry_pk_testkey (result)))
205 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
214 * Extract the public key for the given private key.
216 * @param priv the private key
217 * @param pub where to write the public key
220 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
221 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
227 sexp = decode_private_ecdsa_key (priv);
228 GNUNET_assert (NULL != sexp);
229 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
230 gcry_sexp_release (sexp);
231 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
233 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
234 gcry_mpi_release (q);
235 gcry_ctx_release (ctx);
240 * Extract the public key for the given private key.
242 * @param priv the private key
243 * @param pub where to write the public key
246 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
247 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
253 sexp = decode_private_eddsa_key (priv);
254 GNUNET_assert (NULL != sexp);
255 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
256 gcry_sexp_release (sexp);
257 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
259 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
260 gcry_mpi_release (q);
261 gcry_ctx_release (ctx);
266 * Extract the public key for the given private key.
268 * @param priv the private key
269 * @param pub where to write the public key
272 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
273 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
279 sexp = decode_private_ecdhe_key (priv);
280 GNUNET_assert (NULL != sexp);
281 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
282 gcry_sexp_release (sexp);
283 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
285 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
286 gcry_mpi_release (q);
287 gcry_ctx_release (ctx);
292 * Convert a public key to a string.
294 * @param pub key to convert
295 * @return string representing @a pub
298 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
301 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
305 keylen += 5 - keylen % 5;
307 pubkeybuf = GNUNET_malloc (keylen + 1);
308 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
309 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
314 GNUNET_free (pubkeybuf);
323 * Convert a public key to a string.
325 * @param pub key to convert
326 * @return string representing @a pub
329 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
332 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
336 keylen += 5 - keylen % 5;
338 pubkeybuf = GNUNET_malloc (keylen + 1);
339 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
340 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
345 GNUNET_free (pubkeybuf);
354 * Convert a string representing a public key to a public key.
356 * @param enc encoded public key
357 * @param enclen number of bytes in @a enc (without 0-terminator)
358 * @param pub where to store the public key
359 * @return #GNUNET_OK on success
362 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
364 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
366 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
369 keylen += 5 - keylen % 5;
371 if (enclen != keylen)
372 return GNUNET_SYSERR;
374 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
376 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
377 return GNUNET_SYSERR;
383 * Convert a string representing a public key to a public key.
385 * @param enc encoded public key
386 * @param enclen number of bytes in @a enc (without 0-terminator)
387 * @param pub where to store the public key
388 * @return #GNUNET_OK on success
391 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
393 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
395 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
398 keylen += 5 - keylen % 5;
400 if (enclen != keylen)
401 return GNUNET_SYSERR;
403 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
405 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
406 return GNUNET_SYSERR;
412 * Convert a string representing a private key to a private key.
414 * @param enc encoded public key
415 * @param enclen number of bytes in @a enc (without 0-terminator)
416 * @param priv where to store the private key
417 * @return #GNUNET_OK on success
420 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
422 struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
424 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
427 keylen += 5 - keylen % 5;
429 if (enclen != keylen)
430 return GNUNET_SYSERR;
432 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
434 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
435 return GNUNET_SYSERR;
442 * Clear memory that was used to store a private key.
444 * @param pk location of the key
447 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
449 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
455 * Clear memory that was used to store a private key.
457 * @param pk location of the key
460 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
462 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
468 * Clear memory that was used to store a private key.
470 * @param pk location of the key
473 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
475 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
480 * Create a new private key. Caller must free return value.
482 * @return fresh private key
484 struct GNUNET_CRYPTO_EcdhePrivateKey *
485 GNUNET_CRYPTO_ecdhe_key_create ()
487 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
488 gcry_sexp_t priv_sexp;
489 gcry_sexp_t s_keyparam;
493 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
494 "(genkey(ecc(curve \"" CURVE "\")"
497 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
500 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
502 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
503 gcry_sexp_release (s_keyparam);
506 gcry_sexp_release (s_keyparam);
508 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
510 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
511 gcry_sexp_release (priv_sexp);
515 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
517 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
518 gcry_sexp_release (priv_sexp);
521 gcry_sexp_release (priv_sexp);
522 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
523 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
524 gcry_mpi_release (d);
530 * Create a new private key. Caller must free return value.
532 * @return fresh private key
534 struct GNUNET_CRYPTO_EcdsaPrivateKey *
535 GNUNET_CRYPTO_ecdsa_key_create ()
537 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
538 gcry_sexp_t priv_sexp;
539 gcry_sexp_t s_keyparam;
543 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
544 "(genkey(ecc(curve \"" CURVE "\")"
547 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
550 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
552 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
553 gcry_sexp_release (s_keyparam);
556 gcry_sexp_release (s_keyparam);
558 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
560 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
561 gcry_sexp_release (priv_sexp);
565 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
567 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
568 gcry_sexp_release (priv_sexp);
571 gcry_sexp_release (priv_sexp);
572 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
573 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
574 gcry_mpi_release (d);
579 * Create a new private key. Caller must free return value.
581 * @return fresh private key
583 struct GNUNET_CRYPTO_EddsaPrivateKey *
584 GNUNET_CRYPTO_eddsa_key_create ()
586 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
587 gcry_sexp_t priv_sexp;
588 gcry_sexp_t s_keyparam;
592 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
593 "(genkey(ecc(curve \"" CURVE "\")"
596 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
599 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
601 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
602 gcry_sexp_release (s_keyparam);
605 gcry_sexp_release (s_keyparam);
607 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
609 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
610 gcry_sexp_release (priv_sexp);
614 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
616 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
617 gcry_sexp_release (priv_sexp);
620 gcry_sexp_release (priv_sexp);
621 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
622 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
623 gcry_mpi_release (d);
629 * Get the shared private key we use for anonymous users.
631 * @return "anonymous" private key
633 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
634 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
637 * 'anonymous' pseudonym (global static, d=1, public key = G
640 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
645 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
646 sizeof (anonymous.d),
654 * Wait for a short time (we're trying to lock a file or want
655 * to give another process a shot at finishing a disk write, etc.).
656 * Sleeps for 100ms (as that should be long enough for virtually all
657 * modern systems to context switch and allow another process to do
663 struct GNUNET_TIME_Relative timeout;
665 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
666 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
671 * Create a new private key by reading it from a file. If the
672 * files does not exist, create a new key and write it to the
673 * file. Caller must free return value. Note that this function
674 * can not guarantee that another process might not be trying
675 * the same operation on the same file at the same time.
676 * If the contents of the file
677 * are invalid the old file is deleted and a fresh key is
680 * @param filename name of file to use to store the key
681 * @return new private key, NULL on error (for example,
684 struct GNUNET_CRYPTO_EddsaPrivateKey *
685 GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
687 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
688 struct GNUNET_DISK_FileHandle *fd;
693 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
695 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
697 fd = GNUNET_DISK_file_open (filename,
698 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
699 | GNUNET_DISK_OPEN_FAILIFEXISTS,
700 GNUNET_DISK_PERM_USER_READ |
701 GNUNET_DISK_PERM_USER_WRITE);
706 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
708 /* must exist but not be accessible, fail for good! */
709 if (0 != ACCESS (filename, R_OK))
710 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
712 GNUNET_break (0); /* what is going on!? */
717 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
722 GNUNET_DISK_file_lock (fd, 0,
723 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
730 LOG (GNUNET_ERROR_TYPE_ERROR,
731 _("Could not acquire lock on file `%s': %s...\n"), filename,
735 LOG (GNUNET_ERROR_TYPE_INFO,
736 _("Creating a new private key. This may take a while.\n"));
737 priv = GNUNET_CRYPTO_eddsa_key_create ();
738 GNUNET_assert (NULL != priv);
739 GNUNET_assert (sizeof (*priv) ==
740 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
741 GNUNET_DISK_file_sync (fd);
743 GNUNET_DISK_file_unlock (fd, 0,
744 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
745 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
746 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
749 /* key file exists already, read it! */
750 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
751 GNUNET_DISK_PERM_NONE);
754 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
761 GNUNET_DISK_file_lock (fd, 0,
762 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
768 LOG (GNUNET_ERROR_TYPE_ERROR,
769 _("Could not acquire lock on file `%s': %s...\n"), filename,
771 LOG (GNUNET_ERROR_TYPE_ERROR,
773 ("This may be ok if someone is currently generating a private key.\n"));
778 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
780 /* eh, what!? File we opened is now gone!? */
781 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
783 GNUNET_DISK_file_unlock (fd, 0,
784 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
785 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
786 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
790 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
792 if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
794 /* maybe we got the read lock before the key generating
795 * process had a chance to get the write lock; give it up! */
797 GNUNET_DISK_file_unlock (fd, 0,
798 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
799 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
802 LOG (GNUNET_ERROR_TYPE_ERROR,
803 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
804 filename, (unsigned int) fs,
805 (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
806 LOG (GNUNET_ERROR_TYPE_ERROR,
807 _("This may be ok if someone is currently generating a key.\n"));
809 short_wait (); /* wait a bit longer! */
814 fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
815 priv = GNUNET_malloc (fs);
816 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
818 GNUNET_DISK_file_unlock (fd, 0,
819 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
820 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
821 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
827 * Create a new private key by reading it from a file. If the
828 * files does not exist, create a new key and write it to the
829 * file. Caller must free return value. Note that this function
830 * can not guarantee that another process might not be trying
831 * the same operation on the same file at the same time.
832 * If the contents of the file
833 * are invalid the old file is deleted and a fresh key is
836 * @param filename name of file to use to store the key
837 * @return new private key, NULL on error (for example,
840 struct GNUNET_CRYPTO_EcdsaPrivateKey *
841 GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
843 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
844 struct GNUNET_DISK_FileHandle *fd;
849 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
851 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
853 fd = GNUNET_DISK_file_open (filename,
854 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
855 | GNUNET_DISK_OPEN_FAILIFEXISTS,
856 GNUNET_DISK_PERM_USER_READ |
857 GNUNET_DISK_PERM_USER_WRITE);
862 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
864 /* must exist but not be accessible, fail for good! */
865 if (0 != ACCESS (filename, R_OK))
866 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
868 GNUNET_break (0); /* what is going on!? */
873 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
878 GNUNET_DISK_file_lock (fd, 0,
879 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
886 LOG (GNUNET_ERROR_TYPE_ERROR,
887 _("Could not acquire lock on file `%s': %s...\n"), filename,
891 LOG (GNUNET_ERROR_TYPE_INFO,
892 _("Creating a new private key. This may take a while.\n"));
893 priv = GNUNET_CRYPTO_ecdsa_key_create ();
894 GNUNET_assert (NULL != priv);
895 GNUNET_assert (sizeof (*priv) ==
896 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
897 GNUNET_DISK_file_sync (fd);
899 GNUNET_DISK_file_unlock (fd, 0,
900 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
901 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
902 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
905 /* key file exists already, read it! */
906 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
907 GNUNET_DISK_PERM_NONE);
910 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
917 GNUNET_DISK_file_lock (fd, 0,
918 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
924 LOG (GNUNET_ERROR_TYPE_ERROR,
925 _("Could not acquire lock on file `%s': %s...\n"), filename,
927 LOG (GNUNET_ERROR_TYPE_ERROR,
929 ("This may be ok if someone is currently generating a private key.\n"));
934 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
936 /* eh, what!? File we opened is now gone!? */
937 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
939 GNUNET_DISK_file_unlock (fd, 0,
940 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
941 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
942 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
946 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
948 if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
950 /* maybe we got the read lock before the key generating
951 * process had a chance to get the write lock; give it up! */
953 GNUNET_DISK_file_unlock (fd, 0,
954 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
955 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
958 LOG (GNUNET_ERROR_TYPE_ERROR,
959 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
960 filename, (unsigned int) fs,
961 (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
962 LOG (GNUNET_ERROR_TYPE_ERROR,
963 _("This may be ok if someone is currently generating a key.\n"));
965 short_wait (); /* wait a bit longer! */
970 fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
971 priv = GNUNET_malloc (fs);
972 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
974 GNUNET_DISK_file_unlock (fd, 0,
975 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
976 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
977 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
983 * Create a new private key by reading our peer's key from
984 * the file specified in the configuration.
986 * @param cfg the configuration to use
987 * @return new private key, NULL on error (for example,
990 struct GNUNET_CRYPTO_EddsaPrivateKey *
991 GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
993 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
997 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
999 priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
1006 * Setup a key file for a peer given the name of the
1007 * configuration file (!). This function is used so that
1008 * at a later point code can be certain that reading a
1009 * key is fast (for example in time-dependent testcases).
1011 * @param cfg_name name of the configuration file to use
1014 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1016 struct GNUNET_CONFIGURATION_Handle *cfg;
1017 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1019 cfg = GNUNET_CONFIGURATION_create ();
1020 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1021 priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1024 GNUNET_CONFIGURATION_destroy (cfg);
1029 * Retrieve the identity of the host's peer.
1031 * @param cfg configuration to use
1032 * @param dst pointer to where to write the peer identity
1033 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1034 * could not be retrieved
1037 GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1038 struct GNUNET_PeerIdentity *dst)
1040 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1042 if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1044 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1045 _("Could not load peer's private key\n"));
1046 return GNUNET_SYSERR;
1048 GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1055 * Compare two Peer Identities.
1057 * @param first first peer identity
1058 * @param second second peer identity
1059 * @return bigger than 0 if first > second,
1060 * 0 if they are the same
1061 * smaller than 0 if second > first
1064 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
1065 const struct GNUNET_PeerIdentity *second)
1067 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
1072 * Convert the data specified in the given purpose argument to an
1073 * S-expression suitable for signature operations.
1075 * @param purpose data to convert
1076 * @return converted s-expression
1079 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1081 struct GNUNET_HashCode hc;
1085 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1086 if (0 != (rc = gcry_sexp_build (&data, NULL,
1087 "(data(flags eddsa)(hash-algo %s)(value %b))",
1089 (int)sizeof (hc), &hc)))
1091 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1099 * Convert the data specified in the given purpose argument to an
1100 * S-expression suitable for signature operations.
1102 * @param purpose data to convert
1103 * @return converted s-expression
1106 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1108 struct GNUNET_HashCode hc;
1112 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1113 if (0 != (rc = gcry_sexp_build (&data, NULL,
1114 "(data(flags rfc6979)(hash %s %b))",
1116 (int)sizeof (hc), &hc)))
1118 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1126 * Sign a given block.
1128 * @param priv private key to use for the signing
1129 * @param purpose what to sign (size, purpose)
1130 * @param sig where to write the signature
1131 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1134 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1135 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1136 struct GNUNET_CRYPTO_EcdsaSignature *sig)
1138 gcry_sexp_t priv_sexp;
1139 gcry_sexp_t sig_sexp;
1144 priv_sexp = decode_private_ecdsa_key (priv);
1145 data = data_to_ecdsa_value (purpose);
1146 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1148 LOG (GNUNET_ERROR_TYPE_WARNING,
1149 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1150 __LINE__, gcry_strerror (rc));
1151 gcry_sexp_release (data);
1152 gcry_sexp_release (priv_sexp);
1153 return GNUNET_SYSERR;
1155 gcry_sexp_release (priv_sexp);
1156 gcry_sexp_release (data);
1158 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1160 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1163 gcry_sexp_release (sig_sexp);
1164 return GNUNET_SYSERR;
1166 gcry_sexp_release (sig_sexp);
1167 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1168 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1169 gcry_mpi_release (rs[0]);
1170 gcry_mpi_release (rs[1]);
1176 * Sign a given block.
1178 * @param priv private key to use for the signing
1179 * @param purpose what to sign (size, purpose)
1180 * @param sig where to write the signature
1181 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1184 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1185 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1186 struct GNUNET_CRYPTO_EddsaSignature *sig)
1188 gcry_sexp_t priv_sexp;
1189 gcry_sexp_t sig_sexp;
1194 priv_sexp = decode_private_eddsa_key (priv);
1195 data = data_to_eddsa_value (purpose);
1196 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1198 LOG (GNUNET_ERROR_TYPE_WARNING,
1199 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
1200 __LINE__, gcry_strerror (rc));
1201 gcry_sexp_release (data);
1202 gcry_sexp_release (priv_sexp);
1203 return GNUNET_SYSERR;
1205 gcry_sexp_release (priv_sexp);
1206 gcry_sexp_release (data);
1208 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1210 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1213 gcry_sexp_release (sig_sexp);
1214 return GNUNET_SYSERR;
1216 gcry_sexp_release (sig_sexp);
1217 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
1218 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
1219 gcry_mpi_release (rs[0]);
1220 gcry_mpi_release (rs[1]);
1228 * @param purpose what is the purpose that the signature should have?
1229 * @param validate block to validate (size, purpose, data)
1230 * @param sig signature that is being validated
1231 * @param pub public key of the signer
1232 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1235 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1236 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1237 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1238 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1241 gcry_sexp_t sig_sexpr;
1242 gcry_sexp_t pub_sexpr;
1245 if (purpose != ntohl (validate->purpose))
1246 return GNUNET_SYSERR; /* purpose mismatch */
1248 /* build s-expression for signature */
1249 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1250 "(sig-val(ecdsa(r %b)(s %b)))",
1251 (int)sizeof (sig->r), sig->r,
1252 (int)sizeof (sig->s), sig->s)))
1254 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1255 return GNUNET_SYSERR;
1257 data = data_to_ecdsa_value (validate);
1258 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1259 "(public-key(ecc(curve " CURVE ")(q %b)))",
1260 (int)sizeof (pub->q_y), pub->q_y)))
1262 gcry_sexp_release (data);
1263 gcry_sexp_release (sig_sexpr);
1264 return GNUNET_SYSERR;
1266 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1267 gcry_sexp_release (pub_sexpr);
1268 gcry_sexp_release (data);
1269 gcry_sexp_release (sig_sexpr);
1272 LOG (GNUNET_ERROR_TYPE_INFO,
1273 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1274 __LINE__, gcry_strerror (rc));
1275 return GNUNET_SYSERR;
1285 * @param purpose what is the purpose that the signature should have?
1286 * @param validate block to validate (size, purpose, data)
1287 * @param sig signature that is being validated
1288 * @param pub public key of the signer
1289 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1292 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1293 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1294 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1295 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1298 gcry_sexp_t sig_sexpr;
1299 gcry_sexp_t pub_sexpr;
1302 if (purpose != ntohl (validate->purpose))
1303 return GNUNET_SYSERR; /* purpose mismatch */
1305 /* build s-expression for signature */
1306 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1307 "(sig-val(eddsa(r %b)(s %b)))",
1308 (int)sizeof (sig->r), sig->r,
1309 (int)sizeof (sig->s), sig->s)))
1311 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1312 return GNUNET_SYSERR;
1314 data = data_to_eddsa_value (validate);
1315 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1316 "(public-key(ecc(curve " CURVE ")(q %b)))",
1317 (int)sizeof (pub->q_y), pub->q_y)))
1319 gcry_sexp_release (data);
1320 gcry_sexp_release (sig_sexpr);
1321 return GNUNET_SYSERR;
1323 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1324 gcry_sexp_release (pub_sexpr);
1325 gcry_sexp_release (data);
1326 gcry_sexp_release (sig_sexpr);
1329 LOG (GNUNET_ERROR_TYPE_INFO,
1330 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1331 __LINE__, gcry_strerror (rc));
1332 return GNUNET_SYSERR;
1339 * Derive key material from a public and a private ECDHE key.
1341 * @param priv private key to use for the ECDH (x)
1342 * @param pub public key to use for the ECDH (yG)
1343 * @param key_material where to write the key material (xyG)
1344 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1347 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1348 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1349 struct GNUNET_HashCode *key_material)
1351 gcry_mpi_point_t result;
1355 gcry_sexp_t pub_sexpr;
1356 gcry_mpi_t result_x;
1357 unsigned char xbuf[256 / 8];
1360 /* first, extract the q = dP value from the public key */
1361 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1362 "(public-key(ecc(curve " CURVE ")(q %b)))",
1363 (int)sizeof (pub->q_y), pub->q_y))
1364 return GNUNET_SYSERR;
1365 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1366 gcry_sexp_release (pub_sexpr);
1367 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1369 /* second, extract the d value from our private key */
1370 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1372 /* then call the 'multiply' function, to compute the product */
1373 result = gcry_mpi_point_new (0);
1374 gcry_mpi_ec_mul (result, d, q, ctx);
1375 gcry_mpi_point_release (q);
1376 gcry_mpi_release (d);
1378 /* finally, convert point to string for hashing */
1379 result_x = gcry_mpi_new (256);
1380 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1382 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1383 gcry_mpi_point_release (result);
1384 gcry_ctx_release (ctx);
1385 return GNUNET_SYSERR;
1387 gcry_mpi_point_release (result);
1388 gcry_ctx_release (ctx);
1390 rsize = sizeof (xbuf);
1391 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1392 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1393 as that does not include the sign bit; x should be a 255-bit
1394 value, so with the sign it should fit snugly into the 256-bit
1397 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1399 GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
1400 gcry_mpi_release (result_x);
1406 * Derive the 'h' value for key derivation, where
1409 * @param pub public key for deriviation
1410 * @param label label for deriviation
1411 * @param context additional context to use for HKDF of 'h';
1412 * typically the name of the subsystem/application
1416 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1418 const char *context)
1421 struct GNUNET_HashCode hc;
1423 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1424 "key-derivation", strlen ("key-derivation"),
1426 label, strlen (label),
1427 context, strlen (context),
1429 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof (hc));
1435 * Derive a private key from a given private key and a label.
1436 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1437 * where n is the size of the ECC group and P is the public
1438 * key associated with the private key 'd'.
1440 * @param priv original private key
1441 * @param label label to use for key deriviation
1442 * @param context additional context to use for HKDF of 'h';
1443 * typically the name of the subsystem/application
1444 * @return derived private key
1446 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1447 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1449 const char *context)
1451 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1452 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1459 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1461 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1462 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1464 h = derive_h (&pub, label, context);
1465 GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof (priv->d));
1466 d = gcry_mpi_new (256);
1467 gcry_mpi_mulm (d, h, x, n);
1468 gcry_mpi_release (h);
1469 gcry_mpi_release (x);
1470 gcry_mpi_release (n);
1471 gcry_ctx_release (ctx);
1472 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1473 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1474 gcry_mpi_release (d);
1480 * Derive a public key from a given public key and a label.
1481 * Essentially calculates a public key 'V = H(l,P) * P'.
1483 * @param pub original public key
1484 * @param label label to use for key derivation
1485 * @param context additional context to use for HKDF of 'h';
1486 * typically the name of the subsystem/application
1487 * @param result where to write the derived public key
1490 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1492 const char *context,
1493 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1503 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1505 /* obtain point 'q' from original public key. The provided 'q' is
1506 compressed thus we first store it in the context and then get it
1507 back as a (decompresssed) point. */
1508 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1509 GNUNET_assert (q_y);
1510 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1511 gcry_mpi_release (q_y);
1512 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1515 /* calculate h_mod_n = h % n */
1516 h = derive_h (pub, label, context);
1517 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1518 h_mod_n = gcry_mpi_new (256);
1519 gcry_mpi_mod (h_mod_n, h, n);
1520 /* calculate v = h_mod_n * q */
1521 v = gcry_mpi_point_new (0);
1522 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1523 gcry_mpi_release (h_mod_n);
1524 gcry_mpi_release (h);
1525 gcry_mpi_release (n);
1526 gcry_mpi_point_release (q);
1528 /* convert point 'v' to public key that we return */
1529 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1530 gcry_mpi_point_release (v);
1531 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1532 GNUNET_assert (q_y);
1533 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof result->q_y, q_y);
1534 gcry_mpi_release (q_y);
1535 gcry_ctx_release (ctx);
1539 /* end of crypto_ecc.c */