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) \
45 GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
47 #define LOG_STRERROR_FILE(kind, syscall, filename) \
48 GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
51 * Log an error message at log-level 'level' that indicates
52 * a failure of the command 'cmd' with the message given
53 * by gcry_strerror(rc).
55 #define LOG_GCRY(level, cmd, rc) \
59 _ ("`%s' failed at %s:%d with error: %s\n"), \
63 gcry_strerror (rc)); \
68 * Extract values from an S-expression.
70 * @param array where to store the result(s)
71 * @param sexp S-expression to parse
72 * @param topname top-level name in the S-expression that is of interest
73 * @param elems names of the elements to extract
74 * @return 0 on success
77 key_from_sexp (gcry_mpi_t *array,
86 list = gcry_sexp_find_token (sexp, topname, 0);
89 l2 = gcry_sexp_cadr (list);
90 gcry_sexp_release (list);
96 for (const char *s = elems; *s; s++, idx++)
98 l2 = gcry_sexp_find_token (list, s, 1);
101 for (unsigned int i = 0; i < idx; i++)
103 gcry_free (array[i]);
106 gcry_sexp_release (list);
107 return 3; /* required parameter not found */
109 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
110 gcry_sexp_release (l2);
113 for (unsigned int i = 0; i < idx; i++)
115 gcry_free (array[i]);
118 gcry_sexp_release (list);
119 return 4; /* required parameter is invalid */
122 gcry_sexp_release (list);
128 * Convert the given private key from the network format to the
129 * S-expression that can be used by libgcrypt.
131 * @param priv private key to decode
132 * @return NULL on error
135 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
140 rc = gcry_sexp_build (&result,
142 "(private-key(ecc(curve \"" CURVE "\")"
144 (int) sizeof(priv->d),
148 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
152 if (0 != (rc = gcry_pk_testkey (result)))
154 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
163 * Convert the given private key from the network format to the
164 * S-expression that can be used by libgcrypt.
166 * @param priv private key to decode
167 * @return NULL on error
170 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
175 rc = gcry_sexp_build (&result,
177 "(private-key(ecc(curve \"" CURVE "\")"
178 "(flags eddsa)(d %b)))",
179 (int) sizeof(priv->d),
183 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
187 if (0 != (rc = gcry_pk_testkey (result)))
189 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
198 * Convert the given private key from the network format to the
199 * S-expression that can be used by libgcrypt.
201 * @param priv private key to decode
202 * @return NULL on error
205 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
210 rc = gcry_sexp_build (&result,
212 "(private-key(ecc(curve \"" CURVE "\")"
214 (int) sizeof(priv->d),
218 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
222 if (0 != (rc = gcry_pk_testkey (result)))
224 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
233 * Extract the public key for the given private key.
235 * @param priv the private key
236 * @param pub where to write the public key
239 GNUNET_CRYPTO_ecdsa_key_get_public (
240 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
241 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
247 BENCHMARK_START (ecdsa_key_get_public);
249 sexp = decode_private_ecdsa_key (priv);
250 GNUNET_assert (NULL != sexp);
251 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
252 gcry_sexp_release (sexp);
253 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
254 GNUNET_assert (NULL != q);
255 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
256 gcry_mpi_release (q);
257 gcry_ctx_release (ctx);
259 BENCHMARK_END (ecdsa_key_get_public);
264 * Extract the public key for the given private key.
266 * @param priv the private key
267 * @param pub where to write the public key
270 GNUNET_CRYPTO_eddsa_key_get_public (
271 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
272 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
278 BENCHMARK_START (eddsa_key_get_public);
280 sexp = decode_private_eddsa_key (priv);
281 GNUNET_assert (NULL != sexp);
282 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
283 gcry_sexp_release (sexp);
284 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
286 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
287 gcry_mpi_release (q);
288 gcry_ctx_release (ctx);
290 BENCHMARK_END (eddsa_key_get_public);
295 * Extract the public key for the given private key.
297 * @param priv the private key
298 * @param pub where to write the public key
301 GNUNET_CRYPTO_ecdhe_key_get_public (
302 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
303 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
309 BENCHMARK_START (ecdhe_key_get_public);
311 sexp = decode_private_ecdhe_key (priv);
312 GNUNET_assert (NULL != sexp);
313 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
314 gcry_sexp_release (sexp);
315 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
317 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
318 gcry_mpi_release (q);
319 gcry_ctx_release (ctx);
321 BENCHMARK_END (ecdhe_key_get_public);
326 * Convert a public key to a string.
328 * @param pub key to convert
329 * @return string representing @a pub
332 GNUNET_CRYPTO_ecdsa_public_key_to_string (
333 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
336 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
340 keylen += 5 - keylen % 5;
342 pubkeybuf = GNUNET_malloc (keylen + 1);
344 GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
345 sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
350 GNUNET_free (pubkeybuf);
359 * Convert a public key to a string.
361 * @param pub key to convert
362 * @return string representing @a pub
365 GNUNET_CRYPTO_eddsa_public_key_to_string (
366 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
369 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
373 keylen += 5 - keylen % 5;
375 pubkeybuf = GNUNET_malloc (keylen + 1);
377 GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
378 sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
383 GNUNET_free (pubkeybuf);
392 * Convert a private key to a string.
394 * @param priv key to convert
395 * @return string representing @a pub
398 GNUNET_CRYPTO_eddsa_private_key_to_string (
399 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
402 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
406 keylen += 5 - keylen % 5;
408 privkeybuf = GNUNET_malloc (keylen + 1);
409 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
411 struct GNUNET_CRYPTO_EddsaPrivateKey),
416 GNUNET_free (privkeybuf);
425 * Convert a private key to a string.
427 * @param priv key to convert
428 * @return string representing @a priv
431 GNUNET_CRYPTO_ecdsa_private_key_to_string (
432 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
435 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
439 keylen += 5 - keylen % 5;
441 privkeybuf = GNUNET_malloc (keylen + 1);
442 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
444 struct GNUNET_CRYPTO_EcdsaPrivateKey),
449 GNUNET_free (privkeybuf);
458 * Convert a string representing a public key to a public key.
460 * @param enc encoded public key
461 * @param enclen number of bytes in @a enc (without 0-terminator)
462 * @param pub where to store the public key
463 * @return #GNUNET_OK on success
466 GNUNET_CRYPTO_ecdsa_public_key_from_string (
469 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
471 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
474 keylen += 5 - keylen % 5;
476 if (enclen != keylen)
477 return GNUNET_SYSERR;
480 GNUNET_STRINGS_string_to_data (enc,
484 struct GNUNET_CRYPTO_EcdsaPublicKey)))
485 return GNUNET_SYSERR;
491 * Convert a string representing a public key to a public key.
493 * @param enc encoded public key
494 * @param enclen number of bytes in @a enc (without 0-terminator)
495 * @param pub where to store the public key
496 * @return #GNUNET_OK on success
499 GNUNET_CRYPTO_eddsa_public_key_from_string (
502 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
504 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
507 keylen += 5 - keylen % 5;
509 if (enclen != keylen)
510 return GNUNET_SYSERR;
513 GNUNET_STRINGS_string_to_data (enc,
517 struct GNUNET_CRYPTO_EddsaPublicKey)))
518 return GNUNET_SYSERR;
524 * Convert a string representing a private key to a private key.
526 * @param enc encoded public key
527 * @param enclen number of bytes in @a enc (without 0-terminator)
528 * @param priv where to store the private key
529 * @return #GNUNET_OK on success
532 GNUNET_CRYPTO_eddsa_private_key_from_string (
535 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
537 size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
540 keylen += 5 - keylen % 5;
542 if (enclen != keylen)
543 return GNUNET_SYSERR;
546 GNUNET_STRINGS_string_to_data (enc,
550 struct GNUNET_CRYPTO_EddsaPrivateKey)))
551 return GNUNET_SYSERR;
553 if (GNUNET_OK != check_eddsa_key (priv))
565 * Clear memory that was used to store a private key.
567 * @param pk location of the key
570 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
572 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
578 * Clear memory that was used to store a private key.
580 * @param pk location of the key
583 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
585 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
591 * Clear memory that was used to store a private key.
593 * @param pk location of the key
596 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
598 memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
603 * Create a new private key. Caller must free return value.
605 * @return fresh private key
607 struct GNUNET_CRYPTO_EcdhePrivateKey *
608 GNUNET_CRYPTO_ecdhe_key_create ()
610 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
612 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
613 if (GNUNET_OK != GNUNET_CRYPTO_ecdhe_key_create2 (priv))
624 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
626 * @param[out] pk set to fresh private key;
627 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
630 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
632 gcry_sexp_t priv_sexp;
633 gcry_sexp_t s_keyparam;
637 BENCHMARK_START (ecdhe_key_create);
639 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
640 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
641 disables an expensive key testing routine. We do not want to run
642 the expensive check for ECDHE, as we generate TONS of keys to
643 use for a very short time. */
644 if (0 != (rc = gcry_sexp_build (&s_keyparam,
646 "(genkey(ecc(curve \"" CURVE "\")"
647 "(flags eddsa no-keytest)))")))
649 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
650 return GNUNET_SYSERR;
652 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
654 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
655 gcry_sexp_release (s_keyparam);
656 return GNUNET_SYSERR;
658 gcry_sexp_release (s_keyparam);
660 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
662 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
663 gcry_sexp_release (priv_sexp);
664 return GNUNET_SYSERR;
667 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
669 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
670 gcry_sexp_release (priv_sexp);
671 return GNUNET_SYSERR;
673 gcry_sexp_release (priv_sexp);
674 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof(pk->d), d);
675 gcry_mpi_release (d);
677 BENCHMARK_END (ecdhe_key_create);
684 * Create a new private key. Caller must free return value.
686 * @return fresh private key
688 struct GNUNET_CRYPTO_EcdsaPrivateKey *
689 GNUNET_CRYPTO_ecdsa_key_create ()
691 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
692 gcry_sexp_t priv_sexp;
693 gcry_sexp_t s_keyparam;
697 BENCHMARK_START (ecdsa_key_create);
699 if (0 != (rc = gcry_sexp_build (&s_keyparam,
701 "(genkey(ecc(curve \"" CURVE "\")"
704 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
707 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
709 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
710 gcry_sexp_release (s_keyparam);
713 gcry_sexp_release (s_keyparam);
715 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
717 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
718 gcry_sexp_release (priv_sexp);
722 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
724 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
725 gcry_sexp_release (priv_sexp);
728 gcry_sexp_release (priv_sexp);
729 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
730 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof(priv->d), d);
731 gcry_mpi_release (d);
733 BENCHMARK_END (ecdsa_key_create);
739 * Create a new private key. Caller must free return value.
741 * @return fresh private key
743 struct GNUNET_CRYPTO_EddsaPrivateKey *
744 GNUNET_CRYPTO_eddsa_key_create ()
746 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
747 gcry_sexp_t priv_sexp;
748 gcry_sexp_t s_keyparam;
752 BENCHMARK_START (eddsa_key_create);
757 if (0 != (rc = gcry_sexp_build (&s_keyparam,
759 "(genkey(ecc(curve \"" CURVE "\")"
762 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
765 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
767 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
768 gcry_sexp_release (s_keyparam);
771 gcry_sexp_release (s_keyparam);
773 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
775 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
776 gcry_sexp_release (priv_sexp);
780 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
782 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
783 gcry_sexp_release (priv_sexp);
786 gcry_sexp_release (priv_sexp);
787 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
788 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof(priv->d), d);
789 gcry_mpi_release (d);
792 if (GNUNET_OK != check_eddsa_key (priv))
800 BENCHMARK_END (eddsa_key_create);
807 * Get the shared private key we use for anonymous users.
809 * @return "anonymous" private key
811 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
812 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
815 * 'anonymous' pseudonym (global static, d=1, public key = G
818 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
823 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
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_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
846 struct GNUNET_HashCode hc;
848 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
849 if (0 != (rc = gcry_sexp_build (&data,
851 "(data(flags eddsa)(hash-algo %s)(value %b))",
856 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
860 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
861 if (0 != (rc = gcry_sexp_build (&data,
863 "(data(flags eddsa)(hash-algo %s)(value %b))",
865 ntohl (purpose->size),
868 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
877 * Convert the data specified in the given purpose argument to an
878 * S-expression suitable for signature operations.
880 * @param purpose data to convert
881 * @return converted s-expression
884 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
891 struct GNUNET_HashCode hc;
893 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
894 if (0 != (rc = gcry_sexp_build (&data,
896 "(data(flags rfc6979)(hash %s %b))",
901 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
905 if (0 != (rc = gcry_sexp_build (&data,
907 "(data(flags rfc6979)(hash %s %b))",
909 ntohl (purpose->size),
912 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
921 * Sign a given block.
923 * @param priv private key to use for the signing
924 * @param purpose what to sign (size, purpose)
925 * @param sig where to write the signature
926 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
929 GNUNET_CRYPTO_ecdsa_sign (
930 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
931 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
932 struct GNUNET_CRYPTO_EcdsaSignature *sig)
934 gcry_sexp_t priv_sexp;
935 gcry_sexp_t sig_sexp;
940 BENCHMARK_START (ecdsa_sign);
942 priv_sexp = decode_private_ecdsa_key (priv);
943 data = data_to_ecdsa_value (purpose);
944 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
946 LOG (GNUNET_ERROR_TYPE_WARNING,
947 _ ("ECC signing failed at %s:%d: %s\n"),
951 gcry_sexp_release (data);
952 gcry_sexp_release (priv_sexp);
953 return GNUNET_SYSERR;
955 gcry_sexp_release (priv_sexp);
956 gcry_sexp_release (data);
958 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
960 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
963 gcry_sexp_release (sig_sexp);
964 return GNUNET_SYSERR;
966 gcry_sexp_release (sig_sexp);
967 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
968 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
969 gcry_mpi_release (rs[0]);
970 gcry_mpi_release (rs[1]);
972 BENCHMARK_END (ecdsa_sign);
979 * Sign a given block.
981 * @param priv private key to use for the signing
982 * @param purpose what to sign (size, purpose)
983 * @param sig where to write the signature
984 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
987 GNUNET_CRYPTO_eddsa_sign (
988 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
989 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
990 struct GNUNET_CRYPTO_EddsaSignature *sig)
992 gcry_sexp_t priv_sexp;
993 gcry_sexp_t sig_sexp;
998 BENCHMARK_START (eddsa_sign);
1000 priv_sexp = decode_private_eddsa_key (priv);
1001 data = data_to_eddsa_value (purpose);
1002 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
1004 LOG (GNUNET_ERROR_TYPE_WARNING,
1005 _ ("EdDSA signing failed at %s:%d: %s\n"),
1008 gcry_strerror (rc));
1009 gcry_sexp_release (data);
1010 gcry_sexp_release (priv_sexp);
1011 return GNUNET_SYSERR;
1013 gcry_sexp_release (priv_sexp);
1014 gcry_sexp_release (data);
1016 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
1018 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
1021 gcry_sexp_release (sig_sexp);
1022 return GNUNET_SYSERR;
1024 gcry_sexp_release (sig_sexp);
1025 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
1026 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
1027 gcry_mpi_release (rs[0]);
1028 gcry_mpi_release (rs[1]);
1030 BENCHMARK_END (eddsa_sign);
1039 * @param purpose what is the purpose that the signature should have?
1040 * @param validate block to validate (size, purpose, data)
1041 * @param sig signature that is being validated
1042 * @param pub public key of the signer
1043 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1046 GNUNET_CRYPTO_ecdsa_verify (
1048 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1049 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
1050 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
1053 gcry_sexp_t sig_sexpr;
1054 gcry_sexp_t pub_sexpr;
1057 BENCHMARK_START (ecdsa_verify);
1059 if (purpose != ntohl (validate->purpose))
1060 return GNUNET_SYSERR; /* purpose mismatch */
1062 /* build s-expression for signature */
1063 if (0 != (rc = gcry_sexp_build (&sig_sexpr,
1065 "(sig-val(ecdsa(r %b)(s %b)))",
1066 (int) sizeof(sig->r),
1068 (int) sizeof(sig->s),
1071 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1072 return GNUNET_SYSERR;
1074 data = data_to_ecdsa_value (validate);
1075 if (0 != (rc = gcry_sexp_build (&pub_sexpr,
1077 "(public-key(ecc(curve " CURVE ")(q %b)))",
1078 (int) sizeof(pub->q_y),
1081 gcry_sexp_release (data);
1082 gcry_sexp_release (sig_sexpr);
1083 return GNUNET_SYSERR;
1085 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1086 gcry_sexp_release (pub_sexpr);
1087 gcry_sexp_release (data);
1088 gcry_sexp_release (sig_sexpr);
1091 LOG (GNUNET_ERROR_TYPE_INFO,
1092 _ ("ECDSA signature verification failed at %s:%d: %s\n"),
1095 gcry_strerror (rc));
1096 BENCHMARK_END (ecdsa_verify);
1097 return GNUNET_SYSERR;
1099 BENCHMARK_END (ecdsa_verify);
1107 * @param purpose what is the purpose that the signature should have?
1108 * @param validate block to validate (size, purpose, data)
1109 * @param sig signature that is being validated
1110 * @param pub public key of the signer
1111 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1114 GNUNET_CRYPTO_eddsa_verify (
1116 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
1117 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1118 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1121 gcry_sexp_t sig_sexpr;
1122 gcry_sexp_t pub_sexpr;
1125 BENCHMARK_START (eddsa_verify);
1127 if (purpose != ntohl (validate->purpose))
1128 return GNUNET_SYSERR; /* purpose mismatch */
1130 /* build s-expression for signature */
1131 if (0 != (rc = gcry_sexp_build (&sig_sexpr,
1133 "(sig-val(eddsa(r %b)(s %b)))",
1134 (int) sizeof(sig->r),
1136 (int) sizeof(sig->s),
1139 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1140 return GNUNET_SYSERR;
1142 data = data_to_eddsa_value (validate);
1143 if (0 != (rc = gcry_sexp_build (&pub_sexpr,
1145 "(public-key(ecc(curve " CURVE
1146 ")(flags eddsa)(q %b)))",
1147 (int) sizeof(pub->q_y),
1150 gcry_sexp_release (data);
1151 gcry_sexp_release (sig_sexpr);
1152 return GNUNET_SYSERR;
1154 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1155 gcry_sexp_release (pub_sexpr);
1156 gcry_sexp_release (data);
1157 gcry_sexp_release (sig_sexpr);
1160 LOG (GNUNET_ERROR_TYPE_INFO,
1161 _ ("EdDSA signature verification of type %u failed at %s:%d: %s\n"),
1162 (unsigned int) purpose,
1165 gcry_strerror (rc));
1166 BENCHMARK_END (eddsa_verify);
1167 return GNUNET_SYSERR;
1169 BENCHMARK_END (eddsa_verify);
1175 * Derive key material from a public and a private ECDHE key.
1177 * @param priv private key to use for the ECDH (x)
1178 * @param pub public key to use for the ECDH (yG)
1179 * @param key_material where to write the key material (xyG)
1180 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1183 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1184 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1185 struct GNUNET_HashCode *key_material)
1187 gcry_mpi_point_t result;
1191 gcry_sexp_t pub_sexpr;
1192 gcry_mpi_t result_x;
1193 unsigned char xbuf[256 / 8];
1196 BENCHMARK_START (ecc_ecdh);
1198 /* first, extract the q = dP value from the public key */
1199 if (0 != gcry_sexp_build (&pub_sexpr,
1201 "(public-key(ecc(curve " CURVE ")(q %b)))",
1202 (int) sizeof(pub->q_y),
1204 return GNUNET_SYSERR;
1205 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1206 gcry_sexp_release (pub_sexpr);
1207 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1209 /* second, extract the d value from our private key */
1210 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
1212 /* then call the 'multiply' function, to compute the product */
1213 result = gcry_mpi_point_new (0);
1214 gcry_mpi_ec_mul (result, d, q, ctx);
1215 gcry_mpi_point_release (q);
1216 gcry_mpi_release (d);
1218 /* finally, convert point to string for hashing */
1219 result_x = gcry_mpi_new (256);
1220 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1222 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1223 gcry_mpi_point_release (result);
1224 gcry_ctx_release (ctx);
1225 return GNUNET_SYSERR;
1227 gcry_mpi_point_release (result);
1228 gcry_ctx_release (ctx);
1230 rsize = sizeof(xbuf);
1231 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1232 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1233 as that does not include the sign bit; x should be a 255-bit
1234 value, so with the sign it should fit snugly into the 256-bit
1237 0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
1238 GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
1239 gcry_mpi_release (result_x);
1240 BENCHMARK_END (ecc_ecdh);
1246 * Derive the 'h' value for key derivation, where
1249 * @param pub public key for deriviation
1250 * @param label label for deriviation
1251 * @param context additional context to use for HKDF of 'h';
1252 * typically the name of the subsystem/application
1256 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1258 const char *context)
1261 struct GNUNET_HashCode hc;
1262 static const char *const salt = "key-derivation";
1264 GNUNET_CRYPTO_kdf (&hc,
1276 GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
1282 * Derive a private key from a given private key and a label.
1283 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1284 * where n is the size of the ECC group and P is the public
1285 * key associated with the private key 'd'.
1287 * @param priv original private key
1288 * @param label label to use for key deriviation
1289 * @param context additional context to use for HKDF of 'h';
1290 * typically the name of the subsystem/application
1291 * @return derived private key
1293 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1294 GNUNET_CRYPTO_ecdsa_private_key_derive (
1295 const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1297 const char *context)
1299 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1300 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1307 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1309 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1310 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1312 h = derive_h (&pub, label, context);
1313 GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof(priv->d));
1314 d = gcry_mpi_new (256);
1315 gcry_mpi_mulm (d, h, x, n);
1316 gcry_mpi_release (h);
1317 gcry_mpi_release (x);
1318 gcry_mpi_release (n);
1319 gcry_ctx_release (ctx);
1320 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1321 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof(ret->d), d);
1322 gcry_mpi_release (d);
1328 * Derive a public key from a given public key and a label.
1329 * Essentially calculates a public key 'V = H(l,P) * P'.
1331 * @param pub original public key
1332 * @param label label to use for key derivation
1333 * @param context additional context to use for HKDF of 'h';
1334 * typically the name of the subsystem/application
1335 * @param result where to write the derived public key
1338 GNUNET_CRYPTO_ecdsa_public_key_derive (
1339 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1341 const char *context,
1342 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1352 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1354 /* obtain point 'q' from original public key. The provided 'q' is
1355 compressed thus we first store it in the context and then get it
1356 back as a (decompresssed) point. */
1357 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
1358 GNUNET_assert (NULL != q_y);
1359 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1360 gcry_mpi_release (q_y);
1361 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1364 /* calculate h_mod_n = h % n */
1365 h = derive_h (pub, label, context);
1366 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1367 h_mod_n = gcry_mpi_new (256);
1368 gcry_mpi_mod (h_mod_n, h, n);
1369 /* calculate v = h_mod_n * q */
1370 v = gcry_mpi_point_new (0);
1371 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1372 gcry_mpi_release (h_mod_n);
1373 gcry_mpi_release (h);
1374 gcry_mpi_release (n);
1375 gcry_mpi_point_release (q);
1377 /* convert point 'v' to public key that we return */
1378 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1379 gcry_mpi_point_release (v);
1380 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1381 GNUNET_assert (q_y);
1382 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
1383 gcry_mpi_release (q_y);
1384 gcry_ctx_release (ctx);
1389 * Reverse the sequence of the bytes in @a buffer
1391 * @param[in|out] buffer buffer to invert
1392 * @param length number of bytes in @a buffer
1395 reverse_buffer (unsigned char *buffer, size_t length)
1400 for (i = 0; i < length / 2; i++)
1403 buffer[i] = buffer[length - 1 - i];
1404 buffer[length - 1 - i] = tmp;
1410 * Convert the secret @a d of an EdDSA key to the
1411 * value that is actually used in the EdDSA computation.
1413 * @param d secret input
1414 * @return value used for the calculation in EdDSA
1417 eddsa_d_to_a (gcry_mpi_t d)
1419 unsigned char rawmpi[32]; /* 256-bit value */
1421 unsigned char digest[64]; /* 512-bit hash value */
1422 gcry_buffer_t hvec[2];
1426 b = 256 / 8; /* number of bytes in `d` */
1428 /* Note that we clear DIGEST so we can use it as input to left pad
1429 the key with zeroes for hashing. */
1430 memset (digest, 0, sizeof digest);
1431 memset (hvec, 0, sizeof hvec);
1432 rawmpilen = sizeof(rawmpi);
1434 0 == gcry_mpi_print (GCRYMPI_FMT_USG, rawmpi, rawmpilen, &rawmpilen, d));
1435 hvec[0].data = digest;
1437 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1438 hvec[1].data = rawmpi;
1440 hvec[1].len = rawmpilen;
1442 0 == gcry_md_hash_buffers (GCRY_MD_SHA512, 0 /* flags */, digest, hvec, 2));
1443 /* Compute the A value. */
1444 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1445 digest[0] = (digest[0] & 0x7f) | 0x40;
1448 GNUNET_CRYPTO_mpi_scan_unsigned (&a, digest, 32);
1454 * Take point from ECDH and convert it to key material.
1456 * @param result point from ECDH
1457 * @param ctx ECC context
1458 * @param key_material[out] set to derived key material
1459 * @return #GNUNET_OK on success
1462 point_to_hash (gcry_mpi_point_t result,
1464 struct GNUNET_HashCode *key_material)
1466 gcry_mpi_t result_x;
1467 unsigned char xbuf[256 / 8];
1470 /* finally, convert point to string for hashing */
1471 result_x = gcry_mpi_new (256);
1472 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1474 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1475 return GNUNET_SYSERR;
1478 rsize = sizeof(xbuf);
1479 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1480 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1481 as that does not include the sign bit; x should be a 255-bit
1482 value, so with the sign it should fit snugly into the 256-bit
1485 0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
1486 GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
1487 gcry_mpi_release (result_x);
1494 * Derive key material from a ECDH public key and a private EdDSA key.
1495 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1497 * @param priv private key from EdDSA to use for the ECDH (x)
1498 * @param pub public key to use for the ECDH (yG)
1499 * @param key_material where to write the key material H(h(x)yG)
1500 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1503 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1504 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1505 struct GNUNET_HashCode *key_material)
1507 gcry_mpi_point_t result;
1512 gcry_sexp_t pub_sexpr;
1515 BENCHMARK_START (eddsa_ecdh);
1517 /* first, extract the q = dP value from the public key */
1518 if (0 != gcry_sexp_build (&pub_sexpr,
1520 "(public-key(ecc(curve " CURVE ")(q %b)))",
1521 (int) sizeof(pub->q_y),
1523 return GNUNET_SYSERR;
1524 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1525 gcry_sexp_release (pub_sexpr);
1526 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1528 /* second, extract the d value from our private key */
1529 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
1531 /* NOW, because this is EdDSA, HASH 'd' first! */
1532 a = eddsa_d_to_a (d);
1533 gcry_mpi_release (d);
1535 /* then call the 'multiply' function, to compute the product */
1536 result = gcry_mpi_point_new (0);
1537 gcry_mpi_ec_mul (result, a, q, ctx);
1538 gcry_mpi_point_release (q);
1539 gcry_mpi_release (a);
1541 ret = point_to_hash (result, ctx, key_material);
1542 gcry_mpi_point_release (result);
1543 gcry_ctx_release (ctx);
1544 BENCHMARK_END (eddsa_ecdh);
1551 * Derive key material from a ECDH public key and a private ECDSA key.
1552 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1554 * @param priv private key from ECDSA to use for the ECDH (x)
1555 * @param pub public key to use for the ECDH (yG)
1556 * @param key_material where to write the key material H(h(x)yG)
1557 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1560 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1561 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1562 struct GNUNET_HashCode *key_material)
1564 gcry_mpi_point_t result;
1568 gcry_sexp_t pub_sexpr;
1571 BENCHMARK_START (ecdsa_ecdh);
1573 /* first, extract the q = dP value from the public key */
1574 if (0 != gcry_sexp_build (&pub_sexpr,
1576 "(public-key(ecc(curve " CURVE ")(q %b)))",
1577 (int) sizeof(pub->q_y),
1579 return GNUNET_SYSERR;
1580 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1581 gcry_sexp_release (pub_sexpr);
1582 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1584 /* second, extract the d value from our private key */
1585 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
1587 /* then call the 'multiply' function, to compute the product */
1588 result = gcry_mpi_point_new (0);
1589 gcry_mpi_ec_mul (result, d, q, ctx);
1590 gcry_mpi_point_release (q);
1591 gcry_mpi_release (d);
1593 /* finally, convert point to string for hashing */
1594 ret = point_to_hash (result, ctx, key_material);
1595 gcry_mpi_point_release (result);
1596 gcry_ctx_release (ctx);
1597 BENCHMARK_END (ecdsa_ecdh);
1604 * Derive key material from a EdDSA public key and a private ECDH key.
1605 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1607 * @param priv private key to use for the ECDH (y)
1608 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1609 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1610 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1613 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1614 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1615 struct GNUNET_HashCode *key_material)
1617 gcry_mpi_point_t result;
1621 gcry_sexp_t pub_sexpr;
1624 BENCHMARK_START (ecdh_eddsa);
1626 /* first, extract the q = dP value from the public key */
1627 if (0 != gcry_sexp_build (&pub_sexpr,
1629 "(public-key(ecc(curve " CURVE ")(q %b)))",
1630 (int) sizeof(pub->q_y),
1632 return GNUNET_SYSERR;
1633 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1634 gcry_sexp_release (pub_sexpr);
1635 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1637 /* second, extract the d value from our private key */
1638 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
1640 /* then call the 'multiply' function, to compute the product */
1641 result = gcry_mpi_point_new (0);
1642 gcry_mpi_ec_mul (result, d, q, ctx);
1643 gcry_mpi_point_release (q);
1644 gcry_mpi_release (d);
1646 /* finally, convert point to string for hashing */
1647 ret = point_to_hash (result, ctx, key_material);
1648 gcry_mpi_point_release (result);
1649 gcry_ctx_release (ctx);
1650 BENCHMARK_END (ecdh_eddsa);
1656 * Derive key material from a ECDSA public key and a private ECDH key.
1657 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1659 * @param priv private key to use for the ECDH (y)
1660 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1661 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1662 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1665 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1666 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1667 struct GNUNET_HashCode *key_material)
1669 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1670 (const struct GNUNET_CRYPTO_EddsaPublicKey *)
1675 /* end of crypto_ecc.c */