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 it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
17 * @file util/crypto_ecc.c
18 * @brief public key cryptography (ECC) with libgcrypt
19 * @author Christian Grothoff
23 #include "gnunet_crypto_lib.h"
24 #include "gnunet_strings_lib.h"
26 #define EXTRA_CHECKS 0
29 * Name of the curve we are using. Note that we have hard-coded
30 * structs that use 256 bits, so using a bigger curve will require
31 * changes that break stuff badly. The name of the curve given here
32 * must be agreed by all peers and be supported by libgcrypt.
34 #define CURVE "Ed25519"
36 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
38 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
40 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
43 * Log an error message at log-level 'level' that indicates
44 * a failure of the command 'cmd' with the message given
45 * by gcry_strerror(rc).
47 #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)
50 #include "crypto_bug.c"
54 * Extract values from an S-expression.
56 * @param array where to store the result(s)
57 * @param sexp S-expression to parse
58 * @param topname top-level name in the S-expression that is of interest
59 * @param elems names of the elements to extract
60 * @return 0 on success
63 key_from_sexp (gcry_mpi_t * array,
74 list = gcry_sexp_find_token (sexp, topname, 0);
77 l2 = gcry_sexp_cadr (list);
78 gcry_sexp_release (list);
84 for (s = elems; *s; s++, idx++)
86 l2 = gcry_sexp_find_token (list, s, 1);
89 for (i = 0; i < idx; i++)
94 gcry_sexp_release (list);
95 return 3; /* required parameter not found */
97 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
98 gcry_sexp_release (l2);
101 for (i = 0; i < idx; i++)
103 gcry_free (array[i]);
106 gcry_sexp_release (list);
107 return 4; /* required parameter is invalid */
110 gcry_sexp_release (list);
116 * Convert the given private key from the network format to the
117 * S-expression that can be used by libgcrypt.
119 * @param priv private key to decode
120 * @return NULL on error
123 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
128 rc = gcry_sexp_build (&result, NULL,
129 "(private-key(ecc(curve \"" CURVE "\")"
131 (int) sizeof (priv->d), priv->d);
134 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
138 if (0 != (rc = gcry_pk_testkey (result)))
140 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
149 * Convert the given private key from the network format to the
150 * S-expression that can be used by libgcrypt.
152 * @param priv private key to decode
153 * @return NULL on error
156 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
161 rc = gcry_sexp_build (&result, NULL,
162 "(private-key(ecc(curve \"" CURVE "\")"
163 "(flags eddsa)(d %b)))",
164 (int)sizeof (priv->d), priv->d);
167 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
171 if (0 != (rc = gcry_pk_testkey (result)))
173 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
182 * Convert the given private key from the network format to the
183 * S-expression that can be used by libgcrypt.
185 * @param priv private key to decode
186 * @return NULL on error
189 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
194 rc = gcry_sexp_build (&result, NULL,
195 "(private-key(ecc(curve \"" CURVE "\")"
197 (int)sizeof (priv->d), priv->d);
200 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
204 if (0 != (rc = gcry_pk_testkey (result)))
206 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
215 * Extract the public key for the given private key.
217 * @param priv the private key
218 * @param pub where to write the public key
221 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
222 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
228 sexp = decode_private_ecdsa_key (priv);
229 GNUNET_assert (NULL != sexp);
230 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
231 gcry_sexp_release (sexp);
232 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
233 GNUNET_assert (NULL != q);
234 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
235 gcry_mpi_release (q);
236 gcry_ctx_release (ctx);
241 * Extract the public key for the given private key.
243 * @param priv the private key
244 * @param pub where to write the public key
247 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
248 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
254 sexp = decode_private_eddsa_key (priv);
255 GNUNET_assert (NULL != sexp);
256 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
257 gcry_sexp_release (sexp);
258 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
260 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
261 gcry_mpi_release (q);
262 gcry_ctx_release (ctx);
267 * Extract the public key for the given private key.
269 * @param priv the private key
270 * @param pub where to write the public key
273 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
274 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
280 sexp = decode_private_ecdhe_key (priv);
281 GNUNET_assert (NULL != sexp);
282 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
283 gcry_sexp_release (sexp);
284 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
286 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
287 gcry_mpi_release (q);
288 gcry_ctx_release (ctx);
293 * Convert a public key to a string.
295 * @param pub key to convert
296 * @return string representing @a pub
299 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
302 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
306 keylen += 5 - keylen % 5;
308 pubkeybuf = GNUNET_malloc (keylen + 1);
309 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
310 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
315 GNUNET_free (pubkeybuf);
324 * Convert a public key to a string.
326 * @param pub key to convert
327 * @return string representing @a pub
330 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
333 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
337 keylen += 5 - keylen % 5;
339 pubkeybuf = GNUNET_malloc (keylen + 1);
340 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
341 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
346 GNUNET_free (pubkeybuf);
355 * Convert a private key to a string.
357 * @param priv key to convert
358 * @return string representing @a pub
361 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
364 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
368 keylen += 5 - keylen % 5;
370 privkeybuf = GNUNET_malloc (keylen + 1);
371 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
372 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
377 GNUNET_free (privkeybuf);
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_ecdsa_public_key_from_string (const char *enc,
396 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
398 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
401 keylen += 5 - keylen % 5;
403 if (enclen != keylen)
404 return GNUNET_SYSERR;
407 GNUNET_STRINGS_string_to_data (enc, enclen,
409 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
410 return GNUNET_SYSERR;
416 * Convert a string representing a public key to a public key.
418 * @param enc encoded public key
419 * @param enclen number of bytes in @a enc (without 0-terminator)
420 * @param pub where to store the public key
421 * @return #GNUNET_OK on success
424 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
426 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
428 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
431 keylen += 5 - keylen % 5;
433 if (enclen != keylen)
434 return GNUNET_SYSERR;
437 GNUNET_STRINGS_string_to_data (enc, enclen,
439 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
440 return GNUNET_SYSERR;
446 * Convert a string representing a private key to a private key.
448 * @param enc encoded public key
449 * @param enclen number of bytes in @a enc (without 0-terminator)
450 * @param priv where to store the private key
451 * @return #GNUNET_OK on success
454 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
456 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
458 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
461 keylen += 5 - keylen % 5;
463 if (enclen != keylen)
464 return GNUNET_SYSERR;
467 GNUNET_STRINGS_string_to_data (enc, enclen,
469 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
470 return GNUNET_SYSERR;
473 check_eddsa_key (priv))
485 * Clear memory that was used to store a private key.
487 * @param pk location of the key
490 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
492 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
498 * Clear memory that was used to store a private key.
500 * @param pk location of the key
503 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
505 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
511 * Clear memory that was used to store a private key.
513 * @param pk location of the key
516 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
518 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
523 * Create a new private key. Caller must free return value.
525 * @return fresh private key
527 struct GNUNET_CRYPTO_EcdhePrivateKey *
528 GNUNET_CRYPTO_ecdhe_key_create ()
530 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
532 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
534 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
545 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
547 * @param[out] pk set to fresh private key;
548 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
551 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
553 gcry_sexp_t priv_sexp;
554 gcry_sexp_t s_keyparam;
558 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
559 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
560 disables an expensive key testing routine. We do not want to run
561 the expensive check for ECDHE, as we generate TONS of keys to
562 use for a very short time. */
563 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
564 "(genkey(ecc(curve \"" CURVE "\")"
565 "(flags eddsa no-keytest)))")))
567 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
568 return GNUNET_SYSERR;
570 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
572 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
573 gcry_sexp_release (s_keyparam);
574 return GNUNET_SYSERR;
576 gcry_sexp_release (s_keyparam);
578 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
580 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
581 gcry_sexp_release (priv_sexp);
582 return GNUNET_SYSERR;
585 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
587 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
588 gcry_sexp_release (priv_sexp);
589 return GNUNET_SYSERR;
591 gcry_sexp_release (priv_sexp);
592 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
593 gcry_mpi_release (d);
599 * Create a new private key. Caller must free return value.
601 * @return fresh private key
603 struct GNUNET_CRYPTO_EcdsaPrivateKey *
604 GNUNET_CRYPTO_ecdsa_key_create ()
606 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
607 gcry_sexp_t priv_sexp;
608 gcry_sexp_t s_keyparam;
612 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
613 "(genkey(ecc(curve \"" CURVE "\")"
616 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
619 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
621 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
622 gcry_sexp_release (s_keyparam);
625 gcry_sexp_release (s_keyparam);
627 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
629 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
630 gcry_sexp_release (priv_sexp);
634 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
636 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
637 gcry_sexp_release (priv_sexp);
640 gcry_sexp_release (priv_sexp);
641 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
642 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
643 gcry_mpi_release (d);
648 * Create a new private key. Caller must free return value.
650 * @return fresh private key
652 struct GNUNET_CRYPTO_EddsaPrivateKey *
653 GNUNET_CRYPTO_eddsa_key_create ()
655 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
656 gcry_sexp_t priv_sexp;
657 gcry_sexp_t s_keyparam;
664 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
665 "(genkey(ecc(curve \"" CURVE "\")"
668 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
671 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
673 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
674 gcry_sexp_release (s_keyparam);
677 gcry_sexp_release (s_keyparam);
679 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
681 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
682 gcry_sexp_release (priv_sexp);
686 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
688 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
689 gcry_sexp_release (priv_sexp);
692 gcry_sexp_release (priv_sexp);
693 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
694 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
695 gcry_mpi_release (d);
699 check_eddsa_key (priv))
712 * Get the shared private key we use for anonymous users.
714 * @return "anonymous" private key
716 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
717 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
720 * 'anonymous' pseudonym (global static, d=1, public key = G
723 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
728 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
729 sizeof (anonymous.d),
737 * Compare two Peer Identities.
739 * @param first first peer identity
740 * @param second second peer identity
741 * @return bigger than 0 if first > second,
742 * 0 if they are the same
743 * smaller than 0 if second > first
746 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
747 const struct GNUNET_PeerIdentity *second)
749 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
754 * Convert the data specified in the given purpose argument to an
755 * S-expression suitable for signature operations.
757 * @param purpose data to convert
758 * @return converted s-expression
761 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
763 struct GNUNET_HashCode hc;
767 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
768 if (0 != (rc = gcry_sexp_build (&data, NULL,
769 "(data(flags eddsa)(hash-algo %s)(value %b))",
771 (int)sizeof (hc), &hc)))
773 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
781 * Convert the data specified in the given purpose argument to an
782 * S-expression suitable for signature operations.
784 * @param purpose data to convert
785 * @return converted s-expression
788 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
790 struct GNUNET_HashCode hc;
794 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
795 if (0 != (rc = gcry_sexp_build (&data, NULL,
796 "(data(flags rfc6979)(hash %s %b))",
798 (int)sizeof (hc), &hc)))
800 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
808 * Sign a given block.
810 * @param priv private key to use for the signing
811 * @param purpose what to sign (size, purpose)
812 * @param sig where to write the signature
813 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
816 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
817 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
818 struct GNUNET_CRYPTO_EcdsaSignature *sig)
820 gcry_sexp_t priv_sexp;
821 gcry_sexp_t sig_sexp;
826 priv_sexp = decode_private_ecdsa_key (priv);
827 data = data_to_ecdsa_value (purpose);
828 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
830 LOG (GNUNET_ERROR_TYPE_WARNING,
831 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
832 __LINE__, gcry_strerror (rc));
833 gcry_sexp_release (data);
834 gcry_sexp_release (priv_sexp);
835 return GNUNET_SYSERR;
837 gcry_sexp_release (priv_sexp);
838 gcry_sexp_release (data);
840 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
842 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
845 gcry_sexp_release (sig_sexp);
846 return GNUNET_SYSERR;
848 gcry_sexp_release (sig_sexp);
849 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
850 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
851 gcry_mpi_release (rs[0]);
852 gcry_mpi_release (rs[1]);
858 * Sign a given block.
860 * @param priv private key to use for the signing
861 * @param purpose what to sign (size, purpose)
862 * @param sig where to write the signature
863 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
866 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
867 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
868 struct GNUNET_CRYPTO_EddsaSignature *sig)
870 gcry_sexp_t priv_sexp;
871 gcry_sexp_t sig_sexp;
876 priv_sexp = decode_private_eddsa_key (priv);
877 data = data_to_eddsa_value (purpose);
878 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
880 LOG (GNUNET_ERROR_TYPE_WARNING,
881 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
882 __LINE__, gcry_strerror (rc));
883 gcry_sexp_release (data);
884 gcry_sexp_release (priv_sexp);
885 return GNUNET_SYSERR;
887 gcry_sexp_release (priv_sexp);
888 gcry_sexp_release (data);
890 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
892 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
895 gcry_sexp_release (sig_sexp);
896 return GNUNET_SYSERR;
898 gcry_sexp_release (sig_sexp);
899 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
900 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
901 gcry_mpi_release (rs[0]);
902 gcry_mpi_release (rs[1]);
910 * @param purpose what is the purpose that the signature should have?
911 * @param validate block to validate (size, purpose, data)
912 * @param sig signature that is being validated
913 * @param pub public key of the signer
914 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
917 GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
918 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
919 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
920 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
923 gcry_sexp_t sig_sexpr;
924 gcry_sexp_t pub_sexpr;
927 if (purpose != ntohl (validate->purpose))
928 return GNUNET_SYSERR; /* purpose mismatch */
930 /* build s-expression for signature */
931 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
932 "(sig-val(ecdsa(r %b)(s %b)))",
933 (int) sizeof (sig->r), sig->r,
934 (int) sizeof (sig->s), sig->s)))
936 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
937 return GNUNET_SYSERR;
939 data = data_to_ecdsa_value (validate);
940 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
941 "(public-key(ecc(curve " CURVE ")(q %b)))",
942 (int) sizeof (pub->q_y), pub->q_y)))
944 gcry_sexp_release (data);
945 gcry_sexp_release (sig_sexpr);
946 return GNUNET_SYSERR;
948 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
949 gcry_sexp_release (pub_sexpr);
950 gcry_sexp_release (data);
951 gcry_sexp_release (sig_sexpr);
954 LOG (GNUNET_ERROR_TYPE_INFO,
955 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
956 __LINE__, gcry_strerror (rc));
957 return GNUNET_SYSERR;
967 * @param purpose what is the purpose that the signature should have?
968 * @param validate block to validate (size, purpose, data)
969 * @param sig signature that is being validated
970 * @param pub public key of the signer
971 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
974 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
975 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
976 const struct GNUNET_CRYPTO_EddsaSignature *sig,
977 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
980 gcry_sexp_t sig_sexpr;
981 gcry_sexp_t pub_sexpr;
984 if (purpose != ntohl (validate->purpose))
985 return GNUNET_SYSERR; /* purpose mismatch */
987 /* build s-expression for signature */
988 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
989 "(sig-val(eddsa(r %b)(s %b)))",
990 (int)sizeof (sig->r), sig->r,
991 (int)sizeof (sig->s), sig->s)))
993 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
994 return GNUNET_SYSERR;
996 data = data_to_eddsa_value (validate);
997 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
998 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
999 (int)sizeof (pub->q_y), pub->q_y)))
1001 gcry_sexp_release (data);
1002 gcry_sexp_release (sig_sexpr);
1003 return GNUNET_SYSERR;
1005 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1006 gcry_sexp_release (pub_sexpr);
1007 gcry_sexp_release (data);
1008 gcry_sexp_release (sig_sexpr);
1011 LOG (GNUNET_ERROR_TYPE_INFO,
1012 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1013 __LINE__, gcry_strerror (rc));
1014 return GNUNET_SYSERR;
1021 * Derive key material from a public and a private ECDHE key.
1023 * @param priv private key to use for the ECDH (x)
1024 * @param pub public key to use for the ECDH (yG)
1025 * @param key_material where to write the key material (xyG)
1026 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1029 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1030 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1031 struct GNUNET_HashCode *key_material)
1033 gcry_mpi_point_t result;
1037 gcry_sexp_t pub_sexpr;
1038 gcry_mpi_t result_x;
1039 unsigned char xbuf[256 / 8];
1042 /* first, extract the q = dP value from the public key */
1043 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1044 "(public-key(ecc(curve " CURVE ")(q %b)))",
1045 (int)sizeof (pub->q_y), pub->q_y))
1046 return GNUNET_SYSERR;
1047 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1048 gcry_sexp_release (pub_sexpr);
1049 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1051 /* second, extract the d value from our private key */
1052 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1054 /* then call the 'multiply' function, to compute the product */
1055 result = gcry_mpi_point_new (0);
1056 gcry_mpi_ec_mul (result, d, q, ctx);
1057 gcry_mpi_point_release (q);
1058 gcry_mpi_release (d);
1060 /* finally, convert point to string for hashing */
1061 result_x = gcry_mpi_new (256);
1062 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1064 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1065 gcry_mpi_point_release (result);
1066 gcry_ctx_release (ctx);
1067 return GNUNET_SYSERR;
1069 gcry_mpi_point_release (result);
1070 gcry_ctx_release (ctx);
1072 rsize = sizeof (xbuf);
1073 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1074 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1075 as that does not include the sign bit; x should be a 255-bit
1076 value, so with the sign it should fit snugly into the 256-bit
1079 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1081 GNUNET_CRYPTO_hash (xbuf,
1084 gcry_mpi_release (result_x);
1090 * Derive the 'h' value for key derivation, where
1093 * @param pub public key for deriviation
1094 * @param label label for deriviation
1095 * @param context additional context to use for HKDF of 'h';
1096 * typically the name of the subsystem/application
1100 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1102 const char *context)
1105 struct GNUNET_HashCode hc;
1106 static const char *const salt = "key-derivation";
1108 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1109 salt, strlen (salt),
1111 label, strlen (label),
1112 context, strlen (context),
1114 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1115 (unsigned char *) &hc,
1122 * Derive a private key from a given private key and a label.
1123 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1124 * where n is the size of the ECC group and P is the public
1125 * key associated with the private key 'd'.
1127 * @param priv original private key
1128 * @param label label to use for key deriviation
1129 * @param context additional context to use for HKDF of 'h';
1130 * typically the name of the subsystem/application
1131 * @return derived private key
1133 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1134 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1136 const char *context)
1138 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1139 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1146 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1148 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1149 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1151 h = derive_h (&pub, label, context);
1152 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1155 d = gcry_mpi_new (256);
1156 gcry_mpi_mulm (d, h, x, n);
1157 gcry_mpi_release (h);
1158 gcry_mpi_release (x);
1159 gcry_mpi_release (n);
1160 gcry_ctx_release (ctx);
1161 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1162 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1163 gcry_mpi_release (d);
1169 * Derive a public key from a given public key and a label.
1170 * Essentially calculates a public key 'V = H(l,P) * P'.
1172 * @param pub original public key
1173 * @param label label to use for key derivation
1174 * @param context additional context to use for HKDF of 'h';
1175 * typically the name of the subsystem/application
1176 * @param result where to write the derived public key
1179 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1181 const char *context,
1182 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1192 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1194 /* obtain point 'q' from original public key. The provided 'q' is
1195 compressed thus we first store it in the context and then get it
1196 back as a (decompresssed) point. */
1197 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1198 GNUNET_assert (NULL != q_y);
1199 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1200 gcry_mpi_release (q_y);
1201 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1204 /* calculate h_mod_n = h % n */
1205 h = derive_h (pub, label, context);
1206 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1207 h_mod_n = gcry_mpi_new (256);
1208 gcry_mpi_mod (h_mod_n, h, n);
1209 /* calculate v = h_mod_n * q */
1210 v = gcry_mpi_point_new (0);
1211 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1212 gcry_mpi_release (h_mod_n);
1213 gcry_mpi_release (h);
1214 gcry_mpi_release (n);
1215 gcry_mpi_point_release (q);
1217 /* convert point 'v' to public key that we return */
1218 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1219 gcry_mpi_point_release (v);
1220 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1221 GNUNET_assert (q_y);
1222 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1223 sizeof (result->q_y),
1225 gcry_mpi_release (q_y);
1226 gcry_ctx_release (ctx);
1231 * Reverse the sequence of the bytes in @a buffer
1233 * @param[in|out] buffer buffer to invert
1234 * @param length number of bytes in @a buffer
1237 reverse_buffer (unsigned char *buffer,
1243 for (i=0; i < length/2; i++)
1246 buffer[i] = buffer[length-1-i];
1247 buffer[length-1-i] = tmp;
1253 * Convert the secret @a d of an EdDSA key to the
1254 * value that is actually used in the EdDSA computation.
1256 * @param d secret input
1257 * @return value used for the calculation in EdDSA
1260 eddsa_d_to_a (gcry_mpi_t d)
1262 unsigned char rawmpi[32]; /* 256-bit value */
1264 unsigned char digest[64]; /* 512-bit hash value */
1265 gcry_buffer_t hvec[2];
1269 b = 256 / 8; /* number of bytes in `d` */
1271 /* Note that we clear DIGEST so we can use it as input to left pad
1272 the key with zeroes for hashing. */
1273 memset (digest, 0, sizeof digest);
1274 memset (hvec, 0, sizeof hvec);
1275 rawmpilen = sizeof (rawmpi);
1277 gcry_mpi_print (GCRYMPI_FMT_USG,
1278 rawmpi, rawmpilen, &rawmpilen,
1280 hvec[0].data = digest;
1282 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1283 hvec[1].data = rawmpi;
1285 hvec[1].len = rawmpilen;
1287 gcry_md_hash_buffers (GCRY_MD_SHA512,
1291 /* Compute the A value. */
1292 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1293 digest[0] = (digest[0] & 0x7f) | 0x40;
1296 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1304 * Take point from ECDH and convert it to key material.
1306 * @param result point from ECDH
1307 * @param ctx ECC context
1308 * @param key_material[out] set to derived key material
1309 * @return #GNUNET_OK on success
1312 point_to_hash (gcry_mpi_point_t result,
1314 struct GNUNET_HashCode *key_material)
1316 gcry_mpi_t result_x;
1317 unsigned char xbuf[256 / 8];
1320 /* finally, convert point to string for hashing */
1321 result_x = gcry_mpi_new (256);
1322 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1324 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1325 return GNUNET_SYSERR;
1328 rsize = sizeof (xbuf);
1329 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1330 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1331 as that does not include the sign bit; x should be a 255-bit
1332 value, so with the sign it should fit snugly into the 256-bit
1335 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1337 GNUNET_CRYPTO_hash (xbuf,
1340 gcry_mpi_release (result_x);
1347 * Derive key material from a ECDH public key and a private EdDSA key.
1348 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1350 * @param priv private key from EdDSA to use for the ECDH (x)
1351 * @param pub public key to use for the ECDH (yG)
1352 * @param key_material where to write the key material H(h(x)yG)
1353 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1356 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1357 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1358 struct GNUNET_HashCode *key_material)
1360 gcry_mpi_point_t result;
1365 gcry_sexp_t pub_sexpr;
1368 /* first, extract the q = dP value from the public key */
1369 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1370 "(public-key(ecc(curve " CURVE ")(q %b)))",
1371 (int)sizeof (pub->q_y), pub->q_y))
1372 return GNUNET_SYSERR;
1373 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1374 gcry_sexp_release (pub_sexpr);
1375 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1377 /* second, extract the d value from our private key */
1378 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1380 /* NOW, because this is EdDSA, HASH 'd' first! */
1381 a = eddsa_d_to_a (d);
1382 gcry_mpi_release (d);
1384 /* then call the 'multiply' function, to compute the product */
1385 result = gcry_mpi_point_new (0);
1386 gcry_mpi_ec_mul (result, a, q, ctx);
1387 gcry_mpi_point_release (q);
1388 gcry_mpi_release (a);
1390 ret = point_to_hash (result,
1393 gcry_mpi_point_release (result);
1394 gcry_ctx_release (ctx);
1401 * Derive key material from a ECDH public key and a private ECDSA key.
1402 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1404 * @param priv private key from ECDSA to use for the ECDH (x)
1405 * @param pub public key to use for the ECDH (yG)
1406 * @param key_material where to write the key material H(h(x)yG)
1407 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1410 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1411 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1412 struct GNUNET_HashCode *key_material)
1414 gcry_mpi_point_t result;
1418 gcry_sexp_t pub_sexpr;
1421 /* first, extract the q = dP value from the public key */
1422 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1423 "(public-key(ecc(curve " CURVE ")(q %b)))",
1424 (int)sizeof (pub->q_y), pub->q_y))
1425 return GNUNET_SYSERR;
1426 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1427 gcry_sexp_release (pub_sexpr);
1428 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1430 /* second, extract the d value from our private key */
1431 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1433 /* then call the 'multiply' function, to compute the product */
1434 result = gcry_mpi_point_new (0);
1435 gcry_mpi_ec_mul (result, d, q, ctx);
1436 gcry_mpi_point_release (q);
1437 gcry_mpi_release (d);
1439 /* finally, convert point to string for hashing */
1440 ret = point_to_hash (result,
1443 gcry_mpi_point_release (result);
1444 gcry_ctx_release (ctx);
1452 * Derive key material from a EdDSA public key and a private ECDH key.
1453 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1455 * @param priv private key to use for the ECDH (y)
1456 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1457 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1458 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1461 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1462 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1463 struct GNUNET_HashCode *key_material)
1465 gcry_mpi_point_t result;
1469 gcry_sexp_t pub_sexpr;
1472 /* first, extract the q = dP value from the public key */
1473 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1474 "(public-key(ecc(curve " CURVE ")(q %b)))",
1475 (int)sizeof (pub->q_y), pub->q_y))
1476 return GNUNET_SYSERR;
1477 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1478 gcry_sexp_release (pub_sexpr);
1479 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1481 /* second, extract the d value from our private key */
1482 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1484 /* then call the 'multiply' function, to compute the product */
1485 result = gcry_mpi_point_new (0);
1486 gcry_mpi_ec_mul (result, d, q, ctx);
1487 gcry_mpi_point_release (q);
1488 gcry_mpi_release (d);
1490 /* finally, convert point to string for hashing */
1491 ret = point_to_hash (result,
1494 gcry_mpi_point_release (result);
1495 gcry_ctx_release (ctx);
1501 * Derive key material from a ECDSA public key and a private ECDH key.
1502 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1504 * @param priv private key to use for the ECDH (y)
1505 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1506 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1507 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1510 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1511 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1512 struct GNUNET_HashCode *key_material)
1514 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1515 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1519 /* end of crypto_ecc.c */