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)
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 private key to a string.
359 * @param priv key to convert
360 * @return string representing @a pub
363 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
366 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
370 keylen += 5 - keylen % 5;
372 privkeybuf = GNUNET_malloc (keylen + 1);
373 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
374 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
379 GNUNET_free (privkeybuf);
388 * Convert a string representing a public key to a public key.
390 * @param enc encoded public key
391 * @param enclen number of bytes in @a enc (without 0-terminator)
392 * @param pub where to store the public key
393 * @return #GNUNET_OK on success
396 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
398 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
400 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
403 keylen += 5 - keylen % 5;
405 if (enclen != keylen)
406 return GNUNET_SYSERR;
409 GNUNET_STRINGS_string_to_data (enc, enclen,
411 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
412 return GNUNET_SYSERR;
418 * Convert a string representing a public key to a public key.
420 * @param enc encoded public key
421 * @param enclen number of bytes in @a enc (without 0-terminator)
422 * @param pub where to store the public key
423 * @return #GNUNET_OK on success
426 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
428 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
430 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
433 keylen += 5 - keylen % 5;
435 if (enclen != keylen)
436 return GNUNET_SYSERR;
439 GNUNET_STRINGS_string_to_data (enc, enclen,
441 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
442 return GNUNET_SYSERR;
448 * Convert a string representing a private key to a private key.
450 * @param enc encoded public key
451 * @param enclen number of bytes in @a enc (without 0-terminator)
452 * @param priv where to store the private key
453 * @return #GNUNET_OK on success
456 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
458 struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
460 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
463 keylen += 5 - keylen % 5;
465 if (enclen != keylen)
466 return GNUNET_SYSERR;
468 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
470 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
471 return GNUNET_SYSERR;
478 * Clear memory that was used to store a private key.
480 * @param pk location of the key
483 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
485 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
491 * Clear memory that was used to store a private key.
493 * @param pk location of the key
496 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
498 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
504 * Clear memory that was used to store a private key.
506 * @param pk location of the key
509 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
511 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
516 * Create a new private key. Caller must free return value.
518 * @return fresh private key
520 struct GNUNET_CRYPTO_EcdhePrivateKey *
521 GNUNET_CRYPTO_ecdhe_key_create ()
523 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
525 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
527 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
538 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
540 * @param[out] pk set to fresh private key;
541 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
544 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
546 gcry_sexp_t priv_sexp;
547 gcry_sexp_t s_keyparam;
551 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
552 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
553 disables an expensive key testing routine. We do not want to run
554 the expensive check for ECDHE, as we generate TONS of keys to
555 use for a very short time. */
556 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
557 "(genkey(ecc(curve \"" CURVE "\")"
558 "(flags eddsa no-keytest)))")))
560 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
561 return GNUNET_SYSERR;
563 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
565 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
566 gcry_sexp_release (s_keyparam);
567 return GNUNET_SYSERR;
569 gcry_sexp_release (s_keyparam);
571 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
573 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
574 gcry_sexp_release (priv_sexp);
575 return GNUNET_SYSERR;
578 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
580 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
581 gcry_sexp_release (priv_sexp);
582 return GNUNET_SYSERR;
584 gcry_sexp_release (priv_sexp);
585 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
586 gcry_mpi_release (d);
592 * Create a new private key. Caller must free return value.
594 * @return fresh private key
596 struct GNUNET_CRYPTO_EcdsaPrivateKey *
597 GNUNET_CRYPTO_ecdsa_key_create ()
599 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
600 gcry_sexp_t priv_sexp;
601 gcry_sexp_t s_keyparam;
605 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
606 "(genkey(ecc(curve \"" CURVE "\")"
609 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
612 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
614 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
615 gcry_sexp_release (s_keyparam);
618 gcry_sexp_release (s_keyparam);
620 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
622 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
623 gcry_sexp_release (priv_sexp);
627 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
629 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
630 gcry_sexp_release (priv_sexp);
633 gcry_sexp_release (priv_sexp);
634 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
635 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
636 gcry_mpi_release (d);
641 * Create a new private key. Caller must free return value.
643 * @return fresh private key
645 struct GNUNET_CRYPTO_EddsaPrivateKey *
646 GNUNET_CRYPTO_eddsa_key_create ()
648 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
649 gcry_sexp_t priv_sexp;
650 gcry_sexp_t s_keyparam;
654 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
655 "(genkey(ecc(curve \"" CURVE "\")"
658 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
661 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
663 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
664 gcry_sexp_release (s_keyparam);
667 gcry_sexp_release (s_keyparam);
669 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
671 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
672 gcry_sexp_release (priv_sexp);
676 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
678 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
679 gcry_sexp_release (priv_sexp);
682 gcry_sexp_release (priv_sexp);
683 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
684 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
685 gcry_mpi_release (d);
691 * Get the shared private key we use for anonymous users.
693 * @return "anonymous" private key
695 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
696 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
699 * 'anonymous' pseudonym (global static, d=1, public key = G
702 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
707 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
708 sizeof (anonymous.d),
716 * Compare two Peer Identities.
718 * @param first first peer identity
719 * @param second second peer identity
720 * @return bigger than 0 if first > second,
721 * 0 if they are the same
722 * smaller than 0 if second > first
725 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
726 const struct GNUNET_PeerIdentity *second)
728 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
733 * Convert the data specified in the given purpose argument to an
734 * S-expression suitable for signature operations.
736 * @param purpose data to convert
737 * @return converted s-expression
740 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
742 struct GNUNET_HashCode hc;
746 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
747 if (0 != (rc = gcry_sexp_build (&data, NULL,
748 "(data(flags eddsa)(hash-algo %s)(value %b))",
750 (int)sizeof (hc), &hc)))
752 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
760 * Convert the data specified in the given purpose argument to an
761 * S-expression suitable for signature operations.
763 * @param purpose data to convert
764 * @return converted s-expression
767 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
769 struct GNUNET_HashCode hc;
773 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
774 if (0 != (rc = gcry_sexp_build (&data, NULL,
775 "(data(flags rfc6979)(hash %s %b))",
777 (int)sizeof (hc), &hc)))
779 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
787 * Sign a given block.
789 * @param priv private key to use for the signing
790 * @param purpose what to sign (size, purpose)
791 * @param sig where to write the signature
792 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
795 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
796 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
797 struct GNUNET_CRYPTO_EcdsaSignature *sig)
799 gcry_sexp_t priv_sexp;
800 gcry_sexp_t sig_sexp;
805 priv_sexp = decode_private_ecdsa_key (priv);
806 data = data_to_ecdsa_value (purpose);
807 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
809 LOG (GNUNET_ERROR_TYPE_WARNING,
810 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
811 __LINE__, gcry_strerror (rc));
812 gcry_sexp_release (data);
813 gcry_sexp_release (priv_sexp);
814 return GNUNET_SYSERR;
816 gcry_sexp_release (priv_sexp);
817 gcry_sexp_release (data);
819 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
821 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
824 gcry_sexp_release (sig_sexp);
825 return GNUNET_SYSERR;
827 gcry_sexp_release (sig_sexp);
828 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
829 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
830 gcry_mpi_release (rs[0]);
831 gcry_mpi_release (rs[1]);
837 * Sign a given block.
839 * @param priv private key to use for the signing
840 * @param purpose what to sign (size, purpose)
841 * @param sig where to write the signature
842 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
845 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
846 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
847 struct GNUNET_CRYPTO_EddsaSignature *sig)
849 gcry_sexp_t priv_sexp;
850 gcry_sexp_t sig_sexp;
855 priv_sexp = decode_private_eddsa_key (priv);
856 data = data_to_eddsa_value (purpose);
857 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
859 LOG (GNUNET_ERROR_TYPE_WARNING,
860 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
861 __LINE__, gcry_strerror (rc));
862 gcry_sexp_release (data);
863 gcry_sexp_release (priv_sexp);
864 return GNUNET_SYSERR;
866 gcry_sexp_release (priv_sexp);
867 gcry_sexp_release (data);
869 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
871 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
874 gcry_sexp_release (sig_sexp);
875 return GNUNET_SYSERR;
877 gcry_sexp_release (sig_sexp);
878 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
879 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
880 gcry_mpi_release (rs[0]);
881 gcry_mpi_release (rs[1]);
889 * @param purpose what is the purpose that the signature should have?
890 * @param validate block to validate (size, purpose, data)
891 * @param sig signature that is being validated
892 * @param pub public key of the signer
893 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
896 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
897 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
898 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
899 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
902 gcry_sexp_t sig_sexpr;
903 gcry_sexp_t pub_sexpr;
906 if (purpose != ntohl (validate->purpose))
907 return GNUNET_SYSERR; /* purpose mismatch */
909 /* build s-expression for signature */
910 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
911 "(sig-val(ecdsa(r %b)(s %b)))",
912 (int) sizeof (sig->r), sig->r,
913 (int) sizeof (sig->s), sig->s)))
915 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
916 return GNUNET_SYSERR;
918 data = data_to_ecdsa_value (validate);
919 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
920 "(public-key(ecc(curve " CURVE ")(q %b)))",
921 (int) sizeof (pub->q_y), pub->q_y)))
923 gcry_sexp_release (data);
924 gcry_sexp_release (sig_sexpr);
925 return GNUNET_SYSERR;
927 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
928 gcry_sexp_release (pub_sexpr);
929 gcry_sexp_release (data);
930 gcry_sexp_release (sig_sexpr);
933 LOG (GNUNET_ERROR_TYPE_INFO,
934 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
935 __LINE__, gcry_strerror (rc));
936 return GNUNET_SYSERR;
946 * @param purpose what is the purpose that the signature should have?
947 * @param validate block to validate (size, purpose, data)
948 * @param sig signature that is being validated
949 * @param pub public key of the signer
950 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
953 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
954 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
955 const struct GNUNET_CRYPTO_EddsaSignature *sig,
956 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
959 gcry_sexp_t sig_sexpr;
960 gcry_sexp_t pub_sexpr;
963 if (purpose != ntohl (validate->purpose))
964 return GNUNET_SYSERR; /* purpose mismatch */
966 /* build s-expression for signature */
967 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
968 "(sig-val(eddsa(r %b)(s %b)))",
969 (int)sizeof (sig->r), sig->r,
970 (int)sizeof (sig->s), sig->s)))
972 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
973 return GNUNET_SYSERR;
975 data = data_to_eddsa_value (validate);
976 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
977 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
978 (int)sizeof (pub->q_y), pub->q_y)))
980 gcry_sexp_release (data);
981 gcry_sexp_release (sig_sexpr);
982 return GNUNET_SYSERR;
984 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
985 gcry_sexp_release (pub_sexpr);
986 gcry_sexp_release (data);
987 gcry_sexp_release (sig_sexpr);
990 LOG (GNUNET_ERROR_TYPE_INFO,
991 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
992 __LINE__, gcry_strerror (rc));
993 return GNUNET_SYSERR;
1000 * Derive key material from a public and a private ECDHE key.
1002 * @param priv private key to use for the ECDH (x)
1003 * @param pub public key to use for the ECDH (yG)
1004 * @param key_material where to write the key material (xyG)
1005 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1008 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1009 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1010 struct GNUNET_HashCode *key_material)
1012 gcry_mpi_point_t result;
1016 gcry_sexp_t pub_sexpr;
1017 gcry_mpi_t result_x;
1018 unsigned char xbuf[256 / 8];
1021 /* first, extract the q = dP value from the public key */
1022 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1023 "(public-key(ecc(curve " CURVE ")(q %b)))",
1024 (int)sizeof (pub->q_y), pub->q_y))
1025 return GNUNET_SYSERR;
1026 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1027 gcry_sexp_release (pub_sexpr);
1028 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1030 /* second, extract the d value from our private key */
1031 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1033 /* then call the 'multiply' function, to compute the product */
1034 result = gcry_mpi_point_new (0);
1035 gcry_mpi_ec_mul (result, d, q, ctx);
1036 gcry_mpi_point_release (q);
1037 gcry_mpi_release (d);
1039 /* finally, convert point to string for hashing */
1040 result_x = gcry_mpi_new (256);
1041 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1043 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1044 gcry_mpi_point_release (result);
1045 gcry_ctx_release (ctx);
1046 return GNUNET_SYSERR;
1048 gcry_mpi_point_release (result);
1049 gcry_ctx_release (ctx);
1051 rsize = sizeof (xbuf);
1052 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1053 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1054 as that does not include the sign bit; x should be a 255-bit
1055 value, so with the sign it should fit snugly into the 256-bit
1058 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1060 GNUNET_CRYPTO_hash (xbuf,
1063 gcry_mpi_release (result_x);
1069 * Derive the 'h' value for key derivation, where
1072 * @param pub public key for deriviation
1073 * @param label label for deriviation
1074 * @param context additional context to use for HKDF of 'h';
1075 * typically the name of the subsystem/application
1079 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1081 const char *context)
1084 struct GNUNET_HashCode hc;
1085 static const char *const salt = "key-derivation";
1087 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1088 salt, strlen (salt),
1090 label, strlen (label),
1091 context, strlen (context),
1093 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1094 (unsigned char *) &hc,
1101 * Derive a private key from a given private key and a label.
1102 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1103 * where n is the size of the ECC group and P is the public
1104 * key associated with the private key 'd'.
1106 * @param priv original private key
1107 * @param label label to use for key deriviation
1108 * @param context additional context to use for HKDF of 'h';
1109 * typically the name of the subsystem/application
1110 * @return derived private key
1112 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1113 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1115 const char *context)
1117 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1118 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1125 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1127 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1128 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1130 h = derive_h (&pub, label, context);
1131 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1134 d = gcry_mpi_new (256);
1135 gcry_mpi_mulm (d, h, x, n);
1136 gcry_mpi_release (h);
1137 gcry_mpi_release (x);
1138 gcry_mpi_release (n);
1139 gcry_ctx_release (ctx);
1140 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1141 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1142 gcry_mpi_release (d);
1148 * Derive a public key from a given public key and a label.
1149 * Essentially calculates a public key 'V = H(l,P) * P'.
1151 * @param pub original public key
1152 * @param label label to use for key derivation
1153 * @param context additional context to use for HKDF of 'h';
1154 * typically the name of the subsystem/application
1155 * @param result where to write the derived public key
1158 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1160 const char *context,
1161 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1171 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1173 /* obtain point 'q' from original public key. The provided 'q' is
1174 compressed thus we first store it in the context and then get it
1175 back as a (decompresssed) point. */
1176 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1177 GNUNET_assert (NULL != q_y);
1178 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1179 gcry_mpi_release (q_y);
1180 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1183 /* calculate h_mod_n = h % n */
1184 h = derive_h (pub, label, context);
1185 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1186 h_mod_n = gcry_mpi_new (256);
1187 gcry_mpi_mod (h_mod_n, h, n);
1188 /* calculate v = h_mod_n * q */
1189 v = gcry_mpi_point_new (0);
1190 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1191 gcry_mpi_release (h_mod_n);
1192 gcry_mpi_release (h);
1193 gcry_mpi_release (n);
1194 gcry_mpi_point_release (q);
1196 /* convert point 'v' to public key that we return */
1197 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1198 gcry_mpi_point_release (v);
1199 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1200 GNUNET_assert (q_y);
1201 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1202 sizeof (result->q_y),
1204 gcry_mpi_release (q_y);
1205 gcry_ctx_release (ctx);
1210 * Reverse the sequence of the bytes in @a buffer
1212 * @param[in|out] buffer buffer to invert
1213 * @param length number of bytes in @a buffer
1216 reverse_buffer (unsigned char *buffer,
1222 for (i=0; i < length/2; i++)
1225 buffer[i] = buffer[length-1-i];
1226 buffer[length-1-i] = tmp;
1232 * Convert the secret @a d of an EdDSA key to the
1233 * value that is actually used in the EdDSA computation.
1235 * @param d secret input
1236 * @return value used for the calculation in EdDSA
1239 eddsa_d_to_a (gcry_mpi_t d)
1241 unsigned char rawmpi[32]; /* 256-bit value */
1243 unsigned char digest[64]; /* 512-bit hash value */
1244 gcry_buffer_t hvec[2];
1248 b = 256 / 8; /* number of bytes in `d` */
1250 /* Note that we clear DIGEST so we can use it as input to left pad
1251 the key with zeroes for hashing. */
1252 memset (hvec, 0, sizeof hvec);
1253 rawmpilen = sizeof (rawmpi);
1255 gcry_mpi_print (GCRYMPI_FMT_USG,
1256 rawmpi, rawmpilen, &rawmpilen,
1258 hvec[0].data = digest;
1260 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1261 hvec[1].data = rawmpi;
1263 hvec[1].len = rawmpilen;
1265 gcry_md_hash_buffers (GCRY_MD_SHA512,
1269 /* Compute the A value. */
1270 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1271 digest[0] = (digest[0] & 0x7f) | 0x40;
1274 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1283 * Derive key material from a ECDH public key and a private EdDSA key.
1284 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1286 * @param priv private key from EdDSA to use for the ECDH (x)
1287 * @param pub public key to use for the ECDH (yG)
1288 * @param key_material where to write the key material H(h(x)yG)
1289 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1292 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1293 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1294 struct GNUNET_HashCode *key_material)
1296 gcry_mpi_point_t result;
1301 gcry_sexp_t pub_sexpr;
1302 gcry_mpi_t result_x;
1303 unsigned char xbuf[256 / 8];
1306 /* first, extract the q = dP value from the public key */
1307 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1308 "(public-key(ecc(curve " CURVE ")(q %b)))",
1309 (int)sizeof (pub->q_y), pub->q_y))
1310 return GNUNET_SYSERR;
1311 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1312 gcry_sexp_release (pub_sexpr);
1313 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1315 /* second, extract the d value from our private key */
1316 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1318 /* NOW, because this is EdDSA, HASH 'd' first! */
1319 a = eddsa_d_to_a (d);
1320 gcry_mpi_release (d);
1322 /* then call the 'multiply' function, to compute the product */
1323 result = gcry_mpi_point_new (0);
1324 gcry_mpi_ec_mul (result, a, q, ctx);
1325 gcry_mpi_point_release (q);
1326 gcry_mpi_release (a);
1328 /* finally, convert point to string for hashing */
1329 result_x = gcry_mpi_new (256);
1330 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1332 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1333 gcry_mpi_point_release (result);
1334 gcry_ctx_release (ctx);
1335 return GNUNET_SYSERR;
1337 gcry_mpi_point_release (result);
1338 gcry_ctx_release (ctx);
1340 rsize = sizeof (xbuf);
1341 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1342 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1343 as that does not include the sign bit; x should be a 255-bit
1344 value, so with the sign it should fit snugly into the 256-bit
1347 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1349 GNUNET_CRYPTO_hash (xbuf,
1352 gcry_mpi_release (result_x);
1358 * Derive key material from a ECDH public key and a private ECDSA key.
1359 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1361 * @param priv private key from ECDSA to use for the ECDH (x)
1362 * @param pub public key to use for the ECDH (yG)
1363 * @param key_material where to write the key material H(h(x)yG)
1364 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1367 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1368 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1369 struct GNUNET_HashCode *key_material)
1371 gcry_mpi_point_t result;
1375 gcry_sexp_t pub_sexpr;
1376 gcry_mpi_t result_x;
1377 unsigned char xbuf[256 / 8];
1380 /* first, extract the q = dP value from the public key */
1381 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1382 "(public-key(ecc(curve " CURVE ")(q %b)))",
1383 (int)sizeof (pub->q_y), pub->q_y))
1384 return GNUNET_SYSERR;
1385 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1386 gcry_sexp_release (pub_sexpr);
1387 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1389 /* second, extract the d value from our private key */
1390 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1392 /* then call the 'multiply' function, to compute the product */
1393 result = gcry_mpi_point_new (0);
1394 gcry_mpi_ec_mul (result, d, q, ctx);
1395 gcry_mpi_point_release (q);
1396 gcry_mpi_release (d);
1398 /* finally, convert point to string for hashing */
1399 result_x = gcry_mpi_new (256);
1400 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1402 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1403 gcry_mpi_point_release (result);
1404 gcry_ctx_release (ctx);
1405 return GNUNET_SYSERR;
1407 gcry_mpi_point_release (result);
1408 gcry_ctx_release (ctx);
1410 rsize = sizeof (xbuf);
1411 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1412 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1413 as that does not include the sign bit; x should be a 255-bit
1414 value, so with the sign it should fit snugly into the 256-bit
1417 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1419 GNUNET_CRYPTO_hash (xbuf,
1422 gcry_mpi_release (result_x);
1430 * Derive key material from a EdDSA public key and a private ECDH key.
1431 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1433 * @param priv private key to use for the ECDH (y)
1434 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1435 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1436 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1439 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1440 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1441 struct GNUNET_HashCode *key_material)
1443 gcry_mpi_point_t result;
1447 gcry_sexp_t pub_sexpr;
1448 gcry_mpi_t result_x;
1449 unsigned char xbuf[256 / 8];
1452 /* first, extract the q = dP value from the public key */
1453 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1454 "(public-key(ecc(curve " CURVE ")(q %b)))",
1455 (int)sizeof (pub->q_y), pub->q_y))
1456 return GNUNET_SYSERR;
1457 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1458 gcry_sexp_release (pub_sexpr);
1459 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1461 /* second, extract the d value from our private key */
1462 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1464 /* then call the 'multiply' function, to compute the product */
1465 result = gcry_mpi_point_new (0);
1466 gcry_mpi_ec_mul (result, d, q, ctx);
1467 gcry_mpi_point_release (q);
1468 gcry_mpi_release (d);
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 gcry_mpi_point_release (result);
1476 gcry_ctx_release (ctx);
1477 return GNUNET_SYSERR;
1479 gcry_mpi_point_release (result);
1480 gcry_ctx_release (ctx);
1482 rsize = sizeof (xbuf);
1483 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1484 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1485 as that does not include the sign bit; x should be a 255-bit
1486 value, so with the sign it should fit snugly into the 256-bit
1489 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1491 GNUNET_CRYPTO_hash (xbuf,
1494 gcry_mpi_release (result_x);
1500 * Derive key material from a ECDSA public key and a private ECDH key.
1501 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1503 * @param priv private key to use for the ECDH (y)
1504 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1505 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1506 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1509 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1510 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1511 struct GNUNET_HashCode *key_material)
1513 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1514 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1518 /* end of crypto_ecc.c */