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 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;
492 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
494 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
505 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
507 * @param[out] pk set to fresh private key;
508 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
511 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
513 gcry_sexp_t priv_sexp;
514 gcry_sexp_t s_keyparam;
518 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
519 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
520 disables an expensive key testing routine. We do not want to run
521 the expensive check for ECDHE, as we generate TONS of keys to
522 use for a very short time. */
523 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
524 "(genkey(ecc(curve \"" CURVE "\")"
525 "(flags eddsa no-keytest)))")))
527 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
528 return GNUNET_SYSERR;
530 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
532 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
533 gcry_sexp_release (s_keyparam);
534 return GNUNET_SYSERR;
536 gcry_sexp_release (s_keyparam);
538 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
540 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
541 gcry_sexp_release (priv_sexp);
542 return GNUNET_SYSERR;
545 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
547 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
548 gcry_sexp_release (priv_sexp);
549 return GNUNET_SYSERR;
551 gcry_sexp_release (priv_sexp);
552 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
553 gcry_mpi_release (d);
559 * Create a new private key. Caller must free return value.
561 * @return fresh private key
563 struct GNUNET_CRYPTO_EcdsaPrivateKey *
564 GNUNET_CRYPTO_ecdsa_key_create ()
566 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
567 gcry_sexp_t priv_sexp;
568 gcry_sexp_t s_keyparam;
572 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
573 "(genkey(ecc(curve \"" CURVE "\")"
576 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
579 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
581 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
582 gcry_sexp_release (s_keyparam);
585 gcry_sexp_release (s_keyparam);
587 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
589 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
590 gcry_sexp_release (priv_sexp);
594 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
596 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
597 gcry_sexp_release (priv_sexp);
600 gcry_sexp_release (priv_sexp);
601 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
602 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
603 gcry_mpi_release (d);
608 * Create a new private key. Caller must free return value.
610 * @return fresh private key
612 struct GNUNET_CRYPTO_EddsaPrivateKey *
613 GNUNET_CRYPTO_eddsa_key_create ()
615 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
616 gcry_sexp_t priv_sexp;
617 gcry_sexp_t s_keyparam;
621 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
622 "(genkey(ecc(curve \"" CURVE "\")"
625 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
628 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
630 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
631 gcry_sexp_release (s_keyparam);
634 gcry_sexp_release (s_keyparam);
636 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
638 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
639 gcry_sexp_release (priv_sexp);
643 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
645 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
646 gcry_sexp_release (priv_sexp);
649 gcry_sexp_release (priv_sexp);
650 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
651 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
652 gcry_mpi_release (d);
658 * Get the shared private key we use for anonymous users.
660 * @return "anonymous" private key
662 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
663 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
666 * 'anonymous' pseudonym (global static, d=1, public key = G
669 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
674 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
675 sizeof (anonymous.d),
683 * Compare two Peer Identities.
685 * @param first first peer identity
686 * @param second second peer identity
687 * @return bigger than 0 if first > second,
688 * 0 if they are the same
689 * smaller than 0 if second > first
692 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
693 const struct GNUNET_PeerIdentity *second)
695 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
700 * Convert the data specified in the given purpose argument to an
701 * S-expression suitable for signature operations.
703 * @param purpose data to convert
704 * @return converted s-expression
707 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
709 struct GNUNET_HashCode hc;
713 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
714 if (0 != (rc = gcry_sexp_build (&data, NULL,
715 "(data(flags eddsa)(hash-algo %s)(value %b))",
717 (int)sizeof (hc), &hc)))
719 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
727 * Convert the data specified in the given purpose argument to an
728 * S-expression suitable for signature operations.
730 * @param purpose data to convert
731 * @return converted s-expression
734 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
736 struct GNUNET_HashCode hc;
740 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
741 if (0 != (rc = gcry_sexp_build (&data, NULL,
742 "(data(flags rfc6979)(hash %s %b))",
744 (int)sizeof (hc), &hc)))
746 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
754 * Sign a given block.
756 * @param priv private key to use for the signing
757 * @param purpose what to sign (size, purpose)
758 * @param sig where to write the signature
759 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
762 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
763 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
764 struct GNUNET_CRYPTO_EcdsaSignature *sig)
766 gcry_sexp_t priv_sexp;
767 gcry_sexp_t sig_sexp;
772 priv_sexp = decode_private_ecdsa_key (priv);
773 data = data_to_ecdsa_value (purpose);
774 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
776 LOG (GNUNET_ERROR_TYPE_WARNING,
777 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
778 __LINE__, gcry_strerror (rc));
779 gcry_sexp_release (data);
780 gcry_sexp_release (priv_sexp);
781 return GNUNET_SYSERR;
783 gcry_sexp_release (priv_sexp);
784 gcry_sexp_release (data);
786 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
788 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
791 gcry_sexp_release (sig_sexp);
792 return GNUNET_SYSERR;
794 gcry_sexp_release (sig_sexp);
795 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
796 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
797 gcry_mpi_release (rs[0]);
798 gcry_mpi_release (rs[1]);
804 * Sign a given block.
806 * @param priv private key to use for the signing
807 * @param purpose what to sign (size, purpose)
808 * @param sig where to write the signature
809 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
812 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
813 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
814 struct GNUNET_CRYPTO_EddsaSignature *sig)
816 gcry_sexp_t priv_sexp;
817 gcry_sexp_t sig_sexp;
822 priv_sexp = decode_private_eddsa_key (priv);
823 data = data_to_eddsa_value (purpose);
824 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
826 LOG (GNUNET_ERROR_TYPE_WARNING,
827 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
828 __LINE__, gcry_strerror (rc));
829 gcry_sexp_release (data);
830 gcry_sexp_release (priv_sexp);
831 return GNUNET_SYSERR;
833 gcry_sexp_release (priv_sexp);
834 gcry_sexp_release (data);
836 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
838 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
841 gcry_sexp_release (sig_sexp);
842 return GNUNET_SYSERR;
844 gcry_sexp_release (sig_sexp);
845 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
846 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
847 gcry_mpi_release (rs[0]);
848 gcry_mpi_release (rs[1]);
856 * @param purpose what is the purpose that the signature should have?
857 * @param validate block to validate (size, purpose, data)
858 * @param sig signature that is being validated
859 * @param pub public key of the signer
860 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
863 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
864 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
865 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
866 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
869 gcry_sexp_t sig_sexpr;
870 gcry_sexp_t pub_sexpr;
873 if (purpose != ntohl (validate->purpose))
874 return GNUNET_SYSERR; /* purpose mismatch */
876 /* build s-expression for signature */
877 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
878 "(sig-val(ecdsa(r %b)(s %b)))",
879 (int) sizeof (sig->r), sig->r,
880 (int) sizeof (sig->s), sig->s)))
882 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
883 return GNUNET_SYSERR;
885 data = data_to_ecdsa_value (validate);
886 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
887 "(public-key(ecc(curve " CURVE ")(q %b)))",
888 (int) sizeof (pub->q_y), pub->q_y)))
890 gcry_sexp_release (data);
891 gcry_sexp_release (sig_sexpr);
892 return GNUNET_SYSERR;
894 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
895 gcry_sexp_release (pub_sexpr);
896 gcry_sexp_release (data);
897 gcry_sexp_release (sig_sexpr);
900 LOG (GNUNET_ERROR_TYPE_INFO,
901 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
902 __LINE__, gcry_strerror (rc));
903 return GNUNET_SYSERR;
913 * @param purpose what is the purpose that the signature should have?
914 * @param validate block to validate (size, purpose, data)
915 * @param sig signature that is being validated
916 * @param pub public key of the signer
917 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
920 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
921 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
922 const struct GNUNET_CRYPTO_EddsaSignature *sig,
923 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
926 gcry_sexp_t sig_sexpr;
927 gcry_sexp_t pub_sexpr;
930 if (purpose != ntohl (validate->purpose))
931 return GNUNET_SYSERR; /* purpose mismatch */
933 /* build s-expression for signature */
934 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
935 "(sig-val(eddsa(r %b)(s %b)))",
936 (int)sizeof (sig->r), sig->r,
937 (int)sizeof (sig->s), sig->s)))
939 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
940 return GNUNET_SYSERR;
942 data = data_to_eddsa_value (validate);
943 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
944 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
945 (int)sizeof (pub->q_y), pub->q_y)))
947 gcry_sexp_release (data);
948 gcry_sexp_release (sig_sexpr);
949 return GNUNET_SYSERR;
951 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
952 gcry_sexp_release (pub_sexpr);
953 gcry_sexp_release (data);
954 gcry_sexp_release (sig_sexpr);
957 LOG (GNUNET_ERROR_TYPE_INFO,
958 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
959 __LINE__, gcry_strerror (rc));
960 return GNUNET_SYSERR;
967 * Derive key material from a public and a private ECDHE key.
969 * @param priv private key to use for the ECDH (x)
970 * @param pub public key to use for the ECDH (yG)
971 * @param key_material where to write the key material (xyG)
972 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
975 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
976 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
977 struct GNUNET_HashCode *key_material)
979 gcry_mpi_point_t result;
983 gcry_sexp_t pub_sexpr;
985 unsigned char xbuf[256 / 8];
988 /* first, extract the q = dP value from the public key */
989 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
990 "(public-key(ecc(curve " CURVE ")(q %b)))",
991 (int)sizeof (pub->q_y), pub->q_y))
992 return GNUNET_SYSERR;
993 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
994 gcry_sexp_release (pub_sexpr);
995 q = gcry_mpi_ec_get_point ("q", ctx, 0);
997 /* second, extract the d value from our private key */
998 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1000 /* then call the 'multiply' function, to compute the product */
1001 result = gcry_mpi_point_new (0);
1002 gcry_mpi_ec_mul (result, d, q, ctx);
1003 gcry_mpi_point_release (q);
1004 gcry_mpi_release (d);
1006 /* finally, convert point to string for hashing */
1007 result_x = gcry_mpi_new (256);
1008 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1010 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1011 gcry_mpi_point_release (result);
1012 gcry_ctx_release (ctx);
1013 return GNUNET_SYSERR;
1015 gcry_mpi_point_release (result);
1016 gcry_ctx_release (ctx);
1018 rsize = sizeof (xbuf);
1019 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1020 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1021 as that does not include the sign bit; x should be a 255-bit
1022 value, so with the sign it should fit snugly into the 256-bit
1025 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1027 GNUNET_CRYPTO_hash (xbuf,
1030 gcry_mpi_release (result_x);
1036 * Derive the 'h' value for key derivation, where
1039 * @param pub public key for deriviation
1040 * @param label label for deriviation
1041 * @param context additional context to use for HKDF of 'h';
1042 * typically the name of the subsystem/application
1046 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1048 const char *context)
1051 struct GNUNET_HashCode hc;
1052 static const char *const salt = "key-derivation";
1054 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1055 salt, strlen (salt),
1057 label, strlen (label),
1058 context, strlen (context),
1060 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1061 (unsigned char *) &hc,
1068 * Derive a private key from a given private key and a label.
1069 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1070 * where n is the size of the ECC group and P is the public
1071 * key associated with the private key 'd'.
1073 * @param priv original private key
1074 * @param label label to use for key deriviation
1075 * @param context additional context to use for HKDF of 'h';
1076 * typically the name of the subsystem/application
1077 * @return derived private key
1079 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1080 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1082 const char *context)
1084 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1085 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1092 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1094 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1095 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1097 h = derive_h (&pub, label, context);
1098 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1101 d = gcry_mpi_new (256);
1102 gcry_mpi_mulm (d, h, x, n);
1103 gcry_mpi_release (h);
1104 gcry_mpi_release (x);
1105 gcry_mpi_release (n);
1106 gcry_ctx_release (ctx);
1107 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1108 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1109 gcry_mpi_release (d);
1115 * Derive a public key from a given public key and a label.
1116 * Essentially calculates a public key 'V = H(l,P) * P'.
1118 * @param pub original public key
1119 * @param label label to use for key derivation
1120 * @param context additional context to use for HKDF of 'h';
1121 * typically the name of the subsystem/application
1122 * @param result where to write the derived public key
1125 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1127 const char *context,
1128 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1138 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1140 /* obtain point 'q' from original public key. The provided 'q' is
1141 compressed thus we first store it in the context and then get it
1142 back as a (decompresssed) point. */
1143 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1144 GNUNET_assert (NULL != q_y);
1145 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1146 gcry_mpi_release (q_y);
1147 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1150 /* calculate h_mod_n = h % n */
1151 h = derive_h (pub, label, context);
1152 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1153 h_mod_n = gcry_mpi_new (256);
1154 gcry_mpi_mod (h_mod_n, h, n);
1155 /* calculate v = h_mod_n * q */
1156 v = gcry_mpi_point_new (0);
1157 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1158 gcry_mpi_release (h_mod_n);
1159 gcry_mpi_release (h);
1160 gcry_mpi_release (n);
1161 gcry_mpi_point_release (q);
1163 /* convert point 'v' to public key that we return */
1164 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1165 gcry_mpi_point_release (v);
1166 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1167 GNUNET_assert (q_y);
1168 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1169 sizeof (result->q_y),
1171 gcry_mpi_release (q_y);
1172 gcry_ctx_release (ctx);
1177 * Reverse the sequence of the bytes in @a buffer
1179 * @param[in|out] buffer buffer to invert
1180 * @param length number of bytes in @a buffer
1183 reverse_buffer (unsigned char *buffer,
1189 for (i=0; i < length/2; i++)
1192 buffer[i] = buffer[length-1-i];
1193 buffer[length-1-i] = tmp;
1199 * Convert the secret @a d of an EdDSA key to the
1200 * value that is actually used in the EdDSA computation.
1202 * @param d secret input
1203 * @return value used for the calculation in EdDSA
1206 eddsa_d_to_a (gcry_mpi_t d)
1208 unsigned char rawmpi[32]; /* 256-bit value */
1210 unsigned char digest[64]; /* 512-bit hash value */
1211 gcry_buffer_t hvec[2];
1215 b = 256 / 8; /* number of bytes in `d` */
1217 /* Note that we clear DIGEST so we can use it as input to left pad
1218 the key with zeroes for hashing. */
1219 memset (hvec, 0, sizeof hvec);
1220 rawmpilen = sizeof (rawmpi);
1222 gcry_mpi_print (GCRYMPI_FMT_USG,
1223 rawmpi, rawmpilen, &rawmpilen,
1225 hvec[0].data = digest;
1227 hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
1228 hvec[1].data = rawmpi;
1230 hvec[1].len = rawmpilen;
1232 gcry_md_hash_buffers (GCRY_MD_SHA512,
1236 /* Compute the A value. */
1237 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1238 digest[0] = (digest[0] & 0x7f) | 0x40;
1241 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1250 * Derive key material from a ECDH public key and a private EdDSA key.
1251 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1253 * @param priv private key from EdDSA to use for the ECDH (x)
1254 * @param pub public key to use for the ECDH (yG)
1255 * @param key_material where to write the key material H(h(x)yG)
1256 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1259 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1260 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1261 struct GNUNET_HashCode *key_material)
1263 gcry_mpi_point_t result;
1268 gcry_sexp_t pub_sexpr;
1269 gcry_mpi_t result_x;
1270 unsigned char xbuf[256 / 8];
1273 /* first, extract the q = dP value from the public key */
1274 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1275 "(public-key(ecc(curve " CURVE ")(q %b)))",
1276 (int)sizeof (pub->q_y), pub->q_y))
1277 return GNUNET_SYSERR;
1278 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1279 gcry_sexp_release (pub_sexpr);
1280 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1282 /* second, extract the d value from our private key */
1283 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1285 /* NOW, because this is EdDSA, HASH 'd' first! */
1286 a = eddsa_d_to_a (d);
1287 gcry_mpi_release (d);
1289 /* then call the 'multiply' function, to compute the product */
1290 result = gcry_mpi_point_new (0);
1291 gcry_mpi_ec_mul (result, a, q, ctx);
1292 gcry_mpi_point_release (q);
1293 gcry_mpi_release (a);
1295 /* finally, convert point to string for hashing */
1296 result_x = gcry_mpi_new (256);
1297 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1299 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1300 gcry_mpi_point_release (result);
1301 gcry_ctx_release (ctx);
1302 return GNUNET_SYSERR;
1304 gcry_mpi_point_release (result);
1305 gcry_ctx_release (ctx);
1307 rsize = sizeof (xbuf);
1308 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1309 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1310 as that does not include the sign bit; x should be a 255-bit
1311 value, so with the sign it should fit snugly into the 256-bit
1314 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1316 GNUNET_CRYPTO_hash (xbuf,
1319 gcry_mpi_release (result_x);
1325 * Derive key material from a ECDH public key and a private ECDSA key.
1326 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1328 * @param priv private key from ECDSA to use for the ECDH (x)
1329 * @param pub public key to use for the ECDH (yG)
1330 * @param key_material where to write the key material H(h(x)yG)
1331 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1334 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1335 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1336 struct GNUNET_HashCode *key_material)
1338 gcry_mpi_point_t result;
1342 gcry_sexp_t pub_sexpr;
1343 gcry_mpi_t result_x;
1344 unsigned char xbuf[256 / 8];
1347 /* first, extract the q = dP value from the public key */
1348 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1349 "(public-key(ecc(curve " CURVE ")(q %b)))",
1350 (int)sizeof (pub->q_y), pub->q_y))
1351 return GNUNET_SYSERR;
1352 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1353 gcry_sexp_release (pub_sexpr);
1354 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1356 /* second, extract the d value from our private key */
1357 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1359 /* then call the 'multiply' function, to compute the product */
1360 result = gcry_mpi_point_new (0);
1361 gcry_mpi_ec_mul (result, d, q, ctx);
1362 gcry_mpi_point_release (q);
1363 gcry_mpi_release (d);
1365 /* finally, convert point to string for hashing */
1366 result_x = gcry_mpi_new (256);
1367 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1369 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1370 gcry_mpi_point_release (result);
1371 gcry_ctx_release (ctx);
1372 return GNUNET_SYSERR;
1374 gcry_mpi_point_release (result);
1375 gcry_ctx_release (ctx);
1377 rsize = sizeof (xbuf);
1378 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1379 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1380 as that does not include the sign bit; x should be a 255-bit
1381 value, so with the sign it should fit snugly into the 256-bit
1384 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1386 GNUNET_CRYPTO_hash (xbuf,
1389 gcry_mpi_release (result_x);
1397 * Derive key material from a EdDSA public key and a private ECDH key.
1398 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1400 * @param priv private key to use for the ECDH (y)
1401 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1402 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1403 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1406 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1407 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1408 struct GNUNET_HashCode *key_material)
1410 gcry_mpi_point_t result;
1414 gcry_sexp_t pub_sexpr;
1415 gcry_mpi_t result_x;
1416 unsigned char xbuf[256 / 8];
1419 /* first, extract the q = dP value from the public key */
1420 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1421 "(public-key(ecc(curve " CURVE ")(q %b)))",
1422 (int)sizeof (pub->q_y), pub->q_y))
1423 return GNUNET_SYSERR;
1424 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1425 gcry_sexp_release (pub_sexpr);
1426 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1428 /* second, extract the d value from our private key */
1429 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1431 /* then call the 'multiply' function, to compute the product */
1432 result = gcry_mpi_point_new (0);
1433 gcry_mpi_ec_mul (result, d, q, ctx);
1434 gcry_mpi_point_release (q);
1435 gcry_mpi_release (d);
1437 /* finally, convert point to string for hashing */
1438 result_x = gcry_mpi_new (256);
1439 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1441 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1442 gcry_mpi_point_release (result);
1443 gcry_ctx_release (ctx);
1444 return GNUNET_SYSERR;
1446 gcry_mpi_point_release (result);
1447 gcry_ctx_release (ctx);
1449 rsize = sizeof (xbuf);
1450 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1451 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1452 as that does not include the sign bit; x should be a 255-bit
1453 value, so with the sign it should fit snugly into the 256-bit
1456 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1458 GNUNET_CRYPTO_hash (xbuf,
1461 gcry_mpi_release (result_x);
1467 * Derive key material from a ECDSA public key and a private ECDH key.
1468 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1470 * @param priv private key to use for the ECDH (y)
1471 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1472 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1473 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1476 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1477 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1478 struct GNUNET_HashCode *key_material)
1480 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1481 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1485 /* end of crypto_ecc.c */