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", __VA_ARGS__)
43 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
45 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", 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)
56 * Extract values from an S-expression.
58 * @param array where to store the result(s)
59 * @param sexp S-expression to parse
60 * @param topname top-level name in the S-expression that is of interest
61 * @param elems names of the elements to extract
62 * @return 0 on success
65 key_from_sexp (gcry_mpi_t * array,
76 list = gcry_sexp_find_token (sexp, topname, 0);
79 l2 = gcry_sexp_cadr (list);
80 gcry_sexp_release (list);
86 for (s = elems; *s; s++, idx++)
88 l2 = gcry_sexp_find_token (list, s, 1);
91 for (i = 0; i < idx; i++)
96 gcry_sexp_release (list);
97 return 3; /* required parameter not found */
99 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
100 gcry_sexp_release (l2);
103 for (i = 0; i < idx; i++)
105 gcry_free (array[i]);
108 gcry_sexp_release (list);
109 return 4; /* required parameter is invalid */
112 gcry_sexp_release (list);
118 * Convert the given private key from the network format to the
119 * S-expression that can be used by libgcrypt.
121 * @param priv private key to decode
122 * @return NULL on error
125 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
130 rc = gcry_sexp_build (&result, NULL,
131 "(private-key(ecc(curve \"" CURVE "\")"
133 (int) sizeof (priv->d), priv->d);
136 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
140 if (0 != (rc = gcry_pk_testkey (result)))
142 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
151 * Convert the given private key from the network format to the
152 * S-expression that can be used by libgcrypt.
154 * @param priv private key to decode
155 * @return NULL on error
158 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
163 rc = gcry_sexp_build (&result, NULL,
164 "(private-key(ecc(curve \"" CURVE "\")"
165 "(flags eddsa)(d %b)))",
166 (int)sizeof (priv->d), priv->d);
169 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
173 if (0 != (rc = gcry_pk_testkey (result)))
175 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
184 * Convert the given private key from the network format to the
185 * S-expression that can be used by libgcrypt.
187 * @param priv private key to decode
188 * @return NULL on error
191 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
196 rc = gcry_sexp_build (&result, NULL,
197 "(private-key(ecc(curve \"" CURVE "\")"
199 (int)sizeof (priv->d), priv->d);
202 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
206 if (0 != (rc = gcry_pk_testkey (result)))
208 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
217 * Extract the public key for the given private key.
219 * @param priv the private key
220 * @param pub where to write the public key
223 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
224 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
230 sexp = decode_private_ecdsa_key (priv);
231 GNUNET_assert (NULL != sexp);
232 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
233 gcry_sexp_release (sexp);
234 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
235 GNUNET_assert (NULL != q);
236 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
237 gcry_mpi_release (q);
238 gcry_ctx_release (ctx);
243 * Extract the public key for the given private key.
245 * @param priv the private key
246 * @param pub where to write the public key
249 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
250 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
256 sexp = decode_private_eddsa_key (priv);
257 GNUNET_assert (NULL != sexp);
258 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
259 gcry_sexp_release (sexp);
260 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
262 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
263 gcry_mpi_release (q);
264 gcry_ctx_release (ctx);
269 * Extract the public key for the given private key.
271 * @param priv the private key
272 * @param pub where to write the public key
275 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
276 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
282 sexp = decode_private_ecdhe_key (priv);
283 GNUNET_assert (NULL != sexp);
284 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
285 gcry_sexp_release (sexp);
286 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
288 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
289 gcry_mpi_release (q);
290 gcry_ctx_release (ctx);
295 * Convert a public key to a string.
297 * @param pub key to convert
298 * @return string representing @a pub
301 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
304 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
308 keylen += 5 - keylen % 5;
310 pubkeybuf = GNUNET_malloc (keylen + 1);
311 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
312 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
317 GNUNET_free (pubkeybuf);
326 * Convert a public key to a string.
328 * @param pub key to convert
329 * @return string representing @a pub
332 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
335 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
339 keylen += 5 - keylen % 5;
341 pubkeybuf = GNUNET_malloc (keylen + 1);
342 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
343 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
348 GNUNET_free (pubkeybuf);
357 * Convert a string representing a public key to a public key.
359 * @param enc encoded public key
360 * @param enclen number of bytes in @a enc (without 0-terminator)
361 * @param pub where to store the public key
362 * @return #GNUNET_OK on success
365 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
367 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
369 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
372 keylen += 5 - keylen % 5;
374 if (enclen != keylen)
375 return GNUNET_SYSERR;
377 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
379 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
380 return GNUNET_SYSERR;
386 * Convert a string representing a public key to a public key.
388 * @param enc encoded public key
389 * @param enclen number of bytes in @a enc (without 0-terminator)
390 * @param pub where to store the public key
391 * @return #GNUNET_OK on success
394 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
396 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
398 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
401 keylen += 5 - keylen % 5;
403 if (enclen != keylen)
404 return GNUNET_SYSERR;
406 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
408 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
409 return GNUNET_SYSERR;
415 * Convert a string representing a private key to a private key.
417 * @param enc encoded public key
418 * @param enclen number of bytes in @a enc (without 0-terminator)
419 * @param priv where to store the private key
420 * @return #GNUNET_OK on success
423 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
425 struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
427 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
430 keylen += 5 - keylen % 5;
432 if (enclen != keylen)
433 return GNUNET_SYSERR;
435 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
437 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
438 return GNUNET_SYSERR;
445 * Clear memory that was used to store a private key.
447 * @param pk location of the key
450 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
452 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
458 * Clear memory that was used to store a private key.
460 * @param pk location of the key
463 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
465 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
471 * Clear memory that was used to store a private key.
473 * @param pk location of the key
476 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
478 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
483 * Create a new private key. Caller must free return value.
485 * @return fresh private key
487 struct GNUNET_CRYPTO_EcdhePrivateKey *
488 GNUNET_CRYPTO_ecdhe_key_create ()
490 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
491 gcry_sexp_t priv_sexp;
492 gcry_sexp_t s_keyparam;
496 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
497 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
498 disables an expensive key testing routine. We do not want to run
499 the expensive check for ECDHE, as we generate TONS of keys to
500 use for a very short time. */
501 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
502 "(genkey(ecc(curve \"" CURVE "\")"
503 "(flags eddsa no-keytest)))")))
505 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
508 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
510 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
511 gcry_sexp_release (s_keyparam);
514 gcry_sexp_release (s_keyparam);
516 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
518 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
519 gcry_sexp_release (priv_sexp);
523 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
525 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
526 gcry_sexp_release (priv_sexp);
529 gcry_sexp_release (priv_sexp);
530 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
531 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
532 gcry_mpi_release (d);
538 * Create a new private key. Caller must free return value.
540 * @return fresh private key
542 struct GNUNET_CRYPTO_EcdsaPrivateKey *
543 GNUNET_CRYPTO_ecdsa_key_create ()
545 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
546 gcry_sexp_t priv_sexp;
547 gcry_sexp_t s_keyparam;
551 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
552 "(genkey(ecc(curve \"" CURVE "\")"
555 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
558 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
560 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
561 gcry_sexp_release (s_keyparam);
564 gcry_sexp_release (s_keyparam);
566 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
568 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
569 gcry_sexp_release (priv_sexp);
573 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
575 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
576 gcry_sexp_release (priv_sexp);
579 gcry_sexp_release (priv_sexp);
580 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
581 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
582 gcry_mpi_release (d);
587 * Create a new private key. Caller must free return value.
589 * @return fresh private key
591 struct GNUNET_CRYPTO_EddsaPrivateKey *
592 GNUNET_CRYPTO_eddsa_key_create ()
594 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
595 gcry_sexp_t priv_sexp;
596 gcry_sexp_t s_keyparam;
600 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
601 "(genkey(ecc(curve \"" CURVE "\")"
604 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
607 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
609 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
610 gcry_sexp_release (s_keyparam);
613 gcry_sexp_release (s_keyparam);
615 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
617 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
618 gcry_sexp_release (priv_sexp);
622 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
624 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
625 gcry_sexp_release (priv_sexp);
628 gcry_sexp_release (priv_sexp);
629 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
630 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
631 gcry_mpi_release (d);
637 * Get the shared private key we use for anonymous users.
639 * @return "anonymous" private key
641 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
642 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
645 * 'anonymous' pseudonym (global static, d=1, public key = G
648 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
653 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
654 sizeof (anonymous.d),
662 * Compare two Peer Identities.
664 * @param first first peer identity
665 * @param second second peer identity
666 * @return bigger than 0 if first > second,
667 * 0 if they are the same
668 * smaller than 0 if second > first
671 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
672 const struct GNUNET_PeerIdentity *second)
674 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
679 * Convert the data specified in the given purpose argument to an
680 * S-expression suitable for signature operations.
682 * @param purpose data to convert
683 * @return converted s-expression
686 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
688 struct GNUNET_HashCode hc;
692 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
693 if (0 != (rc = gcry_sexp_build (&data, NULL,
694 "(data(flags eddsa)(hash-algo %s)(value %b))",
696 (int)sizeof (hc), &hc)))
698 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
706 * Convert the data specified in the given purpose argument to an
707 * S-expression suitable for signature operations.
709 * @param purpose data to convert
710 * @return converted s-expression
713 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
715 struct GNUNET_HashCode hc;
719 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
720 if (0 != (rc = gcry_sexp_build (&data, NULL,
721 "(data(flags rfc6979)(hash %s %b))",
723 (int)sizeof (hc), &hc)))
725 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
733 * Sign a given block.
735 * @param priv private key to use for the signing
736 * @param purpose what to sign (size, purpose)
737 * @param sig where to write the signature
738 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
741 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
742 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
743 struct GNUNET_CRYPTO_EcdsaSignature *sig)
745 gcry_sexp_t priv_sexp;
746 gcry_sexp_t sig_sexp;
751 priv_sexp = decode_private_ecdsa_key (priv);
752 data = data_to_ecdsa_value (purpose);
753 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
755 LOG (GNUNET_ERROR_TYPE_WARNING,
756 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
757 __LINE__, gcry_strerror (rc));
758 gcry_sexp_release (data);
759 gcry_sexp_release (priv_sexp);
760 return GNUNET_SYSERR;
762 gcry_sexp_release (priv_sexp);
763 gcry_sexp_release (data);
765 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
767 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
770 gcry_sexp_release (sig_sexp);
771 return GNUNET_SYSERR;
773 gcry_sexp_release (sig_sexp);
774 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
775 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
776 gcry_mpi_release (rs[0]);
777 gcry_mpi_release (rs[1]);
783 * Sign a given block.
785 * @param priv private key to use for the signing
786 * @param purpose what to sign (size, purpose)
787 * @param sig where to write the signature
788 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
791 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
792 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
793 struct GNUNET_CRYPTO_EddsaSignature *sig)
795 gcry_sexp_t priv_sexp;
796 gcry_sexp_t sig_sexp;
801 priv_sexp = decode_private_eddsa_key (priv);
802 data = data_to_eddsa_value (purpose);
803 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
805 LOG (GNUNET_ERROR_TYPE_WARNING,
806 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
807 __LINE__, gcry_strerror (rc));
808 gcry_sexp_release (data);
809 gcry_sexp_release (priv_sexp);
810 return GNUNET_SYSERR;
812 gcry_sexp_release (priv_sexp);
813 gcry_sexp_release (data);
815 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
817 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
820 gcry_sexp_release (sig_sexp);
821 return GNUNET_SYSERR;
823 gcry_sexp_release (sig_sexp);
824 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
825 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
826 gcry_mpi_release (rs[0]);
827 gcry_mpi_release (rs[1]);
835 * @param purpose what is the purpose that the signature should have?
836 * @param validate block to validate (size, purpose, data)
837 * @param sig signature that is being validated
838 * @param pub public key of the signer
839 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
842 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
843 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
844 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
845 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
848 gcry_sexp_t sig_sexpr;
849 gcry_sexp_t pub_sexpr;
852 if (purpose != ntohl (validate->purpose))
853 return GNUNET_SYSERR; /* purpose mismatch */
855 /* build s-expression for signature */
856 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
857 "(sig-val(ecdsa(r %b)(s %b)))",
858 (int) sizeof (sig->r), sig->r,
859 (int) sizeof (sig->s), sig->s)))
861 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
862 return GNUNET_SYSERR;
864 data = data_to_ecdsa_value (validate);
865 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
866 "(public-key(ecc(curve " CURVE ")(q %b)))",
867 (int) sizeof (pub->q_y), pub->q_y)))
869 gcry_sexp_release (data);
870 gcry_sexp_release (sig_sexpr);
871 return GNUNET_SYSERR;
873 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
874 gcry_sexp_release (pub_sexpr);
875 gcry_sexp_release (data);
876 gcry_sexp_release (sig_sexpr);
879 LOG (GNUNET_ERROR_TYPE_INFO,
880 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
881 __LINE__, gcry_strerror (rc));
882 return GNUNET_SYSERR;
892 * @param purpose what is the purpose that the signature should have?
893 * @param validate block to validate (size, purpose, data)
894 * @param sig signature that is being validated
895 * @param pub public key of the signer
896 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
899 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
900 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
901 const struct GNUNET_CRYPTO_EddsaSignature *sig,
902 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
905 gcry_sexp_t sig_sexpr;
906 gcry_sexp_t pub_sexpr;
909 if (purpose != ntohl (validate->purpose))
910 return GNUNET_SYSERR; /* purpose mismatch */
912 /* build s-expression for signature */
913 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
914 "(sig-val(eddsa(r %b)(s %b)))",
915 (int)sizeof (sig->r), sig->r,
916 (int)sizeof (sig->s), sig->s)))
918 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
919 return GNUNET_SYSERR;
921 data = data_to_eddsa_value (validate);
922 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
923 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
924 (int)sizeof (pub->q_y), pub->q_y)))
926 gcry_sexp_release (data);
927 gcry_sexp_release (sig_sexpr);
928 return GNUNET_SYSERR;
930 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
931 gcry_sexp_release (pub_sexpr);
932 gcry_sexp_release (data);
933 gcry_sexp_release (sig_sexpr);
936 LOG (GNUNET_ERROR_TYPE_INFO,
937 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
938 __LINE__, gcry_strerror (rc));
939 return GNUNET_SYSERR;
946 * Derive key material from a public and a private ECDHE key.
948 * @param priv private key to use for the ECDH (x)
949 * @param pub public key to use for the ECDH (yG)
950 * @param key_material where to write the key material (xyG)
951 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
954 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
955 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
956 struct GNUNET_HashCode *key_material)
958 gcry_mpi_point_t result;
962 gcry_sexp_t pub_sexpr;
964 unsigned char xbuf[256 / 8];
967 /* first, extract the q = dP value from the public key */
968 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
969 "(public-key(ecc(curve " CURVE ")(q %b)))",
970 (int)sizeof (pub->q_y), pub->q_y))
971 return GNUNET_SYSERR;
972 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
973 gcry_sexp_release (pub_sexpr);
974 q = gcry_mpi_ec_get_point ("q", ctx, 0);
976 /* second, extract the d value from our private key */
977 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
979 /* then call the 'multiply' function, to compute the product */
980 result = gcry_mpi_point_new (0);
981 gcry_mpi_ec_mul (result, d, q, ctx);
982 gcry_mpi_point_release (q);
983 gcry_mpi_release (d);
985 /* finally, convert point to string for hashing */
986 result_x = gcry_mpi_new (256);
987 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
989 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
990 gcry_mpi_point_release (result);
991 gcry_ctx_release (ctx);
992 return GNUNET_SYSERR;
994 gcry_mpi_point_release (result);
995 gcry_ctx_release (ctx);
997 rsize = sizeof (xbuf);
998 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
999 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1000 as that does not include the sign bit; x should be a 255-bit
1001 value, so with the sign it should fit snugly into the 256-bit
1004 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1006 GNUNET_CRYPTO_hash (xbuf,
1009 gcry_mpi_release (result_x);
1015 * Derive the 'h' value for key derivation, where
1018 * @param pub public key for deriviation
1019 * @param label label for deriviation
1020 * @param context additional context to use for HKDF of 'h';
1021 * typically the name of the subsystem/application
1025 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1027 const char *context)
1030 struct GNUNET_HashCode hc;
1031 static const char *const salt = "key-derivation";
1033 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1034 salt, strlen (salt),
1036 label, strlen (label),
1037 context, strlen (context),
1039 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1040 (unsigned char *) &hc,
1047 * Derive a private key from a given private key and a label.
1048 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1049 * where n is the size of the ECC group and P is the public
1050 * key associated with the private key 'd'.
1052 * @param priv original private key
1053 * @param label label to use for key deriviation
1054 * @param context additional context to use for HKDF of 'h';
1055 * typically the name of the subsystem/application
1056 * @return derived private key
1058 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1059 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1061 const char *context)
1063 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1064 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1071 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1073 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1074 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1076 h = derive_h (&pub, label, context);
1077 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1080 d = gcry_mpi_new (256);
1081 gcry_mpi_mulm (d, h, x, n);
1082 gcry_mpi_release (h);
1083 gcry_mpi_release (x);
1084 gcry_mpi_release (n);
1085 gcry_ctx_release (ctx);
1086 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1087 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1088 gcry_mpi_release (d);
1094 * Derive a public key from a given public key and a label.
1095 * Essentially calculates a public key 'V = H(l,P) * P'.
1097 * @param pub original public key
1098 * @param label label to use for key derivation
1099 * @param context additional context to use for HKDF of 'h';
1100 * typically the name of the subsystem/application
1101 * @param result where to write the derived public key
1104 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1106 const char *context,
1107 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1117 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1119 /* obtain point 'q' from original public key. The provided 'q' is
1120 compressed thus we first store it in the context and then get it
1121 back as a (decompresssed) point. */
1122 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1123 GNUNET_assert (NULL != q_y);
1124 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1125 gcry_mpi_release (q_y);
1126 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1129 /* calculate h_mod_n = h % n */
1130 h = derive_h (pub, label, context);
1131 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1132 h_mod_n = gcry_mpi_new (256);
1133 gcry_mpi_mod (h_mod_n, h, n);
1134 /* calculate v = h_mod_n * q */
1135 v = gcry_mpi_point_new (0);
1136 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1137 gcry_mpi_release (h_mod_n);
1138 gcry_mpi_release (h);
1139 gcry_mpi_release (n);
1140 gcry_mpi_point_release (q);
1142 /* convert point 'v' to public key that we return */
1143 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1144 gcry_mpi_point_release (v);
1145 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1146 GNUNET_assert (q_y);
1147 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1148 sizeof (result->q_y),
1150 gcry_mpi_release (q_y);
1151 gcry_ctx_release (ctx);
1156 * Reverse the sequence of the bytes in @a buffer
1158 * @param[in|out] buffer buffer to invert
1159 * @param length number of bytes in @a buffer
1162 reverse_buffer (unsigned char *buffer,
1168 for (i=0; i < length/2; i++)
1171 buffer[i] = buffer[length-1-i];
1172 buffer[length-1-i] = tmp;
1178 * Convert the secret @a d of an EdDSA key to the
1179 * value that is actually used in the EdDSA computation.
1181 * @param d secret input
1182 * @return value used for the calculation in EdDSA
1185 eddsa_d_to_a (gcry_mpi_t d)
1187 unsigned char rawmpi[32]; /* 256-bit value */
1189 unsigned char digest[64]; /* 512-bit hash value */
1190 gcry_buffer_t hvec[2];
1194 b = 256 / 8; /* number of bytes in `d` */
1196 /* Note that we clear DIGEST so we can use it as input to left pad
1197 the key with zeroes for hashing. */
1198 memset (hvec, 0, sizeof hvec);
1199 rawmpilen = sizeof (rawmpi);
1201 gcry_mpi_print (GCRYMPI_FMT_USG,
1202 rawmpi, rawmpilen, &rawmpilen,
1204 hvec[0].data = digest;
1206 hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
1207 hvec[1].data = rawmpi;
1209 hvec[1].len = rawmpilen;
1211 gcry_md_hash_buffers (GCRY_MD_SHA512,
1215 /* Compute the A value. */
1216 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1217 digest[0] = (digest[0] & 0x7f) | 0x40;
1220 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1229 * Derive key material from a ECDH public key and a private EdDSA key.
1230 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1232 * @param priv private key from EdDSA to use for the ECDH (x)
1233 * @param pub public key to use for the ECDH (yG)
1234 * @param key_material where to write the key material H(h(x)yG)
1235 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1238 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1239 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1240 struct GNUNET_HashCode *key_material)
1242 gcry_mpi_point_t result;
1247 gcry_sexp_t pub_sexpr;
1248 gcry_mpi_t result_x;
1249 unsigned char xbuf[256 / 8];
1252 /* first, extract the q = dP value from the public key */
1253 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1254 "(public-key(ecc(curve " CURVE ")(q %b)))",
1255 (int)sizeof (pub->q_y), pub->q_y))
1256 return GNUNET_SYSERR;
1257 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1258 gcry_sexp_release (pub_sexpr);
1259 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1261 /* second, extract the d value from our private key */
1262 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1264 /* NOW, because this is EdDSA, HASH 'd' first! */
1265 a = eddsa_d_to_a (d);
1266 gcry_mpi_release (d);
1268 /* then call the 'multiply' function, to compute the product */
1269 result = gcry_mpi_point_new (0);
1270 gcry_mpi_ec_mul (result, a, q, ctx);
1271 gcry_mpi_point_release (q);
1272 gcry_mpi_release (a);
1274 /* finally, convert point to string for hashing */
1275 result_x = gcry_mpi_new (256);
1276 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1278 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1279 gcry_mpi_point_release (result);
1280 gcry_ctx_release (ctx);
1281 return GNUNET_SYSERR;
1283 gcry_mpi_point_release (result);
1284 gcry_ctx_release (ctx);
1286 rsize = sizeof (xbuf);
1287 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1288 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1289 as that does not include the sign bit; x should be a 255-bit
1290 value, so with the sign it should fit snugly into the 256-bit
1293 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1295 GNUNET_CRYPTO_hash (xbuf,
1298 gcry_mpi_release (result_x);
1304 * Derive key material from a ECDH public key and a private ECDSA key.
1305 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1307 * @param priv private key from ECDSA to use for the ECDH (x)
1308 * @param pub public key to use for the ECDH (yG)
1309 * @param key_material where to write the key material H(h(x)yG)
1310 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1313 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1314 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1315 struct GNUNET_HashCode *key_material)
1317 gcry_mpi_point_t result;
1321 gcry_sexp_t pub_sexpr;
1322 gcry_mpi_t result_x;
1323 unsigned char xbuf[256 / 8];
1326 /* first, extract the q = dP value from the public key */
1327 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1328 "(public-key(ecc(curve " CURVE ")(q %b)))",
1329 (int)sizeof (pub->q_y), pub->q_y))
1330 return GNUNET_SYSERR;
1331 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1332 gcry_sexp_release (pub_sexpr);
1333 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1335 /* second, extract the d value from our private key */
1336 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1338 /* then call the 'multiply' function, to compute the product */
1339 result = gcry_mpi_point_new (0);
1340 gcry_mpi_ec_mul (result, d, q, ctx);
1341 gcry_mpi_point_release (q);
1342 gcry_mpi_release (d);
1344 /* finally, convert point to string for hashing */
1345 result_x = gcry_mpi_new (256);
1346 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1348 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1349 gcry_mpi_point_release (result);
1350 gcry_ctx_release (ctx);
1351 return GNUNET_SYSERR;
1353 gcry_mpi_point_release (result);
1354 gcry_ctx_release (ctx);
1356 rsize = sizeof (xbuf);
1357 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1358 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1359 as that does not include the sign bit; x should be a 255-bit
1360 value, so with the sign it should fit snugly into the 256-bit
1363 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1365 GNUNET_CRYPTO_hash (xbuf,
1368 gcry_mpi_release (result_x);
1376 * Derive key material from a EdDSA public key and a private ECDH key.
1377 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1379 * @param priv private key to use for the ECDH (y)
1380 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1381 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1382 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1385 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1386 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1387 struct GNUNET_HashCode *key_material)
1389 gcry_mpi_point_t result;
1393 gcry_sexp_t pub_sexpr;
1394 gcry_mpi_t result_x;
1395 unsigned char xbuf[256 / 8];
1398 /* first, extract the q = dP value from the public key */
1399 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1400 "(public-key(ecc(curve " CURVE ")(q %b)))",
1401 (int)sizeof (pub->q_y), pub->q_y))
1402 return GNUNET_SYSERR;
1403 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1404 gcry_sexp_release (pub_sexpr);
1405 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1407 /* second, extract the d value from our private key */
1408 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1410 /* then call the 'multiply' function, to compute the product */
1411 result = gcry_mpi_point_new (0);
1412 gcry_mpi_ec_mul (result, d, q, ctx);
1413 gcry_mpi_point_release (q);
1414 gcry_mpi_release (d);
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 gcry_mpi_point_release (result);
1422 gcry_ctx_release (ctx);
1423 return GNUNET_SYSERR;
1425 gcry_mpi_point_release (result);
1426 gcry_ctx_release (ctx);
1428 rsize = sizeof (xbuf);
1429 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1430 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1431 as that does not include the sign bit; x should be a 255-bit
1432 value, so with the sign it should fit snugly into the 256-bit
1435 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1437 GNUNET_CRYPTO_hash (xbuf,
1440 gcry_mpi_release (result_x);
1446 * Derive key material from a ECDSA public key and a private ECDH key.
1447 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1449 * @param priv private key to use for the ECDH (y)
1450 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1451 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1452 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1455 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1456 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1457 struct GNUNET_HashCode *key_material)
1459 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1460 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1464 /* end of crypto_ecc.c */