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 ALLOW_EXTRA_CHECKS
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 * NOTE: this will change to Curve25519 before GNUnet 0.10.0.
40 #define CURVE "NIST P-256"
42 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
44 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
46 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
49 * Log an error message at log-level 'level' that indicates
50 * a failure of the command 'cmd' with the message given
51 * by gcry_strerror(rc).
53 #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)
57 * Extract values from an S-expression.
59 * @param array where to store the result(s)
60 * @param sexp S-expression to parse
61 * @param topname top-level name in the S-expression that is of interest
62 * @param elems names of the elements to extract
63 * @return 0 on success
66 key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
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 * If target != size, move @a target bytes to the end of the size-sized
118 * buffer and zero out the first @a target - @a size bytes.
120 * @param buf original buffer
121 * @param size number of bytes in @a buf
122 * @param target target size of the buffer
125 adjust (unsigned char *buf,
131 memmove (&buf[target - size], buf, size);
132 memset (buf, 0, target - size);
138 * Output the given MPI value to the given buffer.
140 * @param buf where to output to
141 * @param size number of bytes in @a buf
142 * @param val value to write to @a buf
145 mpi_print (unsigned char *buf,
153 gcry_mpi_print (GCRYMPI_FMT_USG, buf, rsize, &rsize,
155 adjust (buf, rsize, size);
160 * Convert data buffer into MPI value.
162 * @param result where to store MPI value (allocated)
163 * @param data raw data (GCRYMPI_FMT_USG)
164 * @param size number of bytes in data
167 mpi_scan (gcry_mpi_t *result,
168 const unsigned char *data,
173 if (0 != (rc = gcry_mpi_scan (result,
177 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
184 * Convert the given private key from the network format to the
185 * S-expression that can be used by libgcrypt.
187 * @param priv private key to decode
188 * @return NULL on error
191 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
200 rc = gcry_sexp_build (&result, NULL,
201 "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))",
203 gcry_mpi_release (d);
206 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
210 if (0 != (rc = gcry_pk_testkey (result)))
212 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
221 * Convert the given private key from the network format to the
222 * S-expression that can be used by libgcrypt.
224 * @param priv private key to decode
225 * @return NULL on error
228 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
237 rc = gcry_sexp_build (&result, NULL,
238 "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))", // FIXME: eddsa soon!
240 gcry_mpi_release (d);
243 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
247 if (0 != (rc = gcry_pk_testkey (result)))
249 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
258 * Convert the given private key from the network format to the
259 * S-expression that can be used by libgcrypt.
261 * @param priv private key to decode
262 * @return NULL on error
265 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
274 rc = gcry_sexp_build (&result, NULL,
275 "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))", // FIXME: ecdh here?
277 gcry_mpi_release (d);
280 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
284 if (0 != (rc = gcry_pk_testkey (result)))
286 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
295 * Initialize public key struct from the respective point
298 * @param q point on curve
299 * @param pub public key struct to initialize
300 * @param ctx context to use for ECC operations
303 point_to_public_ecdsa_key (gcry_mpi_point_t q,
305 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
310 q_x = gcry_mpi_new (256);
311 q_y = gcry_mpi_new (256);
312 if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
314 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
318 mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
319 mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
320 gcry_mpi_release (q_x);
321 gcry_mpi_release (q_y);
326 * Initialize public key struct from the respective point
329 * @param q point on curve
330 * @param pub public key struct to initialize
331 * @param ctx context to use for ECC operations
334 point_to_public_eddsa_key (gcry_mpi_point_t q,
336 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
341 q_x = gcry_mpi_new (256);
342 q_y = gcry_mpi_new (256);
343 if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
345 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
349 mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
350 mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
351 gcry_mpi_release (q_x);
352 gcry_mpi_release (q_y);
357 * Initialize public key struct from the respective point
360 * @param q point on curve
361 * @param pub public key struct to initialize
362 * @param ctx context to use for ECC operations
365 point_to_public_ecdhe_key (gcry_mpi_point_t q,
367 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
372 q_x = gcry_mpi_new (256);
373 q_y = gcry_mpi_new (256);
374 if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
376 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
380 mpi_print (pub->q_x, sizeof (pub->q_x), q_x);
381 mpi_print (pub->q_y, sizeof (pub->q_y), q_y);
382 gcry_mpi_release (q_x);
383 gcry_mpi_release (q_y);
388 * Extract the public key for the given private key.
390 * @param priv the private key
391 * @param pub where to write the public key
394 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
395 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
401 sexp = decode_private_ecdsa_key (priv);
402 GNUNET_assert (NULL != sexp);
403 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
404 gcry_sexp_release (sexp);
405 q = gcry_mpi_ec_get_point ("q", ctx, 0);
406 point_to_public_ecdsa_key (q, ctx, pub);
407 gcry_ctx_release (ctx);
408 gcry_mpi_point_release (q);
413 * Extract the public key for the given private key.
415 * @param priv the private key
416 * @param pub where to write the public key
419 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
420 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
426 sexp = decode_private_eddsa_key (priv);
427 GNUNET_assert (NULL != sexp);
428 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
429 gcry_sexp_release (sexp);
430 q = gcry_mpi_ec_get_point ("q", ctx, 0);
431 point_to_public_eddsa_key (q, ctx, pub);
432 gcry_ctx_release (ctx);
433 gcry_mpi_point_release (q);
438 * Extract the public key for the given private key.
440 * @param priv the private key
441 * @param pub where to write the public key
444 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
445 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
451 sexp = decode_private_ecdhe_key (priv);
452 GNUNET_assert (NULL != sexp);
453 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
454 gcry_sexp_release (sexp);
455 q = gcry_mpi_ec_get_point ("q", ctx, 0);
456 point_to_public_ecdhe_key (q, ctx, pub);
457 gcry_ctx_release (ctx);
458 gcry_mpi_point_release (q);
463 * Convert a public key to a string.
465 * @param pub key to convert
466 * @return string representing @a pub
469 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
472 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
476 keylen += 5 - keylen % 5;
478 pubkeybuf = GNUNET_malloc (keylen + 1);
479 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
480 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
485 GNUNET_free (pubkeybuf);
494 * Convert a public key to a string.
496 * @param pub key to convert
497 * @return string representing @a pub
500 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
503 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
507 keylen += 5 - keylen % 5;
509 pubkeybuf = GNUNET_malloc (keylen + 1);
510 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
511 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
516 GNUNET_free (pubkeybuf);
525 * Convert a string representing a public key to a public key.
527 * @param enc encoded public key
528 * @param enclen number of bytes in @a enc (without 0-terminator)
529 * @param pub where to store the public key
530 * @return #GNUNET_OK on success
533 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
535 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
537 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
540 keylen += 5 - keylen % 5;
542 if (enclen != keylen)
543 return GNUNET_SYSERR;
545 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
547 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
548 return GNUNET_SYSERR;
554 * Convert a string representing a public key to a public key.
556 * @param enc encoded public key
557 * @param enclen number of bytes in @a enc (without 0-terminator)
558 * @param pub where to store the public key
559 * @return #GNUNET_OK on success
562 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
564 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
566 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
569 keylen += 5 - keylen % 5;
571 if (enclen != keylen)
572 return GNUNET_SYSERR;
574 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
576 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
577 return GNUNET_SYSERR;
583 * Convert the given public key from the network format to the
584 * S-expression that can be used by libgcrypt.
586 * @param pub public key to decode
587 * @return NULL on error
590 decode_public_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
592 gcry_sexp_t pub_sexp;
598 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
599 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
600 q = gcry_mpi_point_new (256);
601 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
602 gcry_mpi_release (q_x);
603 gcry_mpi_release (q_y);
605 /* initialize 'ctx' with 'q' */
606 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); // FIXME: need to say ECDSA?
607 gcry_mpi_ec_set_point ("q", q, ctx);
608 gcry_mpi_point_release (q);
610 /* convert 'ctx' to 'sexp' */
611 GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
612 gcry_ctx_release (ctx);
618 * Convert the given public key from the network format to the
619 * S-expression that can be used by libgcrypt.
621 * @param pub public key to decode
622 * @return NULL on error
625 decode_public_eddsa_key (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
627 gcry_sexp_t pub_sexp;
633 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
634 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
635 q = gcry_mpi_point_new (256);
636 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
637 gcry_mpi_release (q_x);
638 gcry_mpi_release (q_y);
640 /* initialize 'ctx' with 'q' */
641 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE)); // FIXME: need to say EdDSA?
642 gcry_mpi_ec_set_point ("q", q, ctx);
643 gcry_mpi_point_release (q);
645 /* convert 'ctx' to 'sexp' */
646 GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
647 gcry_ctx_release (ctx);
654 * Clear memory that was used to store a private key.
656 * @param pk location of the key
659 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
661 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
667 * Clear memory that was used to store a private key.
669 * @param pk location of the key
672 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
674 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
680 * Clear memory that was used to store a private key.
682 * @param pk location of the key
685 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
687 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
692 * Create a new private key. Caller must free return value.
694 * @return fresh private key
696 struct GNUNET_CRYPTO_EcdhePrivateKey *
697 GNUNET_CRYPTO_ecdhe_key_create ()
699 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
700 gcry_sexp_t priv_sexp;
701 gcry_sexp_t s_keyparam;
705 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
706 "(genkey(ecdsa(curve \"" CURVE "\")))"))) // FIXME: ECDHE?
708 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
711 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
713 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
714 gcry_sexp_release (s_keyparam);
717 gcry_sexp_release (s_keyparam);
719 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
721 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
722 gcry_sexp_release (priv_sexp);
726 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
728 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
729 gcry_sexp_release (priv_sexp);
732 gcry_sexp_release (priv_sexp);
733 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
734 mpi_print (priv->d, sizeof (priv->d), d);
735 gcry_mpi_release (d);
741 * Create a new private key. Caller must free return value.
743 * @return fresh private key
745 struct GNUNET_CRYPTO_EcdsaPrivateKey *
746 GNUNET_CRYPTO_ecdsa_key_create ()
748 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
749 gcry_sexp_t priv_sexp;
750 gcry_sexp_t s_keyparam;
754 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
755 "(genkey(ecdsa(curve \"" CURVE "\")))")))
757 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
760 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
762 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
763 gcry_sexp_release (s_keyparam);
766 gcry_sexp_release (s_keyparam);
768 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
770 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
771 gcry_sexp_release (priv_sexp);
775 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
777 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
778 gcry_sexp_release (priv_sexp);
781 gcry_sexp_release (priv_sexp);
782 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
783 mpi_print (priv->d, sizeof (priv->d), d);
784 gcry_mpi_release (d);
789 * Create a new private key. Caller must free return value.
791 * @return fresh private key
793 struct GNUNET_CRYPTO_EddsaPrivateKey *
794 GNUNET_CRYPTO_eddsa_key_create ()
796 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
797 gcry_sexp_t priv_sexp;
798 gcry_sexp_t s_keyparam;
802 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
803 "(genkey(ecdsa(curve \"" CURVE "\")))"))) // FIXME: EdDSA?
805 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
808 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
810 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
811 gcry_sexp_release (s_keyparam);
814 gcry_sexp_release (s_keyparam);
816 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
818 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
819 gcry_sexp_release (priv_sexp);
823 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
825 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
826 gcry_sexp_release (priv_sexp);
829 gcry_sexp_release (priv_sexp);
830 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
831 mpi_print (priv->d, sizeof (priv->d), d);
832 gcry_mpi_release (d);
838 * Get the shared private key we use for anonymous users.
840 * @return "anonymous" private key
842 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
843 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
846 * 'anonymous' pseudonym (global static, d=1, public key = G
849 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
854 mpi_print (anonymous.d,
855 sizeof (anonymous.d),
863 * Wait for a short time (we're trying to lock a file or want
864 * to give another process a shot at finishing a disk write, etc.).
865 * Sleeps for 100ms (as that should be long enough for virtually all
866 * modern systems to context switch and allow another process to do
872 struct GNUNET_TIME_Relative timeout;
874 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 100);
875 (void) GNUNET_NETWORK_socket_select (NULL, NULL, NULL, timeout);
880 * Create a new private key by reading it from a file. If the
881 * files does not exist, create a new key and write it to the
882 * file. Caller must free return value. Note that this function
883 * can not guarantee that another process might not be trying
884 * the same operation on the same file at the same time.
885 * If the contents of the file
886 * are invalid the old file is deleted and a fresh key is
889 * @param filename name of file to use to store the key
890 * @return new private key, NULL on error (for example,
893 struct GNUNET_CRYPTO_EddsaPrivateKey *
894 GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename)
896 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
897 struct GNUNET_DISK_FileHandle *fd;
902 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
904 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
906 fd = GNUNET_DISK_file_open (filename,
907 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
908 | GNUNET_DISK_OPEN_FAILIFEXISTS,
909 GNUNET_DISK_PERM_USER_READ |
910 GNUNET_DISK_PERM_USER_WRITE);
915 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
917 /* must exist but not be accessible, fail for good! */
918 if (0 != ACCESS (filename, R_OK))
919 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
921 GNUNET_break (0); /* what is going on!? */
926 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
931 GNUNET_DISK_file_lock (fd, 0,
932 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
939 LOG (GNUNET_ERROR_TYPE_ERROR,
940 _("Could not acquire lock on file `%s': %s...\n"), filename,
944 LOG (GNUNET_ERROR_TYPE_INFO,
945 _("Creating a new private key. This may take a while.\n"));
946 priv = GNUNET_CRYPTO_eddsa_key_create ();
947 GNUNET_assert (NULL != priv);
948 GNUNET_assert (sizeof (*priv) ==
949 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
950 GNUNET_DISK_file_sync (fd);
952 GNUNET_DISK_file_unlock (fd, 0,
953 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
954 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
955 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
958 /* key file exists already, read it! */
959 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
960 GNUNET_DISK_PERM_NONE);
963 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
970 GNUNET_DISK_file_lock (fd, 0,
971 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
977 LOG (GNUNET_ERROR_TYPE_ERROR,
978 _("Could not acquire lock on file `%s': %s...\n"), filename,
980 LOG (GNUNET_ERROR_TYPE_ERROR,
982 ("This may be ok if someone is currently generating a private key.\n"));
987 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
989 /* eh, what!? File we opened is now gone!? */
990 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
992 GNUNET_DISK_file_unlock (fd, 0,
993 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
994 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
995 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
999 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1001 if (fs < sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))
1003 /* maybe we got the read lock before the key generating
1004 * process had a chance to get the write lock; give it up! */
1006 GNUNET_DISK_file_unlock (fd, 0,
1007 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
1008 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1009 if (0 == ++cnt % 10)
1011 LOG (GNUNET_ERROR_TYPE_ERROR,
1012 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
1013 filename, (unsigned int) fs,
1014 (unsigned int) sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
1015 LOG (GNUNET_ERROR_TYPE_ERROR,
1016 _("This may be ok if someone is currently generating a key.\n"));
1018 short_wait (); /* wait a bit longer! */
1023 fs = sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey);
1024 priv = GNUNET_malloc (fs);
1025 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
1027 GNUNET_DISK_file_unlock (fd, 0,
1028 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
1029 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1030 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1036 * Create a new private key by reading it from a file. If the
1037 * files does not exist, create a new key and write it to the
1038 * file. Caller must free return value. Note that this function
1039 * can not guarantee that another process might not be trying
1040 * the same operation on the same file at the same time.
1041 * If the contents of the file
1042 * are invalid the old file is deleted and a fresh key is
1045 * @param filename name of file to use to store the key
1046 * @return new private key, NULL on error (for example,
1047 * permission denied)
1049 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1050 GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
1052 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
1053 struct GNUNET_DISK_FileHandle *fd;
1058 if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename))
1060 while (GNUNET_YES != GNUNET_DISK_file_test (filename))
1062 fd = GNUNET_DISK_file_open (filename,
1063 GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE
1064 | GNUNET_DISK_OPEN_FAILIFEXISTS,
1065 GNUNET_DISK_PERM_USER_READ |
1066 GNUNET_DISK_PERM_USER_WRITE);
1069 if (EEXIST == errno)
1071 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1073 /* must exist but not be accessible, fail for good! */
1074 if (0 != ACCESS (filename, R_OK))
1075 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "access", filename);
1077 GNUNET_break (0); /* what is going on!? */
1082 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
1086 while (GNUNET_YES !=
1087 GNUNET_DISK_file_lock (fd, 0,
1088 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1092 if (0 == ++cnt % 10)
1095 LOG (GNUNET_ERROR_TYPE_ERROR,
1096 _("Could not acquire lock on file `%s': %s...\n"), filename,
1100 LOG (GNUNET_ERROR_TYPE_INFO,
1101 _("Creating a new private key. This may take a while.\n"));
1102 priv = GNUNET_CRYPTO_ecdsa_key_create ();
1103 GNUNET_assert (NULL != priv);
1104 GNUNET_assert (sizeof (*priv) ==
1105 GNUNET_DISK_file_write (fd, priv, sizeof (*priv)));
1106 GNUNET_DISK_file_sync (fd);
1108 GNUNET_DISK_file_unlock (fd, 0,
1109 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1110 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1111 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1114 /* key file exists already, read it! */
1115 fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ,
1116 GNUNET_DISK_PERM_NONE);
1119 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename);
1126 GNUNET_DISK_file_lock (fd, 0,
1127 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
1130 if (0 == ++cnt % 60)
1133 LOG (GNUNET_ERROR_TYPE_ERROR,
1134 _("Could not acquire lock on file `%s': %s...\n"), filename,
1136 LOG (GNUNET_ERROR_TYPE_ERROR,
1138 ("This may be ok if someone is currently generating a private key.\n"));
1143 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
1145 /* eh, what!? File we opened is now gone!? */
1146 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "stat", filename);
1148 GNUNET_DISK_file_unlock (fd, 0,
1149 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1150 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1151 GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
1155 if (GNUNET_OK != GNUNET_DISK_file_size (filename, &fs, GNUNET_YES, GNUNET_YES))
1157 if (fs < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))
1159 /* maybe we got the read lock before the key generating
1160 * process had a chance to get the write lock; give it up! */
1162 GNUNET_DISK_file_unlock (fd, 0,
1163 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1164 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1165 if (0 == ++cnt % 10)
1167 LOG (GNUNET_ERROR_TYPE_ERROR,
1168 _("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"),
1169 filename, (unsigned int) fs,
1170 (unsigned int) sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
1171 LOG (GNUNET_ERROR_TYPE_ERROR,
1172 _("This may be ok if someone is currently generating a key.\n"));
1174 short_wait (); /* wait a bit longer! */
1179 fs = sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1180 priv = GNUNET_malloc (fs);
1181 GNUNET_assert (fs == GNUNET_DISK_file_read (fd, priv, fs));
1183 GNUNET_DISK_file_unlock (fd, 0,
1184 sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))
1185 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fcntl", filename);
1186 GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd));
1192 * Create a new private key by reading our peer's key from
1193 * the file specified in the configuration.
1195 * @param cfg the configuration to use
1196 * @return new private key, NULL on error (for example,
1197 * permission denied)
1199 struct GNUNET_CRYPTO_EddsaPrivateKey *
1200 GNUNET_CRYPTO_eddsa_key_create_from_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
1202 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1206 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1208 priv = GNUNET_CRYPTO_eddsa_key_create_from_file (fn);
1215 * Setup a key file for a peer given the name of the
1216 * configuration file (!). This function is used so that
1217 * at a later point code can be certain that reading a
1218 * key is fast (for example in time-dependent testcases).
1220 * @param cfg_name name of the configuration file to use
1223 GNUNET_CRYPTO_eddsa_setup_key (const char *cfg_name)
1225 struct GNUNET_CONFIGURATION_Handle *cfg;
1226 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1228 cfg = GNUNET_CONFIGURATION_create ();
1229 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1230 priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
1233 GNUNET_CONFIGURATION_destroy (cfg);
1238 * Retrieve the identity of the host's peer.
1240 * @param cfg configuration to use
1241 * @param dst pointer to where to write the peer identity
1242 * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
1243 * could not be retrieved
1246 GNUNET_CRYPTO_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
1247 struct GNUNET_PeerIdentity *dst)
1249 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
1251 if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
1253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1254 _("Could not load peer's private key\n"));
1255 return GNUNET_SYSERR;
1257 GNUNET_CRYPTO_eddsa_key_get_public (priv, &dst->public_key);
1264 * Convert the data specified in the given purpose argument to an
1265 * S-expression suitable for signature operations.
1267 * @param purpose data to convert
1268 * @return converted s-expression
1271 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1273 struct GNUNET_HashCode hc;
1277 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1278 if (0 != (rc = gcry_sexp_build (&data, NULL,
1279 "(data(flags rfc6979)(hash %s %b))", // FIXME: use EdDSA encoding!
1284 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1292 * Convert the data specified in the given purpose argument to an
1293 * S-expression suitable for signature operations.
1295 * @param purpose data to convert
1296 * @return converted s-expression
1299 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1301 struct GNUNET_HashCode hc;
1305 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1306 if (0 != (rc = gcry_sexp_build (&data, NULL,
1307 "(data(flags rfc6979)(hash %s %b))",
1312 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1320 * Sign a given block.
1322 * @param priv private key to use for the signing
1323 * @param purpose what to sign (size, purpose)
1324 * @param sig where to write the signature
1325 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1328 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1329 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1330 struct GNUNET_CRYPTO_EcdsaSignature *sig)
1332 gcry_sexp_t priv_sexp;
1333 gcry_sexp_t sig_sexp;
1338 priv_sexp = decode_private_ecdsa_key (priv);
1339 data = data_to_ecdsa_value (purpose);
1340 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1342 LOG (GNUNET_ERROR_TYPE_WARNING,
1343 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1344 __LINE__, gcry_strerror (rc));
1345 gcry_sexp_release (data);
1346 gcry_sexp_release (priv_sexp);
1347 return GNUNET_SYSERR;
1349 gcry_sexp_release (priv_sexp);
1350 gcry_sexp_release (data);
1352 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1354 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1357 gcry_sexp_release (sig_sexp);
1358 return GNUNET_SYSERR;
1360 gcry_sexp_release (sig_sexp);
1361 mpi_print (sig->r, sizeof (sig->r), rs[0]);
1362 mpi_print (sig->s, sizeof (sig->s), rs[1]);
1363 gcry_mpi_release (rs[0]);
1364 gcry_mpi_release (rs[1]);
1370 * Sign a given block.
1372 * @param priv private key to use for the signing
1373 * @param purpose what to sign (size, purpose)
1374 * @param sig where to write the signature
1375 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1378 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1379 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
1380 struct GNUNET_CRYPTO_EddsaSignature *sig)
1382 gcry_sexp_t priv_sexp;
1383 gcry_sexp_t sig_sexp;
1388 priv_sexp = decode_private_eddsa_key (priv);
1389 data = data_to_eddsa_value (purpose);
1390 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1392 LOG (GNUNET_ERROR_TYPE_WARNING,
1393 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
1394 __LINE__, gcry_strerror (rc));
1395 gcry_sexp_release (data);
1396 gcry_sexp_release (priv_sexp);
1397 return GNUNET_SYSERR;
1399 gcry_sexp_release (priv_sexp);
1400 gcry_sexp_release (data);
1402 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1404 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1407 gcry_sexp_release (sig_sexp);
1408 return GNUNET_SYSERR;
1410 gcry_sexp_release (sig_sexp);
1411 mpi_print (sig->r, sizeof (sig->r), rs[0]);
1412 mpi_print (sig->s, sizeof (sig->s), rs[1]);
1413 gcry_mpi_release (rs[0]);
1414 gcry_mpi_release (rs[1]);
1422 * @param purpose what is the purpose that the signature should have?
1423 * @param validate block to validate (size, purpose, data)
1424 * @param sig signature that is being validated
1425 * @param pub public key of the signer
1426 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1429 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1430 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1431 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1432 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1435 gcry_sexp_t sig_sexpr;
1436 gcry_sexp_t pub_sexpr;
1441 if (purpose != ntohl (validate->purpose))
1442 return GNUNET_SYSERR; /* purpose mismatch */
1444 /* build s-expression for signature */
1445 mpi_scan (&r, sig->r, sizeof (sig->r));
1446 mpi_scan (&s, sig->s, sizeof (sig->s));
1447 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1448 "(sig-val(ecdsa(r %m)(s %m)))",
1451 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1452 gcry_mpi_release (r);
1453 gcry_mpi_release (s);
1454 return GNUNET_SYSERR;
1456 gcry_mpi_release (r);
1457 gcry_mpi_release (s);
1458 data = data_to_ecdsa_value (validate);
1459 if (! (pub_sexpr = decode_public_ecdsa_key (pub)))
1461 gcry_sexp_release (data);
1462 gcry_sexp_release (sig_sexpr);
1463 return GNUNET_SYSERR;
1465 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1466 gcry_sexp_release (pub_sexpr);
1467 gcry_sexp_release (data);
1468 gcry_sexp_release (sig_sexpr);
1471 LOG (GNUNET_ERROR_TYPE_INFO,
1472 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1473 __LINE__, gcry_strerror (rc));
1474 return GNUNET_SYSERR;
1484 * @param purpose what is the purpose that the signature should have?
1485 * @param validate block to validate (size, purpose, data)
1486 * @param sig signature that is being validated
1487 * @param pub public key of the signer
1488 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1491 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1492 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1493 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1494 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1497 gcry_sexp_t sig_sexpr;
1498 gcry_sexp_t pub_sexpr;
1503 if (purpose != ntohl (validate->purpose))
1504 return GNUNET_SYSERR; /* purpose mismatch */
1506 /* build s-expression for signature */
1507 mpi_scan (&r, sig->r, sizeof (sig->r));
1508 mpi_scan (&s, sig->s, sizeof (sig->s));
1509 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1510 "(sig-val(ecdsa(r %m)(s %m)))", // FIXME: eddsa soon...
1513 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1514 gcry_mpi_release (r);
1515 gcry_mpi_release (s);
1516 return GNUNET_SYSERR;
1518 gcry_mpi_release (r);
1519 gcry_mpi_release (s);
1520 data = data_to_eddsa_value (validate);
1521 if (! (pub_sexpr = decode_public_eddsa_key (pub)))
1523 gcry_sexp_release (data);
1524 gcry_sexp_release (sig_sexpr);
1525 return GNUNET_SYSERR;
1527 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1528 gcry_sexp_release (pub_sexpr);
1529 gcry_sexp_release (data);
1530 gcry_sexp_release (sig_sexpr);
1533 LOG (GNUNET_ERROR_TYPE_INFO,
1534 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1535 __LINE__, gcry_strerror (rc));
1536 return GNUNET_SYSERR;
1543 * Convert the given public key from the network format to the
1544 * S-expression that can be used by libgcrypt.
1546 * @param pub public key to decode
1547 * @return NULL on error
1550 decode_public_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePublicKey *pub)
1552 gcry_sexp_t pub_sexp;
1558 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
1559 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
1560 q = gcry_mpi_point_new (256);
1561 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1562 gcry_mpi_release (q_x);
1563 gcry_mpi_release (q_y);
1565 /* initialize 'ctx' with 'q' */
1566 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1567 gcry_mpi_ec_set_point ("q", q, ctx);
1568 gcry_mpi_point_release (q);
1570 /* convert 'ctx' to 'sexp' */
1571 GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
1572 gcry_ctx_release (ctx);
1578 * Derive key material from a public and a private ECDHE key.
1580 * @param priv private key to use for the ECDH (x)
1581 * @param pub public key to use for the ECDH (yG)
1582 * @param key_material where to write the key material (xyG)
1583 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1586 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1587 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1588 struct GNUNET_HashCode *key_material)
1590 gcry_mpi_point_t result;
1594 gcry_sexp_t pub_sexpr;
1595 gcry_mpi_t result_x;
1596 gcry_mpi_t result_y;
1597 unsigned char xbuf[256 / 8];
1599 /* first, extract the q = dP value from the public key */
1600 if (! (pub_sexpr = decode_public_ecdhe_key (pub)))
1601 return GNUNET_SYSERR;
1602 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1603 gcry_sexp_release (pub_sexpr);
1604 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1606 /* second, extract the d value from our private key */
1607 mpi_scan (&d, priv->d, sizeof (priv->d));
1609 /* then call the 'multiply' function, to compute the product */
1610 result = gcry_mpi_point_new (0);
1611 gcry_mpi_ec_mul (result, d, q, ctx);
1612 gcry_mpi_point_release (q);
1613 gcry_mpi_release (d);
1615 /* finally, convert point to string for hashing */
1616 result_x = gcry_mpi_new (256);
1617 result_y = gcry_mpi_new (256);
1618 if (gcry_mpi_ec_get_affine (result_x, result_y, result, ctx))
1620 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1621 gcry_mpi_point_release (result);
1622 gcry_ctx_release (ctx);
1623 return GNUNET_SYSERR;
1625 gcry_mpi_point_release (result);
1626 gcry_ctx_release (ctx);
1628 mpi_print (xbuf, sizeof (xbuf), result_x);
1629 GNUNET_CRYPTO_hash (xbuf, sizeof (xbuf), key_material);
1630 gcry_mpi_release (result_x);
1631 gcry_mpi_release (result_y);
1637 * Derive the 'h' value for key derivation, where
1640 * @param pub public key for deriviation
1641 * @param label label for deriviation
1642 * @param context additional context to use for HKDF of 'h';
1643 * typically the name of the subsystem/application
1647 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1649 const char *context)
1652 struct GNUNET_HashCode hc;
1654 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1655 "key-derivation", strlen ("key-derivation"),
1657 label, strlen (label),
1658 context, strlen (context),
1660 mpi_scan (&h, (unsigned char *) &hc, sizeof (hc));
1666 * Derive a private key from a given private key and a label.
1667 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1668 * where n is the size of the ECC group and P is the public
1669 * key associated with the private key 'd'.
1671 * @param priv original private key
1672 * @param label label to use for key deriviation
1673 * @param context additional context to use for HKDF of 'h';
1674 * typically the name of the subsystem/application
1675 * @return derived private key
1677 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1678 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1680 const char *context)
1682 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1683 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1690 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1691 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1692 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1693 h = derive_h (&pub, label, context);
1694 mpi_scan (&x, priv->d, sizeof (priv->d));
1695 d = gcry_mpi_new (256);
1696 gcry_mpi_mulm (d, h, x, n);
1697 gcry_mpi_release (h);
1698 gcry_mpi_release (x);
1699 gcry_mpi_release (n);
1700 gcry_ctx_release (ctx);
1701 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1702 mpi_print (ret->d, sizeof (ret->d), d);
1703 gcry_mpi_release (d);
1709 * Derive a public key from a given public key and a label.
1710 * Essentially calculates a public key 'V = H(l,P) * P'.
1712 * @param pub original public key
1713 * @param label label to use for key deriviation
1714 * @param context additional context to use for HKDF of 'h';
1715 * typically the name of the subsystem/application
1716 * @param result where to write the derived public key
1719 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1721 const char *context,
1722 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1733 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1735 /* obtain point 'q' from original public key */
1736 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
1737 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
1739 q = gcry_mpi_point_new (0);
1740 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1741 gcry_mpi_release (q_x);
1742 gcry_mpi_release (q_y);
1744 /* calulcate h_mod_n = h % n */
1745 h = derive_h (pub, label, context);
1746 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1747 h_mod_n = gcry_mpi_new (256);
1748 gcry_mpi_mod (h_mod_n, h, n);
1749 /* calculate v = h_mod_n * q */
1750 v = gcry_mpi_point_new (0);
1751 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1752 gcry_mpi_release (h_mod_n);
1753 gcry_mpi_release (h);
1754 gcry_mpi_release (n);
1755 gcry_mpi_point_release (q);
1756 /* convert point 'v' to public key that we return */
1757 point_to_public_ecdsa_key (v, ctx, result);
1758 gcry_mpi_point_release (v);
1759 gcry_ctx_release (ctx);
1763 /* end of crypto_ecc.c */