2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2015 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file util/crypto_ecc.c
23 * @brief public key cryptography (ECC) with libgcrypt
24 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
30 #define EXTRA_CHECKS 0
33 * Name of the curve we are using. Note that we have hard-coded
34 * structs that use 256 bits, so using a bigger curve will require
35 * changes that break stuff badly. The name of the curve given here
36 * must be agreed by all peers and be supported by libgcrypt.
38 #define CURVE "Ed25519"
40 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
42 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
44 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
47 * Log an error message at log-level 'level' that indicates
48 * a failure of the command 'cmd' with the message given
49 * by gcry_strerror(rc).
51 #define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
55 * Extract values from an S-expression.
57 * @param array where to store the result(s)
58 * @param sexp S-expression to parse
59 * @param topname top-level name in the S-expression that is of interest
60 * @param elems names of the elements to extract
61 * @return 0 on success
64 key_from_sexp (gcry_mpi_t * array,
75 list = gcry_sexp_find_token (sexp, topname, 0);
78 l2 = gcry_sexp_cadr (list);
79 gcry_sexp_release (list);
85 for (s = elems; *s; s++, idx++)
87 l2 = gcry_sexp_find_token (list, s, 1);
90 for (i = 0; i < idx; i++)
95 gcry_sexp_release (list);
96 return 3; /* required parameter not found */
98 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
99 gcry_sexp_release (l2);
102 for (i = 0; i < idx; i++)
104 gcry_free (array[i]);
107 gcry_sexp_release (list);
108 return 4; /* required parameter is invalid */
111 gcry_sexp_release (list);
117 * Convert the given private key from the network format to the
118 * S-expression that can be used by libgcrypt.
120 * @param priv private key to decode
121 * @return NULL on error
124 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
129 rc = gcry_sexp_build (&result, NULL,
130 "(private-key(ecc(curve \"" CURVE "\")"
132 (int)sizeof (priv->d), priv->d);
135 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
139 if (0 != (rc = gcry_pk_testkey (result)))
141 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
150 * Convert the given private key from the network format to the
151 * S-expression that can be used by libgcrypt.
153 * @param priv private key to decode
154 * @return NULL on error
157 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
162 rc = gcry_sexp_build (&result, NULL,
163 "(private-key(ecc(curve \"" CURVE "\")"
164 "(flags eddsa)(d %b)))",
165 (int)sizeof (priv->d), priv->d);
168 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
172 if (0 != (rc = gcry_pk_testkey (result)))
174 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
183 * Convert the given private key from the network format to the
184 * S-expression that can be used by libgcrypt.
186 * @param priv private key to decode
187 * @return NULL on error
190 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
195 rc = gcry_sexp_build (&result, NULL,
196 "(private-key(ecc(curve \"" CURVE "\")"
198 (int)sizeof (priv->d), priv->d);
201 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
205 if (0 != (rc = gcry_pk_testkey (result)))
207 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
216 * Extract the public key for the given private key.
218 * @param priv the private key
219 * @param pub where to write the public key
222 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
223 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
229 sexp = decode_private_ecdsa_key (priv);
230 GNUNET_assert (NULL != sexp);
231 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
232 gcry_sexp_release (sexp);
233 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
234 GNUNET_assert (NULL != q);
235 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
236 gcry_mpi_release (q);
237 gcry_ctx_release (ctx);
242 * Extract the public key for the given private key.
244 * @param priv the private key
245 * @param pub where to write the public key
248 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
249 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
255 sexp = decode_private_eddsa_key (priv);
256 GNUNET_assert (NULL != sexp);
257 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
258 gcry_sexp_release (sexp);
259 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
261 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
262 gcry_mpi_release (q);
263 gcry_ctx_release (ctx);
268 * Extract the public key for the given private key.
270 * @param priv the private key
271 * @param pub where to write the public key
274 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
275 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
281 sexp = decode_private_ecdhe_key (priv);
282 GNUNET_assert (NULL != sexp);
283 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
284 gcry_sexp_release (sexp);
285 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
287 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
288 gcry_mpi_release (q);
289 gcry_ctx_release (ctx);
294 * Convert a public key to a string.
296 * @param pub key to convert
297 * @return string representing @a pub
300 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
303 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
307 keylen += 5 - keylen % 5;
309 pubkeybuf = GNUNET_malloc (keylen + 1);
310 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
311 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
316 GNUNET_free (pubkeybuf);
325 * Convert a public key to a string.
327 * @param pub key to convert
328 * @return string representing @a pub
331 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
334 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
338 keylen += 5 - keylen % 5;
340 pubkeybuf = GNUNET_malloc (keylen + 1);
341 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
342 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
347 GNUNET_free (pubkeybuf);
356 * Convert a string representing a public key to a public key.
358 * @param enc encoded public key
359 * @param enclen number of bytes in @a enc (without 0-terminator)
360 * @param pub where to store the public key
361 * @return #GNUNET_OK on success
364 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
366 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
368 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
371 keylen += 5 - keylen % 5;
373 if (enclen != keylen)
374 return GNUNET_SYSERR;
376 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
378 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
379 return GNUNET_SYSERR;
385 * Convert a string representing a public key to a public key.
387 * @param enc encoded public key
388 * @param enclen number of bytes in @a enc (without 0-terminator)
389 * @param pub where to store the public key
390 * @return #GNUNET_OK on success
393 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
395 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
397 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
400 keylen += 5 - keylen % 5;
402 if (enclen != keylen)
403 return GNUNET_SYSERR;
405 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
407 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
408 return GNUNET_SYSERR;
414 * Convert a string representing a private key to a private key.
416 * @param enc encoded public key
417 * @param enclen number of bytes in @a enc (without 0-terminator)
418 * @param priv where to store the private key
419 * @return #GNUNET_OK on success
422 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
424 struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
426 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
429 keylen += 5 - keylen % 5;
431 if (enclen != keylen)
432 return GNUNET_SYSERR;
434 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
436 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
437 return GNUNET_SYSERR;
444 * Clear memory that was used to store a private key.
446 * @param pk location of the key
449 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
451 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
457 * Clear memory that was used to store a private key.
459 * @param pk location of the key
462 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
464 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
470 * Clear memory that was used to store a private key.
472 * @param pk location of the key
475 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
477 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
482 * Create a new private key. Caller must free return value.
484 * @return fresh private key
486 struct GNUNET_CRYPTO_EcdhePrivateKey *
487 GNUNET_CRYPTO_ecdhe_key_create ()
489 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
490 gcry_sexp_t priv_sexp;
491 gcry_sexp_t s_keyparam;
495 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
496 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
497 disables an expensive key testing routine. We do not want to run
498 the expensive check for ECDHE, as we generate TONS of keys to
499 use for a very short time. */
500 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
501 "(genkey(ecc(curve \"" CURVE "\")"
502 "(flags eddsa no-keytest)))")))
504 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
507 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
509 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
510 gcry_sexp_release (s_keyparam);
513 gcry_sexp_release (s_keyparam);
515 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
517 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
518 gcry_sexp_release (priv_sexp);
522 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
524 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
525 gcry_sexp_release (priv_sexp);
528 gcry_sexp_release (priv_sexp);
529 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
530 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
531 gcry_mpi_release (d);
537 * Create a new private key. Caller must free return value.
539 * @return fresh private key
541 struct GNUNET_CRYPTO_EcdsaPrivateKey *
542 GNUNET_CRYPTO_ecdsa_key_create ()
544 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
545 gcry_sexp_t priv_sexp;
546 gcry_sexp_t s_keyparam;
550 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
551 "(genkey(ecc(curve \"" CURVE "\")"
554 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
557 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
559 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
560 gcry_sexp_release (s_keyparam);
563 gcry_sexp_release (s_keyparam);
565 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
567 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
568 gcry_sexp_release (priv_sexp);
572 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
574 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
575 gcry_sexp_release (priv_sexp);
578 gcry_sexp_release (priv_sexp);
579 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
580 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
581 gcry_mpi_release (d);
586 * Create a new private key. Caller must free return value.
588 * @return fresh private key
590 struct GNUNET_CRYPTO_EddsaPrivateKey *
591 GNUNET_CRYPTO_eddsa_key_create ()
593 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
594 gcry_sexp_t priv_sexp;
595 gcry_sexp_t s_keyparam;
599 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
600 "(genkey(ecc(curve \"" CURVE "\")"
603 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
606 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
608 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
609 gcry_sexp_release (s_keyparam);
612 gcry_sexp_release (s_keyparam);
614 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
616 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
617 gcry_sexp_release (priv_sexp);
621 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
623 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
624 gcry_sexp_release (priv_sexp);
627 gcry_sexp_release (priv_sexp);
628 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
629 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
630 gcry_mpi_release (d);
636 * Get the shared private key we use for anonymous users.
638 * @return "anonymous" private key
640 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
641 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
644 * 'anonymous' pseudonym (global static, d=1, public key = G
647 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
652 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
653 sizeof (anonymous.d),
661 * Compare two Peer Identities.
663 * @param first first peer identity
664 * @param second second peer identity
665 * @return bigger than 0 if first > second,
666 * 0 if they are the same
667 * smaller than 0 if second > first
670 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
671 const struct GNUNET_PeerIdentity *second)
673 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
678 * Convert the data specified in the given purpose argument to an
679 * S-expression suitable for signature operations.
681 * @param purpose data to convert
682 * @return converted s-expression
685 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
687 struct GNUNET_HashCode hc;
691 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
692 if (0 != (rc = gcry_sexp_build (&data, NULL,
693 "(data(flags eddsa)(hash-algo %s)(value %b))",
695 (int)sizeof (hc), &hc)))
697 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
705 * Convert the data specified in the given purpose argument to an
706 * S-expression suitable for signature operations.
708 * @param purpose data to convert
709 * @return converted s-expression
712 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
714 struct GNUNET_HashCode hc;
718 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
719 if (0 != (rc = gcry_sexp_build (&data, NULL,
720 "(data(flags rfc6979)(hash %s %b))",
722 (int)sizeof (hc), &hc)))
724 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
732 * Sign a given block.
734 * @param priv private key to use for the signing
735 * @param purpose what to sign (size, purpose)
736 * @param sig where to write the signature
737 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
740 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
741 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
742 struct GNUNET_CRYPTO_EcdsaSignature *sig)
744 gcry_sexp_t priv_sexp;
745 gcry_sexp_t sig_sexp;
750 priv_sexp = decode_private_ecdsa_key (priv);
751 data = data_to_ecdsa_value (purpose);
752 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
754 LOG (GNUNET_ERROR_TYPE_WARNING,
755 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
756 __LINE__, gcry_strerror (rc));
757 gcry_sexp_release (data);
758 gcry_sexp_release (priv_sexp);
759 return GNUNET_SYSERR;
761 gcry_sexp_release (priv_sexp);
762 gcry_sexp_release (data);
764 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
766 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
769 gcry_sexp_release (sig_sexp);
770 return GNUNET_SYSERR;
772 gcry_sexp_release (sig_sexp);
773 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
774 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
775 gcry_mpi_release (rs[0]);
776 gcry_mpi_release (rs[1]);
782 * Sign a given block.
784 * @param priv private key to use for the signing
785 * @param purpose what to sign (size, purpose)
786 * @param sig where to write the signature
787 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
790 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
791 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
792 struct GNUNET_CRYPTO_EddsaSignature *sig)
794 gcry_sexp_t priv_sexp;
795 gcry_sexp_t sig_sexp;
800 priv_sexp = decode_private_eddsa_key (priv);
801 data = data_to_eddsa_value (purpose);
802 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
804 LOG (GNUNET_ERROR_TYPE_WARNING,
805 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
806 __LINE__, gcry_strerror (rc));
807 gcry_sexp_release (data);
808 gcry_sexp_release (priv_sexp);
809 return GNUNET_SYSERR;
811 gcry_sexp_release (priv_sexp);
812 gcry_sexp_release (data);
814 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
816 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
819 gcry_sexp_release (sig_sexp);
820 return GNUNET_SYSERR;
822 gcry_sexp_release (sig_sexp);
823 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
824 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
825 gcry_mpi_release (rs[0]);
826 gcry_mpi_release (rs[1]);
834 * @param purpose what is the purpose that the signature should have?
835 * @param validate block to validate (size, purpose, data)
836 * @param sig signature that is being validated
837 * @param pub public key of the signer
838 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
841 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
842 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
843 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
844 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
847 gcry_sexp_t sig_sexpr;
848 gcry_sexp_t pub_sexpr;
851 if (purpose != ntohl (validate->purpose))
852 return GNUNET_SYSERR; /* purpose mismatch */
854 /* build s-expression for signature */
855 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
856 "(sig-val(ecdsa(r %b)(s %b)))",
857 (int)sizeof (sig->r), sig->r,
858 (int)sizeof (sig->s), sig->s)))
860 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
861 return GNUNET_SYSERR;
863 data = data_to_ecdsa_value (validate);
864 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
865 "(public-key(ecc(curve " CURVE ")(q %b)))",
866 (int)sizeof (pub->q_y), pub->q_y)))
868 gcry_sexp_release (data);
869 gcry_sexp_release (sig_sexpr);
870 return GNUNET_SYSERR;
872 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
873 gcry_sexp_release (pub_sexpr);
874 gcry_sexp_release (data);
875 gcry_sexp_release (sig_sexpr);
878 LOG (GNUNET_ERROR_TYPE_INFO,
879 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
880 __LINE__, gcry_strerror (rc));
881 return GNUNET_SYSERR;
891 * @param purpose what is the purpose that the signature should have?
892 * @param validate block to validate (size, purpose, data)
893 * @param sig signature that is being validated
894 * @param pub public key of the signer
895 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
898 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
899 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
900 const struct GNUNET_CRYPTO_EddsaSignature *sig,
901 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
904 gcry_sexp_t sig_sexpr;
905 gcry_sexp_t pub_sexpr;
908 if (purpose != ntohl (validate->purpose))
909 return GNUNET_SYSERR; /* purpose mismatch */
911 /* build s-expression for signature */
912 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
913 "(sig-val(eddsa(r %b)(s %b)))",
914 (int)sizeof (sig->r), sig->r,
915 (int)sizeof (sig->s), sig->s)))
917 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
918 return GNUNET_SYSERR;
920 data = data_to_eddsa_value (validate);
921 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
922 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
923 (int)sizeof (pub->q_y), pub->q_y)))
925 gcry_sexp_release (data);
926 gcry_sexp_release (sig_sexpr);
927 return GNUNET_SYSERR;
929 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
930 gcry_sexp_release (pub_sexpr);
931 gcry_sexp_release (data);
932 gcry_sexp_release (sig_sexpr);
935 LOG (GNUNET_ERROR_TYPE_INFO,
936 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
937 __LINE__, gcry_strerror (rc));
938 return GNUNET_SYSERR;
945 * Derive key material from a public and a private ECDHE key.
947 * @param priv private key to use for the ECDH (x)
948 * @param pub public key to use for the ECDH (yG)
949 * @param key_material where to write the key material (xyG)
950 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
953 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
954 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
955 struct GNUNET_HashCode *key_material)
957 gcry_mpi_point_t result;
961 gcry_sexp_t pub_sexpr;
963 unsigned char xbuf[256 / 8];
966 /* first, extract the q = dP value from the public key */
967 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
968 "(public-key(ecc(curve " CURVE ")(q %b)))",
969 (int)sizeof (pub->q_y), pub->q_y))
970 return GNUNET_SYSERR;
971 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
972 gcry_sexp_release (pub_sexpr);
973 q = gcry_mpi_ec_get_point ("q", ctx, 0);
975 /* second, extract the d value from our private key */
976 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
978 /* then call the 'multiply' function, to compute the product */
979 result = gcry_mpi_point_new (0);
980 gcry_mpi_ec_mul (result, d, q, ctx);
981 gcry_mpi_point_release (q);
982 gcry_mpi_release (d);
984 /* finally, convert point to string for hashing */
985 result_x = gcry_mpi_new (256);
986 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
988 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
989 gcry_mpi_point_release (result);
990 gcry_ctx_release (ctx);
991 return GNUNET_SYSERR;
993 gcry_mpi_point_release (result);
994 gcry_ctx_release (ctx);
996 rsize = sizeof (xbuf);
997 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
998 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
999 as that does not include the sign bit; x should be a 255-bit
1000 value, so with the sign it should fit snugly into the 256-bit
1003 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1005 GNUNET_CRYPTO_hash (xbuf,
1008 gcry_mpi_release (result_x);
1014 * Derive the 'h' value for key derivation, where
1017 * @param pub public key for deriviation
1018 * @param label label for deriviation
1019 * @param context additional context to use for HKDF of 'h';
1020 * typically the name of the subsystem/application
1024 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1026 const char *context)
1029 struct GNUNET_HashCode hc;
1031 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1032 "key-derivation", strlen ("key-derivation"),
1034 label, strlen (label),
1035 context, strlen (context),
1037 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1038 (unsigned char *) &hc,
1045 * Derive a private key from a given private key and a label.
1046 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1047 * where n is the size of the ECC group and P is the public
1048 * key associated with the private key 'd'.
1050 * @param priv original private key
1051 * @param label label to use for key deriviation
1052 * @param context additional context to use for HKDF of 'h';
1053 * typically the name of the subsystem/application
1054 * @return derived private key
1056 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1057 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1059 const char *context)
1061 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1062 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1069 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1071 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1072 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1074 h = derive_h (&pub, label, context);
1075 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1078 d = gcry_mpi_new (256);
1079 gcry_mpi_mulm (d, h, x, n);
1080 gcry_mpi_release (h);
1081 gcry_mpi_release (x);
1082 gcry_mpi_release (n);
1083 gcry_ctx_release (ctx);
1084 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1085 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1086 gcry_mpi_release (d);
1092 * Derive a public key from a given public key and a label.
1093 * Essentially calculates a public key 'V = H(l,P) * P'.
1095 * @param pub original public key
1096 * @param label label to use for key derivation
1097 * @param context additional context to use for HKDF of 'h';
1098 * typically the name of the subsystem/application
1099 * @param result where to write the derived public key
1102 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1104 const char *context,
1105 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1115 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1117 /* obtain point 'q' from original public key. The provided 'q' is
1118 compressed thus we first store it in the context and then get it
1119 back as a (decompresssed) point. */
1120 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1121 GNUNET_assert (NULL != q_y);
1122 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1123 gcry_mpi_release (q_y);
1124 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1127 /* calculate h_mod_n = h % n */
1128 h = derive_h (pub, label, context);
1129 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1130 h_mod_n = gcry_mpi_new (256);
1131 gcry_mpi_mod (h_mod_n, h, n);
1132 /* calculate v = h_mod_n * q */
1133 v = gcry_mpi_point_new (0);
1134 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1135 gcry_mpi_release (h_mod_n);
1136 gcry_mpi_release (h);
1137 gcry_mpi_release (n);
1138 gcry_mpi_point_release (q);
1140 /* convert point 'v' to public key that we return */
1141 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1142 gcry_mpi_point_release (v);
1143 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1144 GNUNET_assert (q_y);
1145 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1146 sizeof (result->q_y),
1148 gcry_mpi_release (q_y);
1149 gcry_ctx_release (ctx);
1154 * Reverse the sequence of the bytes in @a buffer
1156 * @param[in|out] buffer buffer to invert
1157 * @param length number of bytes in @a buffer
1160 reverse_buffer (unsigned char *buffer,
1166 for (i=0; i < length/2; i++)
1169 buffer[i] = buffer[length-1-i];
1170 buffer[length-1-i] = tmp;
1176 * Convert the secret @a d of an EdDSA key to the
1177 * value that is actually used in the EdDSA computation.
1179 * @param d secret input
1180 * @return value used for the calculation in EdDSA
1183 eddsa_d_to_a (gcry_mpi_t d)
1185 unsigned char rawmpi[32]; /* 256-bit value */
1187 unsigned char digest[64]; /* 512-bit hash value */
1188 gcry_buffer_t hvec[2];
1192 b = 256 / 8; /* number of bytes in `d` */
1194 /* Note that we clear DIGEST so we can use it as input to left pad
1195 the key with zeroes for hashing. */
1196 memset (hvec, 0, sizeof hvec);
1197 rawmpilen = sizeof (rawmpi);
1199 gcry_mpi_print (GCRYMPI_FMT_USG,
1200 rawmpi, rawmpilen, &rawmpilen,
1202 hvec[0].data = digest;
1204 hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
1205 hvec[1].data = rawmpi;
1207 hvec[1].len = rawmpilen;
1209 gcry_md_hash_buffers (GCRY_MD_SHA512,
1213 /* Compute the A value. */
1214 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1215 digest[0] = (digest[0] & 0x7f) | 0x40;
1218 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1227 * Derive key material from a ECDH public key and a private EdDSA key.
1228 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1230 * @param priv private key from EdDSA to use for the ECDH (x)
1231 * @param pub public key to use for the ECDH (yG)
1232 * @param key_material where to write the key material H(h(x)yG)
1233 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1236 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1237 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1238 struct GNUNET_HashCode *key_material)
1240 gcry_mpi_point_t result;
1245 gcry_sexp_t pub_sexpr;
1246 gcry_mpi_t result_x;
1247 unsigned char xbuf[256 / 8];
1250 /* first, extract the q = dP value from the public key */
1251 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1252 "(public-key(ecc(curve " CURVE ")(q %b)))",
1253 (int)sizeof (pub->q_y), pub->q_y))
1254 return GNUNET_SYSERR;
1255 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1256 gcry_sexp_release (pub_sexpr);
1257 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1259 /* second, extract the d value from our private key */
1260 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1262 /* NOW, because this is EdDSA, HASH 'd' first! */
1263 a = eddsa_d_to_a (d);
1264 gcry_mpi_release (d);
1266 /* then call the 'multiply' function, to compute the product */
1267 result = gcry_mpi_point_new (0);
1268 gcry_mpi_ec_mul (result, a, q, ctx);
1269 gcry_mpi_point_release (q);
1270 gcry_mpi_release (a);
1272 /* finally, convert point to string for hashing */
1273 result_x = gcry_mpi_new (256);
1274 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1276 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1277 gcry_mpi_point_release (result);
1278 gcry_ctx_release (ctx);
1279 return GNUNET_SYSERR;
1281 gcry_mpi_point_release (result);
1282 gcry_ctx_release (ctx);
1284 rsize = sizeof (xbuf);
1285 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1286 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1287 as that does not include the sign bit; x should be a 255-bit
1288 value, so with the sign it should fit snugly into the 256-bit
1291 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1293 GNUNET_CRYPTO_hash (xbuf,
1296 gcry_mpi_release (result_x);
1303 * Derive key material from a EdDSA public key and a private ECDH key.
1304 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1306 * @param priv private key to use for the ECDH (y)
1307 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1308 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1309 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1312 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1313 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1314 struct GNUNET_HashCode *key_material)
1316 gcry_mpi_point_t result;
1320 gcry_sexp_t pub_sexpr;
1321 gcry_mpi_t result_x;
1322 unsigned char xbuf[256 / 8];
1325 /* first, extract the q = dP value from the public key */
1326 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1327 "(public-key(ecc(curve " CURVE ")(q %b)))",
1328 (int)sizeof (pub->q_y), pub->q_y))
1329 return GNUNET_SYSERR;
1330 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1331 gcry_sexp_release (pub_sexpr);
1332 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1334 /* second, extract the d value from our private key */
1335 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1337 /* then call the 'multiply' function, to compute the product */
1338 result = gcry_mpi_point_new (0);
1339 gcry_mpi_ec_mul (result, d, q, ctx);
1340 gcry_mpi_point_release (q);
1341 gcry_mpi_release (d);
1343 /* finally, convert point to string for hashing */
1344 result_x = gcry_mpi_new (256);
1345 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1347 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1348 gcry_mpi_point_release (result);
1349 gcry_ctx_release (ctx);
1350 return GNUNET_SYSERR;
1352 gcry_mpi_point_release (result);
1353 gcry_ctx_release (ctx);
1355 rsize = sizeof (xbuf);
1356 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1357 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1358 as that does not include the sign bit; x should be a 255-bit
1359 value, so with the sign it should fit snugly into the 256-bit
1362 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1364 GNUNET_CRYPTO_hash (xbuf,
1367 gcry_mpi_release (result_x);
1373 /* end of crypto_ecc.c */