aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/util/Makefile.am1
-rw-r--r--src/util/crypto_ecc.c109
-rw-r--r--src/util/tweetnacl-gnunet.c530
-rw-r--r--src/util/tweetnacl-gnunet.h85
4 files changed, 724 insertions, 1 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index b89250711..fce064d0c 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -93,6 +93,7 @@ libgnunetutil_la_SOURCES = \
93 strings.c \ 93 strings.c \
94 time.c \ 94 time.c \
95 tun.c \ 95 tun.c \
96 tweetnacl-gnunet.c \
96 speedup.c speedup.h \ 97 speedup.c speedup.h \
97 proc_compat.c 98 proc_compat.c
98 99
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
diff --git a/src/util/tweetnacl-gnunet.c b/src/util/tweetnacl-gnunet.c
new file mode 100644
index 000000000..b0d87c2fe
--- /dev/null
+++ b/src/util/tweetnacl-gnunet.c
@@ -0,0 +1,530 @@
1/*
2 This file has been placed in the public domain.
3
4 Based on TweetNaCl version 20140427
5
6 Originally obtained from:
7 https://tweetnacl.cr.yp.to/20140427/tweetnacl.h
8*/
9
10#include "platform.h"
11#include "gnunet_crypto_lib.h"
12#include "tweetnacl-gnunet.h"
13#define FOR(i,n) for (i = 0; i < n; ++i)
14#define sv static void
15
16typedef uint8_t u8;
17typedef uint32_t u32;
18typedef uint64_t u64;
19typedef int64_t i64;
20typedef i64 gf[16];
21
22static void randombytes (u8 *data,u64 len)
23{
24 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, data, len);
25}
26
27static const u8 _9[32] = {9};
28static const gf
29 gf0,
30 gf1 = {1},
31 _121665 = {0xDB41,1},
32 D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898,
33 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
34 D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130,
35 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
36 X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c,
37 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
38 Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
39 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
40 I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7,
41 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
42
43static int vn (const u8 *x,const u8 *y,int n)
44{
45 u32 i,d = 0;
46 FOR (i,n) d |= x[i] ^ y[i];
47 return (1 & ((d - 1) >> 8)) - 1;
48}
49
50int crypto_verify_16 (const u8 *x,const u8 *y)
51{
52 return vn (x,y,16);
53}
54
55int crypto_verify_32 (const u8 *x,const u8 *y)
56{
57 return vn (x,y,32);
58}
59
60sv set25519 (gf r, const gf a)
61{
62 int i;
63 FOR (i,16) r[i] = a[i];
64}
65
66sv car25519 (gf o)
67{
68 int i;
69 i64 c;
70 FOR (i,16) {
71 o[i] += (1LL << 16);
72 c = o[i] >> 16;
73 o[(i + 1) * (i<15)] += c - 1 + 37 * (c - 1) * (i==15);
74 o[i] -= c << 16;
75 }
76}
77
78sv sel25519 (gf p,gf q,int b)
79{
80 i64 t,i,c = ~(b - 1);
81 FOR (i,16) {
82 t = c & (p[i] ^ q[i]);
83 p[i] ^= t;
84 q[i] ^= t;
85 }
86}
87
88sv pack25519 (u8 *o,const gf n)
89{
90 int i,j,b;
91 gf m,t;
92 FOR (i,16) t[i] = n[i];
93 car25519 (t);
94 car25519 (t);
95 car25519 (t);
96 FOR (j,2) {
97 m[0] = t[0] - 0xffed;
98 for (i = 1; i<15; i++) {
99 m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
100 m[i - 1] &= 0xffff;
101 }
102 m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
103 b = (m[15] >> 16) & 1;
104 m[14] &= 0xffff;
105 sel25519 (t,m,1 - b);
106 }
107 FOR (i,16) {
108 o[2 * i] = t[i] & 0xff;
109 o[2 * i + 1] = t[i] >> 8;
110 }
111}
112
113static int neq25519 (const gf a, const gf b)
114{
115 u8 c[32],d[32];
116 pack25519 (c,a);
117 pack25519 (d,b);
118 return crypto_verify_32 (c,d);
119}
120
121static u8 par25519 (const gf a)
122{
123 u8 d[32];
124 pack25519 (d,a);
125 return d[0] & 1;
126}
127
128sv unpack25519 (gf o, const u8 *n)
129{
130 int i;
131 FOR (i,16) o[i] = n[2 * i] + ((i64) n[2 * i + 1] << 8);
132 o[15] &= 0x7fff;
133}
134
135sv A (gf o,const gf a,const gf b)
136{
137 int i;
138 FOR (i,16) o[i] = a[i] + b[i];
139}
140
141sv Z (gf o,const gf a,const gf b)
142{
143 int i;
144 FOR (i,16) o[i] = a[i] - b[i];
145}
146
147sv M (gf o,const gf a,const gf b)
148{
149 i64 i,j,t[31];
150 FOR (i,31) t[i] = 0;
151 FOR (i,16) FOR (j,16) t[i + j] += a[i] * b[j];
152 FOR (i,15) t[i] += 38 * t[i + 16];
153 FOR (i,16) o[i] = t[i];
154 car25519 (o);
155 car25519 (o);
156}
157
158sv S (gf o,const gf a)
159{
160 M (o,a,a);
161}
162
163sv inv25519 (gf o,const gf i)
164{
165 gf c;
166 int a;
167 FOR (a,16) c[a] = i[a];
168 for (a = 253; a>=0; a--) {
169 S (c,c);
170 if ((a!=2)&&(a!=4))
171 M (c,c,i);
172 }
173 FOR (a,16) o[a] = c[a];
174}
175
176sv pow2523 (gf o,const gf i)
177{
178 gf c;
179 int a;
180 FOR (a,16) c[a] = i[a];
181 for (a = 250; a>=0; a--) {
182 S (c,c);
183 if (a!=1)
184 M (c,c,i);
185 }
186 FOR (a,16) o[a] = c[a];
187}
188
189int crypto_scalarmult (u8 *q,const u8 *n,const u8 *p)
190{
191 u8 z[32];
192 i64 x[80],r,i;
193 gf a,b,c,d,e,f;
194 FOR (i,31) z[i] = n[i];
195 z[31] = (n[31] & 127) | 64;
196 z[0] &= 248;
197 unpack25519 (x,p);
198 FOR (i,16) {
199 b[i] = x[i];
200 d[i] = a[i] = c[i] = 0;
201 }
202 a[0] = d[0] = 1;
203 for (i = 254; i>=0; --i) {
204 r = (z[i >> 3] >> (i & 7)) & 1;
205 sel25519 (a,b,r);
206 sel25519 (c,d,r);
207 A (e,a,c);
208 Z (a,a,c);
209 A (c,b,d);
210 Z (b,b,d);
211 S (d,e);
212 S (f,a);
213 M (a,c,a);
214 M (c,b,e);
215 A (e,a,c);
216 Z (a,a,c);
217 S (b,a);
218 Z (c,d,f);
219 M (a,c,_121665);
220 A (a,a,d);
221 M (c,c,a);
222 M (a,d,f);
223 M (d,b,x);
224 S (b,e);
225 sel25519 (a,b,r);
226 sel25519 (c,d,r);
227 }
228 FOR (i,16) {
229 x[i + 16] = a[i];
230 x[i + 32] = c[i];
231 x[i + 48] = b[i];
232 x[i + 64] = d[i];
233 }
234 inv25519 (x + 32,x + 32);
235 M (x + 16,x + 16,x + 32);
236 pack25519 (q,x + 16);
237 return 0;
238}
239
240int crypto_scalarmult_base (u8 *q,const u8 *n)
241{
242 return crypto_scalarmult (q,n,_9);
243}
244
245int crypto_box_keypair (u8 *y,u8 *x)
246{
247 randombytes (x,32);
248 return crypto_scalarmult_base (y,x);
249}
250
251int crypto_hash (u8 *out,const u8 *m,u64 n)
252{
253 struct GNUNET_HashCode *hc = (void *) out;
254 GNUNET_CRYPTO_hash (m, n, hc);
255 return 0;
256}
257
258sv add (gf p[4],gf q[4])
259{
260 gf a,b,c,d,t,e,f,g,h;
261
262 Z (a, p[1], p[0]);
263 Z (t, q[1], q[0]);
264 M (a, a, t);
265 A (b, p[0], p[1]);
266 A (t, q[0], q[1]);
267 M (b, b, t);
268 M (c, p[3], q[3]);
269 M (c, c, D2);
270 M (d, p[2], q[2]);
271 A (d, d, d);
272 Z (e, b, a);
273 Z (f, d, c);
274 A (g, d, c);
275 A (h, b, a);
276
277 M (p[0], e, f);
278 M (p[1], h, g);
279 M (p[2], g, f);
280 M (p[3], e, h);
281}
282
283sv cswap (gf p[4],gf q[4],u8 b)
284{
285 int i;
286 FOR (i,4)
287 sel25519 (p[i],q[i],b);
288}
289
290sv pack (u8 *r,gf p[4])
291{
292 gf tx, ty, zi;
293 inv25519 (zi, p[2]);
294 M (tx, p[0], zi);
295 M (ty, p[1], zi);
296 pack25519 (r, ty);
297 r[31] ^= par25519 (tx) << 7;
298}
299
300sv scalarmult (gf p[4],gf q[4],const u8 *s)
301{
302 int i;
303 set25519 (p[0],gf0);
304 set25519 (p[1],gf1);
305 set25519 (p[2],gf1);
306 set25519 (p[3],gf0);
307 for (i = 255; i >= 0; --i) {
308 u8 b = (s[i / 8] >> (i & 7)) & 1;
309 cswap (p,q,b);
310 add (q,p);
311 add (p,p);
312 cswap (p,q,b);
313 }
314}
315
316sv scalarbase (gf p[4],const u8 *s)
317{
318 gf q[4];
319 set25519 (q[0],X);
320 set25519 (q[1],Y);
321 set25519 (q[2],gf1);
322 M (q[3],X,Y);
323 scalarmult (p,q,s);
324}
325
326static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6,
327 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0x10};
330
331sv modL (u8 *r,i64 x[64])
332{
333 i64 carry,i,j;
334 for (i = 63; i >= 32; --i) {
335 carry = 0;
336 for (j = i - 32; j < i - 12; ++j) {
337 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
338 carry = (x[j] + 128) >> 8;
339 x[j] -= carry << 8;
340 }
341 x[j] += carry;
342 x[i] = 0;
343 }
344 carry = 0;
345 FOR (j,32) {
346 x[j] += carry - (x[31] >> 4) * L[j];
347 carry = x[j] >> 8;
348 x[j] &= 255;
349 }
350 FOR (j,32) x[j] -= carry * L[j];
351 FOR (i,32) {
352 x[i + 1] += x[i] >> 8;
353 r[i] = x[i] & 255;
354 }
355}
356
357sv reduce (u8 *r)
358{
359 i64 x[64],i;
360 FOR (i,64) x[i] = (u64) r[i];
361 FOR (i,64) r[i] = 0;
362 modL (r,x);
363}
364
365static int unpackneg (gf r[4],const u8 p[32])
366{
367 gf t, chk, num, den, den2, den4, den6;
368 set25519 (r[2],gf1);
369 unpack25519 (r[1],p);
370 S (num,r[1]);
371 M (den,num,D);
372 Z (num,num,r[2]);
373 A (den,r[2],den);
374
375 S (den2,den);
376 S (den4,den2);
377 M (den6,den4,den2);
378 M (t,den6,num);
379 M (t,t,den);
380
381 pow2523 (t,t);
382 M (t,t,num);
383 M (t,t,den);
384 M (t,t,den);
385 M (r[0],t,den);
386
387 S (chk,r[0]);
388 M (chk,chk,den);
389 if (neq25519 (chk, num))
390 M (r[0],r[0],I);
391
392 S (chk,r[0]);
393 M (chk,chk,den);
394 if (neq25519 (chk, num))
395 return -1;
396
397 if (par25519 (r[0]) == (p[31] >> 7))
398 Z (r[0],gf0,r[0]);
399
400 M (r[3],r[0],r[1]);
401 return 0;
402}
403
404/* The following functions have been added for GNUnet */
405
406void
407crypto_sign_pk_from_seed (u8 *pk, const u8 *seed)
408{
409 u8 d[64];
410 gf p[4];
411
412 crypto_hash (d, seed, 32);
413 d[0] &= 248;
414 d[31] &= 127;
415 d[31] |= 64;
416
417 scalarbase (p,d);
418 pack (pk,p);
419}
420
421void
422crypto_sign_sk_from_seed (u8 *sk, const u8 *seed)
423{
424 u8 d[64];
425 gf p[4];
426 u8 pk[32];
427 int i;
428
429 crypto_hash (d, seed, 32);
430 d[0] &= 248;
431 d[31] &= 127;
432 d[31] |= 64;
433
434 scalarbase (p,d);
435 pack (pk,p);
436
437 FOR (i,32) sk[i] = seed[i];
438 FOR (i,32) sk[32 + i] = pk[i];
439}
440
441
442int
443crypto_sign_ed25519_pk_to_curve25519 (u8 *x25519_pk, const u8 *ed25519_pk)
444{
445 gf ge_a[4];
446 gf x;
447 gf one_minus_y;
448
449 if (0 != unpackneg (ge_a, ed25519_pk))
450 return -1;
451
452 set25519 (one_minus_y, gf1);
453 Z (one_minus_y, one_minus_y, ge_a[1]);
454
455 set25519 (x, gf1);
456 A (x, x, ge_a[1]);
457
458 inv25519 (one_minus_y, one_minus_y);
459 M (x, x, one_minus_y);
460 pack25519 (x25519_pk, x);
461
462 return 0;
463}
464
465
466int crypto_sign_detached_verify (const u8 *sig,const u8 *m,u64 n,const u8 *pk)
467{
468 struct GNUNET_HashContext *hc;
469 u8 t[32],h[64];
470 gf p[4],q[4];
471
472 if (unpackneg (q,pk))
473 return -1;
474
475 hc = GNUNET_CRYPTO_hash_context_start ();
476 GNUNET_CRYPTO_hash_context_read (hc, sig, 32);
477 GNUNET_CRYPTO_hash_context_read (hc, pk, 32);
478 GNUNET_CRYPTO_hash_context_read (hc, m, n);
479 GNUNET_CRYPTO_hash_context_finish (hc, (void *) h);
480
481 reduce (h);
482 scalarmult (p,q,h);
483
484 scalarbase (q,sig+32);
485 add (p,q);
486 pack (t,p);
487
488 if (crypto_verify_32 (sig, t))
489 return -1;
490 return 0;
491}
492
493
494int
495crypto_sign_detached (u8 *sig,const u8 *m,u64 n,const u8 *sk)
496{
497 struct GNUNET_HashContext *hc;
498 u8 d[64],h[64],r[64];
499 i64 i,j,x[64];
500 gf p[4];
501
502 crypto_hash (d, sk, 32);
503 d[0] &= 248;
504 d[31] &= 127;
505 d[31] |= 64;
506
507 hc = GNUNET_CRYPTO_hash_context_start ();
508 GNUNET_CRYPTO_hash_context_read (hc, d + 32, 32);
509 GNUNET_CRYPTO_hash_context_read (hc, m, n);
510 GNUNET_CRYPTO_hash_context_finish (hc, (void *) r);
511
512 reduce (r);
513 scalarbase (p,r);
514 pack (sig,p);
515
516 hc = GNUNET_CRYPTO_hash_context_start ();
517 GNUNET_CRYPTO_hash_context_read (hc, sig, 32);
518 GNUNET_CRYPTO_hash_context_read (hc, sk + 32, 32);
519 GNUNET_CRYPTO_hash_context_read (hc, m, n);
520 GNUNET_CRYPTO_hash_context_finish (hc, (void *) h);
521
522 reduce (h);
523
524 FOR (i,64) x[i] = 0;
525 FOR (i,32) x[i] = (u64) r[i];
526 FOR (i,32) FOR (j,32) x[i + j] += h[i] * (u64) d[j];
527 modL (sig + 32,x);
528
529 return 0;
530}
diff --git a/src/util/tweetnacl-gnunet.h b/src/util/tweetnacl-gnunet.h
new file mode 100644
index 000000000..776e0d355
--- /dev/null
+++ b/src/util/tweetnacl-gnunet.h
@@ -0,0 +1,85 @@
1/*
2 This file has been placed in the public domain.
3
4 Based on TweetNaCl version 20140427
5
6 Originally obtained from:
7 https://tweetnacl.cr.yp.to/20140427/tweetnacl.h
8 */
9
10
11#ifndef TWEETNACL_H
12#define TWEETNACL_H
13#include <stdint.h>
14#define crypto_scalarmult_PRIMITIVE "curve25519"
15#define crypto_scalarmult crypto_scalarmult_curve25519
16#define crypto_scalarmult_base crypto_scalarmult_curve25519_base
17#define crypto_scalarmult_BYTES crypto_scalarmult_curve25519_BYTES
18#define crypto_scalarmult_SCALARBYTES crypto_scalarmult_curve25519_SCALARBYTES
19#define crypto_scalarmult_IMPLEMENTATION \
20 crypto_scalarmult_curve25519_IMPLEMENTATION
21#define crypto_scalarmult_VERSION crypto_scalarmult_curve25519_VERSION
22#define crypto_scalarmult_curve25519_tweet_BYTES 32
23#define crypto_scalarmult_curve25519_tweet_SCALARBYTES 32
24extern int crypto_scalarmult_curve25519_tweet (uint8_t *,
25 const uint8_t *,
26 const uint8_t *);
27extern int crypto_scalarmult_curve25519_tweet_base (uint8_t *,
28 const uint8_t *);
29#define crypto_scalarmult_curve25519_tweet_VERSION "-"
30#define crypto_scalarmult_curve25519 crypto_scalarmult_curve25519_tweet
31#define crypto_scalarmult_curve25519_base \
32 crypto_scalarmult_curve25519_tweet_base
33#define crypto_scalarmult_curve25519_BYTES \
34 crypto_scalarmult_curve25519_tweet_BYTES
35#define crypto_scalarmult_curve25519_SCALARBYTES \
36 crypto_scalarmult_curve25519_tweet_SCALARBYTES
37#define crypto_scalarmult_curve25519_VERSION \
38 crypto_scalarmult_curve25519_tweet_VERSION
39#define crypto_scalarmult_curve25519_IMPLEMENTATION \
40 "crypto_scalarmult/curve25519/tweet"
41#define crypto_sign_PRIMITIVE "ed25519"
42#define crypto_sign crypto_sign_ed25519
43#define crypto_sign_BYTES crypto_sign_ed25519_BYTES
44#define crypto_sign_PUBLICKEYBYTES crypto_sign_ed25519_PUBLICKEYBYTES
45#define crypto_sign_SECRETKEYBYTES crypto_sign_ed25519_SECRETKEYBYTES
46#define crypto_sign_IMPLEMENTATION crypto_sign_ed25519_IMPLEMENTATION
47#define crypto_sign_VERSION crypto_sign_ed25519_VERSION
48#define crypto_sign_ed25519_tweet_BYTES 64
49#define crypto_sign_ed25519_tweet_PUBLICKEYBYTES 32
50#define crypto_sign_ed25519_tweet_SECRETKEYBYTES 64
51extern int crypto_sign_ed25519_tweet (uint8_t *,
52 uint64_t *,
53 const uint8_t *,
54 uint64_t,
55 const uint8_t *);
56extern int crypto_sign_ed25519_tweet_open (uint8_t *,
57 uint64_t *,
58 const uint8_t *,
59 uint64_t,
60 const uint8_t *);
61extern int crypto_sign_ed25519_tweet_keypair (uint8_t *,uint8_t *);
62#define crypto_sign_ed25519_tweet_VERSION "-"
63#define crypto_sign_ed25519 crypto_sign_ed25519_tweet
64#define crypto_sign_ed25519_open crypto_sign_ed25519_tweet_open
65#define crypto_sign_ed25519_keypair crypto_sign_ed25519_tweet_keypair
66#define crypto_sign_ed25519_BYTES crypto_sign_ed25519_tweet_BYTES
67#define crypto_sign_ed25519_PUBLICKEYBYTES \
68 crypto_sign_ed25519_tweet_PUBLICKEYBYTES
69#define crypto_sign_ed25519_SECRETKEYBYTES \
70 crypto_sign_ed25519_tweet_SECRETKEYBYTES
71#define crypto_sign_ed25519_VERSION crypto_sign_ed25519_tweet_VERSION
72#define crypto_sign_ed25519_IMPLEMENTATION "crypto_sign/ed25519/tweet"
73void crypto_sign_pk_from_seed (uint8_t *pk, const uint8_t *seed);
74void crypto_sign_sk_from_seed (uint8_t *sk, const uint8_t *seed);
75int crypto_sign_ed25519_pk_to_curve25519 (uint8_t *x25519_pk,
76 const uint8_t *ed25519_pk);
77int crypto_sign_detached_verify (const uint8_t *sig,
78 const uint8_t *m,
79 uint64_t n,
80 const uint8_t *pk);
81int crypto_sign_detached (uint8_t *sig,
82 const uint8_t *m,
83 uint64_t n,
84 const uint8_t *sk);
85#endif