From: Christian Grothoff Date: Thu, 17 May 2018 10:26:30 +0000 (+0200) Subject: work-around for crypto bug (to be documented more) X-Git-Tag: v0.11.0pre66~39 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=dd8289771b35e5ea36ebdcbfd5b09b599bd59c67;p=oweals%2Fgnunet.git work-around for crypto bug (to be documented more) --- diff --git a/contrib/testing_hostkeys.ecc b/contrib/testing_hostkeys.ecc index 194d0da78..23e5d3379 100644 Binary files a/contrib/testing_hostkeys.ecc and b/contrib/testing_hostkeys.ecc differ diff --git a/src/cadet/gnunet-service-cadet_tunnels.c b/src/cadet/gnunet-service-cadet_tunnels.c index 2565b8f18..75d454522 100644 --- a/src/cadet/gnunet-service-cadet_tunnels.c +++ b/src/cadet/gnunet-service-cadet_tunnels.c @@ -1889,9 +1889,11 @@ GCT_handle_kx_auth (struct CadetTConnection *ct, GNUNET_NO); LOG (GNUNET_ERROR_TYPE_WARNING, "KX AUTH missmatch!\n"); - send_kx (t, - ct, - &t->ax); + if (NULL == t->kx_task) + t->kx_task + = GNUNET_SCHEDULER_add_at (t->next_kx_attempt, + &retry_kx, + t); return; } /* Yep, we're good. */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am index eb655157d..407f482df 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -598,4 +598,5 @@ EXTRA_DIST = \ test_resolver_api_data.conf \ test_service_data.conf \ test_speedup_data.conf \ - gnunet-qr.py.in + gnunet-qr.py.in \ + crypto_bug.c diff --git a/src/util/crypto_bug.c b/src/util/crypto_bug.c new file mode 100644 index 000000000..c25e79c63 --- /dev/null +++ b/src/util/crypto_bug.c @@ -0,0 +1,79 @@ +/* + This file is part of GNUnet. + Copyright (C) 2018 GNUnet e.V. + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @file util/crypto_bug.c + * @brief work around unidentified public key cryptography bug + * @author Christian Grothoff + */ + +/** + * Enable work-around. Will cause code to call #check_eddsa_key() to + * see if we have a bad key, and if so, create a new one. + */ +#define CRYPTO_BUG 1 + + +#if CRYPTO_BUG +/** + * Check if ECDH works with @a priv_dsa and this version + * of libgcrypt. + * + * @param priv_dsa key to check + * @return #GNUNET_OK if key passes + */ +static int +check_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_dsa) +{ + struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh; + struct GNUNET_CRYPTO_EddsaPublicKey id1; + struct GNUNET_CRYPTO_EcdhePublicKey id2; + struct GNUNET_HashCode dh[2]; + + GNUNET_CRYPTO_eddsa_key_get_public (priv_dsa, + &id1); + for (unsigned int j=0;j<4;j++) + { + priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create (); + /* Extract public keys */ + GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh, + &id2); + /* Do ECDH */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_ecdh (priv_dsa, + &id2, + &dh[0])); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh, + &id1, + &dh[1])); + /* Check that both DH results are equal. */ + if (0 != memcmp (&dh[0], + &dh[1], + sizeof (struct GNUNET_HashCode))) + { + GNUNET_break (0); /* bad EdDSA key! */ + return GNUNET_SYSERR; + } + GNUNET_free (priv_ecdh); + } + return GNUNET_OK; +} +#endif diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index 8cc6c18cb..1abf0fddc 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c @@ -52,6 +52,9 @@ #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) +#include "crypto_bug.c" + + /** * Extract values from an S-expression. * @@ -455,7 +458,7 @@ GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc, int GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, size_t enclen, - struct GNUNET_CRYPTO_EddsaPrivateKey *pub) + struct GNUNET_CRYPTO_EddsaPrivateKey *priv) { size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8; @@ -465,10 +468,19 @@ GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, if (enclen != keylen) return GNUNET_SYSERR; - if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, - pub, - sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) + if (GNUNET_OK != + GNUNET_STRINGS_string_to_data (enc, enclen, + priv, + sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) return GNUNET_SYSERR; +#if CRYPTO_BUG + if (GNUNET_OK != + check_eddsa_key (priv)) + { + GNUNET_break (0); + return GNUNET_OK; + } +#endif return GNUNET_OK; } @@ -651,6 +663,9 @@ GNUNET_CRYPTO_eddsa_key_create () gcry_mpi_t d; int rc; +#if CRYPTO_BUG + again: +#endif if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, "(genkey(ecc(curve \"" CURVE "\")" "(flags eddsa)))"))) @@ -683,6 +698,17 @@ GNUNET_CRYPTO_eddsa_key_create () priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey); GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d); gcry_mpi_release (d); + +#if CRYPTO_BUG + if (GNUNET_OK != + check_eddsa_key (priv)) + { + GNUNET_break (0); + GNUNET_free (priv); + goto again; + } +#endif + return priv; } diff --git a/src/util/crypto_ecc_setup.c b/src/util/crypto_ecc_setup.c index e7caf9ded..76c25dc70 100644 --- a/src/util/crypto_ecc_setup.c +++ b/src/util/crypto_ecc_setup.c @@ -41,6 +41,9 @@ #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) +#include "crypto_bug.c" + + /** * Wait for a short time (we're trying to lock a file or want * to give another process a shot at finishing a disk write, etc.). @@ -221,6 +224,15 @@ GNUNET_CRYPTO_eddsa_key_create_from_file (const char *filename) filename); GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); +#if CRYPTO_BUG + if (GNUNET_OK != + check_eddsa_key (priv)) + { + GNUNET_break (0); + GNUNET_free (priv); + return NULL; + } +#endif return priv; } @@ -248,7 +260,7 @@ GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename) int ec; uint64_t fs; ssize_t sret; - + if (GNUNET_SYSERR == GNUNET_DISK_directory_create_for_file (filename)) return NULL; diff --git a/src/util/test_crypto_ecdh_eddsa.c b/src/util/test_crypto_ecdh_eddsa.c index 246cec27f..356c64bf1 100644 --- a/src/util/test_crypto_ecdh_eddsa.c +++ b/src/util/test_crypto_ecdh_eddsa.c @@ -36,31 +36,35 @@ test_ecdh() struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh; struct GNUNET_CRYPTO_EddsaPublicKey id1; struct GNUNET_CRYPTO_EcdhePublicKey id2; - struct GNUNET_HashCode dh[3]; + struct GNUNET_HashCode dh[2]; /* Generate keys */ priv_dsa = GNUNET_CRYPTO_eddsa_key_create (); - priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create (); - /* Extract public keys */ GNUNET_CRYPTO_eddsa_key_get_public (priv_dsa, &id1); - GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh, - &id2); - /* Do ECDH */ - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_ecdh (priv_dsa, - &id2, - &dh[0])); - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh, - &id1, - &dh[1])); - /* Check that both DH results are equal. */ - GNUNET_assert (0 == memcmp (&dh[0], - &dh[1], - sizeof (struct GNUNET_HashCode))); + for (unsigned int j=0;j<10;j++) + { + fprintf (stderr, ","); + priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create (); + /* Extract public keys */ + GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh, + &id2); + /* Do ECDH */ + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_ecdh (priv_dsa, + &id2, + &dh[0])); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh, + &id1, + &dh[1])); + /* Check that both DH results are equal. */ + GNUNET_assert (0 == memcmp (&dh[0], + &dh[1], + sizeof (struct GNUNET_HashCode))); + GNUNET_free (priv_ecdh); + } GNUNET_free (priv_dsa); - GNUNET_free (priv_ecdh); return 0; } @@ -78,7 +82,7 @@ main (int argc, char *argv[]) if (getenv ("GNUNET_GCRYPT_DEBUG")) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); GNUNET_log_setup ("test-crypto-ecdh-eddsa", "WARNING", NULL); - for (unsigned int i=0;i<10000;i++) + for (unsigned int i=0;i<100;i++) { fprintf (stderr, ".");