aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2018-05-17 12:26:30 +0200
committerChristian Grothoff <christian@grothoff.org>2018-05-17 12:26:30 +0200
commitdd8289771b35e5ea36ebdcbfd5b09b599bd59c67 (patch)
treee79e565302867ab16d9ed8560793919094288716
parent3175cde841a8a7836fcf74a3e1b804c71a3aa153 (diff)
downloadgnunet-dd8289771b35e5ea36ebdcbfd5b09b599bd59c67.tar.gz
gnunet-dd8289771b35e5ea36ebdcbfd5b09b599bd59c67.zip
work-around for crypto bug (to be documented more)
-rw-r--r--contrib/testing_hostkeys.eccbin131072 -> 131072 bytes
-rw-r--r--src/cadet/gnunet-service-cadet_tunnels.c8
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/crypto_bug.c79
-rw-r--r--src/util/crypto_ecc.c34
-rw-r--r--src/util/crypto_ecc_setup.c14
-rw-r--r--src/util/test_crypto_ecdh_eddsa.c44
7 files changed, 153 insertions, 29 deletions
diff --git a/contrib/testing_hostkeys.ecc b/contrib/testing_hostkeys.ecc
index 194d0da78..23e5d3379 100644
--- a/contrib/testing_hostkeys.ecc
+++ b/contrib/testing_hostkeys.ecc
Binary files 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,
1889 GNUNET_NO); 1889 GNUNET_NO);
1890 LOG (GNUNET_ERROR_TYPE_WARNING, 1890 LOG (GNUNET_ERROR_TYPE_WARNING,
1891 "KX AUTH missmatch!\n"); 1891 "KX AUTH missmatch!\n");
1892 send_kx (t, 1892 if (NULL == t->kx_task)
1893 ct, 1893 t->kx_task
1894 &t->ax); 1894 = GNUNET_SCHEDULER_add_at (t->next_kx_attempt,
1895 &retry_kx,
1896 t);
1895 return; 1897 return;
1896 } 1898 }
1897 /* Yep, we're good. */ 1899 /* 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 = \
598 test_resolver_api_data.conf \ 598 test_resolver_api_data.conf \
599 test_service_data.conf \ 599 test_service_data.conf \
600 test_speedup_data.conf \ 600 test_speedup_data.conf \
601 gnunet-qr.py.in 601 gnunet-qr.py.in \
602 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 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2018 GNUnet e.V.
4
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.
9
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.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21/**
22 * @file util/crypto_bug.c
23 * @brief work around unidentified public key cryptography bug
24 * @author Christian Grothoff
25 */
26
27/**
28 * Enable work-around. Will cause code to call #check_eddsa_key() to
29 * see if we have a bad key, and if so, create a new one.
30 */
31#define CRYPTO_BUG 1
32
33
34#if CRYPTO_BUG
35/**
36 * Check if ECDH works with @a priv_dsa and this version
37 * of libgcrypt.
38 *
39 * @param priv_dsa key to check
40 * @return #GNUNET_OK if key passes
41 */
42static int
43check_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv_dsa)
44{
45 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh;
46 struct GNUNET_CRYPTO_EddsaPublicKey id1;
47 struct GNUNET_CRYPTO_EcdhePublicKey id2;
48 struct GNUNET_HashCode dh[2];
49
50 GNUNET_CRYPTO_eddsa_key_get_public (priv_dsa,
51 &id1);
52 for (unsigned int j=0;j<4;j++)
53 {
54 priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create ();
55 /* Extract public keys */
56 GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh,
57 &id2);
58 /* Do ECDH */
59 GNUNET_assert (GNUNET_OK ==
60 GNUNET_CRYPTO_eddsa_ecdh (priv_dsa,
61 &id2,
62 &dh[0]));
63 GNUNET_assert (GNUNET_OK ==
64 GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh,
65 &id1,
66 &dh[1]));
67 /* Check that both DH results are equal. */
68 if (0 != memcmp (&dh[0],
69 &dh[1],
70 sizeof (struct GNUNET_HashCode)))
71 {
72 GNUNET_break (0); /* bad EdDSA key! */
73 return GNUNET_SYSERR;
74 }
75 GNUNET_free (priv_ecdh);
76 }
77 return GNUNET_OK;
78}
79#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 @@
52#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0) 52#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0)
53 53
54 54
55#include "crypto_bug.c"
56
57
55/** 58/**
56 * Extract values from an S-expression. 59 * Extract values from an S-expression.
57 * 60 *
@@ -455,7 +458,7 @@ GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
455int 458int
456GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc, 459GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
457 size_t enclen, 460 size_t enclen,
458 struct GNUNET_CRYPTO_EddsaPrivateKey *pub) 461 struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
459{ 462{
460 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8; 463 size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
461 464
@@ -465,10 +468,19 @@ GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
465 if (enclen != keylen) 468 if (enclen != keylen)
466 return GNUNET_SYSERR; 469 return GNUNET_SYSERR;
467 470
468 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen, 471 if (GNUNET_OK !=
469 pub, 472 GNUNET_STRINGS_string_to_data (enc, enclen,
470 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey))) 473 priv,
474 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
471 return GNUNET_SYSERR; 475 return GNUNET_SYSERR;
476#if CRYPTO_BUG
477 if (GNUNET_OK !=
478 check_eddsa_key (priv))
479 {
480 GNUNET_break (0);
481 return GNUNET_OK;
482 }
483#endif
472 return GNUNET_OK; 484 return GNUNET_OK;
473} 485}
474 486
@@ -651,6 +663,9 @@ GNUNET_CRYPTO_eddsa_key_create ()
651 gcry_mpi_t d; 663 gcry_mpi_t d;
652 int rc; 664 int rc;
653 665
666#if CRYPTO_BUG
667 again:
668#endif
654 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, 669 if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
655 "(genkey(ecc(curve \"" CURVE "\")" 670 "(genkey(ecc(curve \"" CURVE "\")"
656 "(flags eddsa)))"))) 671 "(flags eddsa)))")))
@@ -683,6 +698,17 @@ GNUNET_CRYPTO_eddsa_key_create ()
683 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey); 698 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
684 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d); 699 GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
685 gcry_mpi_release (d); 700 gcry_mpi_release (d);
701
702#if CRYPTO_BUG
703 if (GNUNET_OK !=
704 check_eddsa_key (priv))
705 {
706 GNUNET_break (0);
707 GNUNET_free (priv);
708 goto again;
709 }
710#endif
711
686 return priv; 712 return priv;
687} 713}
688 714
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 @@
41#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) 41#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)
42 42
43 43
44#include "crypto_bug.c"
45
46
44/** 47/**
45 * Wait for a short time (we're trying to lock a file or want 48 * Wait for a short time (we're trying to lock a file or want
46 * to give another process a shot at finishing a disk write, etc.). 49 * 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)
221 filename); 224 filename);
222 GNUNET_assert (GNUNET_YES == 225 GNUNET_assert (GNUNET_YES ==
223 GNUNET_DISK_file_close (fd)); 226 GNUNET_DISK_file_close (fd));
227#if CRYPTO_BUG
228 if (GNUNET_OK !=
229 check_eddsa_key (priv))
230 {
231 GNUNET_break (0);
232 GNUNET_free (priv);
233 return NULL;
234 }
235#endif
224 return priv; 236 return priv;
225} 237}
226 238
@@ -248,7 +260,7 @@ GNUNET_CRYPTO_ecdsa_key_create_from_file (const char *filename)
248 int ec; 260 int ec;
249 uint64_t fs; 261 uint64_t fs;
250 ssize_t sret; 262 ssize_t sret;
251 263
252 if (GNUNET_SYSERR == 264 if (GNUNET_SYSERR ==
253 GNUNET_DISK_directory_create_for_file (filename)) 265 GNUNET_DISK_directory_create_for_file (filename))
254 return NULL; 266 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()
36 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh; 36 struct GNUNET_CRYPTO_EcdhePrivateKey *priv_ecdh;
37 struct GNUNET_CRYPTO_EddsaPublicKey id1; 37 struct GNUNET_CRYPTO_EddsaPublicKey id1;
38 struct GNUNET_CRYPTO_EcdhePublicKey id2; 38 struct GNUNET_CRYPTO_EcdhePublicKey id2;
39 struct GNUNET_HashCode dh[3]; 39 struct GNUNET_HashCode dh[2];
40 40
41 /* Generate keys */ 41 /* Generate keys */
42 priv_dsa = GNUNET_CRYPTO_eddsa_key_create (); 42 priv_dsa = GNUNET_CRYPTO_eddsa_key_create ();
43 priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create ();
44 /* Extract public keys */
45 GNUNET_CRYPTO_eddsa_key_get_public (priv_dsa, 43 GNUNET_CRYPTO_eddsa_key_get_public (priv_dsa,
46 &id1); 44 &id1);
47 GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh, 45 for (unsigned int j=0;j<10;j++)
48 &id2); 46 {
49 /* Do ECDH */ 47 fprintf (stderr, ",");
50 GNUNET_assert (GNUNET_OK == 48 priv_ecdh = GNUNET_CRYPTO_ecdhe_key_create ();
51 GNUNET_CRYPTO_eddsa_ecdh (priv_dsa, 49 /* Extract public keys */
52 &id2, 50 GNUNET_CRYPTO_ecdhe_key_get_public (priv_ecdh,
53 &dh[0])); 51 &id2);
54 GNUNET_assert (GNUNET_OK == 52 /* Do ECDH */
55 GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh, 53 GNUNET_assert (GNUNET_OK ==
56 &id1, 54 GNUNET_CRYPTO_eddsa_ecdh (priv_dsa,
57 &dh[1])); 55 &id2,
58 /* Check that both DH results are equal. */ 56 &dh[0]));
59 GNUNET_assert (0 == memcmp (&dh[0], 57 GNUNET_assert (GNUNET_OK ==
60 &dh[1], 58 GNUNET_CRYPTO_ecdh_eddsa (priv_ecdh,
61 sizeof (struct GNUNET_HashCode))); 59 &id1,
60 &dh[1]));
61 /* Check that both DH results are equal. */
62 GNUNET_assert (0 == memcmp (&dh[0],
63 &dh[1],
64 sizeof (struct GNUNET_HashCode)));
65 GNUNET_free (priv_ecdh);
66 }
62 GNUNET_free (priv_dsa); 67 GNUNET_free (priv_dsa);
63 GNUNET_free (priv_ecdh);
64 return 0; 68 return 0;
65} 69}
66 70
@@ -78,7 +82,7 @@ main (int argc, char *argv[])
78 if (getenv ("GNUNET_GCRYPT_DEBUG")) 82 if (getenv ("GNUNET_GCRYPT_DEBUG"))
79 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0); 83 gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
80 GNUNET_log_setup ("test-crypto-ecdh-eddsa", "WARNING", NULL); 84 GNUNET_log_setup ("test-crypto-ecdh-eddsa", "WARNING", NULL);
81 for (unsigned int i=0;i<10000;i++) 85 for (unsigned int i=0;i<100;i++)
82 { 86 {
83 fprintf (stderr, 87 fprintf (stderr,
84 "."); 88 ".");