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
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
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"
31 #define EXTRA_CHECKS 0
34 * Name of the curve we are using. Note that we have hard-coded
35 * structs that use 256 bits, so using a bigger curve will require
36 * changes that break stuff badly. The name of the curve given here
37 * must be agreed by all peers and be supported by libgcrypt.
39 #define CURVE "Ed25519"
41 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
43 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
45 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' with the message given
50 * by gcry_strerror(rc).
52 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
55 #include "crypto_bug.c"
59 * Extract values from an S-expression.
61 * @param array where to store the result(s)
62 * @param sexp S-expression to parse
63 * @param topname top-level name in the S-expression that is of interest
64 * @param elems names of the elements to extract
65 * @return 0 on success
68 key_from_sexp (gcry_mpi_t * array,
79 list = gcry_sexp_find_token (sexp, topname, 0);
82 l2 = gcry_sexp_cadr (list);
83 gcry_sexp_release (list);
89 for (s = elems; *s; s++, idx++)
91 l2 = gcry_sexp_find_token (list, s, 1);
94 for (i = 0; i < idx; i++)
99 gcry_sexp_release (list);
100 return 3; /* required parameter not found */
102 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
103 gcry_sexp_release (l2);
106 for (i = 0; i < idx; i++)
108 gcry_free (array[i]);
111 gcry_sexp_release (list);
112 return 4; /* required parameter is invalid */
115 gcry_sexp_release (list);
121 * Convert the given private key from the network format to the
122 * S-expression that can be used by libgcrypt.
124 * @param priv private key to decode
125 * @return NULL on error
128 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
133 rc = gcry_sexp_build (&result, NULL,
134 "(private-key(ecc(curve \"" CURVE "\")"
136 (int) sizeof (priv->d), priv->d);
139 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
143 if (0 != (rc = gcry_pk_testkey (result)))
145 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
154 * Convert the given private key from the network format to the
155 * S-expression that can be used by libgcrypt.
157 * @param priv private key to decode
158 * @return NULL on error
161 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
166 rc = gcry_sexp_build (&result, NULL,
167 "(private-key(ecc(curve \"" CURVE "\")"
168 "(flags eddsa)(d %b)))",
169 (int)sizeof (priv->d), priv->d);
172 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
176 if (0 != (rc = gcry_pk_testkey (result)))
178 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
187 * Convert the given private key from the network format to the
188 * S-expression that can be used by libgcrypt.
190 * @param priv private key to decode
191 * @return NULL on error
194 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
199 rc = gcry_sexp_build (&result, NULL,
200 "(private-key(ecc(curve \"" CURVE "\")"
202 (int)sizeof (priv->d), priv->d);
205 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
209 if (0 != (rc = gcry_pk_testkey (result)))
211 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
220 * Extract the public key for the given private key.
222 * @param priv the private key
223 * @param pub where to write the public key
226 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
227 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
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);
246 * Extract the public key for the given private key.
248 * @param priv the private key
249 * @param pub where to write the public key
252 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
253 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
259 sexp = decode_private_eddsa_key (priv);
260 GNUNET_assert (NULL != sexp);
261 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
262 gcry_sexp_release (sexp);
263 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
265 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
266 gcry_mpi_release (q);
267 gcry_ctx_release (ctx);
272 * Extract the public key for the given private key.
274 * @param priv the private key
275 * @param pub where to write the public key
278 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
279 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
285 sexp = decode_private_ecdhe_key (priv);
286 GNUNET_assert (NULL != sexp);
287 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
288 gcry_sexp_release (sexp);
289 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
291 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
292 gcry_mpi_release (q);
293 gcry_ctx_release (ctx);
298 * Convert a public key to a string.
300 * @param pub key to convert
301 * @return string representing @a pub
304 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
307 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
311 keylen += 5 - keylen % 5;
313 pubkeybuf = GNUNET_malloc (keylen + 1);
314 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
315 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
320 GNUNET_free (pubkeybuf);
329 * Convert a public key to a string.
331 * @param pub key to convert
332 * @return string representing @a pub
335 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
338 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
342 keylen += 5 - keylen % 5;
344 pubkeybuf = GNUNET_malloc (keylen + 1);
345 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
346 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
351 GNUNET_free (pubkeybuf);
360 * Convert a private key to a string.
362 * @param priv key to convert
363 * @return string representing @a pub
366 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
369 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
373 keylen += 5 - keylen % 5;
375 privkeybuf = GNUNET_malloc (keylen + 1);
376 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
377 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
382 GNUNET_free (privkeybuf);
391 * Convert a string representing a public key to a public key.
393 * @param enc encoded public key
394 * @param enclen number of bytes in @a enc (without 0-terminator)
395 * @param pub where to store the public key
396 * @return #GNUNET_OK on success
399 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
401 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
403 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
406 keylen += 5 - keylen % 5;
408 if (enclen != keylen)
409 return GNUNET_SYSERR;
412 GNUNET_STRINGS_string_to_data (enc, enclen,
414 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
415 return GNUNET_SYSERR;
421 * Convert a string representing a public key to a public key.
423 * @param enc encoded public key
424 * @param enclen number of bytes in @a enc (without 0-terminator)
425 * @param pub where to store the public key
426 * @return #GNUNET_OK on success
429 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
431 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
433 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
436 keylen += 5 - keylen % 5;
438 if (enclen != keylen)
439 return GNUNET_SYSERR;
442 GNUNET_STRINGS_string_to_data (enc, enclen,
444 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
445 return GNUNET_SYSERR;
451 * Convert a string representing a private key to a private key.
453 * @param enc encoded public key
454 * @param enclen number of bytes in @a enc (without 0-terminator)
455 * @param priv where to store the private key
456 * @return #GNUNET_OK on success
459 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
461 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
463 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
466 keylen += 5 - keylen % 5;
468 if (enclen != keylen)
469 return GNUNET_SYSERR;
472 GNUNET_STRINGS_string_to_data (enc, enclen,
474 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
475 return GNUNET_SYSERR;
478 check_eddsa_key (priv))
490 * Clear memory that was used to store a private key.
492 * @param pk location of the key
495 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
497 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
503 * Clear memory that was used to store a private key.
505 * @param pk location of the key
508 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
510 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
516 * Clear memory that was used to store a private key.
518 * @param pk location of the key
521 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
523 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
528 * Create a new private key. Caller must free return value.
530 * @return fresh private key
532 struct GNUNET_CRYPTO_EcdhePrivateKey *
533 GNUNET_CRYPTO_ecdhe_key_create ()
535 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
537 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
539 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
550 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
552 * @param[out] pk set to fresh private key;
553 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
556 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
558 gcry_sexp_t priv_sexp;
559 gcry_sexp_t s_keyparam;
563 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
564 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
565 disables an expensive key testing routine. We do not want to run
566 the expensive check for ECDHE, as we generate TONS of keys to
567 use for a very short time. */
568 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
569 "(genkey(ecc(curve \"" CURVE "\")"
570 "(flags eddsa no-keytest)))")))
572 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
573 return GNUNET_SYSERR;
575 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
577 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
578 gcry_sexp_release (s_keyparam);
579 return GNUNET_SYSERR;
581 gcry_sexp_release (s_keyparam);
583 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
585 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
586 gcry_sexp_release (priv_sexp);
587 return GNUNET_SYSERR;
590 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
592 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
593 gcry_sexp_release (priv_sexp);
594 return GNUNET_SYSERR;
596 gcry_sexp_release (priv_sexp);
597 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
598 gcry_mpi_release (d);
604 * Create a new private key. Caller must free return value.
606 * @return fresh private key
608 struct GNUNET_CRYPTO_EcdsaPrivateKey *
609 GNUNET_CRYPTO_ecdsa_key_create ()
611 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
612 gcry_sexp_t priv_sexp;
613 gcry_sexp_t s_keyparam;
617 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
618 "(genkey(ecc(curve \"" CURVE "\")"
621 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
624 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
626 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
627 gcry_sexp_release (s_keyparam);
630 gcry_sexp_release (s_keyparam);
632 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
634 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
635 gcry_sexp_release (priv_sexp);
639 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
641 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
642 gcry_sexp_release (priv_sexp);
645 gcry_sexp_release (priv_sexp);
646 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
647 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
648 gcry_mpi_release (d);
653 * Create a new private key. Caller must free return value.
655 * @return fresh private key
657 struct GNUNET_CRYPTO_EddsaPrivateKey *
658 GNUNET_CRYPTO_eddsa_key_create ()
660 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
661 gcry_sexp_t priv_sexp;
662 gcry_sexp_t s_keyparam;
669 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
670 "(genkey(ecc(curve \"" CURVE "\")"
673 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
676 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
678 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
679 gcry_sexp_release (s_keyparam);
682 gcry_sexp_release (s_keyparam);
684 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
686 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
687 gcry_sexp_release (priv_sexp);
691 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
693 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
694 gcry_sexp_release (priv_sexp);
697 gcry_sexp_release (priv_sexp);
698 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
699 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
700 gcry_mpi_release (d);
704 check_eddsa_key (priv))
717 * Get the shared private key we use for anonymous users.
719 * @return "anonymous" private key
721 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
722 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
725 * 'anonymous' pseudonym (global static, d=1, public key = G
728 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
733 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
734 sizeof (anonymous.d),
742 * Compare two Peer Identities.
744 * @param first first peer identity
745 * @param second second peer identity
746 * @return bigger than 0 if first > second,
747 * 0 if they are the same
748 * smaller than 0 if second > first
751 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
752 const struct GNUNET_PeerIdentity *second)
754 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
759 * Convert the data specified in the given purpose argument to an
760 * S-expression suitable for signature operations.
762 * @param purpose data to convert
763 * @return converted s-expression
766 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
768 struct GNUNET_HashCode hc;
772 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
773 if (0 != (rc = gcry_sexp_build (&data, NULL,
774 "(data(flags eddsa)(hash-algo %s)(value %b))",
776 (int)sizeof (hc), &hc)))
778 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
786 * Convert the data specified in the given purpose argument to an
787 * S-expression suitable for signature operations.
789 * @param purpose data to convert
790 * @return converted s-expression
793 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
795 struct GNUNET_HashCode hc;
799 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
800 if (0 != (rc = gcry_sexp_build (&data, NULL,
801 "(data(flags rfc6979)(hash %s %b))",
803 (int)sizeof (hc), &hc)))
805 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
813 * Sign a given block.
815 * @param priv private key to use for the signing
816 * @param purpose what to sign (size, purpose)
817 * @param sig where to write the signature
818 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
821 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
822 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
823 struct GNUNET_CRYPTO_EcdsaSignature *sig)
825 gcry_sexp_t priv_sexp;
826 gcry_sexp_t sig_sexp;
831 priv_sexp = decode_private_ecdsa_key (priv);
832 data = data_to_ecdsa_value (purpose);
833 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
835 LOG (GNUNET_ERROR_TYPE_WARNING,
836 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
837 __LINE__, gcry_strerror (rc));
838 gcry_sexp_release (data);
839 gcry_sexp_release (priv_sexp);
840 return GNUNET_SYSERR;
842 gcry_sexp_release (priv_sexp);
843 gcry_sexp_release (data);
845 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
847 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
850 gcry_sexp_release (sig_sexp);
851 return GNUNET_SYSERR;
853 gcry_sexp_release (sig_sexp);
854 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
855 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
856 gcry_mpi_release (rs[0]);
857 gcry_mpi_release (rs[1]);
863 * Sign a given block.
865 * @param priv private key to use for the signing
866 * @param purpose what to sign (size, purpose)
867 * @param sig where to write the signature
868 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
871 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
872 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
873 struct GNUNET_CRYPTO_EddsaSignature *sig)
875 gcry_sexp_t priv_sexp;
876 gcry_sexp_t sig_sexp;
881 priv_sexp = decode_private_eddsa_key (priv);
882 data = data_to_eddsa_value (purpose);
883 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
885 LOG (GNUNET_ERROR_TYPE_WARNING,
886 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
887 __LINE__, gcry_strerror (rc));
888 gcry_sexp_release (data);
889 gcry_sexp_release (priv_sexp);
890 return GNUNET_SYSERR;
892 gcry_sexp_release (priv_sexp);
893 gcry_sexp_release (data);
895 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
897 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
900 gcry_sexp_release (sig_sexp);
901 return GNUNET_SYSERR;
903 gcry_sexp_release (sig_sexp);
904 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
905 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
906 gcry_mpi_release (rs[0]);
907 gcry_mpi_release (rs[1]);
915 * @param purpose what is the purpose that the signature should have?
916 * @param validate block to validate (size, purpose, data)
917 * @param sig signature that is being validated
918 * @param pub public key of the signer
919 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
922 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
923 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
924 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
925 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
928 gcry_sexp_t sig_sexpr;
929 gcry_sexp_t pub_sexpr;
932 if (purpose != ntohl (validate->purpose))
933 return GNUNET_SYSERR; /* purpose mismatch */
935 /* build s-expression for signature */
936 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
937 "(sig-val(ecdsa(r %b)(s %b)))",
938 (int) sizeof (sig->r), sig->r,
939 (int) sizeof (sig->s), sig->s)))
941 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
942 return GNUNET_SYSERR;
944 data = data_to_ecdsa_value (validate);
945 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
946 "(public-key(ecc(curve " CURVE ")(q %b)))",
947 (int) sizeof (pub->q_y), pub->q_y)))
949 gcry_sexp_release (data);
950 gcry_sexp_release (sig_sexpr);
951 return GNUNET_SYSERR;
953 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
954 gcry_sexp_release (pub_sexpr);
955 gcry_sexp_release (data);
956 gcry_sexp_release (sig_sexpr);
959 LOG (GNUNET_ERROR_TYPE_INFO,
960 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
961 __LINE__, gcry_strerror (rc));
962 return GNUNET_SYSERR;
972 * @param purpose what is the purpose that the signature should have?
973 * @param validate block to validate (size, purpose, data)
974 * @param sig signature that is being validated
975 * @param pub public key of the signer
976 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
979 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
980 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
981 const struct GNUNET_CRYPTO_EddsaSignature *sig,
982 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
985 gcry_sexp_t sig_sexpr;
986 gcry_sexp_t pub_sexpr;
989 if (purpose != ntohl (validate->purpose))
990 return GNUNET_SYSERR; /* purpose mismatch */
992 /* build s-expression for signature */
993 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
994 "(sig-val(eddsa(r %b)(s %b)))",
995 (int)sizeof (sig->r), sig->r,
996 (int)sizeof (sig->s), sig->s)))
998 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
999 return GNUNET_SYSERR;
1001 data = data_to_eddsa_value (validate);
1002 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1003 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1004 (int)sizeof (pub->q_y), pub->q_y)))
1006 gcry_sexp_release (data);
1007 gcry_sexp_release (sig_sexpr);
1008 return GNUNET_SYSERR;
1010 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1011 gcry_sexp_release (pub_sexpr);
1012 gcry_sexp_release (data);
1013 gcry_sexp_release (sig_sexpr);
1016 LOG (GNUNET_ERROR_TYPE_INFO,
1017 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1018 __LINE__, gcry_strerror (rc));
1019 return GNUNET_SYSERR;
1026 * Derive key material from a public and a private ECDHE key.
1028 * @param priv private key to use for the ECDH (x)
1029 * @param pub public key to use for the ECDH (yG)
1030 * @param key_material where to write the key material (xyG)
1031 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1034 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1035 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1036 struct GNUNET_HashCode *key_material)
1038 gcry_mpi_point_t result;
1042 gcry_sexp_t pub_sexpr;
1043 gcry_mpi_t result_x;
1044 unsigned char xbuf[256 / 8];
1047 /* first, extract the q = dP value from the public key */
1048 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1049 "(public-key(ecc(curve " CURVE ")(q %b)))",
1050 (int)sizeof (pub->q_y), pub->q_y))
1051 return GNUNET_SYSERR;
1052 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1053 gcry_sexp_release (pub_sexpr);
1054 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1056 /* second, extract the d value from our private key */
1057 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1059 /* then call the 'multiply' function, to compute the product */
1060 result = gcry_mpi_point_new (0);
1061 gcry_mpi_ec_mul (result, d, q, ctx);
1062 gcry_mpi_point_release (q);
1063 gcry_mpi_release (d);
1065 /* finally, convert point to string for hashing */
1066 result_x = gcry_mpi_new (256);
1067 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1069 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1070 gcry_mpi_point_release (result);
1071 gcry_ctx_release (ctx);
1072 return GNUNET_SYSERR;
1074 gcry_mpi_point_release (result);
1075 gcry_ctx_release (ctx);
1077 rsize = sizeof (xbuf);
1078 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1079 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1080 as that does not include the sign bit; x should be a 255-bit
1081 value, so with the sign it should fit snugly into the 256-bit
1084 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1086 GNUNET_CRYPTO_hash (xbuf,
1089 gcry_mpi_release (result_x);
1095 * Derive the 'h' value for key derivation, where
1098 * @param pub public key for deriviation
1099 * @param label label for deriviation
1100 * @param context additional context to use for HKDF of 'h';
1101 * typically the name of the subsystem/application
1105 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1107 const char *context)
1110 struct GNUNET_HashCode hc;
1111 static const char *const salt = "key-derivation";
1113 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1114 salt, strlen (salt),
1116 label, strlen (label),
1117 context, strlen (context),
1119 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1120 (unsigned char *) &hc,
1127 * Derive a private key from a given private key and a label.
1128 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1129 * where n is the size of the ECC group and P is the public
1130 * key associated with the private key 'd'.
1132 * @param priv original private key
1133 * @param label label to use for key deriviation
1134 * @param context additional context to use for HKDF of 'h';
1135 * typically the name of the subsystem/application
1136 * @return derived private key
1138 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1139 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1141 const char *context)
1143 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1144 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1151 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1153 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1154 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1156 h = derive_h (&pub, label, context);
1157 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1160 d = gcry_mpi_new (256);
1161 gcry_mpi_mulm (d, h, x, n);
1162 gcry_mpi_release (h);
1163 gcry_mpi_release (x);
1164 gcry_mpi_release (n);
1165 gcry_ctx_release (ctx);
1166 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1167 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1168 gcry_mpi_release (d);
1174 * Derive a public key from a given public key and a label.
1175 * Essentially calculates a public key 'V = H(l,P) * P'.
1177 * @param pub original public key
1178 * @param label label to use for key derivation
1179 * @param context additional context to use for HKDF of 'h';
1180 * typically the name of the subsystem/application
1181 * @param result where to write the derived public key
1184 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1186 const char *context,
1187 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1197 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1199 /* obtain point 'q' from original public key. The provided 'q' is
1200 compressed thus we first store it in the context and then get it
1201 back as a (decompresssed) point. */
1202 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1203 GNUNET_assert (NULL != q_y);
1204 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1205 gcry_mpi_release (q_y);
1206 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1209 /* calculate h_mod_n = h % n */
1210 h = derive_h (pub, label, context);
1211 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1212 h_mod_n = gcry_mpi_new (256);
1213 gcry_mpi_mod (h_mod_n, h, n);
1214 /* calculate v = h_mod_n * q */
1215 v = gcry_mpi_point_new (0);
1216 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1217 gcry_mpi_release (h_mod_n);
1218 gcry_mpi_release (h);
1219 gcry_mpi_release (n);
1220 gcry_mpi_point_release (q);
1222 /* convert point 'v' to public key that we return */
1223 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1224 gcry_mpi_point_release (v);
1225 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1226 GNUNET_assert (q_y);
1227 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1228 sizeof (result->q_y),
1230 gcry_mpi_release (q_y);
1231 gcry_ctx_release (ctx);
1236 * Reverse the sequence of the bytes in @a buffer
1238 * @param[in|out] buffer buffer to invert
1239 * @param length number of bytes in @a buffer
1242 reverse_buffer (unsigned char *buffer,
1248 for (i=0; i < length/2; i++)
1251 buffer[i] = buffer[length-1-i];
1252 buffer[length-1-i] = tmp;
1258 * Convert the secret @a d of an EdDSA key to the
1259 * value that is actually used in the EdDSA computation.
1261 * @param d secret input
1262 * @return value used for the calculation in EdDSA
1265 eddsa_d_to_a (gcry_mpi_t d)
1267 unsigned char rawmpi[32]; /* 256-bit value */
1269 unsigned char digest[64]; /* 512-bit hash value */
1270 gcry_buffer_t hvec[2];
1274 b = 256 / 8; /* number of bytes in `d` */
1276 /* Note that we clear DIGEST so we can use it as input to left pad
1277 the key with zeroes for hashing. */
1278 memset (hvec, 0, sizeof hvec);
1279 rawmpilen = sizeof (rawmpi);
1281 gcry_mpi_print (GCRYMPI_FMT_USG,
1282 rawmpi, rawmpilen, &rawmpilen,
1286 memmove (rawmpi + 32 - rawmpilen,
1294 hvec[0].data = digest;
1296 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1297 hvec[1].data = rawmpi;
1299 hvec[1].len = rawmpilen;
1301 gcry_md_hash_buffers (GCRY_MD_SHA512,
1305 /* Compute the A value. */
1306 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1307 digest[0] = (digest[0] & 0x7f) | 0x40;
1310 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1318 * Take point from ECDH and convert it to key material.
1320 * @param result point from ECDH
1321 * @param ctx ECC context
1322 * @param key_material[out] set to derived key material
1323 * @return #GNUNET_OK on success
1326 point_to_hash (gcry_mpi_point_t result,
1328 struct GNUNET_HashCode *key_material)
1330 gcry_mpi_t result_x;
1331 unsigned char xbuf[256 / 8];
1334 /* finally, convert point to string for hashing */
1335 result_x = gcry_mpi_new (256);
1336 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1338 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1339 return GNUNET_SYSERR;
1342 rsize = sizeof (xbuf);
1343 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1344 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1345 as that does not include the sign bit; x should be a 255-bit
1346 value, so with the sign it should fit snugly into the 256-bit
1349 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1351 GNUNET_CRYPTO_hash (xbuf,
1354 gcry_mpi_release (result_x);
1361 * Derive key material from a ECDH public key and a private EdDSA key.
1362 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1364 * @param priv private key from EdDSA to use for the ECDH (x)
1365 * @param pub public key to use for the ECDH (yG)
1366 * @param key_material where to write the key material H(h(x)yG)
1367 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1370 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1371 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1372 struct GNUNET_HashCode *key_material)
1374 gcry_mpi_point_t result;
1379 gcry_sexp_t pub_sexpr;
1382 /* first, extract the q = dP value from the public key */
1383 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1384 "(public-key(ecc(curve " CURVE ")(q %b)))",
1385 (int)sizeof (pub->q_y), pub->q_y))
1386 return GNUNET_SYSERR;
1387 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1388 gcry_sexp_release (pub_sexpr);
1389 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1391 /* second, extract the d value from our private key */
1392 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1394 /* NOW, because this is EdDSA, HASH 'd' first! */
1395 a = eddsa_d_to_a (d);
1396 gcry_mpi_release (d);
1398 /* then call the 'multiply' function, to compute the product */
1399 result = gcry_mpi_point_new (0);
1400 gcry_mpi_ec_mul (result, a, q, ctx);
1401 gcry_mpi_point_release (q);
1402 gcry_mpi_release (a);
1404 ret = point_to_hash (result,
1407 gcry_mpi_point_release (result);
1408 gcry_ctx_release (ctx);
1415 * Derive key material from a ECDH public key and a private ECDSA key.
1416 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1418 * @param priv private key from ECDSA to use for the ECDH (x)
1419 * @param pub public key to use for the ECDH (yG)
1420 * @param key_material where to write the key material H(h(x)yG)
1421 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1424 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1425 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1426 struct GNUNET_HashCode *key_material)
1428 gcry_mpi_point_t result;
1432 gcry_sexp_t pub_sexpr;
1435 /* first, extract the q = dP value from the public key */
1436 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1437 "(public-key(ecc(curve " CURVE ")(q %b)))",
1438 (int)sizeof (pub->q_y), pub->q_y))
1439 return GNUNET_SYSERR;
1440 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1441 gcry_sexp_release (pub_sexpr);
1442 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1444 /* second, extract the d value from our private key */
1445 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1447 /* then call the 'multiply' function, to compute the product */
1448 result = gcry_mpi_point_new (0);
1449 gcry_mpi_ec_mul (result, d, q, ctx);
1450 gcry_mpi_point_release (q);
1451 gcry_mpi_release (d);
1453 /* finally, convert point to string for hashing */
1454 ret = point_to_hash (result,
1457 gcry_mpi_point_release (result);
1458 gcry_ctx_release (ctx);
1466 * Derive key material from a EdDSA public key and a private ECDH key.
1467 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1469 * @param priv private key to use for the ECDH (y)
1470 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1471 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1472 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1475 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1476 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1477 struct GNUNET_HashCode *key_material)
1479 gcry_mpi_point_t result;
1483 gcry_sexp_t pub_sexpr;
1486 /* first, extract the q = dP value from the public key */
1487 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1488 "(public-key(ecc(curve " CURVE ")(q %b)))",
1489 (int)sizeof (pub->q_y), pub->q_y))
1490 return GNUNET_SYSERR;
1491 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1492 gcry_sexp_release (pub_sexpr);
1493 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1495 /* second, extract the d value from our private key */
1496 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1498 /* then call the 'multiply' function, to compute the product */
1499 result = gcry_mpi_point_new (0);
1500 gcry_mpi_ec_mul (result, d, q, ctx);
1501 gcry_mpi_point_release (q);
1502 gcry_mpi_release (d);
1504 /* finally, convert point to string for hashing */
1505 ret = point_to_hash (result,
1508 gcry_mpi_point_release (result);
1509 gcry_ctx_release (ctx);
1515 * Derive key material from a ECDSA public key and a private ECDH key.
1516 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1518 * @param priv private key to use for the ECDH (y)
1519 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1520 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1521 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1524 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1525 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1526 struct GNUNET_HashCode *key_material)
1528 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1529 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1533 /* end of crypto_ecc.c */