aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc.c
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-11-26 18:26:54 +0100
committerFlorian Dold <florian.dold@gmail.com>2019-11-26 18:29:56 +0100
commitbc340979c19807c76baedc7da98778178b9bcc4a (patch)
treec7e0e017a441ea5bc13d9e165417c5156e390c9b /src/util/crypto_ecc.c
parentc36c37830eb909fe73357383136cf8b2405d9633 (diff)
downloadgnunet-bc340979c19807c76baedc7da98778178b9bcc4a.tar.gz
gnunet-bc340979c19807c76baedc7da98778178b9bcc4a.zip
use Curve25519 for ECDH and tweetnacl where we can
This leads to some performance improvements and makes it easier to write software that interoperates with GNUnet / GNU Taler. It also avoids using the rather inconvenient libgcrypt APIs. We still need to keep libgcrypt though, as we need it for RSA, ECDSA and some other primitives. This change is still behind a #define NEW_CRYPTO, as it is a breaking change for both EdDSA (removing the superfluous additional hash) and for ECDHE (using Curve25519 instead of Ed25519).
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r--src/util/crypto_ecc.c109
1 files changed, 108 insertions, 1 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 12284a7a9..86beb9109 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -22,15 +22,20 @@
22 * @file util/crypto_ecc.c 22 * @file util/crypto_ecc.c
23 * @brief public key cryptography (ECC) with libgcrypt 23 * @brief public key cryptography (ECC) with libgcrypt
24 * @author Christian Grothoff 24 * @author Christian Grothoff
25 * @author Florian Dold
25 */ 26 */
26#include "platform.h" 27#include "platform.h"
27#include <gcrypt.h> 28#include <gcrypt.h>
28#include "gnunet_crypto_lib.h" 29#include "gnunet_crypto_lib.h"
29#include "gnunet_strings_lib.h" 30#include "gnunet_strings_lib.h"
30#include "benchmark.h" 31#include "benchmark.h"
32#include "tweetnacl-gnunet.h"
31 33
32#define EXTRA_CHECKS 0 34#define EXTRA_CHECKS 0
33 35
36#define NEW_CRYPTO 0
37
38
34/** 39/**
35 * Name of the curve we are using. Note that we have hard-coded 40 * Name of the curve we are using. Note that we have hard-coded
36 * structs that use 256 bits, so using a bigger curve will require 41 * structs that use 256 bits, so using a bigger curve will require
@@ -159,6 +164,7 @@ decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
159} 164}
160 165
161 166
167#if !NEW_CRYPTO
162/** 168/**
163 * Convert the given private key from the network format to the 169 * Convert the given private key from the network format to the
164 * S-expression that can be used by libgcrypt. 170 * S-expression that can be used by libgcrypt.
@@ -192,8 +198,10 @@ decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
192#endif 198#endif
193 return result; 199 return result;
194} 200}
201#endif /* !NEW_CRYPTO */
195 202
196 203
204#if !NEW_CRYPTO
197/** 205/**
198 * Convert the given private key from the network format to the 206 * Convert the given private key from the network format to the
199 * S-expression that can be used by libgcrypt. 207 * S-expression that can be used by libgcrypt.
@@ -227,6 +235,7 @@ decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
227#endif 235#endif
228 return result; 236 return result;
229} 237}
238#endif /* !NEW_CRYPTO */
230 239
231 240
232/** 241/**
@@ -271,6 +280,11 @@ GNUNET_CRYPTO_eddsa_key_get_public (
271 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, 280 const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
272 struct GNUNET_CRYPTO_EddsaPublicKey *pub) 281 struct GNUNET_CRYPTO_EddsaPublicKey *pub)
273{ 282{
283#if NEW_CRYPTO
284 BENCHMARK_START (eddsa_key_get_public);
285 crypto_sign_pk_from_seed (pub->q_y, priv->d);
286 BENCHMARK_END (eddsa_key_get_public);
287#else
274 gcry_sexp_t sexp; 288 gcry_sexp_t sexp;
275 gcry_ctx_t ctx; 289 gcry_ctx_t ctx;
276 gcry_mpi_t q; 290 gcry_mpi_t q;
@@ -288,6 +302,7 @@ GNUNET_CRYPTO_eddsa_key_get_public (
288 gcry_ctx_release (ctx); 302 gcry_ctx_release (ctx);
289 303
290 BENCHMARK_END (eddsa_key_get_public); 304 BENCHMARK_END (eddsa_key_get_public);
305#endif
291} 306}
292 307
293 308
@@ -302,6 +317,11 @@ GNUNET_CRYPTO_ecdhe_key_get_public (
302 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, 317 const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
303 struct GNUNET_CRYPTO_EcdhePublicKey *pub) 318 struct GNUNET_CRYPTO_EcdhePublicKey *pub)
304{ 319{
320#if NEW_CRYPTO
321 BENCHMARK_START (ecdhe_key_get_public);
322 crypto_scalarmult_curve25519_base (pub->q_y, priv->d);
323 BENCHMARK_END (ecdhe_key_get_public);
324#else
305 gcry_sexp_t sexp; 325 gcry_sexp_t sexp;
306 gcry_ctx_t ctx; 326 gcry_ctx_t ctx;
307 gcry_mpi_t q; 327 gcry_mpi_t q;
@@ -319,6 +339,7 @@ GNUNET_CRYPTO_ecdhe_key_get_public (
319 gcry_ctx_release (ctx); 339 gcry_ctx_release (ctx);
320 340
321 BENCHMARK_END (ecdhe_key_get_public); 341 BENCHMARK_END (ecdhe_key_get_public);
342#endif
322} 343}
323 344
324 345
@@ -629,6 +650,14 @@ GNUNET_CRYPTO_ecdhe_key_create ()
629int 650int
630GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk) 651GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
631{ 652{
653#if NEW_CRYPTO
654 BENCHMARK_START (ecdhe_key_create);
655 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
656 pk,
657 sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
658 BENCHMARK_END (ecdhe_key_create);
659 return GNUNET_OK;
660#else
632 gcry_sexp_t priv_sexp; 661 gcry_sexp_t priv_sexp;
633 gcry_sexp_t s_keyparam; 662 gcry_sexp_t s_keyparam;
634 gcry_mpi_t d; 663 gcry_mpi_t d;
@@ -676,6 +705,7 @@ GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
676 BENCHMARK_END (ecdhe_key_create); 705 BENCHMARK_END (ecdhe_key_create);
677 706
678 return GNUNET_OK; 707 return GNUNET_OK;
708#endif
679} 709}
680 710
681 711
@@ -743,6 +773,18 @@ GNUNET_CRYPTO_ecdsa_key_create ()
743struct GNUNET_CRYPTO_EddsaPrivateKey * 773struct GNUNET_CRYPTO_EddsaPrivateKey *
744GNUNET_CRYPTO_eddsa_key_create () 774GNUNET_CRYPTO_eddsa_key_create ()
745{ 775{
776#if NEW_CRYPTO
777 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
778
779 BENCHMARK_START (eddsa_key_create);
780 priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
781 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
782 priv,
783 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
784 BENCHMARK_END (eddsa_key_create);
785
786 return priv;
787#else
746 struct GNUNET_CRYPTO_EddsaPrivateKey *priv; 788 struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
747 gcry_sexp_t priv_sexp; 789 gcry_sexp_t priv_sexp;
748 gcry_sexp_t s_keyparam; 790 gcry_sexp_t s_keyparam;
@@ -752,7 +794,7 @@ GNUNET_CRYPTO_eddsa_key_create ()
752 BENCHMARK_START (eddsa_key_create); 794 BENCHMARK_START (eddsa_key_create);
753 795
754#if CRYPTO_BUG 796#if CRYPTO_BUG
755again: 797 again:
756#endif 798#endif
757 if (0 != (rc = gcry_sexp_build (&s_keyparam, 799 if (0 != (rc = gcry_sexp_build (&s_keyparam,
758 NULL, 800 NULL,
@@ -800,6 +842,7 @@ again:
800 BENCHMARK_END (eddsa_key_create); 842 BENCHMARK_END (eddsa_key_create);
801 843
802 return priv; 844 return priv;
845#endif
803} 846}
804 847
805 848
@@ -828,6 +871,7 @@ GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
828} 871}
829 872
830 873
874#if !NEW_CRYPTO
831/** 875/**
832 * Convert the data specified in the given purpose argument to an 876 * Convert the data specified in the given purpose argument to an
833 * S-expression suitable for signature operations. 877 * S-expression suitable for signature operations.
@@ -870,6 +914,7 @@ data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
870#endif 914#endif
871 return data; 915 return data;
872} 916}
917#endif /* !NEW_CRYPTO */
873 918
874 919
875/** 920/**
@@ -988,6 +1033,22 @@ GNUNET_CRYPTO_eddsa_sign (
988 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, 1033 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
989 struct GNUNET_CRYPTO_EddsaSignature *sig) 1034 struct GNUNET_CRYPTO_EddsaSignature *sig)
990{ 1035{
1036
1037#if NEW_CRYPTO
1038 size_t mlen = ntohl (purpose->size);
1039 unsigned char sk[crypto_sign_SECRETKEYBYTES];
1040 int res;
1041
1042 BENCHMARK_START (eddsa_sign);
1043 crypto_sign_sk_from_seed (sk, priv->d);
1044 res = crypto_sign_detached ((uint8_t *) sig,
1045 (uint8_t *) purpose,
1046 mlen,
1047 sk);
1048 BENCHMARK_END (eddsa_sign);
1049 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
1050#else
1051
991 gcry_sexp_t priv_sexp; 1052 gcry_sexp_t priv_sexp;
992 gcry_sexp_t sig_sexp; 1053 gcry_sexp_t sig_sexp;
993 gcry_sexp_t data; 1054 gcry_sexp_t data;
@@ -1029,6 +1090,7 @@ GNUNET_CRYPTO_eddsa_sign (
1029 BENCHMARK_END (eddsa_sign); 1090 BENCHMARK_END (eddsa_sign);
1030 1091
1031 return GNUNET_OK; 1092 return GNUNET_OK;
1093#endif
1032} 1094}
1033 1095
1034 1096
@@ -1116,6 +1178,21 @@ GNUNET_CRYPTO_eddsa_verify (
1116 const struct GNUNET_CRYPTO_EddsaSignature *sig, 1178 const struct GNUNET_CRYPTO_EddsaSignature *sig,
1117 const struct GNUNET_CRYPTO_EddsaPublicKey *pub) 1179 const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
1118{ 1180{
1181#if NEW_CRYPTO
1182 unsigned char *m = (void *) validate;
1183 size_t mlen = ntohl (validate->size);
1184 unsigned char *s = (void *) sig;
1185
1186 int res;
1187
1188 if (purpose != ntohl (validate->purpose))
1189 return GNUNET_SYSERR; /* purpose mismatch */
1190
1191 BENCHMARK_START (eddsa_verify);
1192 res = crypto_sign_detached_verify (s, m, mlen, pub->q_y);
1193 BENCHMARK_END (eddsa_verify);
1194 return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
1195#else
1119 gcry_sexp_t data; 1196 gcry_sexp_t data;
1120 gcry_sexp_t sig_sexpr; 1197 gcry_sexp_t sig_sexpr;
1121 gcry_sexp_t pub_sexpr; 1198 gcry_sexp_t pub_sexpr;
@@ -1167,6 +1244,7 @@ GNUNET_CRYPTO_eddsa_verify (
1167 } 1244 }
1168 BENCHMARK_END (eddsa_verify); 1245 BENCHMARK_END (eddsa_verify);
1169 return GNUNET_OK; 1246 return GNUNET_OK;
1247#endif
1170} 1248}
1171 1249
1172 1250
@@ -1183,6 +1261,12 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1183 const struct GNUNET_CRYPTO_EcdhePublicKey *pub, 1261 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1184 struct GNUNET_HashCode *key_material) 1262 struct GNUNET_HashCode *key_material)
1185{ 1263{
1264#if NEW_CRYPTO
1265 uint8_t p[crypto_scalarmult_BYTES];
1266 crypto_scalarmult_curve25519 (p, priv->d, pub->q_y);
1267 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
1268 return GNUNET_OK;
1269#else
1186 gcry_mpi_point_t result; 1270 gcry_mpi_point_t result;
1187 gcry_mpi_point_t q; 1271 gcry_mpi_point_t q;
1188 gcry_mpi_t d; 1272 gcry_mpi_t d;
@@ -1238,6 +1322,7 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1238 gcry_mpi_release (result_x); 1322 gcry_mpi_release (result_x);
1239 BENCHMARK_END (ecc_ecdh); 1323 BENCHMARK_END (ecc_ecdh);
1240 return GNUNET_OK; 1324 return GNUNET_OK;
1325#endif
1241} 1326}
1242 1327
1243 1328
@@ -1384,6 +1469,7 @@ GNUNET_CRYPTO_ecdsa_public_key_derive (
1384} 1469}
1385 1470
1386 1471
1472#if !NEW_CRYPTO
1387/** 1473/**
1388 * Reverse the sequence of the bytes in @a buffer 1474 * Reverse the sequence of the bytes in @a buffer
1389 * 1475 *
@@ -1447,6 +1533,7 @@ eddsa_d_to_a (gcry_mpi_t d)
1447 GNUNET_CRYPTO_mpi_scan_unsigned (&a, digest, 32); 1533 GNUNET_CRYPTO_mpi_scan_unsigned (&a, digest, 32);
1448 return a; 1534 return a;
1449} 1535}
1536#endif
1450 1537
1451 1538
1452/** 1539/**
@@ -1503,6 +1590,16 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1503 const struct GNUNET_CRYPTO_EcdhePublicKey *pub, 1590 const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
1504 struct GNUNET_HashCode *key_material) 1591 struct GNUNET_HashCode *key_material)
1505{ 1592{
1593#if NEW_CRYPTO
1594 struct GNUNET_HashCode hc;
1595 uint8_t a[crypto_scalarmult_BYTES];
1596 uint8_t p[crypto_scalarmult_BYTES];
1597 GNUNET_CRYPTO_hash (priv, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), &hc);
1598 memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
1599 crypto_scalarmult_curve25519 (p, a, pub->q_y);
1600 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
1601 return GNUNET_OK;
1602#else
1506 gcry_mpi_point_t result; 1603 gcry_mpi_point_t result;
1507 gcry_mpi_point_t q; 1604 gcry_mpi_point_t q;
1508 gcry_mpi_t d; 1605 gcry_mpi_t d;
@@ -1542,6 +1639,7 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
1542 gcry_ctx_release (ctx); 1639 gcry_ctx_release (ctx);
1543 BENCHMARK_END (eddsa_ecdh); 1640 BENCHMARK_END (eddsa_ecdh);
1544 return ret; 1641 return ret;
1642#endif
1545} 1643}
1546 1644
1547 1645
@@ -1613,6 +1711,14 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1613 const struct GNUNET_CRYPTO_EddsaPublicKey *pub, 1711 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
1614 struct GNUNET_HashCode *key_material) 1712 struct GNUNET_HashCode *key_material)
1615{ 1713{
1714#if NEW_CRYPTO
1715 uint8_t p[crypto_scalarmult_BYTES];
1716 uint8_t curve25510_pk[crypto_sign_PUBLICKEYBYTES];
1717 crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y);
1718 crypto_scalarmult_curve25519 (p, priv->d, curve25510_pk);
1719 GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
1720 return GNUNET_OK;
1721#else
1616 gcry_mpi_point_t result; 1722 gcry_mpi_point_t result;
1617 gcry_mpi_point_t q; 1723 gcry_mpi_point_t q;
1618 gcry_mpi_t d; 1724 gcry_mpi_t d;
@@ -1648,6 +1754,7 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
1648 gcry_ctx_release (ctx); 1754 gcry_ctx_release (ctx);
1649 BENCHMARK_END (ecdh_eddsa); 1755 BENCHMARK_END (ecdh_eddsa);
1650 return ret; 1756 return ret;
1757#endif
1651} 1758}
1652 1759
1653 1760