aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/Makefile.am3
-rw-r--r--src/util/crypto_ecc.c134
-rw-r--r--src/util/test_crypto_ecc.c11
3 files changed, 78 insertions, 70 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 425cc8cca..9920fce0b 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -342,7 +342,8 @@ test_crypto_crc_LDADD = \
342test_crypto_ecc_SOURCES = \ 342test_crypto_ecc_SOURCES = \
343 test_crypto_ecc.c 343 test_crypto_ecc.c
344test_crypto_ecc_LDADD = \ 344test_crypto_ecc_LDADD = \
345 $(top_builddir)/src/util/libgnunetutil.la 345 $(top_builddir)/src/util/libgnunetutil.la \
346 $(LIBGCRYPT_LIBS)
346 347
347test_crypto_hash_SOURCES = \ 348test_crypto_hash_SOURCES = \
348 test_crypto_hash.c 349 test_crypto_hash.c
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index a3c92a335..088d765cd 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2012 Christian Grothoff (and other contributing authors) 3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -263,9 +263,7 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicK
263 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ 263 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */
264 return NULL; 264 return NULL;
265 } 265 }
266 // FIXME: is this key expected to pass pk_testkey? 266#if EXTRA_CHECKS
267#if 0
268#if EXTRA_CHECKS
269 if (0 != (rc = gcry_pk_testkey (result))) 267 if (0 != (rc = gcry_pk_testkey (result)))
270 { 268 {
271 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); 269 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
@@ -273,7 +271,6 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicK
273 return NULL; 271 return NULL;
274 } 272 }
275#endif 273#endif
276#endif
277 return result; 274 return result;
278} 275}
279 276
@@ -1066,74 +1063,85 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1066 const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub, 1063 const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *pub,
1067 struct GNUNET_HashCode *key_material) 1064 struct GNUNET_HashCode *key_material)
1068{ 1065{
1069 size_t size;
1070 size_t slen; 1066 size_t slen;
1067 size_t erroff;
1071 int rc; 1068 int rc;
1072 gcry_sexp_t data; 1069 unsigned char sdata_buf[2048]; /* big enough to print dh-shared-secret as S-expression */
1073 unsigned char sdata_buf[2048]; /* big enough to print 'sdata' and 'r_sig' */ 1070 gcry_mpi_point_t result;
1071 gcry_mpi_point_t q;
1072 gcry_mpi_t d;
1073 gcry_ctx_t ctx;
1074 gcry_sexp_t psexp;
1075 gcry_mpi_t result_x;
1076 gcry_mpi_t result_y;
1074 1077
1075 /* first, extract the q value from the public key */ 1078 /* first, extract the q = dP value from the public key */
1079 if (! (psexp = decode_public_key (pub)))
1080 return GNUNET_SYSERR;
1081 if (0 != (rc = gcry_mpi_ec_new (&ctx, psexp, NULL)))
1076 { 1082 {
1077 gcry_sexp_t psexp; 1083 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1078 gcry_mpi_t sdata; 1084 return GNUNET_SYSERR;
1079
1080 if (! (psexp = decode_public_key (pub)))
1081 return GNUNET_SYSERR;
1082 rc = key_from_sexp (&sdata, psexp, "public-key", "q");
1083 if (rc)
1084 rc = key_from_sexp (&sdata, psexp, "ecc", "q");
1085 GNUNET_assert (0 == rc);
1086 gcry_sexp_release (psexp);
1087 size = sizeof (sdata_buf);
1088 GNUNET_assert (0 ==
1089 gcry_mpi_print (GCRYMPI_FMT_USG, sdata_buf, size, &size,
1090 sdata));
1091 gcry_mpi_release (sdata);
1092 } 1085 }
1093 /* convert q value into an S-expression -- whatever format libgcrypt wants, 1086 gcry_sexp_release (psexp);
1094 re-using format from sign operation for now... */ 1087 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1088 gcry_ctx_release (ctx);
1089
1090 /* second, extract the d value from our private key */
1091 rc = key_from_sexp (&d, key->sexp, "private-key", "d");
1092 if (rc)
1093 rc = key_from_sexp (&d, key->sexp, "ecc", "d");
1094 if (0 != rc)
1095 { 1095 {
1096 char *sexp_string; 1096 GNUNET_break (0);
1097 1097 gcry_mpi_point_release (q);
1098#define FORMATPREFIX "(4:data(5:flags3:raw)(5:value%u:" 1098 return GNUNET_SYSERR;
1099#define FORMATPOSTFIX "))"
1100 sexp_string = GNUNET_malloc (strlen (FORMATPREFIX) + size + 12 +
1101 strlen (FORMATPOSTFIX) + 1);
1102 GNUNET_snprintf (sexp_string,
1103 strlen (FORMATPREFIX) + 12,
1104 FORMATPREFIX,
1105 size);
1106 slen = strlen (sexp_string);
1107 memcpy (&sexp_string[slen],
1108 sdata_buf,
1109 size);
1110 memcpy (&sexp_string[slen + size],
1111 FORMATPOSTFIX,
1112 strlen (FORMATPOSTFIX) + 1);
1113 GNUNET_assert (0 == gcry_sexp_new (&data,
1114 sexp_string,
1115 slen + size + strlen (FORMATPOSTFIX),
1116 0));
1117 GNUNET_free (sexp_string);
1118 } 1099 }
1119 /* then call the 'multiply' function, hoping it simply multiplies the points; 1100
1120 here we need essentially a WRAPPER around _gcry_mpi_ex_mul_point! - FIXME-WK!*/ 1101 /* create a new context for definitively the correct curve;
1121#if WK 1102 theoretically the 'public_key' might not use the right curve */
1103 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1122 { 1104 {
1123 gcry_sexp_t result; 1105 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1124 1106 gcry_mpi_release (d);
1125 rc = gcry_ecc_mul_point (&result, data /* scalar */, key->sexp /* point and ctx */); 1107 gcry_mpi_point_release (q);
1126 GNUNET_assert (0 == rc); 1108 return GNUNET_SYSERR;
1127 slen = gcry_sexp_sprint (result, GCRYSEXP_FMT_DEFAULT, sdata_buf, sizeof (sdata_buf));
1128 GNUNET_assert (0 != slen);
1129 } 1109 }
1130#else
1131 /* use broken version, insecure! */
1132 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("To be implemented: not secure at the moment, please read README\n"));
1133 slen = sprintf ((char*) sdata_buf, "FIXME-this is not key material");
1134#endif
1135 gcry_sexp_release (data);
1136 1110
1111 /* then call the 'multiply' function, to compute the product */
1112 GNUNET_assert (NULL != ctx);
1113 result = gcry_mpi_point_new (0);
1114 gcry_mpi_ec_mul (result, d, q, ctx);
1115 gcry_mpi_point_release (q);
1116 gcry_mpi_release (d);
1117
1118 /* finally, convert point to string for hashing */
1119 result_x = gcry_mpi_new (256);
1120 result_y = gcry_mpi_new (256);
1121 if (gcry_mpi_ec_get_affine (result_x, result_y, result, ctx))
1122 {
1123 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
1124 gcry_mpi_point_release (result);
1125 gcry_ctx_release (ctx);
1126 return GNUNET_SYSERR;
1127 }
1128 gcry_mpi_point_release (result);
1129 gcry_ctx_release (ctx);
1130 if (0 != (rc = gcry_sexp_build (&psexp, &erroff,
1131 "(dh-shared-secret (x %m)(y %m))",
1132 result_x,
1133 result_y)))
1134 {
1135 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */
1136 gcry_mpi_release (result_x);
1137 gcry_mpi_release (result_y);
1138 return GNUNET_SYSERR;
1139 }
1140 gcry_mpi_release (result_x);
1141 gcry_mpi_release (result_y);
1142 slen = gcry_sexp_sprint (psexp, GCRYSEXP_FMT_DEFAULT, sdata_buf, sizeof (sdata_buf));
1143 GNUNET_assert (0 != slen);
1144 gcry_sexp_release (psexp);
1137 /* finally, get a string of the resulting S-expression and hash it to generate the key material */ 1145 /* finally, get a string of the resulting S-expression and hash it to generate the key material */
1138 GNUNET_CRYPTO_hash (sdata_buf, slen, key_material); 1146 GNUNET_CRYPTO_hash (sdata_buf, slen, key_material);
1139 return GNUNET_OK; 1147 return GNUNET_OK;
diff --git a/src/util/test_crypto_ecc.c b/src/util/test_crypto_ecc.c
index fb6d5968a..8aa58971f 100644
--- a/src/util/test_crypto_ecc.c
+++ b/src/util/test_crypto_ecc.c
@@ -195,12 +195,13 @@ test_ecdh ()
195 GNUNET_CRYPTO_ecc_key_get_public (priv2, &pub2); 195 GNUNET_CRYPTO_ecc_key_get_public (priv2, &pub2);
196 GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1); 196 GNUNET_CRYPTO_ecc_ecdh (priv1, &pub2, &ecdh1);
197 GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2); 197 GNUNET_CRYPTO_ecc_ecdh (priv2, &pub1, &ecdh2);
198 GNUNET_CRYPTO_ecc_key_free (priv1);
199 GNUNET_CRYPTO_ecc_key_free (priv2);
200 GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2, 198 GNUNET_assert (0 == memcmp (&ecdh1, &ecdh2,
201 sizeof (struct GNUNET_HashCode))); 199 sizeof (struct GNUNET_HashCode)));
200 GNUNET_CRYPTO_ecc_key_free (priv1);
201 GNUNET_CRYPTO_ecc_key_free (priv2);
202} 202}
203 203
204
204static void 205static void
205perf_keygen () 206perf_keygen ()
206{ 207{
@@ -216,13 +217,11 @@ perf_keygen ()
216 GNUNET_CRYPTO_ecc_key_free (pk); 217 GNUNET_CRYPTO_ecc_key_free (pk);
217 } 218 }
218 fprintf (stderr, "\n"); 219 fprintf (stderr, "\n");
219 printf ("Creating 10 ECC keys took %llu ms\n", 220 printf ("Creating 10 ECC keys took %s\n",
220 (unsigned long long) 221 GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (start), GNUNET_YES));
221 GNUNET_TIME_absolute_get_duration (start).rel_value);
222} 222}
223 223
224 224
225
226int 225int
227main (int argc, char *argv[]) 226main (int argc, char *argv[])
228{ 227{