2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2015 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file util/crypto_ecc.c
23 * @brief public key cryptography (ECC) with libgcrypt
24 * @author Christian Grothoff
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_strings_lib.h"
30 #include "benchmark.h"
32 #define EXTRA_CHECKS 0
35 * Name of the curve we are using. Note that we have hard-coded
36 * structs that use 256 bits, so using a bigger curve will require
37 * changes that break stuff badly. The name of the curve given here
38 * must be agreed by all peers and be supported by libgcrypt.
40 #define CURVE "Ed25519"
42 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
44 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
46 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", 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,
77 list = gcry_sexp_find_token (sexp, topname, 0);
80 l2 = gcry_sexp_cadr (list);
81 gcry_sexp_release (list);
87 for (s = elems; *s; s++, idx++)
89 l2 = gcry_sexp_find_token (list, s, 1);
92 for (i = 0; i < idx; i++)
97 gcry_sexp_release (list);
98 return 3; /* required parameter not found */
100 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
101 gcry_sexp_release (l2);
104 for (i = 0; i < idx; i++)
106 gcry_free (array[i]);
109 gcry_sexp_release (list);
110 return 4; /* required parameter is invalid */
113 gcry_sexp_release (list);
119 * Convert the given private key from the network format to the
120 * S-expression that can be used by libgcrypt.
122 * @param priv private key to decode
123 * @return NULL on error
126 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
131 rc = gcry_sexp_build (&result, NULL,
132 "(private-key(ecc(curve \"" CURVE "\")"
134 (int) sizeof (priv->d), priv->d);
137 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
141 if (0 != (rc = gcry_pk_testkey (result)))
143 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
152 * Convert the given private key from the network format to the
153 * S-expression that can be used by libgcrypt.
155 * @param priv private key to decode
156 * @return NULL on error
159 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
164 rc = gcry_sexp_build (&result, NULL,
165 "(private-key(ecc(curve \"" CURVE "\")"
166 "(flags eddsa)(d %b)))",
167 (int)sizeof (priv->d), priv->d);
170 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
174 if (0 != (rc = gcry_pk_testkey (result)))
176 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
185 * Convert the given private key from the network format to the
186 * S-expression that can be used by libgcrypt.
188 * @param priv private key to decode
189 * @return NULL on error
192 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
197 rc = gcry_sexp_build (&result, NULL,
198 "(private-key(ecc(curve \"" CURVE "\")"
200 (int)sizeof (priv->d), priv->d);
203 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
207 if (0 != (rc = gcry_pk_testkey (result)))
209 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
218 * Extract the public key for the given private key.
220 * @param priv the private key
221 * @param pub where to write the public key
224 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
225 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
231 BENCHMARK_START (ecdsa_key_get_public);
233 sexp = decode_private_ecdsa_key (priv);
234 GNUNET_assert (NULL != sexp);
235 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
236 gcry_sexp_release (sexp);
237 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
238 GNUNET_assert (NULL != q);
239 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
240 gcry_mpi_release (q);
241 gcry_ctx_release (ctx);
243 BENCHMARK_END (ecdsa_key_get_public);
248 * Extract the public key for the given private key.
250 * @param priv the private key
251 * @param pub where to write the public key
254 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
255 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
261 BENCHMARK_START (eddsa_key_get_public);
263 sexp = decode_private_eddsa_key (priv);
264 GNUNET_assert (NULL != sexp);
265 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
266 gcry_sexp_release (sexp);
267 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
269 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
270 gcry_mpi_release (q);
271 gcry_ctx_release (ctx);
273 BENCHMARK_END (eddsa_key_get_public);
278 * Extract the public key for the given private key.
280 * @param priv the private key
281 * @param pub where to write the public key
284 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
285 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
291 BENCHMARK_START (ecdhe_key_get_public);
293 sexp = decode_private_ecdhe_key (priv);
294 GNUNET_assert (NULL != sexp);
295 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
296 gcry_sexp_release (sexp);
297 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
299 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
300 gcry_mpi_release (q);
301 gcry_ctx_release (ctx);
303 BENCHMARK_END (ecdhe_key_get_public);
308 * Convert a public key to a string.
310 * @param pub key to convert
311 * @return string representing @a pub
314 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
317 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
321 keylen += 5 - keylen % 5;
323 pubkeybuf = GNUNET_malloc (keylen + 1);
324 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
325 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
330 GNUNET_free (pubkeybuf);
339 * Convert a public key to a string.
341 * @param pub key to convert
342 * @return string representing @a pub
345 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
348 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
352 keylen += 5 - keylen % 5;
354 pubkeybuf = GNUNET_malloc (keylen + 1);
355 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
356 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
361 GNUNET_free (pubkeybuf);
370 * Convert a private key to a string.
372 * @param priv key to convert
373 * @return string representing @a pub
376 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
379 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
383 keylen += 5 - keylen % 5;
385 privkeybuf = GNUNET_malloc (keylen + 1);
386 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
387 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
392 GNUNET_free (privkeybuf);
401 * Convert a string representing a public key to a public key.
403 * @param enc encoded public key
404 * @param enclen number of bytes in @a enc (without 0-terminator)
405 * @param pub where to store the public key
406 * @return #GNUNET_OK on success
409 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
411 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
413 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
416 keylen += 5 - keylen % 5;
418 if (enclen != keylen)
419 return GNUNET_SYSERR;
422 GNUNET_STRINGS_string_to_data (enc, enclen,
424 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
425 return GNUNET_SYSERR;
431 * Convert a string representing a public key to a public key.
433 * @param enc encoded public key
434 * @param enclen number of bytes in @a enc (without 0-terminator)
435 * @param pub where to store the public key
436 * @return #GNUNET_OK on success
439 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
441 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
443 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
446 keylen += 5 - keylen % 5;
448 if (enclen != keylen)
449 return GNUNET_SYSERR;
452 GNUNET_STRINGS_string_to_data (enc, enclen,
454 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
455 return GNUNET_SYSERR;
461 * Convert a string representing a private key to a private key.
463 * @param enc encoded public key
464 * @param enclen number of bytes in @a enc (without 0-terminator)
465 * @param priv where to store the private key
466 * @return #GNUNET_OK on success
469 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
471 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
473 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
476 keylen += 5 - keylen % 5;
478 if (enclen != keylen)
479 return GNUNET_SYSERR;
482 GNUNET_STRINGS_string_to_data (enc, enclen,
484 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
485 return GNUNET_SYSERR;
488 check_eddsa_key (priv))
500 * Clear memory that was used to store a private key.
502 * @param pk location of the key
505 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
507 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
513 * Clear memory that was used to store a private key.
515 * @param pk location of the key
518 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
520 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
526 * Clear memory that was used to store a private key.
528 * @param pk location of the key
531 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
533 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
538 * Create a new private key. Caller must free return value.
540 * @return fresh private key
542 struct GNUNET_CRYPTO_EcdhePrivateKey *
543 GNUNET_CRYPTO_ecdhe_key_create ()
545 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
547 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
549 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
560 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
562 * @param[out] pk set to fresh private key;
563 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
566 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
568 gcry_sexp_t priv_sexp;
569 gcry_sexp_t s_keyparam;
573 BENCHMARK_START (ecdhe_key_create);
575 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
576 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
577 disables an expensive key testing routine. We do not want to run
578 the expensive check for ECDHE, as we generate TONS of keys to
579 use for a very short time. */
580 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
581 "(genkey(ecc(curve \"" CURVE "\")"
582 "(flags eddsa no-keytest)))")))
584 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
585 return GNUNET_SYSERR;
587 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
589 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
590 gcry_sexp_release (s_keyparam);
591 return GNUNET_SYSERR;
593 gcry_sexp_release (s_keyparam);
595 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
597 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
598 gcry_sexp_release (priv_sexp);
599 return GNUNET_SYSERR;
602 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
604 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
605 gcry_sexp_release (priv_sexp);
606 return GNUNET_SYSERR;
608 gcry_sexp_release (priv_sexp);
609 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
610 gcry_mpi_release (d);
612 BENCHMARK_END (ecdhe_key_create);
619 * Create a new private key. Caller must free return value.
621 * @return fresh private key
623 struct GNUNET_CRYPTO_EcdsaPrivateKey *
624 GNUNET_CRYPTO_ecdsa_key_create ()
626 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
627 gcry_sexp_t priv_sexp;
628 gcry_sexp_t s_keyparam;
632 BENCHMARK_START (ecdsa_key_create);
634 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
635 "(genkey(ecc(curve \"" CURVE "\")"
638 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
641 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
643 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
644 gcry_sexp_release (s_keyparam);
647 gcry_sexp_release (s_keyparam);
649 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
651 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
652 gcry_sexp_release (priv_sexp);
656 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
658 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
659 gcry_sexp_release (priv_sexp);
662 gcry_sexp_release (priv_sexp);
663 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
664 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
665 gcry_mpi_release (d);
667 BENCHMARK_END (ecdsa_key_create);
673 * Create a new private key. Caller must free return value.
675 * @return fresh private key
677 struct GNUNET_CRYPTO_EddsaPrivateKey *
678 GNUNET_CRYPTO_eddsa_key_create ()
680 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
681 gcry_sexp_t priv_sexp;
682 gcry_sexp_t s_keyparam;
686 BENCHMARK_START (eddsa_key_create);
691 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
692 "(genkey(ecc(curve \"" CURVE "\")"
695 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
698 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
700 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
701 gcry_sexp_release (s_keyparam);
704 gcry_sexp_release (s_keyparam);
706 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
708 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
709 gcry_sexp_release (priv_sexp);
713 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
715 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
716 gcry_sexp_release (priv_sexp);
719 gcry_sexp_release (priv_sexp);
720 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
721 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
722 gcry_mpi_release (d);
726 check_eddsa_key (priv))
734 BENCHMARK_END (eddsa_key_create);
741 * Get the shared private key we use for anonymous users.
743 * @return "anonymous" private key
745 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
746 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
749 * 'anonymous' pseudonym (global static, d=1, public key = G
752 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
757 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
758 sizeof (anonymous.d),
766 * Compare two Peer Identities.
768 * @param first first peer identity
769 * @param second second peer identity
770 * @return bigger than 0 if first > second,
771 * 0 if they are the same
772 * smaller than 0 if second > first
775 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
776 const struct GNUNET_PeerIdentity *second)
778 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
783 * Convert the data specified in the given purpose argument to an
784 * S-expression suitable for signature operations.
786 * @param purpose data to convert
787 * @return converted s-expression
790 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
797 struct GNUNET_HashCode hc;
799 GNUNET_CRYPTO_hash (purpose,
800 ntohl (purpose->size),
802 if (0 != (rc = gcry_sexp_build (&data, NULL,
803 "(data(flags eddsa)(hash-algo %s)(value %b))",
808 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
814 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
815 if (0 != (rc = gcry_sexp_build (&data, NULL,
816 "(data(flags eddsa)(hash-algo %s)(value %b))",
818 ntohl (purpose->size),
821 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
832 * Convert the data specified in the given purpose argument to an
833 * S-expression suitable for signature operations.
835 * @param purpose data to convert
836 * @return converted s-expression
839 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
846 struct GNUNET_HashCode hc;
848 GNUNET_CRYPTO_hash (purpose,
849 ntohl (purpose->size),
851 if (0 != (rc = gcry_sexp_build (&data, NULL,
852 "(data(flags rfc6979)(hash %s %b))",
854 (int)sizeof (hc), &hc)))
856 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
862 if (0 != (rc = gcry_sexp_build (&data, NULL,
863 "(data(flags rfc6979)(hash %s %b))",
865 ntohl (purpose->size),
868 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
879 * Sign a given block.
881 * @param priv private key to use for the signing
882 * @param purpose what to sign (size, purpose)
883 * @param sig where to write the signature
884 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
887 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
888 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
889 struct GNUNET_CRYPTO_EcdsaSignature *sig)
891 gcry_sexp_t priv_sexp;
892 gcry_sexp_t sig_sexp;
897 BENCHMARK_START (ecdsa_sign);
899 priv_sexp = decode_private_ecdsa_key (priv);
900 data = data_to_ecdsa_value (purpose);
901 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
903 LOG (GNUNET_ERROR_TYPE_WARNING,
904 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
905 __LINE__, gcry_strerror (rc));
906 gcry_sexp_release (data);
907 gcry_sexp_release (priv_sexp);
908 return GNUNET_SYSERR;
910 gcry_sexp_release (priv_sexp);
911 gcry_sexp_release (data);
913 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
915 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
918 gcry_sexp_release (sig_sexp);
919 return GNUNET_SYSERR;
921 gcry_sexp_release (sig_sexp);
922 GNUNET_CRYPTO_mpi_print_unsigned (sig->r,
925 GNUNET_CRYPTO_mpi_print_unsigned (sig->s,
928 gcry_mpi_release (rs[0]);
929 gcry_mpi_release (rs[1]);
931 BENCHMARK_END (ecdsa_sign);
938 * Sign a given block.
940 * @param priv private key to use for the signing
941 * @param purpose what to sign (size, purpose)
942 * @param sig where to write the signature
943 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
946 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
947 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
948 struct GNUNET_CRYPTO_EddsaSignature *sig)
950 gcry_sexp_t priv_sexp;
951 gcry_sexp_t sig_sexp;
956 BENCHMARK_START (eddsa_sign);
958 priv_sexp = decode_private_eddsa_key (priv);
959 data = data_to_eddsa_value (purpose);
960 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
962 LOG (GNUNET_ERROR_TYPE_WARNING,
963 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
964 __LINE__, gcry_strerror (rc));
965 gcry_sexp_release (data);
966 gcry_sexp_release (priv_sexp);
967 return GNUNET_SYSERR;
969 gcry_sexp_release (priv_sexp);
970 gcry_sexp_release (data);
972 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
974 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
977 gcry_sexp_release (sig_sexp);
978 return GNUNET_SYSERR;
980 gcry_sexp_release (sig_sexp);
981 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
982 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
983 gcry_mpi_release (rs[0]);
984 gcry_mpi_release (rs[1]);
986 BENCHMARK_END (eddsa_sign);
995 * @param purpose what is the purpose that the signature should have?
996 * @param validate block to validate (size, purpose, data)
997 * @param sig signature that is being validated
998 * @param pub public key of the signer
999 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1002 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
1003 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1004 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1005 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1008 gcry_sexp_t sig_sexpr;
1009 gcry_sexp_t pub_sexpr;
1012 BENCHMARK_START (ecdsa_verify);
1014 if (purpose != ntohl (validate->purpose))
1015 return GNUNET_SYSERR; /* purpose mismatch */
1017 /* build s-expression for signature */
1018 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1019 "(sig-val(ecdsa(r %b)(s %b)))",
1020 (int) sizeof (sig->r), sig->r,
1021 (int) sizeof (sig->s), sig->s)))
1023 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1024 return GNUNET_SYSERR;
1026 data = data_to_ecdsa_value (validate);
1027 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1028 "(public-key(ecc(curve " CURVE ")(q %b)))",
1029 (int) sizeof (pub->q_y), pub->q_y)))
1031 gcry_sexp_release (data);
1032 gcry_sexp_release (sig_sexpr);
1033 return GNUNET_SYSERR;
1035 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1036 gcry_sexp_release (pub_sexpr);
1037 gcry_sexp_release (data);
1038 gcry_sexp_release (sig_sexpr);
1041 LOG (GNUNET_ERROR_TYPE_INFO,
1042 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1043 __LINE__, gcry_strerror (rc));
1044 BENCHMARK_END (ecdsa_verify);
1045 return GNUNET_SYSERR;
1047 BENCHMARK_END (ecdsa_verify);
1056 * @param purpose what is the purpose that the signature should have?
1057 * @param validate block to validate (size, purpose, data)
1058 * @param sig signature that is being validated
1059 * @param pub public key of the signer
1060 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1063 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
1064 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1065 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1066 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1069 gcry_sexp_t sig_sexpr;
1070 gcry_sexp_t pub_sexpr;
1073 BENCHMARK_START (eddsa_verify);
1075 if (purpose != ntohl (validate->purpose))
1076 return GNUNET_SYSERR; /* purpose mismatch */
1078 /* build s-expression for signature */
1079 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
1080 "(sig-val(eddsa(r %b)(s %b)))",
1081 (int)sizeof (sig->r), sig->r,
1082 (int)sizeof (sig->s), sig->s)))
1084 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1085 return GNUNET_SYSERR;
1087 data = data_to_eddsa_value (validate);
1088 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1089 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1090 (int)sizeof (pub->q_y), pub->q_y)))
1092 gcry_sexp_release (data);
1093 gcry_sexp_release (sig_sexpr);
1094 return GNUNET_SYSERR;
1096 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1097 gcry_sexp_release (pub_sexpr);
1098 gcry_sexp_release (data);
1099 gcry_sexp_release (sig_sexpr);
1102 LOG (GNUNET_ERROR_TYPE_INFO,
1103 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1104 __LINE__, gcry_strerror (rc));
1105 BENCHMARK_END (eddsa_verify);
1106 return GNUNET_SYSERR;
1108 BENCHMARK_END (eddsa_verify);
1114 * Derive key material from a public and a private ECDHE key.
1116 * @param priv private key to use for the ECDH (x)
1117 * @param pub public key to use for the ECDH (yG)
1118 * @param key_material where to write the key material (xyG)
1119 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1122 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1123 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1124 struct GNUNET_HashCode *key_material)
1126 gcry_mpi_point_t result;
1130 gcry_sexp_t pub_sexpr;
1131 gcry_mpi_t result_x;
1132 unsigned char xbuf[256 / 8];
1135 BENCHMARK_START (ecc_ecdh);
1137 /* first, extract the q = dP value from the public key */
1138 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1139 "(public-key(ecc(curve " CURVE ")(q %b)))",
1140 (int)sizeof (pub->q_y), pub->q_y))
1141 return GNUNET_SYSERR;
1142 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1143 gcry_sexp_release (pub_sexpr);
1144 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1146 /* second, extract the d value from our private key */
1147 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1149 /* then call the 'multiply' function, to compute the product */
1150 result = gcry_mpi_point_new (0);
1151 gcry_mpi_ec_mul (result, d, q, ctx);
1152 gcry_mpi_point_release (q);
1153 gcry_mpi_release (d);
1155 /* finally, convert point to string for hashing */
1156 result_x = gcry_mpi_new (256);
1157 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1159 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1160 gcry_mpi_point_release (result);
1161 gcry_ctx_release (ctx);
1162 return GNUNET_SYSERR;
1164 gcry_mpi_point_release (result);
1165 gcry_ctx_release (ctx);
1167 rsize = sizeof (xbuf);
1168 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1169 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1170 as that does not include the sign bit; x should be a 255-bit
1171 value, so with the sign it should fit snugly into the 256-bit
1174 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1176 GNUNET_CRYPTO_hash (xbuf,
1179 gcry_mpi_release (result_x);
1180 BENCHMARK_END (ecc_ecdh);
1186 * Derive the 'h' value for key derivation, where
1189 * @param pub public key for deriviation
1190 * @param label label for deriviation
1191 * @param context additional context to use for HKDF of 'h';
1192 * typically the name of the subsystem/application
1196 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1198 const char *context)
1201 struct GNUNET_HashCode hc;
1202 static const char *const salt = "key-derivation";
1204 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1205 salt, strlen (salt),
1207 label, strlen (label),
1208 context, strlen (context),
1210 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1211 (unsigned char *) &hc,
1218 * Derive a private key from a given private key and a label.
1219 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1220 * where n is the size of the ECC group and P is the public
1221 * key associated with the private key 'd'.
1223 * @param priv original private key
1224 * @param label label to use for key deriviation
1225 * @param context additional context to use for HKDF of 'h';
1226 * typically the name of the subsystem/application
1227 * @return derived private key
1229 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1230 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1232 const char *context)
1234 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1235 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1242 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1244 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1245 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1247 h = derive_h (&pub, label, context);
1248 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1251 d = gcry_mpi_new (256);
1252 gcry_mpi_mulm (d, h, x, n);
1253 gcry_mpi_release (h);
1254 gcry_mpi_release (x);
1255 gcry_mpi_release (n);
1256 gcry_ctx_release (ctx);
1257 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1258 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1259 gcry_mpi_release (d);
1265 * Derive a public key from a given public key and a label.
1266 * Essentially calculates a public key 'V = H(l,P) * P'.
1268 * @param pub original public key
1269 * @param label label to use for key derivation
1270 * @param context additional context to use for HKDF of 'h';
1271 * typically the name of the subsystem/application
1272 * @param result where to write the derived public key
1275 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1277 const char *context,
1278 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1288 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1290 /* obtain point 'q' from original public key. The provided 'q' is
1291 compressed thus we first store it in the context and then get it
1292 back as a (decompresssed) point. */
1293 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1294 GNUNET_assert (NULL != q_y);
1295 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1296 gcry_mpi_release (q_y);
1297 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1300 /* calculate h_mod_n = h % n */
1301 h = derive_h (pub, label, context);
1302 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1303 h_mod_n = gcry_mpi_new (256);
1304 gcry_mpi_mod (h_mod_n, h, n);
1305 /* calculate v = h_mod_n * q */
1306 v = gcry_mpi_point_new (0);
1307 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1308 gcry_mpi_release (h_mod_n);
1309 gcry_mpi_release (h);
1310 gcry_mpi_release (n);
1311 gcry_mpi_point_release (q);
1313 /* convert point 'v' to public key that we return */
1314 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1315 gcry_mpi_point_release (v);
1316 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1317 GNUNET_assert (q_y);
1318 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1319 sizeof (result->q_y),
1321 gcry_mpi_release (q_y);
1322 gcry_ctx_release (ctx);
1327 * Reverse the sequence of the bytes in @a buffer
1329 * @param[in|out] buffer buffer to invert
1330 * @param length number of bytes in @a buffer
1333 reverse_buffer (unsigned char *buffer,
1339 for (i=0; i < length/2; i++)
1342 buffer[i] = buffer[length-1-i];
1343 buffer[length-1-i] = tmp;
1349 * Convert the secret @a d of an EdDSA key to the
1350 * value that is actually used in the EdDSA computation.
1352 * @param d secret input
1353 * @return value used for the calculation in EdDSA
1356 eddsa_d_to_a (gcry_mpi_t d)
1358 unsigned char rawmpi[32]; /* 256-bit value */
1360 unsigned char digest[64]; /* 512-bit hash value */
1361 gcry_buffer_t hvec[2];
1365 b = 256 / 8; /* number of bytes in `d` */
1367 /* Note that we clear DIGEST so we can use it as input to left pad
1368 the key with zeroes for hashing. */
1369 memset (digest, 0, sizeof digest);
1370 memset (hvec, 0, sizeof hvec);
1371 rawmpilen = sizeof (rawmpi);
1373 gcry_mpi_print (GCRYMPI_FMT_USG,
1374 rawmpi, rawmpilen, &rawmpilen,
1376 hvec[0].data = digest;
1378 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1379 hvec[1].data = rawmpi;
1381 hvec[1].len = rawmpilen;
1383 gcry_md_hash_buffers (GCRY_MD_SHA512,
1387 /* Compute the A value. */
1388 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1389 digest[0] = (digest[0] & 0x7f) | 0x40;
1392 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1400 * Take point from ECDH and convert it to key material.
1402 * @param result point from ECDH
1403 * @param ctx ECC context
1404 * @param key_material[out] set to derived key material
1405 * @return #GNUNET_OK on success
1408 point_to_hash (gcry_mpi_point_t result,
1410 struct GNUNET_HashCode *key_material)
1412 gcry_mpi_t result_x;
1413 unsigned char xbuf[256 / 8];
1416 /* finally, convert point to string for hashing */
1417 result_x = gcry_mpi_new (256);
1418 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1420 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1421 return GNUNET_SYSERR;
1424 rsize = sizeof (xbuf);
1425 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1426 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1427 as that does not include the sign bit; x should be a 255-bit
1428 value, so with the sign it should fit snugly into the 256-bit
1431 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1433 GNUNET_CRYPTO_hash (xbuf,
1436 gcry_mpi_release (result_x);
1443 * Derive key material from a ECDH public key and a private EdDSA key.
1444 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1446 * @param priv private key from EdDSA to use for the ECDH (x)
1447 * @param pub public key to use for the ECDH (yG)
1448 * @param key_material where to write the key material H(h(x)yG)
1449 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1452 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1453 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1454 struct GNUNET_HashCode *key_material)
1456 gcry_mpi_point_t result;
1461 gcry_sexp_t pub_sexpr;
1464 BENCHMARK_START (eddsa_ecdh);
1466 /* first, extract the q = dP value from the public key */
1467 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1468 "(public-key(ecc(curve " CURVE ")(q %b)))",
1469 (int)sizeof (pub->q_y), pub->q_y))
1470 return GNUNET_SYSERR;
1471 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1472 gcry_sexp_release (pub_sexpr);
1473 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1475 /* second, extract the d value from our private key */
1476 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1478 /* NOW, because this is EdDSA, HASH 'd' first! */
1479 a = eddsa_d_to_a (d);
1480 gcry_mpi_release (d);
1482 /* then call the 'multiply' function, to compute the product */
1483 result = gcry_mpi_point_new (0);
1484 gcry_mpi_ec_mul (result, a, q, ctx);
1485 gcry_mpi_point_release (q);
1486 gcry_mpi_release (a);
1488 ret = point_to_hash (result,
1491 gcry_mpi_point_release (result);
1492 gcry_ctx_release (ctx);
1493 BENCHMARK_END (eddsa_ecdh);
1500 * Derive key material from a ECDH public key and a private ECDSA key.
1501 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1503 * @param priv private key from ECDSA to use for the ECDH (x)
1504 * @param pub public key to use for the ECDH (yG)
1505 * @param key_material where to write the key material H(h(x)yG)
1506 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1509 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1510 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1511 struct GNUNET_HashCode *key_material)
1513 gcry_mpi_point_t result;
1517 gcry_sexp_t pub_sexpr;
1520 BENCHMARK_START (ecdsa_ecdh);
1522 /* first, extract the q = dP value from the public key */
1523 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1524 "(public-key(ecc(curve " CURVE ")(q %b)))",
1525 (int)sizeof (pub->q_y), pub->q_y))
1526 return GNUNET_SYSERR;
1527 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1528 gcry_sexp_release (pub_sexpr);
1529 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1531 /* second, extract the d value from our private key */
1532 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1534 /* then call the 'multiply' function, to compute the product */
1535 result = gcry_mpi_point_new (0);
1536 gcry_mpi_ec_mul (result, d, q, ctx);
1537 gcry_mpi_point_release (q);
1538 gcry_mpi_release (d);
1540 /* finally, convert point to string for hashing */
1541 ret = point_to_hash (result,
1544 gcry_mpi_point_release (result);
1545 gcry_ctx_release (ctx);
1546 BENCHMARK_END (ecdsa_ecdh);
1554 * Derive key material from a EdDSA public key and a private ECDH key.
1555 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1557 * @param priv private key to use for the ECDH (y)
1558 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1559 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1560 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1563 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1564 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1565 struct GNUNET_HashCode *key_material)
1567 gcry_mpi_point_t result;
1571 gcry_sexp_t pub_sexpr;
1574 BENCHMARK_START (ecdh_eddsa);
1576 /* first, extract the q = dP value from the public key */
1577 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1578 "(public-key(ecc(curve " CURVE ")(q %b)))",
1579 (int)sizeof (pub->q_y), pub->q_y))
1580 return GNUNET_SYSERR;
1581 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1582 gcry_sexp_release (pub_sexpr);
1583 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1585 /* second, extract the d value from our private key */
1586 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1588 /* then call the 'multiply' function, to compute the product */
1589 result = gcry_mpi_point_new (0);
1590 gcry_mpi_ec_mul (result, d, q, ctx);
1591 gcry_mpi_point_release (q);
1592 gcry_mpi_release (d);
1594 /* finally, convert point to string for hashing */
1595 ret = point_to_hash (result,
1598 gcry_mpi_point_release (result);
1599 gcry_ctx_release (ctx);
1600 BENCHMARK_END (ecdh_eddsa);
1606 * Derive key material from a ECDSA public key and a private ECDH key.
1607 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1609 * @param priv private key to use for the ECDH (y)
1610 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1611 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1612 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1615 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1616 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1617 struct GNUNET_HashCode *key_material)
1619 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1620 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1624 /* end of crypto_ecc.c */