diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-11-26 18:26:54 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-11-26 18:29:56 +0100 |
commit | bc340979c19807c76baedc7da98778178b9bcc4a (patch) | |
tree | c7e0e017a441ea5bc13d9e165417c5156e390c9b /src/util/crypto_ecc.c | |
parent | c36c37830eb909fe73357383136cf8b2405d9633 (diff) | |
download | gnunet-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.c | 109 |
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 () | |||
629 | int | 650 | int |
630 | GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk) | 651 | GNUNET_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 () | |||
743 | struct GNUNET_CRYPTO_EddsaPrivateKey * | 773 | struct GNUNET_CRYPTO_EddsaPrivateKey * |
744 | GNUNET_CRYPTO_eddsa_key_create () | 774 | GNUNET_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 |
755 | again: | 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 | ||