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 Affero 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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file util/crypto_ecc.c
21 * @brief public key cryptography (ECC) with libgcrypt
22 * @author Christian Grothoff
26 #include "gnunet_crypto_lib.h"
27 #include "gnunet_strings_lib.h"
29 #define EXTRA_CHECKS 0
32 * Name of the curve we are using. Note that we have hard-coded
33 * structs that use 256 bits, so using a bigger curve will require
34 * changes that break stuff badly. The name of the curve given here
35 * must be agreed by all peers and be supported by libgcrypt.
37 #define CURVE "Ed25519"
39 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
41 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
43 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
46 * Log an error message at log-level 'level' that indicates
47 * a failure of the command 'cmd' with the message given
48 * by gcry_strerror(rc).
50 #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)
53 #include "crypto_bug.c"
57 * Extract values from an S-expression.
59 * @param array where to store the result(s)
60 * @param sexp S-expression to parse
61 * @param topname top-level name in the S-expression that is of interest
62 * @param elems names of the elements to extract
63 * @return 0 on success
66 key_from_sexp (gcry_mpi_t * array,
77 list = gcry_sexp_find_token (sexp, topname, 0);
80 l2 = gcry_sexp_cadr (list);
81 gcry_sexp_release (list);
87 for (s = elems; *s; s++, idx++)
89 l2 = gcry_sexp_find_token (list, s, 1);
92 for (i = 0; i < idx; i++)
97 gcry_sexp_release (list);
98 return 3; /* required parameter not found */
100 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
101 gcry_sexp_release (l2);
104 for (i = 0; i < idx; i++)
106 gcry_free (array[i]);
109 gcry_sexp_release (list);
110 return 4; /* required parameter is invalid */
113 gcry_sexp_release (list);
119 * Convert the given private key from the network format to the
120 * S-expression that can be used by libgcrypt.
122 * @param priv private key to decode
123 * @return NULL on error
126 decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
131 rc = gcry_sexp_build (&result, NULL,
132 "(private-key(ecc(curve \"" CURVE "\")"
134 (int) sizeof (priv->d), priv->d);
137 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
141 if (0 != (rc = gcry_pk_testkey (result)))
143 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
152 * Convert the given private key from the network format to the
153 * S-expression that can be used by libgcrypt.
155 * @param priv private key to decode
156 * @return NULL on error
159 decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
164 rc = gcry_sexp_build (&result, NULL,
165 "(private-key(ecc(curve \"" CURVE "\")"
166 "(flags eddsa)(d %b)))",
167 (int)sizeof (priv->d), priv->d);
170 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
174 if (0 != (rc = gcry_pk_testkey (result)))
176 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
185 * Convert the given private key from the network format to the
186 * S-expression that can be used by libgcrypt.
188 * @param priv private key to decode
189 * @return NULL on error
192 decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
197 rc = gcry_sexp_build (&result, NULL,
198 "(private-key(ecc(curve \"" CURVE "\")"
200 (int)sizeof (priv->d), priv->d);
203 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
207 if (0 != (rc = gcry_pk_testkey (result)))
209 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
218 * Extract the public key for the given private key.
220 * @param priv the private key
221 * @param pub where to write the public key
224 GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
225 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
231 sexp = decode_private_ecdsa_key (priv);
232 GNUNET_assert (NULL != sexp);
233 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
234 gcry_sexp_release (sexp);
235 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
236 GNUNET_assert (NULL != q);
237 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
238 gcry_mpi_release (q);
239 gcry_ctx_release (ctx);
244 * Extract the public key for the given private key.
246 * @param priv the private key
247 * @param pub where to write the public key
250 GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
251 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
257 sexp = decode_private_eddsa_key (priv);
258 GNUNET_assert (NULL != sexp);
259 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
260 gcry_sexp_release (sexp);
261 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
263 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
264 gcry_mpi_release (q);
265 gcry_ctx_release (ctx);
270 * Extract the public key for the given private key.
272 * @param priv the private key
273 * @param pub where to write the public key
276 GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
277 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
283 sexp = decode_private_ecdhe_key (priv);
284 GNUNET_assert (NULL != sexp);
285 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
286 gcry_sexp_release (sexp);
287 q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
289 GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
290 gcry_mpi_release (q);
291 gcry_ctx_release (ctx);
296 * Convert a public key to a string.
298 * @param pub key to convert
299 * @return string representing @a pub
302 GNUNET_CRYPTO_ecdsa_public_key_to_string (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
305 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
309 keylen += 5 - keylen % 5;
311 pubkeybuf = GNUNET_malloc (keylen + 1);
312 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
313 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
318 GNUNET_free (pubkeybuf);
327 * Convert a public key to a string.
329 * @param pub key to convert
330 * @return string representing @a pub
333 GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
336 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
340 keylen += 5 - keylen % 5;
342 pubkeybuf = GNUNET_malloc (keylen + 1);
343 end = GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
344 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey),
349 GNUNET_free (pubkeybuf);
358 * Convert a private key to a string.
360 * @param priv key to convert
361 * @return string representing @a pub
364 GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
367 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
371 keylen += 5 - keylen % 5;
373 privkeybuf = GNUNET_malloc (keylen + 1);
374 end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
375 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
380 GNUNET_free (privkeybuf);
389 * Convert a string representing a public key to a public key.
391 * @param enc encoded public key
392 * @param enclen number of bytes in @a enc (without 0-terminator)
393 * @param pub where to store the public key
394 * @return #GNUNET_OK on success
397 GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
399 struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
401 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
404 keylen += 5 - keylen % 5;
406 if (enclen != keylen)
407 return GNUNET_SYSERR;
410 GNUNET_STRINGS_string_to_data (enc, enclen,
412 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
413 return GNUNET_SYSERR;
419 * Convert a string representing a public key to a public key.
421 * @param enc encoded public key
422 * @param enclen number of bytes in @a enc (without 0-terminator)
423 * @param pub where to store the public key
424 * @return #GNUNET_OK on success
427 GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
429 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
431 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
434 keylen += 5 - keylen % 5;
436 if (enclen != keylen)
437 return GNUNET_SYSERR;
440 GNUNET_STRINGS_string_to_data (enc, enclen,
442 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
443 return GNUNET_SYSERR;
449 * Convert a string representing a private key to a private key.
451 * @param enc encoded public key
452 * @param enclen number of bytes in @a enc (without 0-terminator)
453 * @param priv where to store the private key
454 * @return #GNUNET_OK on success
457 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
459 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
461 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
464 keylen += 5 - keylen % 5;
466 if (enclen != keylen)
467 return GNUNET_SYSERR;
470 GNUNET_STRINGS_string_to_data (enc, enclen,
472 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
473 return GNUNET_SYSERR;
476 check_eddsa_key (priv))
488 * Clear memory that was used to store a private key.
490 * @param pk location of the key
493 GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
495 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
501 * Clear memory that was used to store a private key.
503 * @param pk location of the key
506 GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
508 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
514 * Clear memory that was used to store a private key.
516 * @param pk location of the key
519 GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
521 memset (pk, 0, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
526 * Create a new private key. Caller must free return value.
528 * @return fresh private key
530 struct GNUNET_CRYPTO_EcdhePrivateKey *
531 GNUNET_CRYPTO_ecdhe_key_create ()
533 struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
535 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
537 GNUNET_CRYPTO_ecdhe_key_create2 (priv))
548 * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
550 * @param[out] pk set to fresh private key;
551 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
554 GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
556 gcry_sexp_t priv_sexp;
557 gcry_sexp_t s_keyparam;
561 /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
562 but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
563 disables an expensive key testing routine. We do not want to run
564 the expensive check for ECDHE, as we generate TONS of keys to
565 use for a very short time. */
566 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
567 "(genkey(ecc(curve \"" CURVE "\")"
568 "(flags eddsa no-keytest)))")))
570 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
571 return GNUNET_SYSERR;
573 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
575 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
576 gcry_sexp_release (s_keyparam);
577 return GNUNET_SYSERR;
579 gcry_sexp_release (s_keyparam);
581 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
583 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
584 gcry_sexp_release (priv_sexp);
585 return GNUNET_SYSERR;
588 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
590 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
591 gcry_sexp_release (priv_sexp);
592 return GNUNET_SYSERR;
594 gcry_sexp_release (priv_sexp);
595 GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
596 gcry_mpi_release (d);
602 * Create a new private key. Caller must free return value.
604 * @return fresh private key
606 struct GNUNET_CRYPTO_EcdsaPrivateKey *
607 GNUNET_CRYPTO_ecdsa_key_create ()
609 struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
610 gcry_sexp_t priv_sexp;
611 gcry_sexp_t s_keyparam;
615 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
616 "(genkey(ecc(curve \"" CURVE "\")"
619 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
622 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
624 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
625 gcry_sexp_release (s_keyparam);
628 gcry_sexp_release (s_keyparam);
630 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
632 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
633 gcry_sexp_release (priv_sexp);
637 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
639 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
640 gcry_sexp_release (priv_sexp);
643 gcry_sexp_release (priv_sexp);
644 priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
645 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
646 gcry_mpi_release (d);
651 * Create a new private key. Caller must free return value.
653 * @return fresh private key
655 struct GNUNET_CRYPTO_EddsaPrivateKey *
656 GNUNET_CRYPTO_eddsa_key_create ()
658 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
659 gcry_sexp_t priv_sexp;
660 gcry_sexp_t s_keyparam;
667 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
668 "(genkey(ecc(curve \"" CURVE "\")"
671 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
674 if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
676 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
677 gcry_sexp_release (s_keyparam);
680 gcry_sexp_release (s_keyparam);
682 if (0 != (rc = gcry_pk_testkey (priv_sexp)))
684 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
685 gcry_sexp_release (priv_sexp);
689 if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
691 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
692 gcry_sexp_release (priv_sexp);
695 gcry_sexp_release (priv_sexp);
696 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
697 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
698 gcry_mpi_release (d);
702 check_eddsa_key (priv))
715 * Get the shared private key we use for anonymous users.
717 * @return "anonymous" private key
719 const struct GNUNET_CRYPTO_EcdsaPrivateKey *
720 GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
723 * 'anonymous' pseudonym (global static, d=1, public key = G
726 static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
731 GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
732 sizeof (anonymous.d),
740 * Compare two Peer Identities.
742 * @param first first peer identity
743 * @param second second peer identity
744 * @return bigger than 0 if first > second,
745 * 0 if they are the same
746 * smaller than 0 if second > first
749 GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
750 const struct GNUNET_PeerIdentity *second)
752 return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
757 * Convert the data specified in the given purpose argument to an
758 * S-expression suitable for signature operations.
760 * @param purpose data to convert
761 * @return converted s-expression
764 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
766 struct GNUNET_HashCode hc;
770 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
771 if (0 != (rc = gcry_sexp_build (&data, NULL,
772 "(data(flags eddsa)(hash-algo %s)(value %b))",
774 (int)sizeof (hc), &hc)))
776 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
784 * Convert the data specified in the given purpose argument to an
785 * S-expression suitable for signature operations.
787 * @param purpose data to convert
788 * @return converted s-expression
791 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
793 struct GNUNET_HashCode hc;
797 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
798 if (0 != (rc = gcry_sexp_build (&data, NULL,
799 "(data(flags rfc6979)(hash %s %b))",
801 (int)sizeof (hc), &hc)))
803 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
811 * Sign a given block.
813 * @param priv private key to use for the signing
814 * @param purpose what to sign (size, purpose)
815 * @param sig where to write the signature
816 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
819 GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
820 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
821 struct GNUNET_CRYPTO_EcdsaSignature *sig)
823 gcry_sexp_t priv_sexp;
824 gcry_sexp_t sig_sexp;
829 priv_sexp = decode_private_ecdsa_key (priv);
830 data = data_to_ecdsa_value (purpose);
831 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
833 LOG (GNUNET_ERROR_TYPE_WARNING,
834 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
835 __LINE__, gcry_strerror (rc));
836 gcry_sexp_release (data);
837 gcry_sexp_release (priv_sexp);
838 return GNUNET_SYSERR;
840 gcry_sexp_release (priv_sexp);
841 gcry_sexp_release (data);
843 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
845 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
848 gcry_sexp_release (sig_sexp);
849 return GNUNET_SYSERR;
851 gcry_sexp_release (sig_sexp);
852 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
853 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
854 gcry_mpi_release (rs[0]);
855 gcry_mpi_release (rs[1]);
861 * Sign a given block.
863 * @param priv private key to use for the signing
864 * @param purpose what to sign (size, purpose)
865 * @param sig where to write the signature
866 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
869 GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
870 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
871 struct GNUNET_CRYPTO_EddsaSignature *sig)
873 gcry_sexp_t priv_sexp;
874 gcry_sexp_t sig_sexp;
879 priv_sexp = decode_private_eddsa_key (priv);
880 data = data_to_eddsa_value (purpose);
881 if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
883 LOG (GNUNET_ERROR_TYPE_WARNING,
884 _("EdDSA signing failed at %s:%d: %s\n"), __FILE__,
885 __LINE__, gcry_strerror (rc));
886 gcry_sexp_release (data);
887 gcry_sexp_release (priv_sexp);
888 return GNUNET_SYSERR;
890 gcry_sexp_release (priv_sexp);
891 gcry_sexp_release (data);
893 /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
895 if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
898 gcry_sexp_release (sig_sexp);
899 return GNUNET_SYSERR;
901 gcry_sexp_release (sig_sexp);
902 GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
903 GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
904 gcry_mpi_release (rs[0]);
905 gcry_mpi_release (rs[1]);
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_ecdsa_verify (uint32_t purpose,
921 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
922 const struct GNUNET_CRYPTO_EcdsaSignature *sig,
923 const struct GNUNET_CRYPTO_EcdsaPublicKey *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(ecdsa(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_ecdsa_value (validate);
943 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
944 "(public-key(ecc(curve " CURVE ")(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 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
959 __LINE__, gcry_strerror (rc));
960 return GNUNET_SYSERR;
970 * @param purpose what is the purpose that the signature should have?
971 * @param validate block to validate (size, purpose, data)
972 * @param sig signature that is being validated
973 * @param pub public key of the signer
974 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
977 GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
978 const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
979 const struct GNUNET_CRYPTO_EddsaSignature *sig,
980 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
983 gcry_sexp_t sig_sexpr;
984 gcry_sexp_t pub_sexpr;
987 if (purpose != ntohl (validate->purpose))
988 return GNUNET_SYSERR; /* purpose mismatch */
990 /* build s-expression for signature */
991 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
992 "(sig-val(eddsa(r %b)(s %b)))",
993 (int)sizeof (sig->r), sig->r,
994 (int)sizeof (sig->s), sig->s)))
996 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
997 return GNUNET_SYSERR;
999 data = data_to_eddsa_value (validate);
1000 if (0 != (rc = gcry_sexp_build (&pub_sexpr, NULL,
1001 "(public-key(ecc(curve " CURVE ")(flags eddsa)(q %b)))",
1002 (int)sizeof (pub->q_y), pub->q_y)))
1004 gcry_sexp_release (data);
1005 gcry_sexp_release (sig_sexpr);
1006 return GNUNET_SYSERR;
1008 rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
1009 gcry_sexp_release (pub_sexpr);
1010 gcry_sexp_release (data);
1011 gcry_sexp_release (sig_sexpr);
1014 LOG (GNUNET_ERROR_TYPE_INFO,
1015 _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1016 __LINE__, gcry_strerror (rc));
1017 return GNUNET_SYSERR;
1024 * Derive key material from a public and a private ECDHE key.
1026 * @param priv private key to use for the ECDH (x)
1027 * @param pub public key to use for the ECDH (yG)
1028 * @param key_material where to write the key material (xyG)
1029 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1032 GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1033 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1034 struct GNUNET_HashCode *key_material)
1036 gcry_mpi_point_t result;
1040 gcry_sexp_t pub_sexpr;
1041 gcry_mpi_t result_x;
1042 unsigned char xbuf[256 / 8];
1045 /* first, extract the q = dP value from the public key */
1046 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1047 "(public-key(ecc(curve " CURVE ")(q %b)))",
1048 (int)sizeof (pub->q_y), pub->q_y))
1049 return GNUNET_SYSERR;
1050 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1051 gcry_sexp_release (pub_sexpr);
1052 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1054 /* second, extract the d value from our private key */
1055 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1057 /* then call the 'multiply' function, to compute the product */
1058 result = gcry_mpi_point_new (0);
1059 gcry_mpi_ec_mul (result, d, q, ctx);
1060 gcry_mpi_point_release (q);
1061 gcry_mpi_release (d);
1063 /* finally, convert point to string for hashing */
1064 result_x = gcry_mpi_new (256);
1065 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1067 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1068 gcry_mpi_point_release (result);
1069 gcry_ctx_release (ctx);
1070 return GNUNET_SYSERR;
1072 gcry_mpi_point_release (result);
1073 gcry_ctx_release (ctx);
1075 rsize = sizeof (xbuf);
1076 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1077 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1078 as that does not include the sign bit; x should be a 255-bit
1079 value, so with the sign it should fit snugly into the 256-bit
1082 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1084 GNUNET_CRYPTO_hash (xbuf,
1087 gcry_mpi_release (result_x);
1093 * Derive the 'h' value for key derivation, where
1096 * @param pub public key for deriviation
1097 * @param label label for deriviation
1098 * @param context additional context to use for HKDF of 'h';
1099 * typically the name of the subsystem/application
1103 derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1105 const char *context)
1108 struct GNUNET_HashCode hc;
1109 static const char *const salt = "key-derivation";
1111 GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
1112 salt, strlen (salt),
1114 label, strlen (label),
1115 context, strlen (context),
1117 GNUNET_CRYPTO_mpi_scan_unsigned (&h,
1118 (unsigned char *) &hc,
1125 * Derive a private key from a given private key and a label.
1126 * Essentially calculates a private key 'd = H(l,P) * x mod n'
1127 * where n is the size of the ECC group and P is the public
1128 * key associated with the private key 'd'.
1130 * @param priv original private key
1131 * @param label label to use for key deriviation
1132 * @param context additional context to use for HKDF of 'h';
1133 * typically the name of the subsystem/application
1134 * @return derived private key
1136 struct GNUNET_CRYPTO_EcdsaPrivateKey *
1137 GNUNET_CRYPTO_ecdsa_private_key_derive (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1139 const char *context)
1141 struct GNUNET_CRYPTO_EcdsaPublicKey pub;
1142 struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
1149 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1151 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1152 GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
1154 h = derive_h (&pub, label, context);
1155 GNUNET_CRYPTO_mpi_scan_unsigned (&x,
1158 d = gcry_mpi_new (256);
1159 gcry_mpi_mulm (d, h, x, n);
1160 gcry_mpi_release (h);
1161 gcry_mpi_release (x);
1162 gcry_mpi_release (n);
1163 gcry_ctx_release (ctx);
1164 ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
1165 GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof (ret->d), d);
1166 gcry_mpi_release (d);
1172 * Derive a public key from a given public key and a label.
1173 * Essentially calculates a public key 'V = H(l,P) * P'.
1175 * @param pub original public key
1176 * @param label label to use for key derivation
1177 * @param context additional context to use for HKDF of 'h';
1178 * typically the name of the subsystem/application
1179 * @param result where to write the derived public key
1182 GNUNET_CRYPTO_ecdsa_public_key_derive (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1184 const char *context,
1185 struct GNUNET_CRYPTO_EcdsaPublicKey *result)
1195 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1197 /* obtain point 'q' from original public key. The provided 'q' is
1198 compressed thus we first store it in the context and then get it
1199 back as a (decompresssed) point. */
1200 q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8*sizeof (pub->q_y));
1201 GNUNET_assert (NULL != q_y);
1202 GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
1203 gcry_mpi_release (q_y);
1204 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1207 /* calculate h_mod_n = h % n */
1208 h = derive_h (pub, label, context);
1209 n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
1210 h_mod_n = gcry_mpi_new (256);
1211 gcry_mpi_mod (h_mod_n, h, n);
1212 /* calculate v = h_mod_n * q */
1213 v = gcry_mpi_point_new (0);
1214 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1215 gcry_mpi_release (h_mod_n);
1216 gcry_mpi_release (h);
1217 gcry_mpi_release (n);
1218 gcry_mpi_point_release (q);
1220 /* convert point 'v' to public key that we return */
1221 GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
1222 gcry_mpi_point_release (v);
1223 q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
1224 GNUNET_assert (q_y);
1225 GNUNET_CRYPTO_mpi_print_unsigned (result->q_y,
1226 sizeof (result->q_y),
1228 gcry_mpi_release (q_y);
1229 gcry_ctx_release (ctx);
1234 * Reverse the sequence of the bytes in @a buffer
1236 * @param[in|out] buffer buffer to invert
1237 * @param length number of bytes in @a buffer
1240 reverse_buffer (unsigned char *buffer,
1246 for (i=0; i < length/2; i++)
1249 buffer[i] = buffer[length-1-i];
1250 buffer[length-1-i] = tmp;
1256 * Convert the secret @a d of an EdDSA key to the
1257 * value that is actually used in the EdDSA computation.
1259 * @param d secret input
1260 * @return value used for the calculation in EdDSA
1263 eddsa_d_to_a (gcry_mpi_t d)
1265 unsigned char rawmpi[32]; /* 256-bit value */
1267 unsigned char digest[64]; /* 512-bit hash value */
1268 gcry_buffer_t hvec[2];
1272 b = 256 / 8; /* number of bytes in `d` */
1274 /* Note that we clear DIGEST so we can use it as input to left pad
1275 the key with zeroes for hashing. */
1276 memset (digest, 0, sizeof digest);
1277 memset (hvec, 0, sizeof hvec);
1278 rawmpilen = sizeof (rawmpi);
1280 gcry_mpi_print (GCRYMPI_FMT_USG,
1281 rawmpi, rawmpilen, &rawmpilen,
1283 hvec[0].data = digest;
1285 hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
1286 hvec[1].data = rawmpi;
1288 hvec[1].len = rawmpilen;
1290 gcry_md_hash_buffers (GCRY_MD_SHA512,
1294 /* Compute the A value. */
1295 reverse_buffer (digest, 32); /* Only the first half of the hash. */
1296 digest[0] = (digest[0] & 0x7f) | 0x40;
1299 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
1307 * Take point from ECDH and convert it to key material.
1309 * @param result point from ECDH
1310 * @param ctx ECC context
1311 * @param key_material[out] set to derived key material
1312 * @return #GNUNET_OK on success
1315 point_to_hash (gcry_mpi_point_t result,
1317 struct GNUNET_HashCode *key_material)
1319 gcry_mpi_t result_x;
1320 unsigned char xbuf[256 / 8];
1323 /* finally, convert point to string for hashing */
1324 result_x = gcry_mpi_new (256);
1325 if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
1327 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1328 return GNUNET_SYSERR;
1331 rsize = sizeof (xbuf);
1332 GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
1333 /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
1334 as that does not include the sign bit; x should be a 255-bit
1335 value, so with the sign it should fit snugly into the 256-bit
1338 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
1340 GNUNET_CRYPTO_hash (xbuf,
1343 gcry_mpi_release (result_x);
1350 * Derive key material from a ECDH public key and a private EdDSA key.
1351 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1353 * @param priv private key from EdDSA to use for the ECDH (x)
1354 * @param pub public key to use for the ECDH (yG)
1355 * @param key_material where to write the key material H(h(x)yG)
1356 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1359 GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1360 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1361 struct GNUNET_HashCode *key_material)
1363 gcry_mpi_point_t result;
1368 gcry_sexp_t pub_sexpr;
1371 /* first, extract the q = dP value from the public key */
1372 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1373 "(public-key(ecc(curve " CURVE ")(q %b)))",
1374 (int)sizeof (pub->q_y), pub->q_y))
1375 return GNUNET_SYSERR;
1376 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1377 gcry_sexp_release (pub_sexpr);
1378 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1380 /* second, extract the d value from our private key */
1381 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1383 /* NOW, because this is EdDSA, HASH 'd' first! */
1384 a = eddsa_d_to_a (d);
1385 gcry_mpi_release (d);
1387 /* then call the 'multiply' function, to compute the product */
1388 result = gcry_mpi_point_new (0);
1389 gcry_mpi_ec_mul (result, a, q, ctx);
1390 gcry_mpi_point_release (q);
1391 gcry_mpi_release (a);
1393 ret = point_to_hash (result,
1396 gcry_mpi_point_release (result);
1397 gcry_ctx_release (ctx);
1404 * Derive key material from a ECDH public key and a private ECDSA key.
1405 * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
1407 * @param priv private key from ECDSA to use for the ECDH (x)
1408 * @param pub public key to use for the ECDH (yG)
1409 * @param key_material where to write the key material H(h(x)yG)
1410 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1413 GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
1414 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1415 struct GNUNET_HashCode *key_material)
1417 gcry_mpi_point_t result;
1421 gcry_sexp_t pub_sexpr;
1424 /* first, extract the q = dP value from the public key */
1425 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1426 "(public-key(ecc(curve " CURVE ")(q %b)))",
1427 (int)sizeof (pub->q_y), pub->q_y))
1428 return GNUNET_SYSERR;
1429 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1430 gcry_sexp_release (pub_sexpr);
1431 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1433 /* second, extract the d value from our private key */
1434 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1436 /* then call the 'multiply' function, to compute the product */
1437 result = gcry_mpi_point_new (0);
1438 gcry_mpi_ec_mul (result, d, q, ctx);
1439 gcry_mpi_point_release (q);
1440 gcry_mpi_release (d);
1442 /* finally, convert point to string for hashing */
1443 ret = point_to_hash (result,
1446 gcry_mpi_point_release (result);
1447 gcry_ctx_release (ctx);
1455 * Derive key material from a EdDSA public key and a private ECDH key.
1456 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1458 * @param priv private key to use for the ECDH (y)
1459 * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
1460 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1461 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1464 GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1465 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1466 struct GNUNET_HashCode *key_material)
1468 gcry_mpi_point_t result;
1472 gcry_sexp_t pub_sexpr;
1475 /* first, extract the q = dP value from the public key */
1476 if (0 != gcry_sexp_build (&pub_sexpr, NULL,
1477 "(public-key(ecc(curve " CURVE ")(q %b)))",
1478 (int)sizeof (pub->q_y), pub->q_y))
1479 return GNUNET_SYSERR;
1480 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
1481 gcry_sexp_release (pub_sexpr);
1482 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1484 /* second, extract the d value from our private key */
1485 GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d));
1487 /* then call the 'multiply' function, to compute the product */
1488 result = gcry_mpi_point_new (0);
1489 gcry_mpi_ec_mul (result, d, q, ctx);
1490 gcry_mpi_point_release (q);
1491 gcry_mpi_release (d);
1493 /* finally, convert point to string for hashing */
1494 ret = point_to_hash (result,
1497 gcry_mpi_point_release (result);
1498 gcry_ctx_release (ctx);
1504 * Derive key material from a ECDSA public key and a private ECDH key.
1505 * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
1507 * @param priv private key to use for the ECDH (y)
1508 * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
1509 * @param key_material where to write the key material H(yX)=H(h(x)yG)
1510 * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
1513 GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1514 const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
1515 struct GNUNET_HashCode *key_material)
1517 return GNUNET_CRYPTO_ecdh_eddsa (priv,
1518 (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub,
1522 /* end of crypto_ecc.c */